From c0f18416f529232b5555c6410a8765a5125ebcd3 Mon Sep 17 00:00:00 2001 From: Ludovic CHEVALIER Date: Tue, 6 Sep 2016 17:26:20 +0200 Subject: [PATCH] [PLUGINS] ~maj globale --- .../formulaires/menu_lang.html | 20 +- www/plugins/Menu_langue_lien/lang/mll.xml | 3 + www/plugins/Menu_langue_lien/lang/mll_en.php | 6 +- www/plugins/Menu_langue_lien/lang/mll_es.php | 6 +- www/plugins/Menu_langue_lien/lang/mll_fr.php | 6 +- www/plugins/Menu_langue_lien/lang/mll_nl.php | 6 +- www/plugins/Menu_langue_lien/lang/mll_ru.php | 28 + www/plugins/Menu_langue_lien/lang/mll_sk.php | 6 +- .../Menu_langue_lien/lang/paquet-mll.xml | 3 + .../Menu_langue_lien/lang/paquet-mll_en.php | 6 +- .../Menu_langue_lien/lang/paquet-mll_es.php | 6 +- .../Menu_langue_lien/lang/paquet-mll_fr.php | 6 +- .../Menu_langue_lien/lang/paquet-mll_nl.php | 6 +- .../Menu_langue_lien/lang/paquet-mll_ru.php | 16 + .../Menu_langue_lien/lang/paquet-mll_sk.php | 6 +- www/plugins/Menu_langue_lien/paquet.xml | 10 +- www/plugins/Menu_langue_lien/plugin.xml | 10 +- www/plugins/Menu_langue_lien/svn.revision | 8 +- .../compositions_fonctions.php | 953 +-- .../compositions_v3/compositions_ieconfig.php | 26 +- .../compositions_v3/compositions_options.php | 12 + .../compositions_v3/compositions_pipeline.php | 292 +- .../formulaires/configurer_compositions.html | 12 +- .../formulaires/editer_composition_objet.html | 214 +- .../inc-informeur_composition.html | 8 - .../inc-selecteur_composition.html | 20 +- .../images/composition-cours.png | Bin 545 -> 356 bytes .../images/composition-tableau.png | Bin 428 -> 245 bytes .../images/composition-test.png | Bin 506 -> 250 bytes .../compositions_v3/images/objet-blocs.png | Bin 0 -> 189 bytes .../images/objet-intro-blocs.png | Bin 0 -> 207 bytes .../images/objet-liste-contenus-dates.png | Bin 692 -> 343 bytes .../images/objet-liste-contenus.png | Bin 491 -> 244 bytes .../compositions_v3/images/objet-simple.png | Bin 463 -> 237 bytes .../compositions_v3/inc/compositions.php | 25 +- .../compositions_v3/lang/compositions.xml | 19 +- .../compositions_v3/lang/compositions_de.php | 55 + .../compositions_v3/lang/compositions_en.php | 23 +- .../compositions_v3/lang/compositions_es.php | 10 +- .../compositions_v3/lang/compositions_fr.php | 22 +- .../compositions_v3/lang/compositions_nl.php | 23 +- .../compositions_v3/lang/compositions_ru.php | 9 +- .../compositions_v3/lang/compositions_sk.php | 9 +- .../lang/paquet-compositions_en.php | 6 +- .../lang/paquet-compositions_es.php | 6 +- .../lang/paquet-compositions_fr.php | 6 +- .../lang/paquet-compositions_nl.php | 6 +- .../lang/paquet-compositions_ru.php | 6 +- .../lang/paquet-compositions_sk.php | 6 +- www/plugins/compositions_v3/paquet.xml | 18 +- .../prive/editer/compositions.html | 2 +- .../squelettes/contenu/compositions.html | 110 +- .../squelettes/navigation/compositions.html | 8 + .../style_prive_plugin_compositions.html | 13 +- .../themes/spip/images/composition-16.png | Bin 454 -> 405 bytes .../themes/spip/images/composition-24.png | Bin 667 -> 609 bytes .../themes/spip/images/composition-32.png | Bin 917 -> 826 bytes .../themes/spip2/images/composition-16.png | Bin 195 -> 115 bytes .../themes/spip2/images/composition-24.png | Bin 175 -> 118 bytes .../themes/spip2/images/composition-32.png | Bin 188 -> 132 bytes www/plugins/compositions_v3/svn.revision | 8 +- .../base/typoenluminee_upgrade.php | 61 + .../css/enluminurestypo.css | 26 +- .../css/enluminurestypo_prive.css | 4 + .../editeur/supprimer_ligne.png | Bin 655 -> 584 bytes .../enluminures_typo_pipelines.php | 462 +- .../exec/tableau_edit.php | 18 +- .../formulaires/configurer_typoenluminee.html | 235 +- .../icones_barre/avances.png | Bin 666 -> 604 bytes .../icones_barre/barre-tableau.png | Bin 155 -> 147 bytes .../icones_barre/barre-wiki.png | Bin 334 -> 219 bytes .../icones_barre/cadretexte.png | Bin 257 -> 138 bytes .../icones_barre/center.png | Bin 230 -> 98 bytes .../icones_barre/eacute-maj.png | Bin 275 -> 149 bytes .../icones_barre/exposant.png | Bin 265 -> 141 bytes .../icones_barre/indice.png | Bin 209 -> 142 bytes .../icones_barre/intertitre2.png | Bin 263 -> 144 bytes .../icones_barre/intertitre3.png | Bin 263 -> 144 bytes .../icones_barre/left.png | Bin 225 -> 92 bytes .../icones_barre/listenum.png | Bin 246 -> 129 bytes .../icones_barre/listepuces.png | Bin 231 -> 108 bytes .../icones_barre/miseenevidence.png | Bin 261 -> 133 bytes .../icones_barre/miseenevidence2.png | Bin 1261 -> 133 bytes .../icones_barre/oelig-maj.png | Bin 295 -> 162 bytes .../icones_barre/oelig.png | Bin 279 -> 138 bytes .../icones_barre/page_white_code.png | Bin 603 -> 533 bytes .../icones_barre/page_white_code_red.png | Bin 587 -> 519 bytes .../icones_barre/petitescapitales.png | Bin 262 -> 138 bytes .../icones_barre/poesie.png | Bin 194 -> 174 bytes .../icones_barre/right.png | Bin 225 -> 93 bytes .../icones_barre/tag.png | Bin 389 -> 328 bytes .../icones_barre/text_strikethrough.png | Bin 269 -> 212 bytes .../img_pack/e.gif | Bin 344 -> 343 bytes .../img_pack/moinecopiste.gif | Bin 1809 -> 1803 bytes .../lang/enlumtypo.xml | 18 +- .../lang/enlumtypo_ar.php | 6 +- .../lang/enlumtypo_en.php | 6 +- .../lang/enlumtypo_es.php | 6 +- .../lang/enlumtypo_fr.php | 9 +- .../lang/enlumtypo_it.php | 6 +- .../lang/enlumtypo_nl.php | 45 + .../lang/enlumtypo_ru.php | 44 + .../lang/paquet-typoenluminee.xml | 4 + .../lang/paquet-typoenluminee_fr.php | 42 +- .../enluminures_typographiques_v3/paquet.xml | 11 +- .../enluminures_typographiques_v3/plugin.xml | 6 +- .../themes/spip/images/typoenluminee-16.png | Bin 575 -> 433 bytes .../themes/spip/images/typoenluminee-32.png | Bin 1333 -> 1178 bytes .../svn.revision | 12 +- .../typoenluminee.php | 603 +- .../typoenluminee_administrations.php | 59 + .../typoenluminee_options.php | 28 +- .../typoenluminee_pipelines.php | 63 +- www/plugins/facteur/classes/facteur.php | 303 +- .../facteur/emails/test_email_html.html | 45 +- www/plugins/facteur/emails/texte.html | 4 +- www/plugins/facteur/facteur_fonctions.php | 20 +- www/plugins/facteur/facteur_pipelines.php | 4 +- .../formulaires/configurer_facteur.html | 55 +- .../formulaires/configurer_facteur.php | 120 +- www/plugins/facteur/inc/envoyer_mail.php | 76 +- www/plugins/facteur/lang/facteur.xml | 26 +- www/plugins/facteur/lang/facteur_de.php | 24 +- www/plugins/facteur/lang/facteur_en.php | 24 +- www/plugins/facteur/lang/facteur_es.php | 24 +- www/plugins/facteur/lang/facteur_fa.php | 24 +- www/plugins/facteur/lang/facteur_fr.php | 28 +- www/plugins/facteur/lang/facteur_fr_tu.php | 24 +- www/plugins/facteur/lang/facteur_it.php | 78 + www/plugins/facteur/lang/facteur_nl.php | 16 +- .../facteur/lang/facteur_oc_ni_mis.php | 79 + www/plugins/facteur/lang/facteur_pt_br.php | 83 + www/plugins/facteur/lang/facteur_sk.php | 25 +- www/plugins/facteur/lang/paquet-facteur.xml | 3 + .../facteur/lang/paquet-facteur_de.php | 6 +- .../facteur/lang/paquet-facteur_en.php | 6 +- .../facteur/lang/paquet-facteur_es.php | 6 +- .../facteur/lang/paquet-facteur_fr.php | 6 +- .../facteur/lang/paquet-facteur_fr_tu.php | 6 +- .../facteur/lang/paquet-facteur_nl.php | 6 +- .../facteur/lang/paquet-facteur_pt_br.php | 16 + .../facteur/lang/paquet-facteur_ru.php | 6 +- .../facteur/lang/paquet-facteur_sk.php | 6 +- www/plugins/facteur/paquet.xml | 18 +- www/plugins/facteur/phpmailer-php5/LICENSE | 1008 +-- .../phpmailer-php5/PHPMailerAutoload.php | 49 + www/plugins/facteur/phpmailer-php5/README | 178 - www/plugins/facteur/phpmailer-php5/README.md | 184 + www/plugins/facteur/phpmailer-php5/VERSION | 1 + .../facteur/phpmailer-php5/changelog.md | 620 ++ .../phpmailer-php5/class.phpmailer.php | 6141 +++++++++++------ .../phpmailer-php5/class.phpmaileroauth.php | 196 + .../class.phpmaileroauthgoogle.php | 76 + .../facteur/phpmailer-php5/class.pop3.php | 752 +- .../facteur/phpmailer-php5/class.smtp.php | 1995 +++--- .../facteur/phpmailer-php5/composer.json | 45 + .../phpmailer-php5/extras/EasyPeasyICS.php | 148 + .../facteur/phpmailer-php5/extras/README.md | 17 + .../phpmailer-php5/extras/htmlfilter.php | 1166 ++++ .../extras/ntlm_sasl_client.php | 185 + .../phpmailer-php5/get_oauth_token.php | 60 + .../language/phpmailer.lang-am.php | 26 + .../language/phpmailer.lang-ar.php | 42 +- .../language/phpmailer.lang-az.php | 26 + .../language/phpmailer.lang-be.php | 26 + .../language/phpmailer.lang-bg.php | 26 + .../language/phpmailer.lang-br.php | 54 +- .../language/phpmailer.lang-ca.php | 52 +- .../language/phpmailer.lang-ch.php | 34 +- .../language/phpmailer.lang-cz.php | 50 +- .../language/phpmailer.lang-de.php | 50 +- .../language/phpmailer.lang-dk.php | 52 +- .../language/phpmailer.lang-el.php | 25 + .../language/phpmailer.lang-en.php | 25 - .../language/phpmailer.lang-eo.php | 25 + .../language/phpmailer.lang-es.php | 52 +- .../language/phpmailer.lang-et.php | 25 +- .../language/phpmailer.lang-fa.php | 27 + .../language/phpmailer.lang-fi.php | 54 +- .../language/phpmailer.lang-fo.php | 53 +- .../language/phpmailer.lang-fr.php | 54 +- .../language/phpmailer.lang-gl.php | 26 + .../language/phpmailer.lang-he.php | 26 + .../language/phpmailer.lang-hr.php | 26 + .../language/phpmailer.lang-hu.php | 51 +- .../language/phpmailer.lang-id.php | 26 + .../language/phpmailer.lang-it.php | 54 +- .../language/phpmailer.lang-ja.php | 53 +- .../language/phpmailer.lang-ka.php | 26 + .../language/phpmailer.lang-ko.php | 26 + .../language/phpmailer.lang-lt.php | 26 + .../language/phpmailer.lang-lv.php | 26 + .../language/phpmailer.lang-ms.php | 26 + .../language/phpmailer.lang-nl.php | 51 +- .../language/phpmailer.lang-no.php | 50 +- .../language/phpmailer.lang-pl.php | 51 +- .../language/phpmailer.lang-pt.php | 26 + .../language/phpmailer.lang-ro.php | 53 +- .../language/phpmailer.lang-ru.php | 52 +- .../language/phpmailer.lang-se.php | 52 +- .../language/phpmailer.lang-sk.php | 26 + .../language/phpmailer.lang-sl.php | 26 + .../language/phpmailer.lang-sr.php | 26 + .../language/phpmailer.lang-tr.php | 56 +- .../language/phpmailer.lang-uk.php | 27 + .../language/phpmailer.lang-vi.php | 26 + .../language/phpmailer.lang-zh.php | 48 +- .../language/phpmailer.lang-zh_cn.php | 45 +- .../phpmailer-php5/travis.phpunit.xml.dist | 34 + www/plugins/facteur/svn.revision | 8 +- .../action/dupliquer_formulaire.php | 33 +- .../formidable/action/editer_formulaire.php | 65 +- .../action/exporter_analyse_reponses.php | 108 - .../formidable/action/exporter_formulaire.php | 16 +- .../action/exporter_formulaires_reponses.php | 85 - .../action/supprimer_formulaire.php | 19 +- .../action/supprimer_formulaires_reponse.php | 19 +- .../formidable/action/vider_formulaire.php | 38 +- .../formidable/base/formidable_tables.php | 120 +- .../formidable/echanger/formulaire/forms.php | 763 +- .../formidable/echanger/formulaire/wcs.php | 88 +- .../formidable/echanger/formulaire/yaml.php | 47 +- .../exec/puce_statut_formulaires.php | 27 +- .../formidable/formidable_administrations.php | 253 +- .../formidable/formidable_autorisations.php | 158 +- .../formidable/formidable_fonctions.php | 62 +- www/plugins/formidable/formidable_options.php | 43 +- .../formidable/formidable_pipelines.php | 167 +- .../configurer_formidable_analyse.html | 17 +- .../formulaires/editer_formulaire.html | 9 +- .../formulaires/editer_formulaire.php | 44 +- .../formulaires/editer_formulaire_champs.php | 76 +- .../editer_formulaire_traitements.html | 4 +- .../editer_formulaire_traitements.php | 65 +- .../exporter_formulaire_analyse.html | 29 + .../exporter_formulaire_analyse.php | 131 + .../exporter_formulaire_reponses.html | 35 + .../exporter_formulaire_reponses.php | 155 + .../formidable/formulaires/formidable.html | 10 +- .../formidable/formulaires/formidable.php | 176 +- .../formulaires/importer_formulaire.html | 4 +- .../formulaires/importer_formulaire.php | 40 +- .../formulaires/inc-formidable-unicite.html | 21 + .../collectionjson/formulaires-ressource.html | 11 + .../http/collectionjson/formulaires.html | 38 + .../formulaires_reponses-ressource.html | 11 + .../collectionjson/formulaires_reponses.html | 39 + .../collectionjson/formulaires_reponses.php | 132 + .../http/collectionjson/inc-formulaire.html | 43 + .../inc-formulaires_reponse.html | 36 + .../formidable/icones_barre/formulaire.png | Bin 688 -> 623 bytes .../formidable/images/formidable-128.png | Bin 12158 -> 9963 bytes .../formidable/images/formidable-24.png | Bin 1357 -> 1230 bytes .../formidable/images/formidable-64.png | Bin 5234 -> 4773 bytes .../formidable/images/formulaire-24.png | Bin 843 -> 730 bytes .../images/formulaire-action-ajouter.png | Bin 629 -> 535 bytes .../images/formulaire-analyse-24.png | Bin 1176 -> 1057 bytes .../images/formulaire-config-auteurs-24.png | Bin 1141 -> 1047 bytes .../images/formulaire-config-champs-24.png | Bin 979 -> 816 bytes .../formulaire-config-traitements-24.png | Bin 1393 -> 1016 bytes .../images/formulaire-dupliquer-24.png | Bin 1300 -> 1166 bytes .../images/formulaire-editer-24.png | Bin 1097 -> 986 bytes .../images/formulaire-exporter-24.png | Bin 1127 -> 999 bytes .../images/formulaire-nouveau-48.png | Bin 2443 -> 2203 bytes .../images/formulaire-reponse-24.png | Bin 667 -> 515 bytes .../formulaire-reponse-supprimer-24.png | Bin 1190 -> 1016 bytes .../images/formulaire-reponses-24.png | Bin 1108 -> 1013 bytes .../formulaire-reponses-exporter-24.png | Bin 1213 -> 1095 bytes .../formulaire-reponses-supprimer-24.png | Bin 1423 -> 1328 bytes .../images/formulaire-supprimer-24.png | Bin 1387 -> 1274 bytes www/plugins/formidable/inc/formidable.php | 556 +- ...res_reponse_formulaires_reponses_champ.php | 30 +- www/plugins/formidable/lang/formidable.xml | 25 +- www/plugins/formidable/lang/formidable_ar.php | 171 + www/plugins/formidable/lang/formidable_de.php | 9 +- www/plugins/formidable/lang/formidable_en.php | 45 +- www/plugins/formidable/lang/formidable_es.php | 11 +- www/plugins/formidable/lang/formidable_fr.php | 36 +- www/plugins/formidable/lang/formidable_it.php | 7 +- .../formidable/lang/formidable_pt_br.php | 233 + www/plugins/formidable/lang/formidable_ru.php | 215 + www/plugins/formidable/lang/formidable_sk.php | 7 +- www/plugins/formidable/lang/formulaire.xml | 7 + www/plugins/formidable/lang/formulaire_fr.php | 10 +- www/plugins/formidable/lang/formulaire_ru.php | 21 + .../formidable/lang/formulaires_reponse.xml | 4 + .../lang/formulaires_reponse_fr.php | 24 +- .../formidable/lang/paquet-formidable.xml | 3 + .../formidable/lang/paquet-formidable_en.php | 15 + .../formidable/lang/paquet-formidable_es.php | 6 +- .../formidable/lang/paquet-formidable_fr.php | 6 +- www/plugins/formidable/modeles/form.html | 8 +- .../modeles/formulaires_reponse.html | 2 +- www/plugins/formidable/paquet.xml | 20 +- .../prive/objets/liste/formulaires.html | 4 +- .../objets/liste/formulaires_associer.html | 72 + .../liste/formulaires_associer_fonctions.php | 16 + .../prive/objets/liste/formulaires_lies.html | 62 + .../liste/formulaires_lies_fonctions.php | 15 + .../prive/squelettes/contenu/formulaire.html | 2 +- .../contenu/formulaires_reponse.html | 2 +- .../prive/squelettes/extra/formulaire.html | 2 +- .../squelettes/extra/formulaires_analyse.html | 9 +- .../extra/formulaires_reponses.html | 14 +- .../inclure/formulaires_reponses-filtres.html | 23 +- .../squelettes/navigation/formulaire.html | 76 +- .../navigation/formulaires_analyse.html | 4 +- .../navigation/formulaires_reponse.html | 4 + .../navigation/formulaires_reponses.html | 5 +- .../themes/basic/images/formulaire-16.png | Bin 742 -> 654 bytes .../themes/spip/images/formulaire-16.png | Bin 742 -> 654 bytes .../themes/spip/images/formulaire-24.png | Bin 843 -> 730 bytes .../spip/images/formulaires_reponse-24.png | Bin 1108 -> 1013 bytes .../formidable/public/formidable_criteres.php | 25 +- .../puce_statut/formulaires_reponse.php | 57 +- www/plugins/formidable/svn.revision | 8 +- www/plugins/formidable/traiter/email.php | 160 +- www/plugins/formidable/traiter/email.yaml | 12 + .../formidable/traiter/enregistrement.php | 341 +- www/plugins/gis/action/editer_gis.php | 132 +- www/plugins/gis/action/editer_lien_gis.php | 19 +- .../gis/action/gis_geocoder_rechercher.php | 41 +- www/plugins/gis/action/kml_infos.php | 46 +- www/plugins/gis/action/supprimer_gis.php | 18 +- www/plugins/gis/base/gis.php | 66 +- www/plugins/gis/crud/gis.php | 51 +- www/plugins/gis/css/leaflet_nodirection.css | 19 + www/plugins/gis/embed/kml_fonctions.php | 6 +- .../gis/formulaires/configurer_gis.html | 21 +- .../gis/formulaires/configurer_gis.php | 25 +- www/plugins/gis/formulaires/editer_gis.html | 37 +- www/plugins/gis/formulaires/editer_gis.php | 69 +- .../gis_inserer_modeles_traiter.php | 73 +- .../gis/formulaires/rechercher_gis.php | 18 +- www/plugins/gis/gis_administrations.php | 33 +- www/plugins/gis/gis_autoriser.php | 76 +- www/plugins/gis/gis_fonctions.php | 271 +- www/plugins/gis/gis_options.php | 24 +- www/plugins/gis/gis_pipelines.php | 197 +- www/plugins/gis/icones_barre/gis.png | Bin 267 -> 251 bytes www/plugins/gis/images/gis-16.png | Bin 267 -> 251 bytes www/plugins/gis/images/gis-24.png | Bin 714 -> 350 bytes www/plugins/gis/images/gis.png | Bin 6005 -> 5559 bytes www/plugins/gis/inc/gis_xmlrpc.php | 90 +- www/plugins/gis/inc/iptc.php | 362 +- www/plugins/gis/inc/kml_infos.php | 185 +- www/plugins/gis/javascript/.eslintrc | 32 + www/plugins/gis/javascript/gis.js.html | 18 +- www/plugins/gis/javascript/gis_geocoder.js | 154 +- www/plugins/gis/javascript/gis_utils.js | 6 +- www/plugins/gis/javascript/leaflet.gis.js | 190 +- www/plugins/gis/json/gis.html | 3 +- www/plugins/gis/json/gis_articles.html | 3 +- .../gis/json/gis_articles_branche.html | 3 +- www/plugins/gis/json/gis_auteurs.html | 3 +- www/plugins/gis/json/gis_documents.html | 3 +- www/plugins/gis/json/gis_evenements.html | 3 +- www/plugins/gis/json/gis_mots.html | 3 +- www/plugins/gis/json/gis_organisations.html | 3 +- www/plugins/gis/json/gis_rubriques.html | 3 +- www/plugins/gis/json/gis_sites.html | 3 +- .../gis_tous_avec_liens_espace_prive.html | 3 +- www/plugins/gis/lang/gis.xml | 14 +- www/plugins/gis/lang/gis_de.php | 21 +- www/plugins/gis/lang/gis_en.php | 47 +- www/plugins/gis/lang/gis_es.php | 21 +- www/plugins/gis/lang/gis_fr.php | 49 +- www/plugins/gis/lang/gis_nl.php | 49 +- www/plugins/gis/lang/gis_ru.php | 19 +- www/plugins/gis/lang/gis_sk.php | 21 +- www/plugins/gis/lang/paquet-gis_en.php | 2 - www/plugins/gis/lang/paquet-gis_es.php | 2 - www/plugins/gis/lang/paquet-gis_fr.php | 2 - www/plugins/gis/lang/paquet-gis_nl.php | 2 - www/plugins/gis/lang/paquet-gis_ru.php | 2 - www/plugins/gis/lang/paquet-gis_sk.php | 2 - www/plugins/gis/lib/leaflet/README.md | 58 +- www/plugins/gis/lib/leaflet/plugins/Bing.js | 31 +- .../lib/leaflet/plugins/Control.FullScreen.js | 86 +- .../lib/leaflet/plugins/Control.MiniMap.js | 553 +- .../gis/lib/leaflet/plugins/GPX.Speed.js | 16 +- www/plugins/gis/lib/leaflet/plugins/GPX.js | 51 +- www/plugins/gis/lib/leaflet/plugins/Google.js | 135 +- www/plugins/gis/lib/leaflet/plugins/KML.js | 51 +- .../gis/lib/leaflet/plugins/Marker.Rotate.js | 15 +- .../gis/lib/leaflet/plugins/TOPOJSON.js | 636 ++ .../plugins/images/icon-fullscreen-2x.png | Bin 228 -> 215 bytes .../plugins/images/icon-fullscreen.png | Bin 389 -> 139 bytes .../gis/lib/leaflet/plugins/images/toggle.png | Bin 345 -> 219 bytes .../gis/lib/leaflet/plugins/images/toggle.svg | 224 + .../lib/leaflet/plugins/leaflet-plugins.css | 32 +- .../lib/leaflet/plugins/leaflet-providers.js | 54 +- .../plugins/leaflet.markercluster-src.js | 1012 ++- .../leaflet/plugins/leaflet.markercluster.css | 8 + www/plugins/gis/modeles/carte_gis.html | 22 +- .../gis/modeles/carte_gis_preview.html | 8 +- www/plugins/gis/paquet.xml | 7 +- www/plugins/gis/prive/contenu/gis_objet.html | 7 +- .../prive/inclure/gis_objet_formulaires.html | 43 +- .../gis/prive/objets/liste/gis_associer.html | 2 +- .../objets/liste/gis_associer_fonctions.php | 6 +- .../gis/prive/objets/liste/gis_lies.html | 6 +- .../prive/objets/liste/gis_lies_fonctions.php | 6 +- .../gis/prive/squelettes/contenu/gis.html | 2 +- .../gis/prive/style_prive_plugin_gis.html | 5 +- .../gis/prive/themes/spip/images/gis-16.png | Bin 267 -> 251 bytes .../gis/prive/themes/spip/images/gis-24.png | Bin 714 -> 350 bytes .../prive/themes/spip/images/gis-new-16.png | Bin 616 -> 457 bytes www/plugins/gis/saisies/carte.html | 8 +- www/plugins/gis/svn.revision | 8 +- www/plugins/gis/tests/gis_connect_sql.php | 20 +- www/plugins/menus_1/action/editer_menu.php | 2 +- .../menus_1/action/editer_menus_entree.php | 2 + www/plugins/menus_1/action/generer_menus.php | 29 + www/plugins/menus_1/css/menuspip.css | 1 + .../menus_1/formulaires/editer_menu.html | 22 +- .../menus_1/formulaires/editer_menu.php | 6 +- .../formulaires/editer_menus_entree.html | 8 +- .../formulaires/editer_menus_entree.php | 47 +- .../formulaires/inc-menus_entrees.html | 27 +- .../formulaires/inc-nouvelle_entree-1.html | 8 +- .../formulaires/inc-nouvelle_entree-2.html | 10 +- .../menus_1/images/menus_rechercher.png | Bin 0 -> 2123 bytes www/plugins/menus_1/inc/menus.php | 3 +- www/plugins/menus_1/lang/menus.xml | 28 +- www/plugins/menus_1/lang/menus_ar.php | 6 +- www/plugins/menus_1/lang/menus_ca.php | 6 +- www/plugins/menus_1/lang/menus_de.php | 14 +- www/plugins/menus_1/lang/menus_en.php | 8 +- www/plugins/menus_1/lang/menus_es.php | 14 +- www/plugins/menus_1/lang/menus_fa.php | 8 +- www/plugins/menus_1/lang/menus_fr.php | 17 +- www/plugins/menus_1/lang/menus_it.php | 6 +- www/plugins/menus_1/lang/menus_nl.php | 15 +- www/plugins/menus_1/lang/menus_pt_br.php | 177 + www/plugins/menus_1/lang/menus_ru.php | 6 +- www/plugins/menus_1/lang/menus_sk.php | 14 +- www/plugins/menus_1/lang/paquet-menus.xml | 3 + www/plugins/menus_1/lang/paquet-menus_ar.php | 6 +- www/plugins/menus_1/lang/paquet-menus_de.php | 6 +- www/plugins/menus_1/lang/paquet-menus_en.php | 6 +- www/plugins/menus_1/lang/paquet-menus_es.php | 6 +- www/plugins/menus_1/lang/paquet-menus_fr.php | 6 +- www/plugins/menus_1/lang/paquet-menus_it.php | 6 +- www/plugins/menus_1/lang/paquet-menus_nl.php | 6 +- .../menus_1/lang/paquet-menus_pt_br.php | 23 + www/plugins/menus_1/lang/paquet-menus_sk.php | 6 +- www/plugins/menus_1/menus/lien.html | 2 +- www/plugins/menus_1/menus/objet.html | 14 +- www/plugins/menus_1/menus/objet.xml | 1 + www/plugins/menus_1/menus/page_speciale.html | 2 +- www/plugins/menus_1/menus/recherche.html | 9 + www/plugins/menus_1/menus/recherche.xml | 7 + www/plugins/menus_1/menus_fonctions.php | 18 +- www/plugins/menus_1/menus_ieconfig.php | 17 +- www/plugins/menus_1/paquet.xml | 12 +- .../prive/squelettes/contenu/menus_tous.html | 23 +- www/plugins/menus_1/svn.revision | 8 +- www/plugins/multilang/CHANGELOG.md | 22 + .../formulaires/configurer_multilang.html | 2 +- .../configurer_multilang_fonctions.php | 9 +- www/plugins/multilang/images/background.png | Bin 7909 -> 7561 bytes .../multilang/images/multi_forbidden.png | Bin 357 -> 234 bytes .../multilang/images/multi_undefined.png | Bin 340 -> 206 bytes www/plugins/multilang/images/multilang-16.png | Bin 2034 -> 843 bytes www/plugins/multilang/images/multilang-24.png | Bin 1392 -> 1163 bytes www/plugins/multilang/images/multilang-32.png | Bin 1784 -> 1597 bytes www/plugins/multilang/images/multilang-48.png | Bin 2479 -> 2322 bytes www/plugins/multilang/javascript/multilang.js | 38 +- .../multilang_init.js_fonctions.php | 68 +- www/plugins/multilang/lang/multilang.xml | 9 + www/plugins/multilang/lang/multilang_de.php | 38 + www/plugins/multilang/lang/multilang_en.php | 6 +- www/plugins/multilang/lang/multilang_es.php | 6 +- www/plugins/multilang/lang/multilang_fa.php | 6 +- www/plugins/multilang/lang/multilang_fr.php | 6 +- www/plugins/multilang/lang/multilang_nl.php | 6 +- www/plugins/multilang/lang/multilang_ru.php | 38 + www/plugins/multilang/lang/multilang_sk.php | 6 +- www/plugins/multilang/lang/multilang_uk.php | 38 + .../multilang/lang/paquet-multilang.xml | 7 + .../multilang/lang/paquet-multilang_de.php | 15 + .../multilang/lang/paquet-multilang_en.php | 6 +- .../multilang/lang/paquet-multilang_es.php | 6 +- .../multilang/lang/paquet-multilang_fr.php | 6 +- .../multilang/lang/paquet-multilang_it.php | 6 +- .../multilang/lang/paquet-multilang_nl.php | 6 +- .../multilang/lang/paquet-multilang_ru.php | 8 +- .../multilang/lang/paquet-multilang_sk.php | 6 +- .../multilang/lang/paquet-multilang_uk.php | 15 + www/plugins/multilang/multilang.css.html | 5 +- .../multilang/multilang_administrations.php | 113 +- www/plugins/multilang/multilang_pipelines.php | 338 +- www/plugins/multilang/paquet.xml | 8 +- .../prive/style_prive_plugin_multilang.html | 4 +- .../prive/themes/spip/images/multilang-16.png | Bin 1268 -> 643 bytes .../prive/themes/spip/images/multilang-24.png | Bin 1392 -> 1163 bytes www/plugins/multilang/svn.revision | 8 +- www/plugins/nospam/inc/detecter_langue.php | 366 +- www/plugins/nospam/lang/nospam.xml | 3 + www/plugins/nospam/lang/nospam_ar.php | 6 +- www/plugins/nospam/lang/nospam_de.php | 29 + www/plugins/nospam/lang/nospam_en.php | 6 +- www/plugins/nospam/lang/nospam_es.php | 6 +- www/plugins/nospam/lang/nospam_fa.php | 6 +- www/plugins/nospam/lang/nospam_fr.php | 6 +- www/plugins/nospam/lang/nospam_fr_tu.php | 6 +- www/plugins/nospam/lang/nospam_nl.php | 6 +- www/plugins/nospam/lang/nospam_sk.php | 6 +- www/plugins/nospam/lang/paquet-nospam_ar.php | 6 +- www/plugins/nospam/lang/paquet-nospam_de.php | 6 +- www/plugins/nospam/lang/paquet-nospam_en.php | 6 +- www/plugins/nospam/lang/paquet-nospam_es.php | 6 +- www/plugins/nospam/lang/paquet-nospam_fr.php | 6 +- .../nospam/lang/paquet-nospam_fr_tu.php | 6 +- www/plugins/nospam/lang/paquet-nospam_nl.php | 6 +- www/plugins/nospam/lang/paquet-nospam_sk.php | 6 +- .../nospam/verifier_formulaire_forum.php | 55 +- www/plugins/nospam/nospam_pipelines.php | 31 +- www/plugins/nospam/paquet.xml | 6 +- www/plugins/nospam/plugin.xml | 6 +- www/plugins/nospam/svn.revision | 8 +- .../formulaires/abonner_notifications.php | 2 +- .../formulaires/configurer_notifications.html | 33 +- .../notifications2/lang/notifications.xml | 17 +- .../notifications2/lang/notifications_de.php | 135 + .../notifications2/lang/notifications_en.php | 27 +- .../notifications2/lang/notifications_es.php | 18 +- .../notifications2/lang/notifications_fa.php | 12 +- .../notifications2/lang/notifications_fr.php | 28 +- .../notifications2/lang/notifications_nl.php | 26 +- .../notifications2/lang/notifications_sk.php | 18 +- .../lang/paquet-notifications.xml | 3 + .../lang/paquet-notifications_de.php | 15 + .../lang/paquet-notifications_en.php | 6 +- .../lang/paquet-notifications_es.php | 6 +- .../lang/paquet-notifications_fa.php | 6 +- .../lang/paquet-notifications_fr.php | 6 +- .../lang/paquet-notifications_nl.php | 6 +- .../lang/paquet-notifications_sk.php | 6 +- .../notifications/article_refuse.html | 25 + .../notifications/forum_poste.html | 2 +- .../notifications/forumvalide.php | 74 +- .../notifications/instituerarticle.php | 4 + .../notifications_pipelines.php | 77 +- www/plugins/notifications2/paquet.xml | 10 +- www/plugins/notifications2/svn.revision | 8 +- .../odt2spip_30/action/odt2spip_importe.php | 2 +- www/plugins/odt2spip_30/paquet.xml | 4 +- www/plugins/odt2spip_30/svn.revision | 8 +- .../images/redirhttps-128.png | Bin .../lang/paquet-redirhttps.xml | 0 .../lang/paquet-redirhttps_en.php | 0 .../lang/paquet-redirhttps_es.php | 0 .../lang/paquet-redirhttps_fr.php | 0 .../lang/paquet-redirhttps_sk.php | 0 .../lang/redirhttps.xml | 0 .../{redirhttps => redirhttps.bak}/paquet.xml | 0 .../{redirhttps => redirhttps.bak}/plugin.xml | 0 .../redirhttps_options.php | 0 .../svn.revision | 0 .../rss_article_3_0/base/rssarticle.php | 26 +- .../rss_article_3_0/exec/rss_article.php | 46 +- .../formulaires/configurer_rssarticle.html | 114 +- .../formulaires/editer_rssarticle.html | 26 +- .../formulaires/editer_rssarticle.php | 57 +- .../genie/rssarticle_copie.php | 312 +- .../rss_article_3_0/lang/rssarticle_ar.php | 44 +- .../rss_article_3_0/lang/rssarticle_fr.php | 75 +- www/plugins/rss_article_3_0/paquet.xml | 16 +- .../prive/contenu/rssarticle.html | 2 +- .../themes/spip/images/rssarticle-128.png | Bin 2860 -> 1887 bytes .../themes/spip/images/rssarticle-16.png | Bin 981 -> 566 bytes .../themes/spip/images/rssarticle-32.png | Bin 1218 -> 1105 bytes .../themes/spip/images/rssarticle-64.png | Bin 2860 -> 1869 bytes .../rssarticle_administrations.php | 81 +- .../rss_article_3_0/rssarticle_pipelines.php | 64 +- www/plugins/rss_article_3_0/svn.revision | 8 +- .../saisies/action/deplacer_saisie.php | 17 +- .../saisies/balise/configurer_saisie.php | 10 +- .../saisies/balise/generer_saisies.php | 11 +- www/plugins/saisies/balise/saisie.php | 54 +- www/plugins/saisies/balise/voir_saisie.php | 12 +- www/plugins/saisies/balise/voir_saisies.php | 14 +- .../formulaires/construire_formulaire.html | 3 +- .../formulaires/construire_formulaire.php | 247 +- .../saisies/formulaires/saisies_cvt.php | 7 +- .../saisies/images/formulaire-annuler-16.png | Bin 714 -> 508 bytes .../images/formulaire-configurer-16.png | Bin 843 -> 734 bytes .../saisies/images/formulaire-deplacer-16.png | Bin 575 -> 391 bytes .../images/formulaire-dupliquer-16.png | Bin 1080 -> 846 bytes .../images/formulaire-enregistrer-16.png | Bin 743 -> 560 bytes .../images/formulaire-reinitialiser-24.png | Bin 1503 -> 1251 bytes .../images/formulaire-saisie-defaut.png | Bin 511 -> 306 bytes .../images/formulaire-supprimer-16.png | Bin 319 -> 231 bytes www/plugins/saisies/images/logo_saisie_48.png | Bin 1220 -> 588 bytes .../saisies/images/saisies_auteurs.png | Bin 742 -> 583 bytes www/plugins/saisies/images/saisies_case.png | Bin 360 -> 185 bytes .../saisies/images/saisies_checkbox.png | Bin 463 -> 211 bytes www/plugins/saisies/images/saisies_date.png | Bin 1476 -> 662 bytes .../saisies/images/saisies_explication.png | Bin 390 -> 259 bytes .../saisies/images/saisies_fieldset.png | Bin 233 -> 128 bytes www/plugins/saisies/images/saisies_hidden.png | Bin 429 -> 96 bytes www/plugins/saisies/images/saisies_input.png | Bin 609 -> 279 bytes .../saisies/images/saisies_oui_non.png | Bin 422 -> 326 bytes www/plugins/saisies/images/saisies_radio.png | Bin 560 -> 266 bytes .../images/saisies_selecteur_article.png | Bin 256 -> 168 bytes .../images/saisies_selecteur_rubrique.png | Bin 254 -> 168 bytes .../saisies_selecteur_rubrique_article.png | Bin 292 -> 193 bytes .../saisies/images/saisies_selection.png | Bin 456 -> 270 bytes .../images/saisies_selection_multiple.png | Bin 501 -> 313 bytes .../saisies/images/saisies_textarea.png | Bin 417 -> 246 bytes www/plugins/saisies/inc/saisies.php | 1029 ++- www/plugins/saisies/inc/saisies_afficher.php | 37 +- www/plugins/saisies/inc/saisies_lister.php | 15 +- www/plugins/saisies/inc/saisies_manipuler.php | 18 +- .../inclure/configurer_saisie_fonctions.php | 22 +- .../saisies/lang/paquet-saisies_ar.php | 2 - .../saisies/lang/paquet-saisies_de.php | 2 - .../saisies/lang/paquet-saisies_en.php | 2 - .../saisies/lang/paquet-saisies_es.php | 2 - .../saisies/lang/paquet-saisies_fr.php | 2 - .../saisies/lang/paquet-saisies_fr_tu.php | 2 - .../saisies/lang/paquet-saisies_nl.php | 2 - .../saisies/lang/paquet-saisies_pt_br.php | 2 - .../saisies/lang/paquet-saisies_ru.php | 2 - .../saisies/lang/paquet-saisies_sk.php | 2 - www/plugins/saisies/lang/saisies.xml | 24 +- www/plugins/saisies/lang/saisies_ca.php | 2 - www/plugins/saisies/lang/saisies_de.php | 2 - www/plugins/saisies/lang/saisies_en.php | 5 +- www/plugins/saisies/lang/saisies_es.php | 2 - www/plugins/saisies/lang/saisies_fa.php | 2 - www/plugins/saisies/lang/saisies_fr.php | 4 +- www/plugins/saisies/lang/saisies_fr_tu.php | 2 - www/plugins/saisies/lang/saisies_it.php | 2 - www/plugins/saisies/lang/saisies_nl.php | 9 +- www/plugins/saisies/lang/saisies_pt_br.php | 3 +- www/plugins/saisies/lang/saisies_ru.php | 2 - www/plugins/saisies/lang/saisies_sk.php | 2 - www/plugins/saisies/paquet.xml | 3 +- .../selecteur_article_fonctions.php | 6 +- www/plugins/saisies/saisies/_base.html | 5 +- www/plugins/saisies/saisies/checkbox.html | 10 +- .../saisies/saisies/choisir_objets.html | 5 +- www/plugins/saisies/saisies/fieldset.html | 3 +- www/plugins/saisies/saisies/input.html | 3 +- www/plugins/saisies/saisies/oui_non.html | 4 +- .../saisies/saisies/selecteur_article.html | 2 +- .../saisies/saisies/selecteur_article.yaml | 6 + www/plugins/saisies/saisies/selection.html | 2 +- www/plugins/saisies/saisies/textarea.html | 2 +- www/plugins/saisies/saisies_fonctions.php | 77 +- www/plugins/saisies/saisies_options.php | 32 +- www/plugins/saisies/saisies_pipelines.php | 80 +- www/plugins/saisies/svn.revision | 8 +- www/plugins/seo-dev/action/editer_seo.php | 60 + www/plugins/seo-dev/base/seo_tables.php | 41 + .../seo-dev/formulaires/configurer_seo.html | 383 + .../seo-dev/formulaires/configurer_seo.php | 19 + .../seo-dev/formulaires/editer_seo.html | 74 + .../formulaires/editer_seo.php | 32 +- .../seo-dev/formulaires/inc-editer-seo.html | 78 + .../{seo-v1 => seo-dev}/img_pack/alexa-24.png | Bin .../{seo-v1 => seo-dev}/img_pack/bing-24.png | Bin .../img_pack/canonical_url-24.png | Bin .../img_pack/google_analytics-24.png | Bin .../img_pack/google_webmaster-24.png | Bin .../img_pack/meta_tags-24.png | Bin .../{seo-v1 => seo-dev}/img_pack/seo-24.png | Bin www/plugins/seo-dev/inclure/seo-head.html | 2 + .../javascript/jquery.simplycountable.js | 115 + www/plugins/seo-dev/javascript/seo.js.html | 27 + www/plugins/seo-dev/lang/paquet-seo.xml | 22 + .../lang/paquet-seo_en.php | 6 +- www/plugins/seo-dev/lang/paquet-seo_es.php | 16 + www/plugins/seo-dev/lang/paquet-seo_fr.php | 14 + www/plugins/seo-dev/lang/paquet-seo_nl.php | 16 + www/plugins/seo-dev/lang/paquet-seo_pt_br.php | 16 + .../lang/paquet-seo_ru.php | 6 +- .../lang/paquet-seo_sk.php | 6 +- www/plugins/seo-dev/lang/seo.xml | 26 + .../{seo-v1 => seo-dev}/lang/seo_en.php | 31 +- www/plugins/seo-dev/lang/seo_es.php | 72 + .../{seo-v1 => seo-dev}/lang/seo_fr.php | 47 +- www/plugins/seo-dev/lang/seo_nl.php | 72 + www/plugins/seo-dev/lang/seo_pt_br.php | 72 + .../{seo-v1 => seo-dev}/lang/seo_ru.php | 19 +- .../{seo-v1 => seo-dev}/lang/seo_sk.php | 35 +- www/plugins/seo-dev/paquet.xml | 37 + .../seo-dev/prive/objets/seo-metas.html | 10 + .../squelettes/contenu/configurer_seo.html | 10 + .../prive/squelettes/inclure/seo_metas.html | 0 .../prive/style_prive_plugin_seo.html | 2 + .../prive/themes/spip/images/seo-16.png | Bin 0 -> 1365 bytes .../prive/themes/spip/images/seo-24.png | Bin www/plugins/{seo-v1 => seo-dev}/seo.png | Bin .../seo_administrations.php | 26 +- www/plugins/seo-dev/seo_fonctions.php | 461 ++ www/plugins/seo-dev/seo_pipelines.php | 76 + www/plugins/seo-dev/seo_pipelines_ecrire.php | 128 + www/plugins/seo-dev/svn.revision | 10 + www/plugins/seo-v1/action/editer_seo.php | 36 - www/plugins/seo-v1/base/seo_tables.php | 33 - www/plugins/seo-v1/exec/seo_config.php | 56 - .../formulaires/configurer_seo_alexa.html | 36 - .../formulaires/configurer_seo_alexa.php | 35 - .../formulaires/configurer_seo_bing.html | 36 - .../formulaires/configurer_seo_bing.php | 35 - .../configurer_seo_ganalytics.html | 36 - .../formulaires/configurer_seo_ganalytics.php | 35 - .../configurer_seo_insert_head.html | 31 - .../configurer_seo_insert_head.php | 35 - .../formulaires/configurer_seo_metas.html | 132 - .../formulaires/configurer_seo_metas.php | 63 - .../configurer_seo_urls_canoniques.html | 25 - .../configurer_seo_urls_canoniques.php | 33 - .../configurer_seo_webmaster_tools.html | 36 - .../configurer_seo_webmaster_tools.php | 35 - .../seo-v1/formulaires/editer_seo.html | 46 - www/plugins/seo-v1/lang/paquet-seo.xml | 11 - www/plugins/seo-v1/lang/paquet-seo_fr.php | 14 - www/plugins/seo-v1/lang/seo.xml | 13 - www/plugins/seo-v1/paquet.xml | 30 - .../seo-v1/pipelines/seo_affichage_final.php | 73 - .../seo-v1/pipelines/seo_affiche_milieu.php | 58 - .../seo-v1/pipelines/seo_ajouter_onglets.php | 28 - .../seo-v1/pipelines/seo_autoriser.php | 15 - .../seo-v1/pipelines/seo_insert_head.php | 74 - www/plugins/seo-v1/plugin.xml | 61 - www/plugins/seo-v1/prive/configurer_seo.html | 52 - .../squelettes/contenu/configurer_seo.html | 1 - .../prive/themes/spip/images/seo-16.png | Bin 1819 -> 0 bytes www/plugins/seo-v1/seo_fonctions.php | 275 - www/plugins/seo-v1/svn.revision | 10 - www/plugins/skel_lhc/plugin.xml | 1 - .../img_pack/annuler-recherche.png | Bin 713 -> 408 bytes .../spip-bonux-3/img_pack/article-12.png | Bin 619 -> 438 bytes .../spip-bonux-3/img_pack/deplier-droite.png | Bin 480 -> 240 bytes .../spip-bonux-3/img_pack/frame-close.png | Bin 443 -> 244 bytes .../spip-bonux-3/img_pack/item-add.png | Bin 654 -> 552 bytes .../spip-bonux-3/img_pack/item-remove.png | Bin 456 -> 352 bytes .../spip-bonux-3/img_pack/logo-bonux.gif | Bin 5902 -> 5894 bytes .../img_pack/message_erreur-24.png | Bin 1400 -> 1276 bytes .../img_pack/message_notice-24.png | Bin 1108 -> 914 bytes .../spip-bonux-3/img_pack/message_ok-24.png | Bin 1126 -> 772 bytes .../spip-bonux-3/img_pack/spip-bonux.png | Bin 39439 -> 36121 bytes .../spip-bonux-3/img_pack/tri_asc-12.png | Bin 476 -> 390 bytes .../spip-bonux-3/img_pack/tri_asc-16.png | Bin 628 -> 536 bytes .../spip-bonux-3/img_pack/tri_asc-24.png | Bin 786 -> 604 bytes www/plugins/spip-bonux-3/img_pack/tri_asc.png | Bin 477 -> 408 bytes .../spip-bonux-3/img_pack/tri_desc-12.png | Bin 462 -> 389 bytes .../spip-bonux-3/img_pack/tri_desc-16.png | Bin 615 -> 538 bytes .../spip-bonux-3/img_pack/tri_desc-24.png | Bin 772 -> 592 bytes www/plugins/spip-bonux-3/inc/date_gestion.php | 28 +- www/plugins/spip-bonux-3/inc/exporter_csv.php | 43 +- www/plugins/spip-bonux-3/inc/importer_csv.php | 59 +- .../spip-bonux-3/lang/paquet-spip_bonux.xml | 3 + .../lang/paquet-spip_bonux_ar.php | 6 +- .../lang/paquet-spip_bonux_de.php | 6 +- .../lang/paquet-spip_bonux_en.php | 6 +- .../lang/paquet-spip_bonux_es.php | 6 +- .../lang/paquet-spip_bonux_fa.php | 6 +- .../lang/paquet-spip_bonux_fr.php | 6 +- .../lang/paquet-spip_bonux_nl.php | 6 +- .../lang/paquet-spip_bonux_pt_br.php | 17 + .../lang/paquet-spip_bonux_ru.php | 6 +- .../lang/paquet-spip_bonux_sk.php | 6 +- www/plugins/spip-bonux-3/lang/spip_bonux.xml | 3 + .../spip-bonux-3/lang/spip_bonux_ar.php | 6 +- .../spip-bonux-3/lang/spip_bonux_de.php | 6 +- .../spip-bonux-3/lang/spip_bonux_en.php | 6 +- .../spip-bonux-3/lang/spip_bonux_es.php | 6 +- .../spip-bonux-3/lang/spip_bonux_fa.php | 6 +- .../spip-bonux-3/lang/spip_bonux_fr.php | 6 +- .../spip-bonux-3/lang/spip_bonux_nl.php | 6 +- .../spip-bonux-3/lang/spip_bonux_pt_br.php | 36 + .../spip-bonux-3/lang/spip_bonux_ru.php | 6 +- .../spip-bonux-3/lang/spip_bonux_sk.php | 6 +- .../lib/array_column/array_column.php | 115 + .../modeles/pagination_noancre.html | 2 +- www/plugins/spip-bonux-3/paquet.xml | 10 +- .../public/spip_bonux_balises.php | 47 +- .../public/spip_bonux_criteres.php | 114 +- .../spip-bonux-3/spip_bonux_fonctions.php | 112 +- .../spip-bonux-3/spip_bonux_options.php | 218 +- www/plugins/spip-bonux-3/svn.revision | 8 +- www/plugins/spip_piwik_2_0/balise/piwik.php | 12 +- .../spip_piwik_2_0/lang/paquet-piwik.xml | 5 +- .../spip_piwik_2_0/lang/paquet-piwik_de.php | 15 + .../spip_piwik_2_0/lang/paquet-piwik_en.php | 6 +- .../spip_piwik_2_0/lang/paquet-piwik_es.php | 6 +- .../spip_piwik_2_0/lang/paquet-piwik_fa.php | 6 +- .../spip_piwik_2_0/lang/paquet-piwik_fr.php | 8 +- .../spip_piwik_2_0/lang/paquet-piwik_nl.php | 6 +- .../spip_piwik_2_0/lang/paquet-piwik_ru.php | 6 +- .../spip_piwik_2_0/lang/paquet-piwik_sk.php | 6 +- www/plugins/spip_piwik_2_0/lang/piwik.xml | 5 +- www/plugins/spip_piwik_2_0/lang/piwik_ca.php | 6 +- www/plugins/spip_piwik_2_0/lang/piwik_de.php | 19 +- www/plugins/spip_piwik_2_0/lang/piwik_en.php | 6 +- www/plugins/spip_piwik_2_0/lang/piwik_es.php | 6 +- www/plugins/spip_piwik_2_0/lang/piwik_fa.php | 6 +- www/plugins/spip_piwik_2_0/lang/piwik_fr.php | 8 +- .../spip_piwik_2_0/lang/piwik_fr_tu.php | 6 +- www/plugins/spip_piwik_2_0/lang/piwik_nl.php | 6 +- www/plugins/spip_piwik_2_0/lang/piwik_sk.php | 6 +- www/plugins/spip_piwik_2_0/paquet.xml | 6 +- www/plugins/spip_piwik_2_0/plugin.xml | 6 +- www/plugins/spip_piwik_2_0/svn.revision | 12 +- .../verifier/aide/verifier_fonctions.php | 18 +- www/plugins/verifier/images/verifier-128.png | Bin 9687 -> 7566 bytes www/plugins/verifier/inc/is_email.php | 2455 +++---- www/plugins/verifier/inc/verifier.php | 39 +- www/plugins/verifier/lang/paquet-verifier.xml | 3 + .../verifier/lang/paquet-verifier_de.php | 6 +- .../verifier/lang/paquet-verifier_en.php | 6 +- .../verifier/lang/paquet-verifier_es.php | 6 +- .../verifier/lang/paquet-verifier_fr.php | 6 +- .../verifier/lang/paquet-verifier_fr_tu.php | 6 +- .../verifier/lang/paquet-verifier_nl.php | 16 + .../verifier/lang/paquet-verifier_ru.php | 6 +- .../verifier/lang/paquet-verifier_sk.php | 6 +- www/plugins/verifier/lang/verifier.xml | 28 +- www/plugins/verifier/lang/verifier_ca.php | 6 +- www/plugins/verifier/lang/verifier_de.php | 6 +- www/plugins/verifier/lang/verifier_en.php | 32 +- www/plugins/verifier/lang/verifier_es.php | 7 +- www/plugins/verifier/lang/verifier_fa.php | 6 +- www/plugins/verifier/lang/verifier_fr.php | 30 +- www/plugins/verifier/lang/verifier_fr_tu.php | 6 +- www/plugins/verifier/lang/verifier_it.php | 6 +- www/plugins/verifier/lang/verifier_nl.php | 138 + www/plugins/verifier/lang/verifier_pt_br.php | 32 +- www/plugins/verifier/lang/verifier_ru.php | 6 +- www/plugins/verifier/lang/verifier_sk.php | 6 +- www/plugins/verifier/paquet.xml | 6 +- www/plugins/verifier/plugin.xml | 9 +- www/plugins/verifier/svn.revision | 8 +- www/plugins/verifier/verifier/code_postal.php | 26 +- .../verifier/verifier/code_postal.yaml | 10 + .../verifier/verifier/comparaison_champ.php | 22 +- .../verifier/verifier/comparaison_champ.yaml | 29 + www/plugins/verifier/verifier/couleur.php | 25 +- www/plugins/verifier/verifier/date.php | 90 +- www/plugins/verifier/verifier/decimal.php | 38 +- www/plugins/verifier/verifier/email.php | 58 +- www/plugins/verifier/verifier/entier.php | 31 +- www/plugins/verifier/verifier/id_document.php | 19 +- .../verifier/verifier/id_document.yaml | 3 + www/plugins/verifier/verifier/id_objet.php | 38 + www/plugins/verifier/verifier/id_objet.yaml | 3 + www/plugins/verifier/verifier/isbn.php | 70 +- www/plugins/verifier/verifier/isbn.yaml | 3 + www/plugins/verifier/verifier/regex.php | 14 +- www/plugins/verifier/verifier/siren_siret.php | 82 +- www/plugins/verifier/verifier/taille.php | 37 +- www/plugins/verifier/verifier/telephone.php | 44 +- www/plugins/verifier/verifier/url.php | 102 +- .../yaml/experimental/yaml_fonctions.php | 13 +- www/plugins/yaml/inc/yaml.php | 59 +- www/plugins/yaml/inc/yaml_sfyaml.php | 67 +- www/plugins/yaml/inc/yaml_to_array.php | 11 +- www/plugins/yaml/lang/paquet-yaml.xml | 3 + www/plugins/yaml/lang/paquet-yaml_en.php | 6 +- www/plugins/yaml/lang/paquet-yaml_es.php | 6 +- www/plugins/yaml/lang/paquet-yaml_fa.php | 6 +- www/plugins/yaml/lang/paquet-yaml_fr.php | 6 +- www/plugins/yaml/lang/paquet-yaml_nl.php | 16 + www/plugins/yaml/lang/paquet-yaml_ru.php | 6 +- www/plugins/yaml/lang/paquet-yaml_sk.php | 6 +- www/plugins/yaml/paquet.xml | 8 +- www/plugins/yaml/plugin.xml | 6 +- www/plugins/yaml/svn.revision | 8 +- www/plugins/yaml/yaml_fonctions.php | 8 +- .../zen-garden-2/images/themes-128.png | Bin 33832 -> 32123 bytes www/plugins/zen-garden-2/images/themes-32.png | Bin 2777 -> 2640 bytes www/plugins/zen-garden-2/images/themes-64.png | Bin 9150 -> 8557 bytes www/plugins/zen-garden-2/inc/zengarden.php | 17 +- .../inclure/zengarden_switcher.js | 6 +- .../zen-garden-2/lang/paquet-zengarden.xml | 3 + .../zen-garden-2/lang/paquet-zengarden_de.php | 15 + .../zen-garden-2/lang/paquet-zengarden_en.php | 6 +- .../zen-garden-2/lang/paquet-zengarden_es.php | 6 +- .../zen-garden-2/lang/paquet-zengarden_fa.php | 6 +- .../zen-garden-2/lang/paquet-zengarden_fr.php | 6 +- .../zen-garden-2/lang/paquet-zengarden_nl.php | 6 +- .../zen-garden-2/lang/paquet-zengarden_ru.php | 6 +- .../zen-garden-2/lang/paquet-zengarden_sk.php | 6 +- .../zen-garden-2/lang/zengarden_de.php | 6 +- .../zen-garden-2/lang/zengarden_en.php | 6 +- .../zen-garden-2/lang/zengarden_es.php | 6 +- .../zen-garden-2/lang/zengarden_fa.php | 6 +- .../zen-garden-2/lang/zengarden_fr.php | 6 +- .../zen-garden-2/lang/zengarden_nl.php | 6 +- .../zen-garden-2/lang/zengarden_sk.php | 6 +- www/plugins/zen-garden-2/paquet.xml | 8 +- .../squelettes/inclure/zengarden_theme.html | 4 +- .../inclure/zengarden_theme_actif.html | 4 +- .../prive/themes/spip/images/themes-16.png | Bin 936 -> 842 bytes www/plugins/zen-garden-2/svn.revision | 8 +- .../zen-garden-2/zengarden_fonctions.php | 38 +- .../zen-garden-2/zengarden_options.php | 10 +- .../zen-garden-2/zengarden_pipelines.php | 6 +- 904 files changed, 28553 insertions(+), 16566 deletions(-) create mode 100644 www/plugins/Menu_langue_lien/lang/mll_ru.php create mode 100644 www/plugins/Menu_langue_lien/lang/paquet-mll_ru.php create mode 100644 www/plugins/compositions_v3/compositions_options.php delete mode 100644 www/plugins/compositions_v3/formulaires/inc-informeur_composition.html create mode 100644 www/plugins/compositions_v3/images/objet-blocs.png create mode 100644 www/plugins/compositions_v3/images/objet-intro-blocs.png create mode 100644 www/plugins/compositions_v3/lang/compositions_de.php create mode 100644 www/plugins/compositions_v3/prive/squelettes/navigation/compositions.html create mode 100644 www/plugins/enluminures_typographiques_v3/base/typoenluminee_upgrade.php create mode 100644 www/plugins/enluminures_typographiques_v3/lang/enlumtypo_nl.php create mode 100644 www/plugins/enluminures_typographiques_v3/lang/enlumtypo_ru.php create mode 100644 www/plugins/enluminures_typographiques_v3/lang/paquet-typoenluminee.xml create mode 100644 www/plugins/enluminures_typographiques_v3/typoenluminee_administrations.php create mode 100644 www/plugins/facteur/lang/facteur_it.php create mode 100644 www/plugins/facteur/lang/facteur_oc_ni_mis.php create mode 100644 www/plugins/facteur/lang/facteur_pt_br.php create mode 100644 www/plugins/facteur/lang/paquet-facteur_pt_br.php create mode 100644 www/plugins/facteur/phpmailer-php5/PHPMailerAutoload.php delete mode 100755 www/plugins/facteur/phpmailer-php5/README create mode 100644 www/plugins/facteur/phpmailer-php5/README.md create mode 100644 www/plugins/facteur/phpmailer-php5/VERSION create mode 100644 www/plugins/facteur/phpmailer-php5/changelog.md create mode 100644 www/plugins/facteur/phpmailer-php5/class.phpmaileroauth.php create mode 100644 www/plugins/facteur/phpmailer-php5/class.phpmaileroauthgoogle.php create mode 100644 www/plugins/facteur/phpmailer-php5/composer.json create mode 100644 www/plugins/facteur/phpmailer-php5/extras/EasyPeasyICS.php create mode 100644 www/plugins/facteur/phpmailer-php5/extras/README.md create mode 100644 www/plugins/facteur/phpmailer-php5/extras/htmlfilter.php create mode 100644 www/plugins/facteur/phpmailer-php5/extras/ntlm_sasl_client.php create mode 100644 www/plugins/facteur/phpmailer-php5/get_oauth_token.php create mode 100755 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-am.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-az.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-be.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-bg.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-el.php delete mode 100755 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-en.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-eo.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-fa.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-gl.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-he.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-hr.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-id.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-ka.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-ko.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-lt.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-lv.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-ms.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-pt.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-sk.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-sl.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-sr.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-uk.php create mode 100644 www/plugins/facteur/phpmailer-php5/language/phpmailer.lang-vi.php create mode 100644 www/plugins/facteur/phpmailer-php5/travis.phpunit.xml.dist delete mode 100755 www/plugins/formidable/action/exporter_analyse_reponses.php delete mode 100644 www/plugins/formidable/action/exporter_formulaires_reponses.php create mode 100644 www/plugins/formidable/formulaires/exporter_formulaire_analyse.html create mode 100644 www/plugins/formidable/formulaires/exporter_formulaire_analyse.php create mode 100644 www/plugins/formidable/formulaires/exporter_formulaire_reponses.html create mode 100644 www/plugins/formidable/formulaires/exporter_formulaire_reponses.php create mode 100644 www/plugins/formidable/formulaires/inc-formidable-unicite.html create mode 100644 www/plugins/formidable/http/collectionjson/formulaires-ressource.html create mode 100644 www/plugins/formidable/http/collectionjson/formulaires.html create mode 100644 www/plugins/formidable/http/collectionjson/formulaires_reponses-ressource.html create mode 100644 www/plugins/formidable/http/collectionjson/formulaires_reponses.html create mode 100644 www/plugins/formidable/http/collectionjson/formulaires_reponses.php create mode 100644 www/plugins/formidable/http/collectionjson/inc-formulaire.html create mode 100644 www/plugins/formidable/http/collectionjson/inc-formulaires_reponse.html create mode 100644 www/plugins/formidable/lang/formidable_ar.php create mode 100644 www/plugins/formidable/lang/formidable_pt_br.php create mode 100644 www/plugins/formidable/lang/formidable_ru.php create mode 100644 www/plugins/formidable/lang/formulaire.xml create mode 100644 www/plugins/formidable/lang/formulaire_ru.php create mode 100644 www/plugins/formidable/lang/formulaires_reponse.xml create mode 100644 www/plugins/formidable/lang/paquet-formidable_en.php create mode 100644 www/plugins/formidable/prive/objets/liste/formulaires_associer.html create mode 100644 www/plugins/formidable/prive/objets/liste/formulaires_associer_fonctions.php create mode 100644 www/plugins/formidable/prive/objets/liste/formulaires_lies.html create mode 100644 www/plugins/formidable/prive/objets/liste/formulaires_lies_fonctions.php create mode 100644 www/plugins/gis/css/leaflet_nodirection.css create mode 100644 www/plugins/gis/javascript/.eslintrc create mode 100644 www/plugins/gis/lib/leaflet/plugins/TOPOJSON.js create mode 100644 www/plugins/gis/lib/leaflet/plugins/images/toggle.svg create mode 100644 www/plugins/menus_1/action/generer_menus.php create mode 100755 www/plugins/menus_1/images/menus_rechercher.png create mode 100644 www/plugins/menus_1/lang/menus_pt_br.php create mode 100644 www/plugins/menus_1/lang/paquet-menus_pt_br.php create mode 100644 www/plugins/menus_1/menus/recherche.html create mode 100644 www/plugins/menus_1/menus/recherche.xml create mode 100644 www/plugins/multilang/CHANGELOG.md create mode 100644 www/plugins/multilang/lang/multilang_de.php create mode 100644 www/plugins/multilang/lang/multilang_ru.php create mode 100644 www/plugins/multilang/lang/multilang_uk.php create mode 100644 www/plugins/multilang/lang/paquet-multilang_de.php create mode 100644 www/plugins/multilang/lang/paquet-multilang_uk.php create mode 100644 www/plugins/nospam/lang/nospam_de.php create mode 100644 www/plugins/notifications2/lang/notifications_de.php create mode 100644 www/plugins/notifications2/lang/paquet-notifications_de.php create mode 100644 www/plugins/notifications2/notifications/article_refuse.html rename www/plugins/{redirhttps => redirhttps.bak}/images/redirhttps-128.png (100%) rename www/plugins/{redirhttps => redirhttps.bak}/lang/paquet-redirhttps.xml (100%) rename www/plugins/{redirhttps => redirhttps.bak}/lang/paquet-redirhttps_en.php (100%) rename www/plugins/{redirhttps => redirhttps.bak}/lang/paquet-redirhttps_es.php (100%) rename www/plugins/{redirhttps => redirhttps.bak}/lang/paquet-redirhttps_fr.php (100%) rename www/plugins/{redirhttps => redirhttps.bak}/lang/paquet-redirhttps_sk.php (100%) rename www/plugins/{redirhttps => redirhttps.bak}/lang/redirhttps.xml (100%) rename www/plugins/{redirhttps => redirhttps.bak}/paquet.xml (100%) rename www/plugins/{redirhttps => redirhttps.bak}/plugin.xml (100%) rename www/plugins/{redirhttps => redirhttps.bak}/redirhttps_options.php (100%) rename www/plugins/{redirhttps => redirhttps.bak}/svn.revision (100%) create mode 100644 www/plugins/seo-dev/action/editer_seo.php create mode 100644 www/plugins/seo-dev/base/seo_tables.php create mode 100644 www/plugins/seo-dev/formulaires/configurer_seo.html create mode 100644 www/plugins/seo-dev/formulaires/configurer_seo.php create mode 100644 www/plugins/seo-dev/formulaires/editer_seo.html rename www/plugins/{seo-v1 => seo-dev}/formulaires/editer_seo.php (58%) create mode 100644 www/plugins/seo-dev/formulaires/inc-editer-seo.html rename www/plugins/{seo-v1 => seo-dev}/img_pack/alexa-24.png (100%) rename www/plugins/{seo-v1 => seo-dev}/img_pack/bing-24.png (100%) rename www/plugins/{seo-v1 => seo-dev}/img_pack/canonical_url-24.png (100%) rename www/plugins/{seo-v1 => seo-dev}/img_pack/google_analytics-24.png (100%) rename www/plugins/{seo-v1 => seo-dev}/img_pack/google_webmaster-24.png (100%) rename www/plugins/{seo-v1 => seo-dev}/img_pack/meta_tags-24.png (100%) rename www/plugins/{seo-v1 => seo-dev}/img_pack/seo-24.png (100%) create mode 100644 www/plugins/seo-dev/inclure/seo-head.html create mode 100644 www/plugins/seo-dev/javascript/jquery.simplycountable.js create mode 100644 www/plugins/seo-dev/javascript/seo.js.html create mode 100644 www/plugins/seo-dev/lang/paquet-seo.xml rename www/plugins/{seo-v1 => seo-dev}/lang/paquet-seo_en.php (92%) create mode 100644 www/plugins/seo-dev/lang/paquet-seo_es.php create mode 100644 www/plugins/seo-dev/lang/paquet-seo_fr.php create mode 100644 www/plugins/seo-dev/lang/paquet-seo_nl.php create mode 100644 www/plugins/seo-dev/lang/paquet-seo_pt_br.php rename www/plugins/{seo-v1 => seo-dev}/lang/paquet-seo_ru.php (93%) rename www/plugins/{seo-v1 => seo-dev}/lang/paquet-seo_sk.php (93%) create mode 100644 www/plugins/seo-dev/lang/seo.xml rename www/plugins/{seo-v1 => seo-dev}/lang/seo_en.php (67%) create mode 100644 www/plugins/seo-dev/lang/seo_es.php rename www/plugins/{seo-v1 => seo-dev}/lang/seo_fr.php (53%) create mode 100644 www/plugins/seo-dev/lang/seo_nl.php create mode 100644 www/plugins/seo-dev/lang/seo_pt_br.php rename www/plugins/{seo-v1 => seo-dev}/lang/seo_ru.php (82%) rename www/plugins/{seo-v1 => seo-dev}/lang/seo_sk.php (66%) create mode 100644 www/plugins/seo-dev/paquet.xml create mode 100644 www/plugins/seo-dev/prive/objets/seo-metas.html create mode 100644 www/plugins/seo-dev/prive/squelettes/contenu/configurer_seo.html rename www/plugins/{seo-v1 => seo-dev}/prive/squelettes/inclure/seo_metas.html (100%) rename www/plugins/{seo-v1 => seo-dev}/prive/style_prive_plugin_seo.html (86%) create mode 100644 www/plugins/seo-dev/prive/themes/spip/images/seo-16.png rename www/plugins/{seo-v1 => seo-dev}/prive/themes/spip/images/seo-24.png (100%) rename www/plugins/{seo-v1 => seo-dev}/seo.png (100%) rename www/plugins/{seo-v1 => seo-dev}/seo_administrations.php (75%) create mode 100644 www/plugins/seo-dev/seo_fonctions.php create mode 100644 www/plugins/seo-dev/seo_pipelines.php create mode 100644 www/plugins/seo-dev/seo_pipelines_ecrire.php create mode 100644 www/plugins/seo-dev/svn.revision delete mode 100644 www/plugins/seo-v1/action/editer_seo.php delete mode 100644 www/plugins/seo-v1/base/seo_tables.php delete mode 100644 www/plugins/seo-v1/exec/seo_config.php delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_alexa.html delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_alexa.php delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_bing.html delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_bing.php delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_ganalytics.html delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_ganalytics.php delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_insert_head.html delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_insert_head.php delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_metas.html delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_metas.php delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_urls_canoniques.html delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_urls_canoniques.php delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_webmaster_tools.html delete mode 100644 www/plugins/seo-v1/formulaires/configurer_seo_webmaster_tools.php delete mode 100644 www/plugins/seo-v1/formulaires/editer_seo.html delete mode 100644 www/plugins/seo-v1/lang/paquet-seo.xml delete mode 100644 www/plugins/seo-v1/lang/paquet-seo_fr.php delete mode 100644 www/plugins/seo-v1/lang/seo.xml delete mode 100644 www/plugins/seo-v1/paquet.xml delete mode 100644 www/plugins/seo-v1/pipelines/seo_affichage_final.php delete mode 100644 www/plugins/seo-v1/pipelines/seo_affiche_milieu.php delete mode 100644 www/plugins/seo-v1/pipelines/seo_ajouter_onglets.php delete mode 100644 www/plugins/seo-v1/pipelines/seo_autoriser.php delete mode 100644 www/plugins/seo-v1/pipelines/seo_insert_head.php delete mode 100644 www/plugins/seo-v1/plugin.xml delete mode 100644 www/plugins/seo-v1/prive/configurer_seo.html delete mode 100644 www/plugins/seo-v1/prive/squelettes/contenu/configurer_seo.html delete mode 100644 www/plugins/seo-v1/prive/themes/spip/images/seo-16.png delete mode 100644 www/plugins/seo-v1/seo_fonctions.php delete mode 100644 www/plugins/seo-v1/svn.revision create mode 100644 www/plugins/spip-bonux-3/lang/paquet-spip_bonux_pt_br.php create mode 100644 www/plugins/spip-bonux-3/lang/spip_bonux_pt_br.php create mode 100755 www/plugins/spip-bonux-3/lib/array_column/array_column.php create mode 100644 www/plugins/spip_piwik_2_0/lang/paquet-piwik_de.php create mode 100644 www/plugins/verifier/lang/paquet-verifier_nl.php create mode 100644 www/plugins/verifier/lang/verifier_nl.php create mode 100644 www/plugins/verifier/verifier/code_postal.yaml create mode 100644 www/plugins/verifier/verifier/comparaison_champ.yaml create mode 100644 www/plugins/verifier/verifier/id_document.yaml create mode 100644 www/plugins/verifier/verifier/id_objet.php create mode 100644 www/plugins/verifier/verifier/id_objet.yaml create mode 100644 www/plugins/verifier/verifier/isbn.yaml create mode 100644 www/plugins/yaml/lang/paquet-yaml_nl.php create mode 100644 www/plugins/zen-garden-2/lang/paquet-zengarden_de.php diff --git a/www/plugins/Menu_langue_lien/formulaires/menu_lang.html b/www/plugins/Menu_langue_lien/formulaires/menu_lang.html index 80d16017..a74bb00f 100644 --- a/www/plugins/Menu_langue_lien/formulaires/menu_lang.html +++ b/www/plugins/Menu_langue_lien/formulaires/menu_lang.html @@ -1,13 +1,3 @@ -[(#REM) - Stocker les traductions eventuelles de l'article en cours -] - -#SET{ListeTraductions, #ARRAY{}} - - #SET_MERGE{ListeTraductions,#GET{ListeTraductions},#ARRAY{#LANG,#URL_ARTICLE}} - - - [(#REM) Stocker les traductions eventuelles de la rubrique en cours si le plugin Tradrub est installe (permet l'utilisation du critere traduction sur les rubriques) @@ -21,6 +11,16 @@ +[(#REM) + Stocker les traductions eventuelles de l'article en cours +] + +#SET{ListeTraductions, #ARRAY{}} + + #SET_MERGE{ListeTraductions,#GET{ListeTraductions},#ARRAY{#LANG,#URL_ARTICLE}} + + + [(#REM) Y-a-t'il plus d'une langue reellement utilisee dans le site (moins les langues "invisibles") ? Si oui, on affiche le menu de langue diff --git a/www/plugins/Menu_langue_lien/lang/mll.xml b/www/plugins/Menu_langue_lien/lang/mll.xml index 58c62299..336685f8 100644 --- a/www/plugins/Menu_langue_lien/lang/mll.xml +++ b/www/plugins/Menu_langue_lien/lang/mll.xml @@ -10,6 +10,9 @@ + + + diff --git a/www/plugins/Menu_langue_lien/lang/mll_en.php b/www/plugins/Menu_langue_lien/lang/mll_en.php index c759efab..8b614014 100755 --- a/www/plugins/Menu_langue_lien/lang/mll_en.php +++ b/www/plugins/Menu_langue_lien/lang/mll_en.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/mll?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -24,5 +26,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_langues_invisibles' => 'Invisible languages in the​​ menu', 'label_separateur' => 'Language divider' ); - -?> diff --git a/www/plugins/Menu_langue_lien/lang/mll_es.php b/www/plugins/Menu_langue_lien/lang/mll_es.php index bb9236f8..ab843cb3 100644 --- a/www/plugins/Menu_langue_lien/lang/mll_es.php +++ b/www/plugins/Menu_langue_lien/lang/mll_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/mll?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -22,5 +24,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_format_liste_liste' => 'Lista por viñetas', 'label_langues_invisibles' => 'Idiomas invisibles del menú' ); - -?> diff --git a/www/plugins/Menu_langue_lien/lang/mll_fr.php b/www/plugins/Menu_langue_lien/lang/mll_fr.php index 9889529a..f0dc0fe1 100755 --- a/www/plugins/Menu_langue_lien/lang/mll_fr.php +++ b/www/plugins/Menu_langue_lien/lang/mll_fr.php @@ -1,7 +1,9 @@ 'Langues invisibles du menu', 'label_separateur' => 'Séparateur des langues' ); - -?> diff --git a/www/plugins/Menu_langue_lien/lang/mll_nl.php b/www/plugins/Menu_langue_lien/lang/mll_nl.php index 63846f29..dde735e7 100644 --- a/www/plugins/Menu_langue_lien/lang/mll_nl.php +++ b/www/plugins/Menu_langue_lien/lang/mll_nl.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/mll?lang_cible=nl // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -24,5 +26,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_langues_invisibles' => 'Talen die niet in het menu zichtbaar zijn', 'label_separateur' => 'Scheiding van de talen' ); - -?> diff --git a/www/plugins/Menu_langue_lien/lang/mll_ru.php b/www/plugins/Menu_langue_lien/lang/mll_ru.php new file mode 100644 index 00000000..ebcde7b9 --- /dev/null +++ b/www/plugins/Menu_langue_lien/lang/mll_ru.php @@ -0,0 +1,28 @@ + 'Языковое меню в виде ссылок', + + // E + 'explication_langues_invisibles' => 'Позволяет удалить некоторые языки из меню', + 'explication_separateur' => 'Текст, используемый для разделения языков в меню', + + // L + 'label_format' => 'Формат отображения языков', + 'label_format_abrege' => 'Краткий (например, Fr)', + 'label_format_complet' => 'Полный (например, Français)', + 'label_format_liste' => 'Формат отображения списка языков', + 'label_format_liste_bloc' => 'Блок, разделенный пробелами (или настроить сепаратор)', + 'label_format_liste_liste' => 'Маркированный список', + 'label_langues_invisibles' => 'Невидимые языки в меню', + 'label_separateur' => 'Разделитель языков' +); diff --git a/www/plugins/Menu_langue_lien/lang/mll_sk.php b/www/plugins/Menu_langue_lien/lang/mll_sk.php index 5c6b96fc..2bef5f35 100644 --- a/www/plugins/Menu_langue_lien/lang/mll_sk.php +++ b/www/plugins/Menu_langue_lien/lang/mll_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/mll?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -24,5 +26,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_langues_invisibles' => 'Jazyky, ktoré nebudú zobrazené v menu', 'label_separateur' => 'Oddeľovač jazykov' ); - -?> diff --git a/www/plugins/Menu_langue_lien/lang/paquet-mll.xml b/www/plugins/Menu_langue_lien/lang/paquet-mll.xml index 5d3c7f0f..4fda2f29 100644 --- a/www/plugins/Menu_langue_lien/lang/paquet-mll.xml +++ b/www/plugins/Menu_langue_lien/lang/paquet-mll.xml @@ -9,6 +9,9 @@ + + + diff --git a/www/plugins/Menu_langue_lien/lang/paquet-mll_en.php b/www/plugins/Menu_langue_lien/lang/paquet-mll_en.php index b31b6dfc..55644484 100644 --- a/www/plugins/Menu_langue_lien/lang/paquet-mll_en.php +++ b/www/plugins/Menu_langue_lien/lang/paquet-mll_en.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-mll?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'mll_nom' => 'Language menu as links', 'mll_slogan' => 'View languages ​​as clickable links' ); - -?> diff --git a/www/plugins/Menu_langue_lien/lang/paquet-mll_es.php b/www/plugins/Menu_langue_lien/lang/paquet-mll_es.php index 15d889a1..2f349fc5 100644 --- a/www/plugins/Menu_langue_lien/lang/paquet-mll_es.php +++ b/www/plugins/Menu_langue_lien/lang/paquet-mll_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-mll?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'mll_nom' => 'Menú de idiomas con enlaces', 'mll_slogan' => 'Mostrar los idiomas bajo la forma de enlaces en los que hacer click' ); - -?> diff --git a/www/plugins/Menu_langue_lien/lang/paquet-mll_fr.php b/www/plugins/Menu_langue_lien/lang/paquet-mll_fr.php index 5e0ef81f..d424e052 100644 --- a/www/plugins/Menu_langue_lien/lang/paquet-mll_fr.php +++ b/www/plugins/Menu_langue_lien/lang/paquet-mll_fr.php @@ -1,7 +1,9 @@ 'Menu de langues avec liens', 'mll_slogan' => 'Afficher les langues sous forme de liens cliquables' ); - -?> diff --git a/www/plugins/Menu_langue_lien/lang/paquet-mll_nl.php b/www/plugins/Menu_langue_lien/lang/paquet-mll_nl.php index 4a4c7927..20a84846 100644 --- a/www/plugins/Menu_langue_lien/lang/paquet-mll_nl.php +++ b/www/plugins/Menu_langue_lien/lang/paquet-mll_nl.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-mll?lang_cible=nl // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'mll_nom' => 'Taalmenu met links', 'mll_slogan' => 'Toon een taalkeuze met klik-optie' ); - -?> diff --git a/www/plugins/Menu_langue_lien/lang/paquet-mll_ru.php b/www/plugins/Menu_langue_lien/lang/paquet-mll_ru.php new file mode 100644 index 00000000..2454cf59 --- /dev/null +++ b/www/plugins/Menu_langue_lien/lang/paquet-mll_ru.php @@ -0,0 +1,16 @@ + 'Заменить оригинальное языковое меню интерактивным меню. Это меню отображается только если по крайней мере два языка на самом деле используется на сайте.', + 'mll_nom' => 'Языковое меню в виде ссылок', + 'mll_slogan' => 'Отображать языки как кликабельные ссылки' +); diff --git a/www/plugins/Menu_langue_lien/lang/paquet-mll_sk.php b/www/plugins/Menu_langue_lien/lang/paquet-mll_sk.php index f7117e72..b39fbdcf 100644 --- a/www/plugins/Menu_langue_lien/lang/paquet-mll_sk.php +++ b/www/plugins/Menu_langue_lien/lang/paquet-mll_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-mll?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'mll_nom' => 'Jazykové menu s odkazmi', 'mll_slogan' => 'ZobraziÅ¥ jazyky vo forme klikateľných odkazov' ); - -?> diff --git a/www/plugins/Menu_langue_lien/paquet.xml b/www/plugins/Menu_langue_lien/paquet.xml index c91eeb78..4f7ae87d 100644 --- a/www/plugins/Menu_langue_lien/paquet.xml +++ b/www/plugins/Menu_langue_lien/paquet.xml @@ -1,15 +1,15 @@ Menu de langues avec liens - Jacques + Jacques Jean-Baptiste Pressac kent1 Cédric Morin @@ -17,7 +17,7 @@ 2009-2014 GPL 3 - + \ No newline at end of file diff --git a/www/plugins/Menu_langue_lien/plugin.xml b/www/plugins/Menu_langue_lien/plugin.xml index 6412fc32..a95f1871 100644 --- a/www/plugins/Menu_langue_lien/plugin.xml +++ b/www/plugins/Menu_langue_lien/plugin.xml @@ -11,10 +11,10 @@ [en]View languages ​​as clickable links - [Jacques->http://www.spip-contrib.net/_Jacques-PYRAT_] - Jean-Baptiste Pressac - Quentin Drouet - Cedric Morin + [Jacques->http://contrib.spip.net/RealET] - Jean-Baptiste Pressac - Quentin Drouet - Cedric Morin © 2009-2014 GNU/GPL - http://www.spip-contrib.net/Menu-de-langues-sous-forme-de-liens - 1.2.0 + http://contrib.spip.net/Menu-de-langues-sous-forme-de-liens + 1.2.4 stable @@ -33,8 +33,8 @@ Icon by [FatCow->http://www.fatcow.com/free-icons] insert_head_css mll_pipelines.php - - + + navigation diff --git a/www/plugins/Menu_langue_lien/svn.revision b/www/plugins/Menu_langue_lien/svn.revision index 86492343..5dcca629 100644 --- a/www/plugins/Menu_langue_lien/svn.revision +++ b/www/plugins/Menu_langue_lien/svn.revision @@ -1,10 +1,10 @@ Origine: file:///home/svn/repository/spip-zone/_plugins_/menu_langues_liens -Revision: 81566 -Dernier commit: 2014-03-22 05:38:58 +0100 +Revision: 97400 +Dernier commit: 2016-05-07 22:04:34 +0200 file:///home/svn/repository/spip-zone/_plugins_/menu_langues_liens -81566 -2014-03-22 05:38:58 +0100 +97400 +2016-05-07 22:04:34 +0200 \ No newline at end of file diff --git a/www/plugins/compositions_v3/compositions_fonctions.php b/www/plugins/compositions_v3/compositions_fonctions.php index 415e17a3..82a20a18 100644 --- a/www/plugins/compositions_v3/compositions_fonctions.php +++ b/www/plugins/compositions_v3/compositions_fonctions.php @@ -1,458 +1,495 @@ -array('type' => $type,'informer' => $informer), - 'data'=> $res - ) - ); - return $res; -} - -/** - * Liste les id d'un type donne utilisant une composition donnee - * - * @param string $type - * @param string $composition - * @return array - */ -function compositions_lister_utilisations($type,$composition){ - $table_sql = table_objet_sql($type); - if (!in_array($table_sql, sql_alltable())) return; - $_id_table_objet = id_table_objet($type); - return sql_allfetsel("$_id_table_objet as id,titre", $table_sql, "composition=".sql_quote($composition)); -} - -/** - * Selectionner le fond en fonction du type et de la composition - * en prenant en compte la configuration pour le chemin - * et le fait que la composition a pu etre supprimee - * - * @param string $composition - * @param string $type - * @param string $defaut - * @param string $ext - * @param bool $fullpath - * @param string $vide - * @return string - */ -function compositions_selectionner($composition,$type,$defaut="",$ext="html",$fullpath = false, $vide="composition-vide"){ - if ($type=='syndic') $type='site'; //grml - $fond = compositions_chemin() . $type; - - // regarder si compositions/article-xxx est disponible - if (strlen($composition) - AND $f = find_in_path("$fond-$composition.$ext")) - return $fullpath ? $f : $fond . "-$composition"; - else - // sinon regarder si compositions/article-defaut est disponible - if (strlen($defaut) - AND $f = find_in_path("$fond-$defaut.$ext")) - return $fullpath ? $f : $fond . "-$defaut"; - - // se rabattre sur compositions/article si disponible - if ($f = find_in_path("$fond.$ext")) - return $fullpath ? $f : $fond; - - // sinon une composition vide pour ne pas generer d'erreur - if ($vide AND $f = find_in_path("$vide.$ext")) - return $fullpath ? $f : $vide; - - // rien mais ca fera une erreur dans le squelette si appele en filtre - return ''; -} - -/** - * Decrire une composition pour un objet - * @param string $type - * @param string $composition - * @return array|bool|string - */ -function compositions_decrire($type, $composition){ - static $compositions = array(); - if (!function_exists('compositions_charger_infos')) - include_spip('inc/compositions'); - if ($type=='syndic') $type='site'; //grml - if (isset($compositions[$type][$composition])) - return $compositions[$type][$composition]; - $ext = "html"; - $fond = compositions_chemin() . $type; - if (strlen($composition) - AND $f = find_in_path("$fond-$composition.$ext") - AND $desc = compositions_charger_infos($f)) - return $compositions[$type][$composition] = $desc; - return $compositions[$type][$composition] = false; -} - -/** - * Un filtre a utiliser sur [(#COMPOSITION|composition_class{#ENV{type}})] - * pour poser des classes generiques sur le - * si une balise toto est definie dans la composition c'est elle qui est appliquee - * sinon on pose simplement le nom de la composition - * - * @param string $composition - * @param string $type - * @return string - */ -function composition_class($composition,$type){ - if ($desc = compositions_decrire($type, $composition) - AND isset($desc['class']) - AND strlen($desc['class'])) - return $desc['class']; - return $composition; -} - -/** - * Liste les types d'objets qui ont une composition ET sont autorises par la configuration - * utilise la valeur en cache meta sauf si demande de recalcul - * ou pas encore definie - * - * @staticvar array $liste - * @return array - */ -function compositions_types(){ - static $liste = null; - if (is_null($liste)) { - if (_VAR_MODE OR !isset($GLOBALS['meta']['compositions_types'])){ - include_spip('inc/compositions'); - compositions_cacher(); - } - $liste = explode(',',$GLOBALS['meta']['compositions_types']); - } - return $liste; -} - -/** - * Renvoie les parametres necessaires pour utiliser l'heritage de composition de façon generique - * recupere les donnes du pipeline compositions_declarer_heritage. - * Si $type n'est pas precise, on renvoie simplement le tableau des objets pouvant heriter. - * - * @param string $type - * @staticvar array $heritages - * @return array - */ -function compositions_recuperer_heritage($type=NULL){ - static $heritages = NULL; - if (is_null($heritages)) // recuperer les heritages declares via le pipeline compositions_declarer_heritage - $heritages = pipeline('compositions_declarer_heritage', array()); - - if (is_null($type)) - return $heritages; - - if (array_key_exists($type, $heritages)) { - $type_parent = $heritages[$type]; - $table_parent = table_objet_sql($type_parent); - $nom_id_parent = ($type==$type_parent) ? 'id_parent' : id_table_objet($type_parent); // Recursivite pour les rubriques, nom de l'identifiant du parent dans la table enfant - $nom_id_table_parent = id_table_objet($type_parent); // Nom de l'identifiant du parent dans la table parent - - // verifier que table et champs existent... - $trouver_table = charger_fonction('trouver_table', 'base'); - if (!$type_parent - OR !$desc = $trouver_table($table_parent) - OR !isset($desc['field']['composition']) - OR !isset($desc['field'][$nom_id_parent])) - return ''; - - return array( - 'type_parent' => $type_parent, - 'table_parent' => $table_parent, - 'nom_id_parent' => $nom_id_parent, - 'nom_id_table_parent' => $nom_id_table_parent - ); - } - return array(); -} - -/** - * Renvoie la composition qui s'applique a un objet - * en tenant compte, le cas echeant, de la composition heritee - * si etoile=true on renvoi directment le champ sql - * - * @param string $type - * @param integer $id - * @param string $serveur - * @param bool $etoile - * @return string - */ -function compositions_determiner($type, $id, $serveur='', $etoile = false){ - static $composition = array(); - $id = intval($id); - - if (isset($composition[$etoile][$serveur][$type][$id])) - return $composition[$etoile][$serveur][$type][$id]; - - include_spip('base/abstract_sql'); - $table = table_objet($type); - $table_sql = table_objet_sql($type); - $_id_table = id_table_objet($type); - - $retour = ''; - - $trouver_table = charger_fonction('trouver_table', 'base'); - $desc = $trouver_table($table,$serveur); - if (isset($desc['field']['composition']) AND $id){ - $select = "composition"; - - $heritage = compositions_recuperer_heritage($type); - if (isset($desc['field'][$heritage['nom_id_parent']])) - $select .= ', '.$heritage['nom_id_parent'].' as id_parent'; - - $row = sql_fetsel($select, $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur); - if ($row['composition'] != '') - $retour = $row['composition']; - elseif (!$etoile - AND isset($row['id_parent']) - AND $row['id_parent']) - $retour = compositions_heriter($type, $id, $row['id_parent'], $serveur); - } - return $composition[$etoile][$serveur][$type][$id] = (($retour == '-') ? '' : $retour); -} - -/** - * Renvoie la composition heritee par un objet selon son identifiant. - * Optionnellement, on peut lui transmettre directement l'id du parent s'il a ate calcule. - * - * @param string $type - * @param integer $id - * @param integer $id_parent - * @param string $serveur - * @return string - */ -function compositions_heriter($type, $id, $id_parent=NULL, $serveur=''){ - if ($type=='syndic') $type='site'; //grml - if (intval($id) < 1) return ''; - static $infos = null; - $compo_parent = ''; - - $heritage = compositions_recuperer_heritage($type); - - /* Si aucun héritage n'a été défini pour le type d'objet, ce - * n'est pas la peine d'aller plus loin. */ - if(count($heritage) == 0) - return ''; - - $type_parent = $heritage['type_parent']; - $table_parent = $heritage['table_parent']; - $nom_id_parent = $heritage['nom_id_parent']; - $nom_id_table_parent = $heritage['nom_id_table_parent']; - - if (is_null($id_parent)) - $id_parent = sql_getfetsel($nom_id_parent, table_objet_sql($type), id_table_objet($type).'='.intval($id)); - - $heritages = compositions_recuperer_heritage(); - - do { - $select = 'composition'; - if ($heritages[$type_parent]==$type_parent) // S'il y a recursivite sur le parent - $select .= ', id_parent'; - $row = sql_fetsel($select, $table_parent, $nom_id_table_parent.'='.intval($id_parent),'','','','',$serveur); - if (strlen($row['composition']) AND $row['composition']!='-') - $compo_parent = $row['composition']; - elseif (strlen($row['composition'])==0 AND isset($heritages[$type_parent])) // Si le parent peut heriter, il faut verifier s'il y a heritage - $compo_parent = compositions_determiner($type_parent, $id_parent, $serveur=''); - - if (strlen($compo_parent) AND is_null($infos)) - $infos = compositions_lister_disponibles(''); - - } - while ($id_parent = $row['id_parent'] - AND - (!strlen($compo_parent) OR !isset($infos[$type_parent][$compo_parent]['branche'][$type]))); - - if (strlen($compo_parent) AND isset($infos[$type_parent][$compo_parent]['branche'][$type])) - return $infos[$type_parent][$compo_parent]['branche'][$type]; - - return ''; -} - -/** - * #COMPOSITION - * Renvoie la composition s'appliquant a un objet - * en tenant compte, le cas echeant, de l'heritage. - * - * Sans precision, l'objet et son identifiant sont pris - * dans la boucle en cours, mais l'on peut specifier notre recherche - * en passant objet et id_objet en argument de la balise : - * #COMPOSITION{article, 8} - * - * #COMPOSITION* renvoie toujours le champs brut, sans tenir compte de l'heritage - * - * @param array $p AST au niveau de la balise - * @return array AST->code modifie pour calculer le nom de la composition - */ -function balise_COMPOSITION_dist($p) { - $_composition = ""; - if ($_objet = interprete_argument_balise(1, $p)) { - $_id_objet = interprete_argument_balise(2, $p); - } else { - $_composition = champ_sql('composition',$p); - $_id_objet = champ_sql($p->boucles[$p->id_boucle]->primary, $p); - $_objet = "objet_type('" . $p->boucles[$p->id_boucle]->id_table . "')"; - } - // si on veut le champ brut, et qu'on l'a sous la main, inutile d'invoquer toute la machinerie - if ($_composition AND $p->etoile) - $p->code = $_composition; - else { - $connect = $p->boucles[$p->id_boucle]->sql_serveur; - $p->code = "compositions_determiner($_objet, $_id_objet, '$connect', ".($p->etoile?'true':'false').")"; - // ne declencher l'usine a gaz que si composition est vide ... - if ($_composition) - $p->code = "((\$zc=$_composition)?(\$zc=='-'?'':\$zc):".$p->code.")"; - } - return $p; -} - -/** - * Indique si la composition d'un objet est verrouillee ou non, - * auquel cas, seul le webmaster peut la modifier - * - * @param string $type - * @param integer $id - * @param string $serveur - * @return string - */ -function compositions_verrouiller($type, $id, $serveur=''){ - $config = unserialize($GLOBALS['meta']['compositions']); - if (isset($config['tout_verrouiller']) AND $config['tout_verrouiller'] == 'oui') - return true; - - include_spip('base/abstract_sql'); - $table = table_objet($type); - $table_sql = table_objet_sql($type); - $_id_table = id_table_objet($type); - - $trouver_table = charger_fonction('trouver_table', 'base'); - $desc = $trouver_table($table,$serveur); - if (isset($desc['field']['composition_lock']) AND $id){ - $lock = sql_getfetsel('composition_lock', $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur); - if ($lock) - return true; - elseif (isset($desc['field']['id_rubrique'])) { - $id_rubrique = sql_getfetsel('id_rubrique', $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur); - return compositions_verrou_branche($id_rubrique, $serveur); - } - else - return false; - } - else return false; -} - -/** - * Indique si les objets d'une branche sont verrouilles - * @param integer $id_rubrique - * @param string $serveur - * @return string - */ -function compositions_verrou_branche($id_rubrique, $serveur=''){ - - if (intval($id_rubrique) < 1) return false; - if($infos_rubrique = sql_fetsel(array('id_parent','composition_branche_lock'),'spip_rubriques','id_rubrique='.intval($id_rubrique),'','','','',$serveur)) { - if ($infos_rubrique['composition_branche_lock']) - return true; - else - return compositions_verrou_branche($infos_rubrique['id_parent'],$serveur); - } - return ''; -} -?> +array('type' => $type,'informer' => $informer), + 'data'=> $res + )); + return $res; +} + +/** + * Liste les id d'un type donne utilisant une composition donnee + * + * @param string $type + * @param string $composition + * @return array + */ +function compositions_lister_utilisations($type, $composition) { + $table_sql = table_objet_sql($type); + if (!in_array($table_sql, sql_alltable())) { + return; + } + $trouver_table = charger_fonction('trouver_table', 'base'); + $desc = $trouver_table($table_sql); + $_id_table_objet = id_table_objet($type); + $titre = isset($desc['titre']) ? $desc['titre'] : "'' AS titre"; + return sql_allfetsel("$_id_table_objet as id, $titre", $table_sql, 'composition='.sql_quote($composition)); +} + +/** + * Selectionner le fond en fonction du type et de la composition + * en prenant en compte la configuration pour le chemin + * et le fait que la composition a pu etre supprimee + * + * @param string $composition + * @param string $type + * @param string $defaut + * @param string $ext + * @param bool $fullpath + * @param string $vide + * @return string + */ +function compositions_selectionner($composition, $type, $defaut = '', $ext = 'html', $fullpath = false, $vide = 'composition-vide') { + if ($type=='syndic') { + $type='site'; //grml + } + $fond = compositions_chemin() . $type; + + // regarder si compositions/article-xxx est disponible + if (strlen($composition) + and $f = find_in_path("$fond-$composition.$ext")) { + return $fullpath ? $f : $fond . "-$composition"; + } elseif (strlen($defaut) + and $f = find_in_path("$fond-$defaut.$ext")) { + // sinon regarder si compositions/article-defaut est disponible + return $fullpath ? $f : $fond . "-$defaut"; + } + + // se rabattre sur compositions/article si disponible + if ($f = find_in_path("$fond.$ext")) { + return $fullpath ? $f : $fond; + } + + // sinon une composition vide pour ne pas generer d'erreur + if ($vide and $f = find_in_path("$vide.$ext")) { + return $fullpath ? $f : $vide; + } + + // rien mais ca fera une erreur dans le squelette si appele en filtre + return ''; +} + +/** + * Decrire une composition pour un objet + * @param string $type + * @param string $composition + * @return array|bool|string + */ +function compositions_decrire($type, $composition) { + static $compositions = array(); + if (!function_exists('compositions_charger_infos')) { + include_spip('inc/compositions'); + } + if ($type=='syndic') { + $type='site'; //grml + } + if (isset($compositions[$type][$composition])) { + return $compositions[$type][$composition]; + } + $ext = 'html'; + $fond = compositions_chemin() . $type; + if (strlen($composition) + and $f = find_in_path("$fond-$composition.$ext") + and $desc = compositions_charger_infos($f)) { + return $compositions[$type][$composition] = $desc; + } + return $compositions[$type][$composition] = false; +} + +/** + * Un filtre a utiliser sur [(#COMPOSITION|composition_class{#ENV{type}})] + * pour poser des classes generiques sur le + * si une balise toto est definie dans la composition c'est elle qui est appliquee + * sinon on pose simplement le nom de la composition + * + * @param string $composition + * @param string $type + * @return string + */ +function composition_class($composition, $type) { + if ($desc = compositions_decrire($type, $composition) + and isset($desc['class']) + and strlen($desc['class'])) { + return $desc['class']; + } + return $composition; +} + +/** + * Liste les types d'objets qui ont une composition ET sont autorises par la configuration + * utilise la valeur en cache meta sauf si demande de recalcul + * ou pas encore definie + * + * @staticvar array $liste + * @return array + */ +function compositions_types() { + static $liste = null; + if (is_null($liste)) { + if (_VAR_MODE or !isset($GLOBALS['meta']['compositions_types'])) { + include_spip('inc/compositions'); + compositions_cacher(); + } + $liste = explode(',', $GLOBALS['meta']['compositions_types']); + } + return $liste; +} + +/** + * Renvoie les parametres necessaires pour utiliser l'heritage de composition de façon generique + * recupere les donnes du pipeline compositions_declarer_heritage. + * Si $type n'est pas precise, on renvoie simplement le tableau des objets pouvant heriter. + * + * @param string $type + * @staticvar array $heritages + * @return array + */ +function compositions_recuperer_heritage($type = null) { + static $heritages = null; + if (is_null($heritages)) { + // recuperer les heritages declares via le pipeline compositions_declarer_heritage + $heritages = pipeline('compositions_declarer_heritage', array()); + } + + if (is_null($type)) { + return $heritages; + } + + if (array_key_exists($type, $heritages)) { + $type_parent = $heritages[$type]; + $table_parent = table_objet_sql($type_parent); + $nom_id_parent = ($type==$type_parent) ? 'id_parent' : id_table_objet($type_parent); // Recursivite pour les rubriques, nom de l'identifiant du parent dans la table enfant + $nom_id_table_parent = id_table_objet($type_parent); // Nom de l'identifiant du parent dans la table parent + + // verifier que table et champs existent... + $trouver_table = charger_fonction('trouver_table', 'base'); + if (!$type_parent + or !$desc = $trouver_table($table_parent) + or !isset($desc['field']['composition']) + or !isset($desc['field'][$nom_id_parent])) { + return ''; + } + + return array( + 'type_parent' => $type_parent, + 'table_parent' => $table_parent, + 'nom_id_parent' => $nom_id_parent, + 'nom_id_table_parent' => $nom_id_table_parent + ); + } + return array(); +} + +/** + * Renvoie la composition qui s'applique a un objet + * en tenant compte, le cas echeant, de la composition heritee + * si etoile=true on renvoi directment le champ sql + * + * @param string $type + * @param integer $id + * @param string $serveur + * @param bool $etoile + * @return string + */ +function compositions_determiner($type, $id, $serveur = '', $etoile = false) { + static $composition = array(); + $id = intval($id); + + if (isset($composition[$etoile][$serveur][$type][$id])) { + return $composition[$etoile][$serveur][$type][$id]; + } + + include_spip('base/abstract_sql'); + $table = table_objet($type); + $table_sql = table_objet_sql($type); + $_id_table = id_table_objet($type); + + $retour = ''; + + $trouver_table = charger_fonction('trouver_table', 'base'); + $desc = $trouver_table($table,$serveur); + if (isset($desc['field']['composition']) and $id) { + $select = 'composition'; + + $heritage = compositions_recuperer_heritage($type); + if (isset($desc['field'][$heritage['nom_id_parent']])) { + $select .= ', '.$heritage['nom_id_parent'].' as id_parent'; + } + + $row = sql_fetsel($select, $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur); + if ($row['composition'] != '') { + $retour = $row['composition']; + } elseif (!$etoile + and isset($row['id_parent']) + and $row['id_parent']) { + $retour = compositions_heriter($type, $id, $row['id_parent'], $serveur); + } + } + return $composition[$etoile][$serveur][$type][$id] = (($retour == '-') ? '' : $retour); +} + +/** + * Renvoie la composition heritee par un objet selon son identifiant. + * Optionnellement, on peut lui transmettre directement l'id du parent s'il a ate calcule. + * + * @param string $type + * @param integer $id + * @param integer $id_parent + * @param string $serveur + * @return string + */ +function compositions_heriter($type, $id, $id_parent = null, $serveur = '') { + if ($type=='syndic') { + $type='site'; //grml + } + if (intval($id) < 1) { + return ''; + } + static $infos = null; + $compo_parent = ''; + + $heritage = compositions_recuperer_heritage($type); + + /* Si aucun héritage n'a été défini pour le type d'objet, ce + * n'est pas la peine d'aller plus loin. */ + if (count($heritage) == 0) { + return ''; + } + + $type_parent = $heritage['type_parent']; + $table_parent = $heritage['table_parent']; + $nom_id_parent = $heritage['nom_id_parent']; + $nom_id_table_parent = $heritage['nom_id_table_parent']; + + if (is_null($id_parent)) { + $id_parent = sql_getfetsel($nom_id_parent, table_objet_sql($type), id_table_objet($type).'='.intval($id)); + } + + $heritages = compositions_recuperer_heritage(); + + do { + $select = 'composition'; + if ($heritages[$type_parent]==$type_parent) { + // S'il y a recursivite sur le parent + $select .= ', id_parent'; + } + $row = sql_fetsel($select, $table_parent, $nom_id_table_parent.'='.intval($id_parent), '', '', '', '', $serveur); + if (strlen($row['composition']) and $row['composition']!='-') { + $compo_parent = $row['composition']; + } elseif (strlen($row['composition'])==0 and isset($heritages[$type_parent])) { + // Si le parent peut heriter, il faut verifier s'il y a heritage + $compo_parent = compositions_determiner($type_parent, $id_parent, $serveur = ''); + } + + if (strlen($compo_parent) and is_null($infos)) { + $infos = compositions_lister_disponibles(''); + } + } while ($id_parent = $row['id_parent'] + and + (!strlen($compo_parent) or !isset($infos[$type_parent][$compo_parent]['branche'][$type]))); + + if (strlen($compo_parent) and isset($infos[$type_parent][$compo_parent]['branche'][$type])) { + return $infos[$type_parent][$compo_parent]['branche'][$type]; + } + + return ''; +} + +/** + * #COMPOSITION + * Renvoie la composition s'appliquant a un objet + * en tenant compte, le cas echeant, de l'heritage. + * + * Sans precision, l'objet et son identifiant sont pris + * dans la boucle en cours, mais l'on peut specifier notre recherche + * en passant objet et id_objet en argument de la balise : + * #COMPOSITION{article, 8} + * + * #COMPOSITION* renvoie toujours le champs brut, sans tenir compte de l'heritage + * + * @param array $p AST au niveau de la balise + * @return array AST->code modifie pour calculer le nom de la composition + */ +function balise_COMPOSITION_dist($p) { + $_composition = ''; + if ($_objet = interprete_argument_balise(1, $p)) { + $_id_objet = interprete_argument_balise(2, $p); + } else { + $_composition = champ_sql('composition', $p); + $_id_objet = champ_sql($p->boucles[$p->id_boucle]->primary, $p); + $_objet = "objet_type('" . $p->boucles[$p->id_boucle]->id_table . "')"; + } + // si on veut le champ brut, et qu'on l'a sous la main, inutile d'invoquer toute la machinerie + if ($_composition and $p->etoile) { + $p->code = $_composition; + } else { + $connect = $p->boucles[$p->id_boucle]->sql_serveur; + $p->code = "compositions_determiner($_objet, $_id_objet, '$connect', ".($p->etoile?'true':'false').")"; + // ne declencher l'usine a gaz que si composition est vide ... + if ($_composition) { + $p->code = "((\$zc=$_composition)?(\$zc=='-'?'':\$zc):".$p->code.")"; + } + } + return $p; +} + +/** + * Indique si la composition d'un objet est verrouillee ou non, + * auquel cas, seul le webmaster peut la modifier + * + * @param string $type + * @param integer $id + * @param string $serveur + * @return string + */ +function compositions_verrouiller($type, $id, $serveur = '') { + $config = (isset($GLOBALS['meta']['compositions']) ? unserialize($GLOBALS['meta']['compositions']) : array()); + if (isset($config['tout_verrouiller']) and $config['tout_verrouiller'] == 'oui') { + return true; + } + + include_spip('base/abstract_sql'); + $table = table_objet($type); + $table_sql = table_objet_sql($type); + $_id_table = id_table_objet($type); + + $trouver_table = charger_fonction('trouver_table', 'base'); + $desc = $trouver_table($table,$serveur); + if (isset($desc['field']['composition_lock']) and $id) { + $lock = sql_getfetsel('composition_lock', $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur); + if ($lock) { + return true; + } elseif (isset($desc['field']['id_rubrique'])) { + $id_rubrique = sql_getfetsel('id_rubrique', $table_sql, "$_id_table=".intval($id), '', '', '', '', $serveur); + return compositions_verrou_branche($id_rubrique, $serveur); + } else { + return false; + } + } else { + return false; + } +} + +/** + * Indique si les objets d'une branche sont verrouilles + * @param integer $id_rubrique + * @param string $serveur + * @return string + */ +function compositions_verrou_branche($id_rubrique, $serveur = '') { + + if (intval($id_rubrique) < 1) { + return false; + } + if ($infos_rubrique = sql_fetsel(array('id_parent', 'composition_branche_lock'), 'spip_rubriques', 'id_rubrique='.intval($id_rubrique), '', '', '', '', $serveur)) { + if ($infos_rubrique['composition_branche_lock']) { + return true; + } else { + return compositions_verrou_branche($infos_rubrique['id_parent'], $serveur); + } + } + return ''; +} diff --git a/www/plugins/compositions_v3/compositions_ieconfig.php b/www/plugins/compositions_v3/compositions_ieconfig.php index ea5c5206..b190b01a 100644 --- a/www/plugins/compositions_v3/compositions_ieconfig.php +++ b/www/plugins/compositions_v3/compositions_ieconfig.php @@ -1,14 +1,14 @@ - \ No newline at end of file diff --git a/www/plugins/compositions_v3/compositions_options.php b/www/plugins/compositions_v3/compositions_options.php new file mode 100644 index 00000000..e9132b93 --- /dev/null +++ b/www/plugins/compositions_v3/compositions_options.php @@ -0,0 +1,12 @@ +$type, - 'id'=>$id, - ) - ); - - if (($p = strpos($flux['data'],''))!==false) - $flux['data'] = substr_replace($flux['data'],$texte,$p,0); - else - $flux['data'] .= $texte; - } - } - } - - return $flux; -} - -/** - * Le pipeline compositions_declarer_heritage permet de declarer les heritages - * sous la forme : - * $heritages['objet'] = 'parent'; - * ce qui permet ensuite de faire dans le fichier parent-ma_compo.xml - * - * - * A partir de compositions 3.3.0 cette declaration est obligatoire. - * Les objets "standards" de SPIP sont declares ici. (a deplacer dans leurs plugins respectifs ?) - */ -function compositions_compositions_declarer_heritage($heritages){ - $heritages['mot'] = 'groupe_mots'; - $heritages['rubrique'] = 'rubrique'; - $heritages['article'] = 'rubrique'; - $heritages['breve'] = 'rubrique'; - $heritages['site'] = 'rubrique'; - return $heritages; -} - - -?> +$type, + 'id'=>$id, + ) + ); + + if (($p = strpos($flux['data'],''))!==false) + $flux['data'] = substr_replace($flux['data'],$texte,$p,0); + else + $flux['data'] .= $texte; + } + } + } + + return $flux; +} + +/** + * Le pipeline compositions_declarer_heritage permet de declarer les heritages + * sous la forme : + * $heritages['objet'] = 'parent'; + * ce qui permet ensuite de faire dans le fichier parent-ma_compo.xml + * + * + * A partir de compositions 3.3.0 cette declaration est obligatoire. + * Les objets "standards" de SPIP sont declares ici. (a deplacer dans leurs plugins respectifs ?) + */ +function compositions_compositions_declarer_heritage($heritages){ + $heritages['mot'] = 'groupe_mots'; + $heritages['rubrique'] = 'rubrique'; + $heritages['article'] = 'rubrique'; + $heritages['breve'] = 'rubrique'; + $heritages['site'] = 'rubrique'; + return $heritages; +} + + +?> diff --git a/www/plugins/compositions_v3/formulaires/configurer_compositions.html b/www/plugins/compositions_v3/formulaires/configurer_compositions.html index f43a62d2..39a474b6 100644 --- a/www/plugins/compositions_v3/formulaires/configurer_compositions.html +++ b/www/plugins/compositions_v3/formulaires/configurer_compositions.html @@ -6,8 +6,8 @@
#ACTION_FORMULAIRE -
    - #SET{name,objets}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}} +
      + #SET{name,objets}#SET{erreurs,#ENV**{erreurs/#GET{name}}}
    • [ (#GET{erreurs}) @@ -15,7 +15,7 @@ #INCLURE{fond=formulaires/inc-choisir-objets,name=#GET{name},selected=#ENV**{#GET{name},#LISTE{spip_articles,spip_rubriques}}}
    • -
    • +
    • [(#PLUGIN{z}|ou{#PLUGIN{zcore}}|non)
      <:compositions:label_chemin_compositions_details:>
      ] @@ -28,14 +28,14 @@
] -
  • +
  • -
  • +
  • @@ -46,4 +46,4 @@

  • - \ No newline at end of file + diff --git a/www/plugins/compositions_v3/formulaires/editer_composition_objet.html b/www/plugins/compositions_v3/formulaires/editer_composition_objet.html index 959bcd5a..0eda9b0d 100644 --- a/www/plugins/compositions_v3/formulaires/editer_composition_objet.html +++ b/www/plugins/compositions_v3/formulaires/editer_composition_objet.html @@ -1,105 +1,109 @@ -
    - [

    (#ENV*{message_ok})

    ] - [

    (#ENV*{message_erreur})

    ] - [(#ENV{editable}) -
    - [(#REM) declarer les hidden qui declencheront le service du formulaire - parametre : url d'action ] - #ACTION_FORMULAIRE{#ENV{action}} - ] - - <:compositions:composition_utilisee:> - [(#ENV{composition}|oui)[(#ENV{_compositions}|table_valeur{#ENV{composition}}|table_valeur{nom}|supprimer_numero|sinon{#ENV{composition}})] - ][(#ENV{composition}|non) - [(#ENV{composition_heritee}|oui) - [(#ENV{composition_heritee}|=={'-'}|oui)<:compositions:composition_defaut:>] - [(#ENV{composition_heritee}|!={'-'}|oui)[(#ENV{_compositions}|table_valeur{''}|table_valeur{nom}|supprimer_numero|sinon{#ENV{composition_heritee}})]] - (<:compositions:composition_heritee:>) - ] - [(#ENV{composition_heritee}|non)<:compositions:composition_defaut:>] - ][(#ENV{composition_verrouillee}|oui) ] - - - [(#ENV{editable}) - - ] -
    - [(#ENV{composition_verrouillee}|oui)

    <:compositions:composition_verrouillee:>

    ] -

    <:compositions:heritages:> #CLE (#VALEUR).

    -
    - - [(#ENV{editable}) -
      - #SET{fl,compositions} - #SET{name,composition}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}#SET{obli,''} - [
    • - - [(#GET{erreurs})] - (#INCLURE{fond=formulaires/inc-selecteur_composition}{name=#GET{name}}{id=#GET{name}}{id_rubrique}{selected=#ENV{#GET{name}}}{_compositions}{composition_heritee}) -
    • ] - - #SET{lock,''} - [(#AUTORISER{webmestre}|et{#ENV{verrou_branche}|non}|et{#CONFIG{compositions/tout_verrouiller}|non}|oui) - #SET{name,composition_lock}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}#SET{obli,''} -
    • - [(#GET{erreurs})] - - [(#ENV{_compositions}|is_array|oui) -
      - - -
      - ] - [(#ENV{_compositions}|is_array|non)] - [(#ENV{objet}|=={rubrique}|oui) - #SET{name,composition_branche_lock}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}#SET{obli,''} - [(#GET{erreurs})] -
      - - -
      - ] -
    • - #SET{lock,'oui'} - ] - [(#ENV{verrou_branche}|oui) -
    • - - <:compositions:label_branche_verrouillee:> -
    • - ] - [(#CONFIG{compositions/tout_verrouiller}|oui) -
    • - - <:compositions:label_toutes_verrouilles:> -
    • - ] -
    - [(#GET{lock}|non) - - [(#ENV{objet}|=={rubrique}|oui) - - ] - ] - - [(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ] - -

    -   - - -

    -
    - ] -
    - \ No newline at end of file +
    + [

    (#ENV*{message_ok})

    ] + [

    (#ENV*{message_erreur})

    ] + [(#ENV{editable}) +
    + [(#REM) declarer les hidden qui declencheront le service du formulaire + parametre : url d'action ] + #ACTION_FORMULAIRE{#ENV{action}} + ] + + <:compositions:composition_utilisee:> + [(#ENV{composition}|oui)[(#ENV{_compositions/#ENV{composition}/nom}|supprimer_numero|sinon{#ENV{composition}})] + ][(#ENV{composition}|non) + [(#ENV{composition_heritee}|oui) + [(#ENV{composition_heritee}|=={'-'}|oui)<:compositions:composition_defaut:>] + [(#ENV{composition_heritee}|!={'-'}|oui)[(#ENV{_compositions}|table_valeur{''}|table_valeur{nom}|supprimer_numero|sinon{#ENV{composition_heritee}})]] + (<:compositions:composition_heritee:>) + ] + [(#ENV{composition_heritee}|non)<:compositions:composition_defaut:>] + ][(#ENV{composition_verrouillee}|oui) ] + + + [(#ENV{editable}) + + ] +
    + [(#ENV{composition_verrouillee}|oui)

    <:compositions:composition_verrouillee:>

    ] + +

    <:compositions:heritages:> + #CLE (#VALEUR) + .

    +
    +
    + + [(#ENV{editable}) +
      + #SET{fl,compositions} + #SET{name,composition}#SET{erreurs,#ENV**{erreurs/#GET{name}}}#SET{obli,''} + [
    • + + [(#GET{erreurs})] + (#INCLURE{fond=formulaires/inc-selecteur_composition}{name=#GET{name}}{id=#GET{name}}{id_rubrique}{selected=#ENV{#GET{name}}}{_compositions}{composition_heritee}) +
    • ] + + #SET{lock,''} + [(#AUTORISER{webmestre}|et{#ENV{verrou_branche}|non}|et{#CONFIG{compositions/tout_verrouiller}|non}|oui) + #SET{name,composition_lock}#SET{erreurs,#ENV**{erreurs/#GET{name}}}#SET{obli,''} +
    • + [(#GET{erreurs})] + + [(#ENV{_compositions}|is_array|oui) +
      + + +
      + ] + [(#ENV{_compositions}|is_array|non)] + [(#ENV{objet}|=={rubrique}|oui) + #SET{name,composition_branche_lock}#SET{erreurs,#ENV**{erreurs/#GET{name}}}#SET{obli,''} + [(#GET{erreurs})] +
      + + +
      + ] +
    • + #SET{lock,'oui'} + ] + [(#ENV{verrou_branche}|oui) +
    • + + <:compositions:label_branche_verrouillee:> +
    • + ] + [(#CONFIG{compositions/tout_verrouiller}|oui) +
    • + + <:compositions:label_toutes_verrouilles:> +
    • + ] +
    + [(#GET{lock}|non) + + [(#ENV{objet}|=={rubrique}|oui) + + ] + ] + + [(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ] + +

    +   + + +

    +
    + ] +
    + diff --git a/www/plugins/compositions_v3/formulaires/inc-informeur_composition.html b/www/plugins/compositions_v3/formulaires/inc-informeur_composition.html deleted file mode 100644 index 0ac26149..00000000 --- a/www/plugins/compositions_v3/formulaires/inc-informeur_composition.html +++ /dev/null @@ -1,8 +0,0 @@ - - -
    [(#VALEUR|table_valeur{icon}|image_reduire{24,24}|inserer_attribut{class,logo})] -[(#VALEUR|table_valeur{nom})] -[
    (#VALEUR|table_valeur{description})] -
    - -
    \ No newline at end of file diff --git a/www/plugins/compositions_v3/formulaires/inc-selecteur_composition.html b/www/plugins/compositions_v3/formulaires/inc-selecteur_composition.html index d63dfc40..44c21028 100644 --- a/www/plugins/compositions_v3/formulaires/inc-selecteur_composition.html +++ b/www/plugins/compositions_v3/formulaires/inc-selecteur_composition.html @@ -1,7 +1,13 @@ - - -
    - -
    - -
    \ No newline at end of file + +
    + + +
    + diff --git a/www/plugins/compositions_v3/images/composition-cours.png b/www/plugins/compositions_v3/images/composition-cours.png index 96fd12580b55e720b33db6a5bf2e895808b4d74f..63c3822065a87eda49681736ee66e59c3f735d4d 100644 GIT binary patch delta 340 zcmZ3;@`P!EWIZzj1H;_yjc)s;XbUe7Sf3L05Ng{fCbqj~+iUVdBL3m6KNhHL;Zh`2{oVx37=a zpR1Eakt!T9!CD`T^PKx^WimAk9I&)<+|QSSM-midnhqbrm1b8FTsQS(=q z@|EPQljm1xXt4Kq`kaO7b>Iy@(Wri{i49kki}z_6NV{ENew^i!c3|@(nW%(UM=I-m zMGolI9MrqwE;#W({@wtAj1tdh8yymI%~j66nEo=smwQKN|La4lk&pOU8Ce88xYww~ gJa1U}QS;Ha<8KZN_J6-s40Iubr>mdKI;Vst05-0d<^TWy delta 531 zcmaFDw2)EaktaqG>^{eFiWWY|BPdQFb zyr+KW{q$`vP3i9+J3oK)=})bZ%grBWzfL`!_VRLhU+UZ&vzDdSecpSId3GH`z~N0R zV(f%i6;ADYVG49E0xWX-^;TY{|F}q7qLz5HhRBMjwf}e>_TTS!yW^uK%+;hI$`BfQ zvfkwEjn_Pf6^<7^V&1WCcIW=e)mLwEG$?f_?MPmE{dI`eRH3!9eC>ajOLoU*na%FJ zc52fcy@qwKrMo@nY+$mM;Q3+AwEC)6VD_JRH*?yQI2afTZm`wfzd!TQSAB*TOfQ%; zniw3!J$6=9&YS*XnVNBVGY^A1)R7yMb0^gA?Ohq-qh~JO!noIO`ALSH+kMZReU(=i zo>Dzfv~$7niyBqNQ#cxU>-R2O{#;y-@y4<9x8A<(YnXC6aN~+1&IKn>i5*1K;EV&xt}2hj~CsJzf1=);T3K F0RSb!*}eb( diff --git a/www/plugins/compositions_v3/images/composition-tableau.png b/www/plugins/compositions_v3/images/composition-tableau.png index ce4f60ecb11b39775f856201ad9f1ed5618e0508..3479d45b14d475854daca1915c009751d18d57fd 100755 GIT binary patch delta 228 zcmZ3({FQNnWIZzj1H;_yjci7|NsBe zg$q8td{$Xm+27y4zR!0xP#arGkY6yve*5}({kdw&JV23bPZ!6KinzDecJnnT2)G2+ zylr~_|9_P5!m9@wP98h6mg8tHJj;+mEQudiJ9 z?Npee3+-9Hh1e{)d^(l6q2aA0XMx+f6Oucb8kbrm-?w4<+$h$#@_6yr*kgUGr|TM< RSOe{4@O1TaS?83{1OQ5>VXFWD delta 413 zcmey$xQ2OxWIY=L1H-D!!h1kUvcxr_Bsf2=MUC}!B<%rfbzT8PP#j$)R0#qSF|xh_9G z=I1D=`Fuf}w}9Cs?$dp;93Ce=FK4{D`0BgM=X{PXS(kmWUgq*&Z;7_k&kEN+eGoZq zuN;HP$49^aH9xipum54I2tY%=i y(sNM7^T;NhtqiLdX{6oCJK*yB`RDsgVmu7)*H&9x4w(20q{`FP&t;ucLK6Uvc&vc{ diff --git a/www/plugins/compositions_v3/images/composition-test.png b/www/plugins/compositions_v3/images/composition-test.png index d4ba8cdbdac6a7d7fc2e10f57b14f556eb5af927..acc14529d828937d9dd9e1419d1833dc9e7c5353 100644 GIT binary patch delta 233 zcmVP3i!*mQv>@I0!g))A^tKvvri1R?^TT2J^> zTtHSujmQWf(0LXNvJfGlG|oR=;L$ir=K?)G0xlt!kV{x+&|(Wp3oL75xB|PH7{vVehvfrL^_DW(*Y1!MtP5D-|Y j>(=oL%*4D4q&|cOR8gIriM(Da00000NkvXXu0mjf&{SU| delta 491 zcmVeSaefwW^{L9a%BKPWN%_+AW3auXJt}l zVPtu6$z?nM00EpyL_t(|+U%P#ii1EDhQ}qH%|b-mt+dfQELtmATJ0WT!4vEOv={6x z1rOks_IBD>E8f9%0tsg0u8SCBGXH}xVF=8;&-wrN7!22S9e-gtxFZ0|vfldPg_XpU zB>AM{ZZP+*>-wuCNe`cV6h(Bn06+}GAeyGJ0^kr&gz;b=z;0}^u4|H}=_WVa`xIHy zr$zxZO>?G`ErqJ8ivoZL0001>3S5LJio|i8O>UU(?dkxi%Wf3_Bme*_cmR!}DDFPF z{eDjbL6`@iEPu5eXiXxZ%6=D0961IKovk0 zfCO+Mf(sEy02d;-5J4-9Rv0FTRv4`?B!DV_DgX(f3NTa!&Q3rWhJ@#NW+m`ZRn;?V h9>B5w_xW!D1^`sDzOWPmmnHxJ002ovPDHLkV1n-9%`*T1 diff --git a/www/plugins/compositions_v3/images/objet-blocs.png b/www/plugins/compositions_v3/images/objet-blocs.png new file mode 100644 index 0000000000000000000000000000000000000000..76939671fb270bd8dc24e823bda3dcd0ef563483 GIT binary patch literal 189 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_7U7Ec$)kP61PR~;E090Xb)=BhNY zOm<{0R~MWkdPB-8rz_VmkAdNU{d*2OvGX=bDwDqSU1?AXuC8>EW>`MmU!LK>YFmRk z+XE|QB-j}a2=8xt{=b9a$>fX9-x)!cFfdp#yqZxCVFnz(VhCY5$R3{+Gfz!n!iT;Y a>OP$RE2G+I!+Bt2dIT-G@yGywpz!#Xzr literal 0 HcmV?d00001 diff --git a/www/plugins/compositions_v3/images/objet-intro-blocs.png b/www/plugins/compositions_v3/images/objet-intro-blocs.png new file mode 100644 index 0000000000000000000000000000000000000000..2f256defb4208322fa5e9ee08cb0a7fb16a25e6f GIT binary patch literal 207 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_7UX`U{QAr*{oubML+3J`I7_?&}N zV~141fpaY^X*>!H%oP=vizlc(IzKJW)5-RGPiFkC-yIv9=iU$GtcWS8u3W}-;PunX zYz!UYdk=rCX_&rt20Oz8?)yx3E(}XHRNgdru&?srVaELZtTrtm$gr+C^J*!`b|9!b vZo>>_G~73A@Mo4Ot*Q(?aPHgt6Saq)EY^Sda7n=1Cm?xGS3j3^P6}Q3@h+?c67+%Dy9I-sFV^a<=-Z3_%4|BJ!o<62rtm$ z1#GM`+Qi*s9YDn>qgen)vib*Tuo=FLN-3jRSpUm1Vi^Szpa2CZFoMzGyc8HPgE1&l Z$ODVP$y(K8CL;g<002ovPDHLkV1iYQkG=o^ delta 679 zcmV;Y0$Bam0<;B?8Gi-<0063Kaozv`02y>eSaefwW^{L9a%BKPWN%_+AW3auXJt}l zVPtu6$z?nM00LG?L_t(|+U%RVY63wNh9|*GAws|#ViPPBLD5P<5Q5r?_EyOw1bl+L zfW2UEXCc_y2ntqqqJ>r>-YP2_jb~to@e(x~CF9KbVc9*)u7B)&JLk;#7kt`ow?t(b zw1ZqO_rBY`sxt6et@gDCV5g5{GWq6mxuhR_rBZ?25de}(rAR0gQUw6jGf`a112CLA zIh{^PqtOuZfp>L^+_Fxc1TdS;_VPp|1%ttx0>B!801yDK0!MN>og|;n3;DqCYX0s8y-L4P7U@&-i06w4ZA^=Q*bM$0L0o?%nem@pL zEP_}Bu?S)j#8wyqAOHlQ6$|RBLEouWHO=0kw}DeyIppy zX*eA2-BT0ZpAwhd3M#7LUhc)?O|a zi-&KX40>*g#bPWacohl-`2Yk00b;dUSsj3>ug!!*9nOgV)+Hl!6#&ThX0yrS)oQgD z^J=%-LIL1cs9yu%jl^cNp?kO6&CXdY7P5{RdVf8#Ua#pnuh&as>CF&yfqYj8N~hBlfYd3#x3{qIHn?7|lT0Rabgi^z2;Mxr z@oKet_Btue5EzO?B0-H1fPlP**#N1brG(UG2+R*mc@Pvp{-cN%D`SR?Mk6&ue2iuY z%@CR)^a2O~0U!VbfB|33dMzyMe=&B6j-O)3BY N002ovPDHLkV1ih~C6NFC diff --git a/www/plugins/compositions_v3/images/objet-liste-contenus.png b/www/plugins/compositions_v3/images/objet-liste-contenus.png index 0c39d8e73f86d09d14c6a4cef9c2da228082ecb5..86f1fa00c05c2e9886495aa9f40cb8433318e91a 100644 GIT binary patch delta 227 zcmV<9038481M~rq8Gi%-0001Bxm5rF0J}*V`OJS z0Byzq0%CwE1~SC~O$5F7lJauScdvn8>Z?>l8q&$pGhi}Yjgwba7XY_Po_hd*SpnhA-vP{Obk}{F zVOlVt7pA`eg64O?GE9F5m@xg}8Kwigjtx`3VgL*yh7rSvVZ<;}3;+NCKx@@b-b+AD d>N#3z$QpQazZ}eHZ)^Yn002ovPDHLkV1hypSh4^B delta 476 zcmeyu_?mfwWIY=L1H-D!!h1l9v%n*=n1O*?7=#%aX3dcR3QCr^MwA5Sr)8!T==V`w>j zii<%PD6wHLdp$>J=+`etSFSo`;v3DjVBPEG>Dom3nf&x2{ z0~0Pb09gtG2lk(3^qgei8hC=KB7fGiR>v)0G!HN&d`-Rccixp~kP1&%KbLh*2~7Zu C-@(uT diff --git a/www/plugins/compositions_v3/images/objet-simple.png b/www/plugins/compositions_v3/images/objet-simple.png index 1f387f3439d37fd1a7d4dba10afb527f6e75b869..75e0d0910ea65aeb8263745e1d4b2f9bd88b64ca 100644 GIT binary patch delta 220 zcmX@l{FZToWIYQ55G3pj1(I7lT^vIy7~ftq7iBUKX?7+-A^uJ^h2>HjbgE?n%SjBH!g%d(* z3=9_@ig@HWF??*731a%g-=+EsnMbi@2{=EIe$9G03L%X#3U%iwca(gp T@@!li29oe}^>bP0l+XkK09sWB delta 448 zcmaFMc%FHJWIY=L1H-D!!h1l9v%n*=n1O*?7=#%aX3dcR3QCr^MwA5Srl5r^v>}-d->lzSU5}J`4o{D-xxLNi4&#DNI+~}AbQ$W3F1%y-%Fx%ZHa&IW zzW1(THD5*EzFgVPaIN(3W%Wsumc3lZ@Brw11{>CQLM)6|OLaFTtb6;C;l`#Q#s#cE z@p94szojpOuU77Vrp^k7v?}v4_nQh*$vN`{sz2SY&O0gZOx6Nif zk37cbF^NT}g+rNaK9;ALtBAkQmdKI;Vst00qFTqyPW_ diff --git a/www/plugins/compositions_v3/inc/compositions.php b/www/plugins/compositions_v3/inc/compositions.php index f705be13..028e995d 100644 --- a/www/plugins/compositions_v3/inc/compositions.php +++ b/www/plugins/compositions_v3/inc/compositions.php @@ -19,9 +19,9 @@ include_spip('compositions_fonctions'); function compositions_decomposer_nom($nom){ $reg = ",^([a-z][^-.]*)("._COMPOSITIONS_MATCH.")?$,i"; if ( - // recuperer le type et la composition + /* recuperer le type et la composition */ preg_match($reg,$nom,$matches) - // il y a bien un type + /* il y a bien un type */ AND $type=$matches[1] ){ $composition = isset($matches[3])?$matches[3]:''; @@ -38,7 +38,7 @@ function compositions_decomposer_nom($nom){ * @return array|string */ function compositions_charger_infos($nom,$info=""){ - // on peut appeller avec le nom du squelette + /* on peut appeller avec le nom du squelette */ $nom = preg_replace(',[.]html$,i','',$nom).".xml"; include_spip('inc/xml'); $composition = array(); @@ -49,13 +49,16 @@ function compositions_charger_infos($nom,$info=""){ $composition['description'] = isset($xml['description'])?_T_ou_typo(spip_xml_aplatit($xml['description'])):''; if (isset($xml['icon'])) { $icon = chemin_image(reset($xml['icon'])); - if (!$icon) + if (!$icon) { $icon = find_in_path(reset($xml['icon'])); - } else + } + } else { $icon = ''; + } + $composition['image_exemple'] = isset($xml['image_exemple']) ? find_in_path(reset($xml['image_exemple'])) : ''; $composition['icon'] = $icon; - $composition['class'] = isset($xml['class'])?trim(reset($xml['class'])):''; - $composition['configuration'] = isset($xml['configuration'])?spip_xml_aplatit($xml['configuration']):''; + $composition['class'] = isset($xml['class']) ? trim(reset($xml['class'])) : ''; + $composition['configuration'] = isset($xml['configuration']) ? spip_xml_aplatit($xml['configuration']) : ''; $composition['branche'] = array(); if (spip_xml_match_nodes(',^branche,', $xml, $branches)){ foreach (array_keys($branches) as $branche){ @@ -67,7 +70,7 @@ function compositions_charger_infos($nom,$info=""){ } if (!$info) return $composition; - else + else return isset($composition[$info])?$composition[$info]:""; } @@ -86,12 +89,12 @@ function compositions_charger_infos($nom,$info=""){ * @param array $liste */ function compositions_cacher($liste=null){ - // lister les compositions vraiment utilisees + /* lister les compositions vraiment utilisees */ if (!is_array($liste)){ include_spip('compositions_fonctions'); $liste = compositions_lister_disponibles('',false); } - // lister les objets dont on a active la composition dans la configuration + /* lister les objets dont on a active la composition dans la configuration */ $config = compositions_objets_actives(); $liste = array_intersect($config,array_keys($liste)); @@ -99,4 +102,4 @@ function compositions_cacher($liste=null){ spip_log('compositions: maj des compositions_types ['.$GLOBALS['meta']['compositions_types'].']'); } -?> \ No newline at end of file +?> diff --git a/www/plugins/compositions_v3/lang/compositions.xml b/www/plugins/compositions_v3/lang/compositions.xml index 60ecc2fa..637cc868 100644 --- a/www/plugins/compositions_v3/lang/compositions.xml +++ b/www/plugins/compositions_v3/lang/compositions.xml @@ -1,19 +1,26 @@ - + + + + + + - + + - + - + + - + - + diff --git a/www/plugins/compositions_v3/lang/compositions_de.php b/www/plugins/compositions_v3/lang/compositions_de.php new file mode 100644 index 00000000..f088f022 --- /dev/null +++ b/www/plugins/compositions_v3/lang/compositions_de.php @@ -0,0 +1,55 @@ + 'Komposition', + 'composition_defaut' => 'Standardkomposition', + 'composition_heritee' => 'vererbt', + 'composition_utilisee' => 'Komposition:', + 'composition_verrouillee' => 'Diese Komposition ist durch den Webmaster gesperrt.', + 'compositions' => 'Kompositionen', + + // D + 'des_utilisations' => '@nb@ Nutzungen', + + // H + 'heritages' => 'Diese Komposition bestimmt die Standardkomposition für folgende Objekte:', + + // I + 'info_aucune_composition' => 'Keine Komposition', + + // L + 'label_activer_composition_objets' => 'Komposition für die Objekte verwenden', + 'label_branche_verrouillee' => 'Die Kompositionen dieses Zweigs sind gesperrt.', + 'label_chemin_compositions' => 'Kompositionsverzeichnis', + 'label_chemin_compositions_details' => 'Geben Sie den Pfad an unter dem die Skelette für die Kompostionen gefunden werden.', + 'label_composition' => 'Komposition', + 'label_composition_branche_lock' => 'Komposition für alle Objekte im Zweig festlegen.', + 'label_composition_explication' => 'Sie sind Webmaster, sie können', + 'label_composition_lock' => 'Komposition sperren', + 'label_composition_rubrique' => 'Kompositionen für Rubriken', + 'label_heritages' => 'Vererbungen', + 'label_information' => 'Information', + 'label_masquer_formulaire' => 'Formular verbergen', + 'label_masquer_formulaire_composition' => 'Das Formular zur Auswahl einer Komposition verbergen, wenn der Nutzer keine Berechtigung zum Ändern hat.', + 'label_pas_de_composition' => 'Keine Komposition', + 'label_styliser' => 'Auswahl der Skelette', + 'label_styliser_auto' => 'Skelette nicht automatisch auswählen. Die Auswahl wird von meinen Skeletten unterstützt.', + 'label_tout_verrouiller' => 'Alle sperren', + 'label_toutes_verrouilles' => 'Alle Kompositionen sind gesperrt.', + 'label_verrouiller_toutes_compositions' => 'Alle Kompostionen sperren (nur Webmaster können Sie verändern).', + + // U + 'une_utilisation' => '1 Nutzung', + + // V + 'voir_image_exemple' => 'Beispielbild anzeigen' +); diff --git a/www/plugins/compositions_v3/lang/compositions_en.php b/www/plugins/compositions_v3/lang/compositions_en.php index 56b47190..f40580a4 100644 --- a/www/plugins/compositions_v3/lang/compositions_en.php +++ b/www/plugins/compositions_v3/lang/compositions_en.php @@ -3,10 +3,15 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/compositions?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( + // A + 'ajouter_compositions' => 'Add compositions', + // C 'composition' => 'Composition', 'composition_defaut' => 'default composition', @@ -21,6 +26,11 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // H 'heritages' => 'This composition defines default compositions for the following objects:', + // I + 'info_1_composition' => '1 composition', + 'info_aucune_composition' => 'No composition', + 'info_nb_compositions' => '@nb@ compositions', + // L 'label_activer_composition_objets' => 'Use compositions on objects', 'label_branche_verrouillee' => 'The compositions of this branch are locked.', @@ -31,6 +41,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_composition_explication' => 'You are Webmaster, you can', 'label_composition_lock' => 'Lock the composition', 'label_composition_rubrique' => 'Sections composition', + 'label_heritages' => 'Heritages', 'label_information' => 'Information', 'label_masquer_formulaire' => 'Hide the form', 'label_masquer_formulaire_composition' => 'Hide the selection form of a composition when the user does not have the rights to edit it.', @@ -41,8 +52,12 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_toutes_verrouilles' => 'All compositions are locked.', 'label_verrouiller_toutes_compositions' => 'Lock all compositions (only the webmasters can change them).', + // M + 'message_info_ajouter_compositions' => 'To create your own compositions, see the documentation : @url_doc@.', + // U - 'une_utilisation' => '1 use' -); + 'une_utilisation' => '1 use', -?> + // V + 'voir_image_exemple' => 'See an image sample' +); diff --git a/www/plugins/compositions_v3/lang/compositions_es.php b/www/plugins/compositions_v3/lang/compositions_es.php index 4c1aa3b0..d7b79923 100644 --- a/www/plugins/compositions_v3/lang/compositions_es.php +++ b/www/plugins/compositions_v3/lang/compositions_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/compositions?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -21,6 +23,9 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // H 'heritages' => 'Esta composición define las composiciones por defecto para los siguientes objetos:', + // I + 'info_aucune_composition' => ' Ninguna composición', + // L 'label_activer_composition_objets' => 'Utilizar las composiciones en los objetos', 'label_branche_verrouillee' => 'Las composiciones de esta rama están bloqueadas.', @@ -31,6 +36,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_composition_explication' => 'Usted es administrador, puede', 'label_composition_lock' => 'Bloquear la composición', 'label_composition_rubrique' => 'Composición de las secciones', + 'label_heritages' => 'Herencias', 'label_information' => 'Información', 'label_masquer_formulaire' => 'Ocultar el formulario', 'label_masquer_formulaire_composition' => 'Ocultar el formulario de elección de una composición cuando el usuario no tenga los derechos para modificarla. ', @@ -44,5 +50,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'une_utilisation' => '1 utilización' ); - -?> diff --git a/www/plugins/compositions_v3/lang/compositions_fr.php b/www/plugins/compositions_v3/lang/compositions_fr.php index e351a84c..7aa60c54 100644 --- a/www/plugins/compositions_v3/lang/compositions_fr.php +++ b/www/plugins/compositions_v3/lang/compositions_fr.php @@ -1,10 +1,15 @@ 'Ajouter des compositions', + // C 'composition' => 'Composition', 'composition_defaut' => 'composition par défaut', @@ -19,6 +24,11 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // H 'heritages' => 'Cette composition définit des compositions par défaut pour les objets suivants :', + // I + 'info_1_composition' => '1 composition', + 'info_aucune_composition' => 'Aucune composition', + 'info_nb_compositions' => '@nb@ compositions', + // L 'label_activer_composition_objets' => 'Utiliser les compositions sur les objets', 'label_branche_verrouillee' => 'Les compositions de cette branche sont verrouillées.', @@ -40,8 +50,12 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_toutes_verrouilles' => 'Toutes les compositions sont verrouillées.', 'label_verrouiller_toutes_compositions' => 'Verrouiller toutes les compositions (seuls les webmestres pourront les modifier).', + // M + 'message_info_ajouter_compositions' => 'Pour créer vos propres compositions, consultez la documentation : @url_doc@.', + // U - 'une_utilisation' => '1 utilisation' -); + 'une_utilisation' => '1 utilisation', -?> + // V + 'voir_image_exemple' => 'Voir une image d’exemple' +); diff --git a/www/plugins/compositions_v3/lang/compositions_nl.php b/www/plugins/compositions_v3/lang/compositions_nl.php index 366e0480..9998be51 100644 --- a/www/plugins/compositions_v3/lang/compositions_nl.php +++ b/www/plugins/compositions_v3/lang/compositions_nl.php @@ -3,10 +3,15 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/compositions?lang_cible=nl // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( + // A + 'ajouter_compositions' => 'Composities toevoegen', + // C 'composition' => 'Compositie', 'composition_defaut' => 'standaard compositie', @@ -21,6 +26,11 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // H 'heritages' => 'Deze compositie legt de standaardcompositie vast van de volgende objecten:', + // I + 'info_1_composition' => '1 compositie', + 'info_aucune_composition' => 'Geen enkele compositie', + 'info_nb_compositions' => '@nb@ composities', + // L 'label_activer_composition_objets' => 'Pas de composities toe op de objecten', 'label_branche_verrouillee' => 'De composities van deze tak zijn vergrendeld.', @@ -31,6 +41,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_composition_explication' => 'Je bent webmaster. Je mag', 'label_composition_lock' => 'Vergrendel de compositie', 'label_composition_rubrique' => 'Compositie van rubrieken', + 'label_heritages' => 'Erfenis', 'label_information' => 'Informatie', 'label_masquer_formulaire' => 'Het formulier verbergen', 'label_masquer_formulaire_composition' => 'Verberg het compositie-keuzemenu wanneer de gebruiker het recht niet heeft ze te veranderen.', @@ -41,8 +52,12 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_toutes_verrouilles' => 'Alle composities zijn vergrendeld.', 'label_verrouiller_toutes_compositions' => 'Alle composities vergrendelen (alleen webmasters kunnen ze aanpassen).', + // M + 'message_info_ajouter_compositions' => 'Om je eigen composities te maken, raadpleeg je de documentatie: @url_doc@.', + // U - 'une_utilisation' => '1 toepassing' -); + 'une_utilisation' => '1 toepassing', -?> + // V + 'voir_image_exemple' => 'Een voorbeeldafbeelding bekijken' +); diff --git a/www/plugins/compositions_v3/lang/compositions_ru.php b/www/plugins/compositions_v3/lang/compositions_ru.php index 6cf56ccd..33e51186 100644 --- a/www/plugins/compositions_v3/lang/compositions_ru.php +++ b/www/plugins/compositions_v3/lang/compositions_ru.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/compositions?lang_cible=ru // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -21,6 +23,9 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // H 'heritages' => 'Этот шаблон определяет шаблоны страниц по умолчанию для следующих объектов:', + // I + 'info_aucune_composition' => 'Нет шаблонов', + // L 'label_activer_composition_objets' => 'Использовать выбор шаблонов для объектов', 'label_branche_verrouillee' => 'Выбор шаблонов в этой ветке заблокирован вебмастером.', @@ -44,5 +49,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'une_utilisation' => '1 использование' ); - -?> diff --git a/www/plugins/compositions_v3/lang/compositions_sk.php b/www/plugins/compositions_v3/lang/compositions_sk.php index 76684b3e..acb7bf22 100644 --- a/www/plugins/compositions_v3/lang/compositions_sk.php +++ b/www/plugins/compositions_v3/lang/compositions_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/compositions?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -21,6 +23,9 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // H 'heritages' => 'Toto rozmiestnenie je predvolených rozmiestnením pre tieto objekty:', + // I + 'info_aucune_composition' => 'Žiadne rozmiestnenie', + // L 'label_activer_composition_objets' => 'Rozmiestnenia používať na objekty', 'label_branche_verrouillee' => 'Rozmiestnenia tejto vetvy sú zamknuté.', @@ -44,5 +49,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'une_utilisation' => '1 použitie' ); - -?> diff --git a/www/plugins/compositions_v3/lang/paquet-compositions_en.php b/www/plugins/compositions_v3/lang/paquet-compositions_en.php index e89f0465..003f0639 100644 --- a/www/plugins/compositions_v3/lang/paquet-compositions_en.php +++ b/www/plugins/compositions_v3/lang/paquet-compositions_en.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-compositions?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'compositions_nom' => 'Compositions', 'compositions_slogan' => 'Differ page layouts according to sections, articles...' ); - -?> diff --git a/www/plugins/compositions_v3/lang/paquet-compositions_es.php b/www/plugins/compositions_v3/lang/paquet-compositions_es.php index 8acdb0e1..da44f28c 100644 --- a/www/plugins/compositions_v3/lang/paquet-compositions_es.php +++ b/www/plugins/compositions_v3/lang/paquet-compositions_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-compositions?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'compositions_nom' => 'Composiciones', 'compositions_slogan' => 'Variar los formateos según las secciones, los artículos...' ); - -?> diff --git a/www/plugins/compositions_v3/lang/paquet-compositions_fr.php b/www/plugins/compositions_v3/lang/paquet-compositions_fr.php index e7c7f831..28c6eb89 100644 --- a/www/plugins/compositions_v3/lang/paquet-compositions_fr.php +++ b/www/plugins/compositions_v3/lang/paquet-compositions_fr.php @@ -1,7 +1,9 @@ 'Compositions', 'compositions_slogan' => 'Varier les mises en page selon les rubriques, les articles...' ); - -?> diff --git a/www/plugins/compositions_v3/lang/paquet-compositions_nl.php b/www/plugins/compositions_v3/lang/paquet-compositions_nl.php index 00a21e83..3dfeb728 100644 --- a/www/plugins/compositions_v3/lang/paquet-compositions_nl.php +++ b/www/plugins/compositions_v3/lang/paquet-compositions_nl.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-compositions?lang_cible=nl // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'compositions_nom' => 'Composities', 'compositions_slogan' => 'Varieer de indeling van de bladzijdes volgens rubriek, artikel, ...' ); - -?> diff --git a/www/plugins/compositions_v3/lang/paquet-compositions_ru.php b/www/plugins/compositions_v3/lang/paquet-compositions_ru.php index 2c5a3a62..00dab0e7 100644 --- a/www/plugins/compositions_v3/lang/paquet-compositions_ru.php +++ b/www/plugins/compositions_v3/lang/paquet-compositions_ru.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-compositions?lang_cible=ru // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'compositions_nom' => 'Шаблоны страниц (Compositions)', 'compositions_slogan' => 'Возможность задавать определенный шаблон для вывода статьи, раздела и т.д.' ); - -?> diff --git a/www/plugins/compositions_v3/lang/paquet-compositions_sk.php b/www/plugins/compositions_v3/lang/paquet-compositions_sk.php index e282cd8f..cb4c2f9c 100644 --- a/www/plugins/compositions_v3/lang/paquet-compositions_sk.php +++ b/www/plugins/compositions_v3/lang/paquet-compositions_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-compositions?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'compositions_nom' => 'Rozmiestnenia', 'compositions_slogan' => 'Meňte rozmiestnenie podľa rubrík, článkov, atď.' ); - -?> diff --git a/www/plugins/compositions_v3/paquet.xml b/www/plugins/compositions_v3/paquet.xml index 9323646a..eb081440 100644 --- a/www/plugins/compositions_v3/paquet.xml +++ b/www/plugins/compositions_v3/paquet.xml @@ -1,9 +1,9 @@ - - - - - + + + - + + + diff --git a/www/plugins/compositions_v3/prive/editer/compositions.html b/www/plugins/compositions_v3/prive/editer/compositions.html index e448f8ef..ceb43b9e 100644 --- a/www/plugins/compositions_v3/prive/editer/compositions.html +++ b/www/plugins/compositions_v3/prive/editer/compositions.html @@ -1 +1 @@ -[
    (#FORMULAIRE_EDITER_COMPOSITION_OBJET{#ENV{type},#ENV{id}})
    ] +[
    (#FORMULAIRE_EDITER_COMPOSITION_OBJET{#ENV{type},#ENV{id}})
    ] diff --git a/www/plugins/compositions_v3/prive/squelettes/contenu/compositions.html b/www/plugins/compositions_v3/prive/squelettes/contenu/compositions.html index 5c55d22b..b4374868 100644 --- a/www/plugins/compositions_v3/prive/squelettes/contenu/compositions.html +++ b/www/plugins/compositions_v3/prive/squelettes/contenu/compositions.html @@ -1,48 +1,62 @@ -#SET{compositions,#REM|compositions_lister_disponibles} - - - - - [(#BOITE_OUVRIR{[(#CLE|objet_info{texte_objets}|_T)], simple, section})] - -
    -
      - -
    • - [(#ICON|image_reduire{24,24}|inserer_attribut{class,logo})] - -

      [(#NOM|supprimer_numero)]

      - - [
      (#DESCRIPTION)
      ] - - - [(#BOITE_OUVRIR{<:compositions:label_heritages:>, raccourcis})] - <:compositions:heritages:> -
        - -
      • #CLE (#VALEUR)
      • - -
      - #BOITE_FERMER -
      - - - [(#BOITE_OUVRIR{[(#TOTAL_BOUCLE|singulier_ou_pluriel{compositions:une_utilisation,compositions:des_utilisations})], raccourcis})] - - -
    • - -
    -
    - - #BOITE_FERMER -
    - +#SET{compositions,#REM|compositions_lister_disponibles} + +

    <:compositions:compositions:>

    + + +[

    (#GRAND_TOTAL|singulier_ou_pluriel{compositions:info_1_composition,compositions:info_nb_compositions})

    ] + + + + + + [(#BOITE_OUVRIR{[(#CLE|objet_info{texte_objets}|_T)], simple, section})] + +
    + +
    + + #BOITE_FERMER +
    + + +

    <:compositions:info_aucune_composition:>

    + diff --git a/www/plugins/compositions_v3/prive/squelettes/navigation/compositions.html b/www/plugins/compositions_v3/prive/squelettes/navigation/compositions.html new file mode 100644 index 00000000..db70f0c4 --- /dev/null +++ b/www/plugins/compositions_v3/prive/squelettes/navigation/compositions.html @@ -0,0 +1,8 @@ +[(#REM) + Message expliquant comment ajouter des compositions, réservé aux admins +] +[(#AUTORISER{configurer,compositions}|oui) +[(#BOITE_OUVRIR{<:compositions:ajouter_compositions:>,info})] +<:compositions:message_info_ajouter_compositions{url_doc=#PLUGIN{compositions,documentation}}|propre:> +[(#BOITE_FERMER)] +] diff --git a/www/plugins/compositions_v3/prive/style_prive_plugin_compositions.html b/www/plugins/compositions_v3/prive/style_prive_plugin_compositions.html index 340dfa54..c5ef3bde 100644 --- a/www/plugins/compositions_v3/prive/style_prive_plugin_compositions.html +++ b/www/plugins/compositions_v3/prive/style_prive_plugin_compositions.html @@ -4,6 +4,8 @@ .formulaire_editer_composition_objet .editer_composition .choix input {display:block;float: #ENV{left};} .formulaire_editer_composition_objet .editer_composition .choix label {display:block;float: #ENV{left}; width: 80%; padding-#ENV{left}: 34px; margin-bottom: 0.5em;} .formulaire_editer_composition_objet .editer_composition .choix img.logo {float:#ENV{left};margin-#ENV{left}: -34px;margin-#ENV{right}:5px;} +.formulaire_editer_composition_objet .editer_composition .choix .exemple img.logo { padding-bottom:2px; border-bottom:1px dotted #666; } +.formulaire_editer_composition_objet .editer_composition .choix .exemple img.logo:hover { border-bottom:1px solid #666; } .formulaire_editer_composition_objet h4 { padding-#ENV{left}: 30px; @@ -22,5 +24,14 @@ .formulaire_editer_composition_objet span.descriptif {font-style: italic; font-size: 0.875em;} -body.compositions #contenu .item > h4 {margin-bottom:0; } +body.compositions #contenu .item .logo {margin-#ENV{right}:1em; float: #ENV{left}; } +body.compositions #contenu .item .exemple .logo { padding-bottom:2px; border-bottom:1px dotted #666; } +body.compositions #contenu .item .exemple .logo:hover { border-bottom:1px solid #666; } +body.compositions #contenu .item .presentation { overflow:auto; } +body.compositions #contenu .item .presentation h4 {margin-bottom:0; } body.compositions #contenu .item .raccourcis ul {margin-bottom:0; } + +body.compositions #contenu .compositions { border-top:none; margin-bottom:0; } +body.compositions #contenu .compositions > .item + .item { margin-top:.5em; } +body.compositions #contenu .compositions .item:last-child { border-bottom:none; } + diff --git a/www/plugins/compositions_v3/prive/themes/spip/images/composition-16.png b/www/plugins/compositions_v3/prive/themes/spip/images/composition-16.png index 79cd6b0cd5ebc0f482f315db1fd79034967bd3f3..31400d1d7e3f1624dea81de4502d2911550835c8 100644 GIT binary patch delta 378 zcmV-=0fqj?1C;}iB!65wtmx=iu=fcC2gOhi_F`d{FQ7k0 zXO>`OdQlP7gS|2ZW3wyJ*gc>K>X9i(N=XMtzi@B~h#;K(34d@BhkCGAN^p010xx%0 z@cwuMZ}&I!`QhdQ?yt|qxVt)o%acQCL0V=u+4-Yp<`%%>#1M4UmO^_?i5QcE-IOtO z@Q}HP^qkJ@WAryy!_Ut*e15zO`1<^W*2*I3894ZcQ8=Txl0+_nkucCwO@ZyTWdR@W zZ*l}ap(LniYIElca0VneJ38P)f|iOxX@Q+LJpy!(PSPXbI`lPF!O!#0<{907*qoM6N<$f}~fj4*&oF delta 428 zcmV;d0aN~!1I7c8B!7)bL_t(Ijir;nOIuMC$3N%3#40fwVzrv^ajJAG zx}=jJye@GQ$)6!ztCT9~(z=M7h?6ejsC5XXRA{L#f*E7;-aQWKGsYKUv1ZnOo*F{lNr7SGy{B~_*Tw;Trey0OXrx9=Dc6c`^#Gxltd(?7pMAj$4W^z;p2 z^;(E~2ZgH;jel|YnE%X^o*1vD-r{>+O-|bzYXBG#Om!frDo2F^sumGJ1gvlQ_4CKo zvDU92Vvt&*v*TuqSbIE_LkPfXMMYOv5)p&7`p=Fb7O#RD34hSMd^% WLlU!4t2xd90000ppcB!4JLL_t(|0j-q->>Obb#ovcTZQHhO+qSK+u^QF3Z8J`T+O}fD|M7$15g{s;miU@1{oZ|ZCba;7lx_MC zrC7tB0H6W9|MuMjGiCZroV#%!Q7Ba)Cnk&?4dbct2j_1-z<;1VJrRY)E7!pAUjPw- zxp4V1l0u21McE@fz>q(GUPLD#pnTE%ShQj_BETNu0bSZO{q?|KNFmJVMz3Jwt^+uE z=_aHAJOU~dFMv)ho8Zok>v;9z8HhZ@g%A>{)1^n2oOy!-j$gQrq5b;;AOHdjmaRaK z_AT-9`4cp3(|;M{QQQGi;Lx@W;S~rW01yrzJ^ry~<%-Gqv(gqAHotoD+;bsBas)s` z9}5>Rm63?zA5+)T$<1e_6bzPSr4&NAAptVp9vE!ffXD^sqHu)i6}Y12>*Mfl_Ufs0Lhwor-;uo znd>B%LW1?axze!RWG=#SSra%#X7cJ*Esr@%mP10o1EE2+3Se^QFNFPD)*>O~E>H-@ z(~!A!zd@lCYuJ;$H2^ra{l4vhVJZ24ln9X!0OC!H=J_Vy4C450 z-u?T1_dE9--W4D?eBsK=@b~U7I(qYJ4}U;?erQ-X8%0h6RbA*A zI0wMB>o*vm`C8NIJ6oH$eCZ-f%N~FrKKXI>8)pYj)g*BD;p4J?nSd7KKQTGEA@Uu$ zT*Q$mP(n7_vLS&alnHd@vfLSYR1;xWE?ZfkKYxh+eE9|=Qd8=d2|RoCh7X@-F#=wp zyQ7uky$AU+Gk?vmpFdFbRmnsQTedc^y{RQxU~FQV;i1!j0>bV4Bb+?e%lzDT4&+au zzPb}J!rK>5D?1PoKza9mY;o_dof#3q1`YuA%G9UvIT6Vuk*n%rdq?NCs##Q;OuHac z>RW50dFNcch@>kBn56NAJ)kC?aiRp)C_AW!}EsUEI3&0E6IB_V4KipgG&d>*r6ZaId1d zwT(C@Kx5zF=KquX28R`B3;R07*qoM6N<$f{?^8a{vGU diff --git a/www/plugins/compositions_v3/prive/themes/spip/images/composition-32.png b/www/plugins/compositions_v3/prive/themes/spip/images/composition-32.png index a0a14ee6cd055b0d09e996f0afd8be5ae346704e..1cef16d1bb8e9f95d896613aa6a6957dff78f766 100644 GIT binary patch delta 803 zcmV+;1Kj+T2f7B3B!2-(L_t(|0lk(3ki=LJhQIFjl0DnDZQHhOlwDWWm3_8t+qP}n zo|*JjSM94!?k1^Z_01yw|M#c6YXpcpo_xy9`JX@RG#D6#8B>Xh5Q6Z}jC0*_=jo^J z4lv8^N1b5PjcdAg1ZMD+J1;!`5Lp&cRYZiz#LOs)f?luBT7MgFfor;U1T@7yGBUzl zk3Gw4AAHVKu*y;kv%@Cq;*4r)q(saz7w7mR52q*wOeU&>gH&bjCkRDZ_ecjsncOpG;`U(z+|4Y=U`yKTpzSyqWEwNQUh_%?`)s}}mbKL7Oo zsW%W}DK)3sjNZ72^lRc$tq zh%xind`=I&+0FQV8$_g>a)W`&h3YqAV&y{e_>-B`(_QC5Lk(z5aT8;71HSFQ75Cl& zA*On1mw$lYV`gY*o`il;t$}jns_hN<{p}J6vDy*;ZN?BP^&q0Op*%A}Qv#G$m}T*Q zs}R++-7x_fOR=d4rCjA{yY9TF)t%vUz^o)Nr02^uP~PrFN-k;C4x%&%e7itIOD3dt zptMDsCZUK_+R*=}P5@`@yaesK`sPVk7I0B7LVpa9WUOk`C#9LSodf9^&2zv>tM+fm zKJ`RpGzBUhkmY&T37B4Ea{^mzuokDEe-Vn1C@{9(aBZB$mRgp(uD^ouu-MYeGK~3l zI_x-`Zd}u~6(EbsbdxkAK%V8l?Q!&pv-J7}W=ts};Nq^C%6<-D31BX!mmh$SBJi7U h032U1z5L_a{{jS+8P1#lM6Cb-002ovPDHLkV1kR1lXL(8 delta 894 zcmV-^1A+Xy29*bpB!65`m zihsu7WTWCDQAda)egi*%-yn+!lEj6eAR>qcvT+eXQ365+gM>jBS%^Ar288MEcU`=$ z>Q_D0HT`Ge*>%0Dy62s9?tRq)_!r-M|I7T}jiqka2xi<)sDB8~30rr}e*Mk450(LD zmRDBo|HkslssS?|*wgLCU0?g|Te8ffs))$0?%d1>A<%AjSbXXPy_$PGpoQ$MR*TD5 zf8_f5tz9i%;Nkg$ym0(6fWm6^=?y;1xW0aiciwt~5W2fsT-9;@!X-{V{bc2Om4J&s zyWI|JH*Nq-ZGVOJ)IGAWP^nQ%Kvl~J_U+q?AWWMC0}Lz4sA>ZNr#&K${rhL9EM0}F ztJJ6^U?Sy#r!TYfRO)CUMgx6kvj?-CIk*a8+PB%o0Cdh@E z(P?+sYHtlE;JoLvudZ)OwwTVcinM;^hhzgoWoj&ZG-}bU$NQaqoRnk=gl^f%MWYQ-fqNVq$x~->2!Jul@4D^l$ zGsAly37D0(6zt6c&byJvbbL>2;l@FvPRoLI1X9UWM<-yG+SsH(5;Er;u^*D1B>u&3 zhS4lYXNGH1fMkbRR$VePq_-Xqm2ni1zKTsDlz%kkH3^r2E|>(hbD*#&-C=rTnt{4J zjEeL)E^5{cqTYgcn1#~kShz3wBm`oOhDn$nzux=kyGWAa{<@4g1BNL#V5F2pvdqU8 zknNvkB7*l>rM;RUBIP?8=RmS)sf}-NW}}Nx@|Vr5D-orTjbnF z7kAO*#(?q66Gs7go_hP;nRX{IVy-5JNGzUb`6k3f+zH$V?Cy8?&e#Bc6QT+;z<9Bq9$UcXf5R{r UCxWqooB#j-07*qoM6N<$f>4gdGXMYp diff --git a/www/plugins/compositions_v3/prive/themes/spip2/images/composition-16.png b/www/plugins/compositions_v3/prive/themes/spip2/images/composition-16.png index b131f9c10bc862a61d516e8eb0f71bf243d6207f..fd8d63e26d4ab5b282513bda0413ebc8f7a9da6f 100644 GIT binary patch delta 96 zcmX@iSUf>8ij9GRLH_gqL?C75>Eakt!I;d@^j{>=pi%aZ{o*x^{J|F)avILD^+-8X zI$ioctF!OmBnt+gyazlBrim}nG(9lGY9j-KfPk>IgWk;bKvNhzUHx3vIVCg!0Afxd Ap#T5? delta 177 zcmXRu%s4@^o|%DxK|_~67)VK$xJHx&=ckpFCl;kLIHu$$r7C#lCZ?wbr6#6S7M@JC z0V)y=@CkAK|KIrke`$TMng9R)KclPx6b3SWUzutOWU-e7`2_>HK)@j7&FlsgGW2wD z45_%4l;FzDvnEI3z$qry8!R&%8=f&qX!9jAF?Lv`g{3tyNkmCpWR)<;W#lkmu#98= U{p`UdW1wyZPgg&ebxsLQ0LzFzcK`qY diff --git a/www/plugins/compositions_v3/prive/themes/spip2/images/composition-24.png b/www/plugins/compositions_v3/prive/themes/spip2/images/composition-24.png index 954f8f02995454a8cbcfbf91ac9fec180476e560..917adafa01371cab24c518ab09d59c78a1f67dd0 100644 GIT binary patch delta 99 zcmZ3_ST;d2mWhFZAzyUWdLU)%>Eakt!I->2?MFXXgHrkwQxB&jk|tRKY71sLI@|TQ z@k*I?oN~CIt!Biub7BTVpv?@PMeD8~S(z>%%E+L0>Rw|0+)7`dK@6U*elF{r5}E)i C5Fr8p delta 157 zcmXS0&p1J{o|%Dx;rhz6r+}1XiEBhjaDG}zd16s2gJVj5QmTSyZen_BP-Eh> diff --git a/www/plugins/compositions_v3/prive/themes/spip2/images/composition-32.png b/www/plugins/compositions_v3/prive/themes/spip2/images/composition-32.png index 78f420af78500718af9e8273efe2a7e9bade8e07..2c4e64ce8194ac4f4c8468aacf20876adbdb34b4 100644 GIT binary patch delta 114 zcmV-&0FD2=0fYgN8EXOn008_L?V|ty082?kK~#7FW1t84j|~9D&nRn9h=zg%qZW)> zfCmg23q~V()B=KN)Phk9=mhk=W?~|c&nN&8?E`7Ss0H+iWNBJkphIg5jOmfd0Hctx Ux9;Ph3IG5A07*qoM6N<$f*VRJO8@`> delta 171 zcmZo++`~9QvYwfNfx%@-*D)X^S>hT|5}cn_Ql40p%HWuipOmWLnVXoN8kCxtQdxL1 z)dr|YG{7gs_5Xk4|NnLV|CiSHnh6y9|Ns9PWsSobPa=UFTTd6qkcwML35pC75fO?F zt-RV2mRt!9HLQyjJ-?qgG;`HVMTRsXu7pHc7A_7It4W;`nB1JWBskbb92yuIR2GV~ UDtgOy0Zn4?boFyt=akR{0LcP3`~Uy| diff --git a/www/plugins/compositions_v3/svn.revision b/www/plugins/compositions_v3/svn.revision index fe9e80a9..7d27a580 100644 --- a/www/plugins/compositions_v3/svn.revision +++ b/www/plugins/compositions_v3/svn.revision @@ -1,10 +1,10 @@ Origine: file:///home/svn/repository/spip-zone/_plugins_/compositions/trunk -Revision: 82892 -Dernier commit: 2014-06-07 05:50:07 +0200 +Revision: 99105 +Dernier commit: 2016-08-03 11:04:01 +0200 file:///home/svn/repository/spip-zone/_plugins_/compositions/trunk -82892 -2014-06-07 05:50:07 +0200 +99105 +2016-08-03 11:04:01 +0200 \ No newline at end of file diff --git a/www/plugins/enluminures_typographiques_v3/base/typoenluminee_upgrade.php b/www/plugins/enluminures_typographiques_v3/base/typoenluminee_upgrade.php new file mode 100644 index 00000000..a15ea295 --- /dev/null +++ b/www/plugins/enluminures_typographiques_v3/base/typoenluminee_upgrade.php @@ -0,0 +1,61 @@ + $article) { + $id_article = $article['id_article']; + $article['texte'] = preg_replace('/({1{)(.*)(}1})/Uims', '{{{\\2}}}', $article['texte']); + $article['texte'] = preg_replace('/({2{)(.*)(}2})/Uims', '{{{**\\2}}}', $article['texte']); + $article['texte'] = preg_replace('/({3{)(.*)(}3})/Uims', '{{{***\\2}}}', $article['texte']); + $article['texte'] = preg_replace('/({4{)(.*)(}4})/Uims', '{{{****\\2}}}', $article['texte']); + $article['texte'] = preg_replace('/({5{)(.*)(}5})/Uims', '{{{*****\\2}}}', $article['texte']); + $article['texte'] = trim($article['texte']); + sql_updateq('spip_articles', array('texte' => $article['texte']), 'id_article=' . intval($article['id_article'])); + if (time() >= _UPGRADE_TIME_OUT) { + return; + } + } +} + + + +/** + * Desinstallation + * + * @param string $nom_meta_base_version + */ +function typoenluminee_vider_tables($nom_meta_base_version) { + include_spip('inc/meta'); + effacer_meta($nom_meta_base_version); +} diff --git a/www/plugins/enluminures_typographiques_v3/css/enluminurestypo.css b/www/plugins/enluminures_typographiques_v3/css/enluminurestypo.css index 876c5b37..1873bdd0 100644 --- a/www/plugins/enluminures_typographiques_v3/css/enluminurestypo.css +++ b/www/plugins/enluminures_typographiques_v3/css/enluminurestypo.css @@ -33,16 +33,28 @@ background: transparent; font-size:x-small; } +sub, sup, sup.typo_exposants { + /* Specified in % so that the sup/sup is the + right size relative to the surrounding text */ + font-size: 75%; + /* Zero out the line-height so that it doesn't + interfere with the positioning that follows */ + line-height: 0; + /* Where the magic happens: makes all browsers position + the sup/sup properly, relative to the surrounding text */ + position: relative; + /* Note that if you're using Eric Meyer's reset.css, this + is already set and you can remove this rule */ + vertical-align: baseline; +} sup, sup.typo_exposants { - font-size: 78%; - font-variant: normal; - vertical-align: 24%; + /* Move the superscripted text up */ + top: -0.5em; } - sub { - font-size: 60%; - font-variant: normal; - vertical-align: -20%; + /* Move the subscripted text down, but only + half as far down as the superscript moved up */ + bottom: -0.25em; } .caps { diff --git a/www/plugins/enluminures_typographiques_v3/css/enluminurestypo_prive.css b/www/plugins/enluminures_typographiques_v3/css/enluminurestypo_prive.css index 0bce269d..04e2979a 100644 --- a/www/plugins/enluminures_typographiques_v3/css/enluminurestypo_prive.css +++ b/www/plugins/enluminures_typographiques_v3/css/enluminurestypo_prive.css @@ -23,3 +23,7 @@ h5.spip { } acronym, abbr { border-bottom: .1em dotted; cursor: help; } + +.preview ol.spip { + padding: 0; +} \ No newline at end of file diff --git a/www/plugins/enluminures_typographiques_v3/editeur/supprimer_ligne.png b/www/plugins/enluminures_typographiques_v3/editeur/supprimer_ligne.png index 1514d51a3cf1b67e1c5b9ada36f1fd474e2d214a..b0da4ee9843f82b270b3ed90b619fa0eff7cf9d4 100644 GIT binary patch delta 560 zcmV-00?+-A1;_-DBYy%9Nkl--ww6W7*K2LY|r*=XP@sm=X=hje~sFP ze05+FO2$Bs4TJ+Brg?nvs>5aK4`&Y0N@tf3aqZy3@M>(|r=T>{XG-tW|OCXgNS_wsO9lQkIy@#GXY73wq zl$quYFshEmUJRhT76{^e@hLBf3s<^Y)ME*Ozld>N$pCNOf~V4`g~FifXzWIT?BUOU z*xp)a5PSjP3)uSHNKopl*=KLi74jUa<1g>|8h8$1Fj0`*dV!9FHH6 zJb;o$d45qZnni;D5~|DFUKK#wfWrl>If4Bo&22+|YKHw8mOM;#d(j9-fTTiT3W(7- zWT3Y0M9FBzmx;;#B2}lGsV)y1@)kgAR3$gaEMAx~>3?PG<4Kv`NT6ni9??AMlFB3WQ`_*z7nP8^_6w;ol;3Sz^^8p%Ij! zu1g@Zc;Sh$W7y}h3E|V|UH;81LbWg9>-aq!UpI(dUC?ETm8BIFO|v?g)#LW*?GfSQ y@Gahf`zb}yXcqI2rw6X;#BftMzBWYge~cfN(Ml8orsanK0000*dPl z>f+M9e}KPYcLs7Ur&YSo6(jsQuKgef3Kb|^r3)sC{>i0@OA)HvOI2swn z!L32w0dUY}2{oGoN+1Mj)d31iEk4tC0{b>H#=Z{USAQA>NY(}X7=3{K8#cacher('stroke_through'); - - $module_barre = "barre_outils"; - if (intval($GLOBALS['spip_version_branche'])>2) - $module_barre = "barreoutils"; - - $barre->set('header1', array( - // groupe formatage paragraphe - "dropMenu" => array( - // bouton - array( - "id" => 'intertitre', - "name" => _T('barre_intertitre'), - "className" => 'outil_intertitre1', - "openWith" => "\n{{{", - "closeWith" => "}}}\n", - "display" => true, - "selectionType" => "line", - ), - array( - "id" => 'intertitre2', - "name" => _T('enlumtypo:barre_intertitre2'), - "className" => 'outil_intertitre2', - "openWith" => "\n{{{**", - "closeWith" => "}}}\n", - "display" => true, - "selectionType" => "line", - ), - array( - "id" => 'intertitre3', - "name" => _T('enlumtypo:barre_intertitre3'), - "className" => 'outil_intertitre3', - "openWith" => "\n{{{***", - "closeWith" => "}}}\n", - "display" => true, - "selectionType" => "line", - ), - array( - "id" => 'alignerdroite', - "name" => _T('enlumtypo:barre_alignerdroite'), - "className" => 'outil_alignerdroite', - "openWith" => "\n[/", - "closeWith" => "/]\n", - "display" => true, - "selectionType" => "line", - ), - array( - "id" => 'alignergauche', - "name" => _T('enlumtypo:barre_alignergauche'), - "className" => 'outil_alignergauche', - "openWith" => "\n[!", - "closeWith" => "!]\n", - "display" => true, - "lang" => array('ar','fa'), - "selectionType" => "line", - ), - array( - "id" => 'cadretexte', - "name" => _T('enlumtypo:barre_encadrer'), - "className" => 'outil_cadretexte', - "openWith" => "\n[(", - "closeWith" => ")]\n", - "display" => true, - "selectionType" => "line", - ), - // code spip - array( - "id" => 'barre_cadre', - "name" => _T($module_barre.':barre_cadre'), - "className" => "outil_barre_cadre", - "openWith" => "\n<cadre>", - "closeWith" => "</cadre>\n", - "display" => true, - "selectionType" => "line", - ), - ), - )); - - $barre->set('bold', array( - // groupe formatage texte - "dropMenu" => array( - // Mise en évidence (gras + couleur) - array( - "id" => 'miseenevidence', - "name" => _T('enlumtypo:barre_miseenevidence'), - "className" => "outil_miseenevidence", - "openWith" => "[*", - "closeWith" => "*]", - "display" => true, - "selectionType" => "word", - ), - // Mise en évidence2 (gras + autre couleur) - array( - "id" => 'miseenevidence2', - "name" => _T('enlumtypo:barre_miseenevidence2'), - "className" => "outil_miseenevidence2", - "openWith" => "[**", - "closeWith" => "*]", - "display" => true, - "selectionType" => "word", - ), - // montrer une suppression - array( - "id" => 'stroke_through_et', - "name" => _T('enlumtypo:barre_barre'), // :-) - "className" => "outil_stroke_through_et", - "openWith" => "", - "closeWith" => "", - "display" => true, - "selectionType" => "word", - ), - // Mise en exposant - array( - "id" => 'exposant', - "name" => _T('enlumtypo:barre_exposant'), - "className" => "outil_exposant", - "openWith" => "", - "closeWith" => "", - "display" => true, - "selectionType" => "word", - ), - // Mise en indice - array( - "id" => 'indice', - "name" => _T('enlumtypo:barre_indice'), - "className" => "outil_indice", - "openWith" => "", - "closeWith" => "", - "display" => true, - "selectionType" => "word", - ), - // cadre spip - array( - "id" => 'barre_code', - "name" => _T($module_barre.':barre_code'), - "className" => "outil_barre_code", - "openWith" => "<code>", - "closeWith" => "</code>", - "display" => true, - "selectionType" => "word", - ), - ), - )); - - // Appel Tableau - $barre->ajouterApres('notes', array( - "id" => 'barre_tableau', - "name" => _T('enlumtypo:barre_tableau'), - "className" => "outil_barre_tableau", - "replaceWith" => 'function(markitup) { zone_selection = markitup.textarea; window.open("?exec=tableau_edit", "","scrollbars=yes,resizable=yes,width=700,height=600") }', - "display" => true, - "selectionType" => "line", - )); - - $barre->set('quote', array( - "dropMenu" => array( - // poesie spip - array( - "id" => 'barre_poesie', - "name" => _T($module_barre.':barre_poesie'), - "className" => "outil_barre_poesie", - "openWith" => "\n<poesie>", - "closeWith" => "</poesie>\n", - "display" => true, - "selectionType" => "line", - ), - ), - )); - - // Petites capitales - $barre->ajouterApres('italic', array( - "id" => 'petitescapitales', - "name" => _T('enlumtypo:barre_petitescapitales'), - "className" => "outil_petitescapitales", - "openWith" => "", - "closeWith" => "", - "display" => true, - "selectionType" => "word", - )); - - return $barres; -} - -function typoenluminee_porte_plume_lien_classe_vers_icone($flux){ - return array_merge($flux, array( - 'outil_intertitre1' => array('spt-v1.png','-10px -226px'), //'intertitre.png' - 'outil_intertitre2' => array('intertitre2.png','0'), - 'outil_intertitre3' => array('intertitre3.png','0'), - 'outil_alignerdroite' => array('right.png','0'), - 'outil_alignergauche' => array('left.png','0'), - 'outil_stroke_through_et' => array('spt-v1.png','-10px -946px'), //'text_strikethrough.png' - 'outil_cadretexte' => array('cadretexte.png','0'), - 'outil_speciaux' => array('tag.png','0'), - 'outil_barre_code' => array('page_white_code_red.png','0'), - 'outil_barre_cadre' => array('page_white_code.png','0'), - - 'outil_miseenevidence' => array('miseenevidence.png','0'), - 'outil_miseenevidence2' => array('miseenevidence2.png','0'), - 'outil_exposant' => array('exposant.png','0'), - 'outil_indice' => array('indice.png','0'), - 'outil_petitescapitales' => array('petitescapitales.png','0'), - 'outil_barre_poesie' => array('poesie.png','0'), - - 'outil_barre_tableau' => array('barre-tableau.png','0'), - )); -} - -?> +cacher('italic'); + $barre->cacher('stroke_through'); + $barre->cacher('notes'); + $barre->cacher('sepCode'); + $barre->cacher('grpCode'); + + $module_barre = 'barre_outils'; + if (intval($GLOBALS['spip_version_branche']) > 2) { + $module_barre = 'barreoutils'; + } + + $barre->set('header1', array( + // groupe formatage paragraphe + 'dropMenu' => array( + array( + 'id' => 'intertitre', + 'name' => _T('barre_intertitre'), + 'className' => 'outil_intertitre1', + 'openWith' => "\n{{{", + 'closeWith' => "}}}\n", + 'display' => true, + 'selectionType' => 'line', + ), + array( + 'id' => 'intertitre2', + 'name' => _T('enlumtypo:barre_intertitre2'), + 'className' => 'outil_intertitre2', + 'openWith' => "\n{{{**", + 'closeWith' => "}}}\n", + 'display' => true, + 'selectionType' => 'line', + ), + array( + 'id' => 'intertitre3', + 'name' => _T('enlumtypo:barre_intertitre3'), + 'className' => 'outil_intertitre3', + 'openWith' => "\n{{{***", + 'closeWith' => "}}}\n", + 'display' => true, + 'selectionType' => 'line', + ), + array( + 'id' => 'alignerdroite', + 'name' => _T('enlumtypo:barre_alignerdroite'), + 'className' => 'outil_alignerdroite', + 'openWith' => "\n[/", + 'closeWith' => "/]\n", + 'display' => true, + 'selectionType' => 'line', + ), + array( + 'id' => 'alignergauche', + 'name' => _T('enlumtypo:barre_alignergauche'), + 'className' => 'outil_alignergauche', + 'openWith' => "\n[!", + 'closeWith' => "!]\n", + 'display' => true, + 'lang' => array('ar', 'fa'), + 'selectionType' => 'line', + ), + array( + 'id' => 'cadretexte', + 'name' => _T('enlumtypo:barre_encadrer'), + 'className' => 'outil_cadretexte', + 'openWith' => "\n[(", + 'closeWith' => ")]\n", + 'display' => true, + 'selectionType' => 'line', + ), + array( + 'id' => 'barre_cadre', + 'name' => _T($module_barre . ':barre_cadre'), + 'className' => 'outil_barre_cadre', + 'openWith' => "\n<cadre>", + 'closeWith' => "</cadre>\n", + 'display' => true, + 'selectionType' => 'line', + ), + ), + )); + + $barre->set('bold', array( + // groupe formatage texte + 'dropMenu' => array( + // Italic - { + array( + 'id' => 'italic', + 'name' => _T('barreoutils:barre_italic'), + 'key' => 'I', + 'className' => 'outil_italic', + 'replaceWith' => "function(h){ return espace_si_accolade(h, '{', '}');}", + //'openWith' => '{', + //'closeWith' => '}', + 'display' => true, + 'selectionType' => 'word', + ), + // Petites capitales + array( + 'id' => 'petitescapitales', + 'name' => _T('enlumtypo:barre_petitescapitales'), + 'className' => 'outil_petitescapitales', + 'openWith' => '', + 'closeWith' => '', + 'display' => true, + 'selectionType' => 'word', + ), + // montrer une suppression + array( + 'id' => 'stroke_through_et', + 'name' => _T('enlumtypo:barre_barre'), // :-) + 'className' => 'outil_stroke_through_et', + 'openWith' => '', + 'closeWith' => '', + 'display' => true, + 'selectionType' => 'word', + ), + // Mise en évidence (gras + couleur) + array( + 'id' => 'miseenevidence', + 'name' => _T('enlumtypo:barre_miseenevidence'), + 'className' => 'outil_miseenevidence', + 'openWith' => '[*', + 'closeWith' => '*]', + 'display' => true, + 'selectionType' => 'word', + ), + // Mise en évidence2 (gras + autre couleur) + array( + 'id' => 'miseenevidence2', + 'name' => _T('enlumtypo:barre_miseenevidence2'), + 'className' => 'outil_miseenevidence2', + 'openWith' => '[**', + 'closeWith' => '*]', + 'display' => true, + 'selectionType' => 'word', + ), + // Mise en exposant + array( + 'id' => 'exposant', + 'name' => _T('enlumtypo:barre_exposant'), + 'className' => 'outil_exposant', + 'openWith' => '', + 'closeWith' => '', + 'display' => true, + 'selectionType' => 'word', + ), + // Mise en indice + array( + 'id' => 'indice', + 'name' => _T('enlumtypo:barre_indice'), + 'className' => 'outil_indice', + 'openWith' => '', + 'closeWith' => '', + 'display' => true, + 'selectionType' => 'word', + ), + // cadre spip + array( + 'id' => 'barre_code', + 'name' => _T($module_barre . ':barre_code'), + 'className' => 'outil_barre_code', + 'openWith' => '<code>', + 'closeWith' => '</code>', + 'display' => true, + 'selectionType' => 'word', + ), + ), + )); + + $barre->set('link', array( + // groupe formatage texte + 'dropMenu' => array( + array( + 'id' => 'notes', + 'name' => _T('barreoutils:barre_note'), + 'className' => 'outil_notes', + 'openWith' => '[[', + 'closeWith' => ']]', + 'display' => true, + 'selectionType' => 'word', + ), + ), + )); + + // Appel Tableau + $barre->ajouterApres('notes', array( + 'id' => 'barre_tableau', + 'name' => _T('enlumtypo:barre_tableau'), + 'className' => 'outil_barre_tableau', + 'replaceWith' => 'function(markitup) { zone_selection = markitup.textarea; window.open("?exec=tableau_edit", "","scrollbars=yes,resizable=yes,width=700,height=600") }', + 'display' => true, + 'selectionType' => 'line', + )); + + $barre->set('quote', array( + 'openWith' => '', + 'closeWith' => '', + )); + + $barre->set('quote', array( + 'dropMenu' => array( + // poesie spip + array( + 'id' => 'barre_poesie', + 'name' => _T($module_barre . ':barre_poesie'), + 'className' => 'outil_barre_poesie', + 'openWith' => "\n<poesie>\n", + 'closeWith' => "\n</poesie>\n", + 'display' => true, + 'selectionType' => 'word', + ), + ), + )); + + return $barres; +} + +function typoenluminee_porte_plume_lien_classe_vers_icone($flux) { + return array_merge($flux, array( + 'outil_intertitre1' => array('spt-v1.png', '-10px -226px'), //'intertitre.png' + 'outil_intertitre2' => array('intertitre2.png', '0'), + 'outil_intertitre3' => array('intertitre3.png', '0'), + 'outil_alignerdroite' => array('right.png', '0'), + 'outil_alignergauche' => array('left.png', '0'), + 'outil_stroke_through_et' => array('spt-v1.png', '-10px -946px'), //'text_strikethrough.png' + 'outil_cadretexte' => array('cadretexte.png', '0'), + 'outil_speciaux' => array('tag.png', '0'), + 'outil_barre_code' => array('page_white_code_red.png', '0'), + 'outil_barre_cadre' => array('page_white_code.png', '0'), + + 'outil_miseenevidence' => array('miseenevidence.png', '0'), + 'outil_miseenevidence2' => array('miseenevidence2.png', '0'), + 'outil_exposant' => array('exposant.png', '0'), + 'outil_indice' => array('indice.png', '0'), + 'outil_petitescapitales' => array('petitescapitales.png', '0'), + 'outil_barre_poesie' => array('poesie.png', '0'), + + 'outil_barre_tableau' => array('barre-tableau.png', '0'), + )); +} diff --git a/www/plugins/enluminures_typographiques_v3/exec/tableau_edit.php b/www/plugins/enluminures_typographiques_v3/exec/tableau_edit.php index a99aa003..e961d255 100644 --- a/www/plugins/enluminures_typographiques_v3/exec/tableau_edit.php +++ b/www/plugins/enluminures_typographiques_v3/exec/tableau_edit.php @@ -1,8 +1,10 @@ - \ No newline at end of file + -[

    (#ENV*{message_ok})

    ] -[

    (#ENV*{message_erreur})

    ] - -
    [(#ENV{_cfg_}|form_hidden)]
    - #ACTION_FORMULAIRE{#ENV{action}} - -
    • <:enlumtypo:cfg_puces:>
    • - -
    • Configuré dans le mes_options par 'barre_typo_pas_de_fausses_puces' :
      RemplacementConserver le traitement par défaut de SPIP

    • - -
    • -

      Remplacement des fausses puces de SPIP (- en début de ligne) par de vraies listes à puces (-* en début de ligne)

      -
    • - -
    -
    <:enlumtypo:cfg_titraille:> -

    Les valeurs par défaut sont basées sur la valeur historique de SPIP pour {{{}}} <=> H3. En HTML, il n'y a pas de H7 ce qui explique la balise choisie pour le niveau 5.

    -

    N'oubliez pas que la titraille sert à donner un sens dans la hiérarchisation des idées d'un texte, et surtout pas à obtenir un effet de taille de texte !

    -
    • Titraille de premier niveau : {{{}}} ou {{{* }}}

    • - -
    • Configuré dans le mes_options par 'debut_intertitre' et 'fin_intertitre'

    • - -
    • - - '})]" size="30" class="fondl" />
      - - - -
    • -
    • Titraille de deuxième niveau : {{{** }}}

    • - -
    • Configuré dans le mes_options par 'debut_intertitre_2' et 'fin_intertitre_2'

    • - -
    • - - '})]" size="30" class="fondl" />
      - - - -
    • -
    • Titraille de troisième niveau : {{{*** }}}

    • - -
    • Configuré dans le mes_options par 'debut_intertitre_3' et 'fin_intertitre_3'

    • - -
    • - - '})]" size="30" class="fondl" />
      - - - -
    • -
    • Titraille de quatrième niveau : {{{**** }}}

    • - -
    • Configuré dans le mes_options par 'debut_intertitre_4' et 'fin_intertitre_4'

    • - -
    • - - '})]" size="30" class="fondl" />
      - - - -
    • -
    • Titraille de cinquième niveau : {{{***** }}}

    • - -
    • Configuré dans le mes_options par 'debut_intertitre_5' et 'fin_intertitre_5'

    • - -
    • - - '})]" size="30" class="fondl" />
      - - - -
    • -
    -
    -
    • <:enlumtypo:cfg_insertcss:>
    • - -
    • Configuré dans le mes_options par 'BarreTypoEnrichie_Preserve_Header' - -

    • - -
    • -

      Insertion automatique des CSS spécifiques à la BTE dans l'espace public (via #INSERT_HEAD dans les squelettes)

      -
    • - -
    - - -

    - - -

    - -
    - \ No newline at end of file +
    + [

    (#ENV*{message_ok})

    ] + [

    (#ENV*{message_erreur})

    ] + +
    +
    [(#ENV{_cfg_}|form_hidden)]
    + #ACTION_FORMULAIRE{#ENV{action}} + +
    + <:enlumtypo:cfg_puces:> +
      + +
    • Configuré dans le mes_options par 'barre_typo_pas_de_fausses_puces' :
      RemplacementConserver le traitement par défaut de SPIP

    • + +
    • +

      Remplacement des fausses puces de SPIP (- en début de ligne) par de vraies listes à puces (-* en début de ligne)

      +
    • + +
    +
    +
    + <:enlumtypo:cfg_titraille:> +

    Les valeurs par défaut sont basées sur la valeur historique de SPIP pour {{{}}} <=> H3. En HTML, il n'y a pas de H7 ce qui explique la balise choisie pour le niveau 5.

    +

    N'oubliez pas que la titraille sert à donner un sens dans la hiérarchisation des idées d'un texte, et surtout pas à obtenir un effet de taille de texte !

    +
      +
    • Titraille de premier niveau : {{{}}} ou {{{* }}}

    • + +
    • Configuré dans le mes_options par 'debut_intertitre' et 'fin_intertitre'

    • + +
    • + + '})]" size="30" class="fondl text" /> +
    • +
    • + + + +
    • + +
    • Titraille de deuxième niveau : {{{** }}}

    • + +
    • Configuré dans le mes_options par 'debut_intertitre_2' et 'fin_intertitre_2'

    • + +
    • + + '})]" size="30" class="fondl text" />
      +
    • +
    • + + + +
    • + +
    • Titraille de troisième niveau : {{{*** }}}

    • + +
    • Configuré dans le mes_options par 'debut_intertitre_3' et 'fin_intertitre_3'

    • + +
    • + + '})]" size="30" class="fondl text" />
      +
    • +
    • + + + +
    • + +
    • Titraille de quatrième niveau : {{{**** }}}

    • + +
    • Configuré dans le mes_options par 'debut_intertitre_4' et 'fin_intertitre_4'

    • + +
    • + + '})]" size="30" class="fondl text" /> +
    • +
    • + + + +
    • + +
    • Titraille de cinquième niveau : {{{***** }}}

    • + +
    • Configuré dans le mes_options par 'debut_intertitre_5' et 'fin_intertitre_5'

    • + +
    • + + '})]" size="30" class="fondl text" />
      +
    • +
    • + + + +
    • +
    +
    +
    + <:enlumtypo:cfg_insertcss:> +
      + +
    • Configuré dans le fichier mes_options.php par 'BarreTypoEnrichie_Preserve_Header' + +

    • + +
    • + +

      Insertion automatique des CSS spécifiques à la BTE dans l'espace public (via #INSERT_HEAD dans les squelettes)

      +
    • + +
    +
    + +

    + + +

    + +
    +
    diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/avances.png b/www/plugins/enluminures_typographiques_v3/icones_barre/avances.png index 628cf2dae3d419ae220c8928ac71393b480745a3..310298137a1bfa9240a3086eb6c85eb6289b9144 100644 GIT binary patch delta 580 zcmV-K0=xa11>6LXBYy%TNkl z!E4Dy5v&Gt5ls;Ui5|Urkb)o;(UYi%2M^xVB0@ksh@jv>p`v&&NYIv`runx!^L)D@ zP}&6#{lRbE=7X7?yv0t@0DsmBbGjt?K{A(_D{DdSzt@tzt z;5K{^k{Dan4L!!pS!?V9%*1gwyGl(bro>i-U&zD{LWxX769Ps!26H$QbBFl7Y}*DM zW^hU}&qqej!Ct=)=l64T?#+UUb87h1e>afK53TXMV5fqwFCOE|$~~}MLUi)7&crvB z*sR$6V^=hs>3`@>O@#LxMeTbYQo^%dyoN|JjbQ)WEH&(m5^Y8M!R(1x%)D%lEP$PL zfW2-{W*c1pjIQyMVB#gUskQAdF!5b8aiS;KJpy~}2>_`!GSNb!QM!dtUqao-sUfFs zUs1wUxTQ1Ro0QDQI`=JtYOCPt8@LQi#<6?#ZRgqgh24~XENr_g0000eOSYYtbpBV}~vsBnU!_?2tr-P=|^TEDP& z$`k#K;do!ePjP4HriM82bocc5<6Yr&y=fV!=-uqHSgv83uyeu)mdC;rz5HJc;?Emu zCwuFK;?Rj-r+=I1qPj_beXzqH>)u}bPX<)IAF66K)t|%XzK0lnb_eQBqM+u2rJ@~w zU1Gd98p|k*R_AOviiK~jAOR9s9B)Hzqy?EJO^u_sD`RN^;=R$3sf@Q}xWENJyOFjZXWPcR|SA@Ztyn*bZGUQdB-0UxU z7gy#ClK9cHCqmUvrH2M=S$GF;>K0T1Gb0Q0$ysFPC@hPx@|t1g9>GvYohy!Cz4KCX z)Lc3m?G9}_XH(}Ovu^+@0OHHwFs43E03bkxpX!HU&ZDTlHQ+nmH2^TaKdEc6@@slF zHMPT^eR~Nnac@bI5~KkTFfGEM3sPWO8co4^fI6lPnA)Y{ef%@{+ cSnoUk0+dW+*{8WvF8}}l07*qoM6N<$f^m{1`v3p{ diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/barre-tableau.png b/www/plugins/enluminures_typographiques_v3/icones_barre/barre-tableau.png index c895a1f386092e1d399e333d74d318095a81035f..8695775a5e28c2cc8a2c9449e5633b0794208e13 100644 GIT binary patch delta 130 zcmV-|0Db?P0h0lc7<&i;0001xk!Usm003G^L_t(|0b_Xc@&04L!Z;7ZXoK-9rWWP{;c29f|_8_>9f k{eZFT7_@!>0Hjxlg36T2P9OME?Sh3bL0#I pYk;7-dRm8+sHlkM3XVKehI3r}Q_I&B_JC~hboFy#S?83{1OQ(uFK++< diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/barre-wiki.png b/www/plugins/enluminures_typographiques_v3/icones_barre/barre-wiki.png index 8d1a0350cbcf7b55aa82d9c941929df48efd35f4..e71178bf182116403b88564f14ca6b60673a8a8b 100644 GIT binary patch delta 129 zcmV-{0Dk|@0^0$QB$1XtcVbCIK~#7FW55D3XF4*bO>tmgm~-Zc=bqyRKt^b&)lxwa zV^^bj#c~isGSDJ0MS+1KdsU=qRU44uB{|J9Fd4{jZ=GT$2$FJEGFCQL0y0bjla$#-Ls@E`o`R)9R$^Y6o`R8qfr)~lv6Z2b zm8p?}wt=C6!TF=<#S9D#>?NMQuIyJBIeFA9o?i{91qyK%ctirF}1CmdjzX)G&wd6|WQ!5PcqBgN+nnH7{xu4JuL z=-9aW;+`bS4n@ff!5NDV9GI|I>(Z80yeB?Pnv*6ugC}Ljc0WU57EeoUNo{FuMoG0s oPp`Z~YzmttMH9Di7$h(=IC)B>zT|LW2HMZy>FVdQ&MBb@0ImK`#Q*>R diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/cadretexte.png b/www/plugins/enluminures_typographiques_v3/icones_barre/cadretexte.png index 29c4ec9508f1a65e0397fd228c177110c73ad1eb..743454c54d02ed310642a8137645c93088c89bc3 100644 GIT binary patch delta 88 zcmZo<>SCNA!O6tTz`&3+SNzk&$*L~;o-U3d6^zLY%xgnehZ$%X7!(+2w6Rq=L@Fv8 sOk1Jd!WziV*3`I8QDBFVdQ&MBb@07)|${r~^~ delta 211 zcmeBTY-E}sQP085z`&rP%O4D+^h#VKN}P*Q6H7Al^Atidb5j}0QuFi_EETd6^UCxT zj0_A+6by~6j0~+zjTE#E3=ItS3hXKb>SQnR^mS#w!pO-Z!I!z}-b|nnXMsm#F$06# zK@esd8CY~;iAr-fh6Am!=XfUWWC~+U_5nxy% z`C&x@L-HIgfvgRy9m?6+8lo5sI|NsAxz%inU|Z-2Pb-Am@w13bUu{|c}%Gf#Q=pZi$D3P%IGAOHXJ hq^TGf7%YrnWMxR_$%)(h=Jza+eV(pzf5M!#>m`scS>hT|5}cn_Ql40p%HWui zpOmWLnVXoN8kCxtQdxL1)dr|YE5Ikj6-X;7DRp#oxVX3&8yoN5y?fQFRf2+oXU?2S zOG|tA?%m9pGw^n{mX>#21bTM%v`sp^qu<-w1C0W)z4*}Q$iB}9!qZu diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/exposant.png b/www/plugins/enluminures_typographiques_v3/icones_barre/exposant.png index 4cb2cfe694d63d4d8f7233f4f2bdfcc68cbaf016..dce6382b0e1f0d2b4a189774f01667e902b2861a 100644 GIT binary patch delta 88 zcmeBV>SdfD!O6tTz`&3+SNzk&$r>*Do-U3d6^zLT7<{B1o-iw<+R sL*^EP$Sf`)wv83WjY(^K8DH#TjQqi|Ch3B?HP8qKPgg&ebxsLQ0JMc1aR2}S delta 216 zcmeBW>|~lCQP0B6z`*eK?xP?erB~t_QQ};bnpl#VpQjL#nVZT`mYS!hV5yLmm{+E! zU}RumqF`ujWn^w;V632RU}#_vH}m{6picG@PhVH|D~y~xioE~SnPvioI14-?iy0W? z4uUY_;mnX=pdd@Sqpu?a!^VE@KZ&eBKF>r|6+cT)7srr_TgeFu3^S%A>L_cRUBjR< zg=Yrq%qa~#u8Gcy9ZrsptQ}0Qjw_sIbS#{pFVdQ&MBb@ E0O;i$`Tzg` diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/intertitre2.png b/www/plugins/enluminures_typographiques_v3/icones_barre/intertitre2.png index da86b80a8768cd2c9da21f135d108c9dfb949b4a..4da8a35104ae7aa3288fa81b07cceb76bf3b8060 100644 GIT binary patch delta 94 zcmV-k0HObf0+0ca7zqLc0001DofqJOBUy07*qoM6N<$fRTqMn19fq_9omp>Rt>6N%flsFfqCYEI8=P86_=B6@~rRM1=SSn;C=9TFw z7#SFtC>R=AnHXCc8YpNR7#bKT-Q=1M)X84r>FdgVg_T!WS8s0aOIx52XMsm#F$06# zK@eseJR-P`7Ar-fh6Am!+Xf!l3Zs$@Ha1csQ zauQ}NRA34?Y`~JRN+O`w@wxFr3!W3{N0u>MP4u}T<94E$Az~WCdM|~GtAR!_c)I$z JtaD0e0s!G-JvRUV diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/intertitre3.png b/www/plugins/enluminures_typographiques_v3/icones_barre/intertitre3.png index 34f3a6aaa086d815f6902a75a387ac896d742e05..9bb24494b4b0ef3eb5d74156077446d3b7c8df9c 100644 GIT binary patch delta 94 zcmZo?n!q?gf|H4vfq@}uuK1^klU2P;JzX3_Dj1U)m@i(qARwWg%{U=yYg1!m=0PsD yiwoEk1P`zZF$?oJhYH9}1AO=rYKbLh*2~7Ydog2OY delta 217 zcmbQh*v>RTqMn19fq_9omp>Rt>6N%flsFfqCYEI8=P86_=B6@~rRM1=SSn;C=9TFw z7#SFtC>R=AnHXCc8YpNR7#bKT-Q=1M)X84r>FdgVg_T!WSEo3+Ll7v$S>O>_%)lUb z5QG^IXNG`mU`coMb!1@J*w6hZkrkw9qN<|5m8XkiNX4z>gaZsc8V!w%+qu*P9E8%7 zoJ1KnD>4aeKH!tWxI#_jvLQ>r76YZ3jd#UX?4GeXW%sUR90a8pQL4LsujEqzMt^@K!JzX3_Dj1XhoM&)ie{^t(v78wT YBg3Rvfn3?78&M!_p00i_>zopr0RJZyEC2ui delta 208 zcma!f$T&fwo`aczfk8u;KNv{qmAFQfI2WZRmSpDVDTHL^rZSYJ=IJR|Dr6<*mFX!M z85o!-7#dp{8d;f|C}!lvI6;RUI9KKuK)l42eLyCU9JOCj3q&S!3+-1ZlnP@ w;+`&!Ar-fh6BL*X4lyK(T8Q$B8FMf&sOU2|?D={z38;j@)78&qol`;+0PzJi4*&oF diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/listenum.png b/www/plugins/enluminures_typographiques_v3/icones_barre/listenum.png index 049238749622c79bc06392c5940f80e1ddde714f..c2bb45c8fbfd1a7fa256e8f9fab08456ded8576f 100644 GIT binary patch delta 79 zcmeyy*vL3Rf|H4vfq@}uuK1^klU1$NJY5_^Dj1U)nB4>pp4yVdI^`*Y(m@@Amn~Y1 j>4r@u1{Muh9T^#}?qiJ)wAhjf)XCuK>gTe~DWM4f*PaRt>6N%flsFfqCYEI8=P86_=B6@~rRM1=SSn;C=9TFw z7#SFtC>R=B8CqJI7%6BQ7#bM-?w=zC)X84r>FdgVg^`m-L`R_hLLpFyv%n*=n1Mm= zAP6%a&I|$Bz>@Ch>&U>cv7h@-A}dJIL{&vQO-~ockcwN$2?v-YF8)+tRMR-HuxTQr r{eeXd6S>-ql4f;gY3y3ba)yOL?JI*@z-6WzK%ESpu6{1-oD!MFVdQ&MBb@00bo-mH+?% delta 213 zcmd0K&NxA`o|%DxK|_~67)a@rxJHyX7o{eaWaj57gky+8e17!SQ(orXd4(B7}Q3bW(VqIFY)wsWxvA6$s??MzA;)ID8yOd5n0T@Aa@Xi z84qWMfNWq%cl32+VA$Bt{U?zXq$t4OC&cyt|NmTE|AAcZ`YG8!im@cfFPOpM*^M+H zN6OR1F{I*Fa>4wS nZ{x`>r^u$pbq0nC%!~{+_t{Mz{w!|<>SpkC^>bP0l+XkK`$!r8 delta 215 zcmZo=Y-O4tQP085z`&rP%O4D+^h#VKN}P*Q6H7Al^Atidb5j}0QuFi_EETd6^UCxT zj0_A+6by~6j7+SIEETj33=Ir|f9qTW>SQnR^mS#w!pO-ZrTg>u*-W4iXMsm#F$06# zK@esde7M?DSAr-fh6Am!+I2<^@u~b4*V#Df$ zmQ#;|4<0yjgymQSLr53rB9VSwgUuUOCN%64TrasJbt40Vg&sqEbi%P9pg|0tu6{1- HoD!M<9veZ7 diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/miseenevidence2.png b/www/plugins/enluminures_typographiques_v3/icones_barre/miseenevidence2.png index 87a3c72ed5399f26e201593f52b44c0fea9b78dd..c0aac3abc3b05afa74226b125bca145abefce968 100644 GIT binary patch delta 116 zcmaFM*~&OUBA1Dofq@}uuJ|V)#Tnoe;tHhY>#p-Y#tcpFc4IYl-#t}`%HU}j{nxzBF$@Mn1= PP#1%ztDnm{r-UW|XU-zh literal 1261 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GbKJOS+@4BLl<6e(pbstPBjy3;{kN zu0U})IXQ;^|ACBAFd70QEd)G|etE{gz{pS%Z-2kUY;K(eS|L zaQ?*4_Ba34SDyc1@b7=U;e;zKU;qDK{rCLO^8p3_|JSp!-TTkO`P@;-^uMIkuST8; yv)VTW9Lrz!&pzk>|6j&`?2j=p{hU$8$Z-01l1TSU!)OL>phcdpelF{r5}E**fzf5M!#>m`scS>hT|5}cn_Ql40p%HWui zpOmWLnVXoN8kCxtQdxL1)dr|YH^3*v6-cM0rJXr*MoCFYP*Cvh-MjDJy>oGK>FDU# zy?gh}nKR4F%U7*h6&f1)|NsB}ze`pDHSm`N`32Vl`AC4_%AFYtfpV#yE{-7;x90SF z^EDW7u*y%l)PL%4zqadb7jv~uN|zssCagcCzd&WiQNCFsX0H|M^|AsiokVxJTYbxz z#9SmQ{fX7BWxE3ZtYc<9UAr7oR(RAgWP7|TsF{5_q9^n1(=WfL1vfA*)n3;Ok RFc4@XgQu&X%Q~loCIG&)bxgI?g3IvB|(0{4E)b@F02IdoIPC}Ln;`PfAF(DF{;zpP?Olf zZY1^H-{7}0V@k*W|EIp&OP)yh|G&AhQSwBRtv7|ftIx;YR|DNig)WpGT% zPfAtr%uP&B4N6T+sVqF1Y6DcH8{iY-3Z#vVjXOFzl$4YN1qI8?%hS@*cJJPO=FFMU z&`=i_m%DfGzI*p>=FFM@|Nnm+*1Hs_fxjfkFSs7aM*<92?#x&SlneEAaSW-rwWsea zUxNWhGxwY0x$EBl-*G4{>Cwr_drf{W5c#0`hwVzkIle8tCZT>F4=0v1PN}_6Fv(TS zfx$I{xj4D6_xB2=M{18V8Q1WAJo4w$4b=k-Q}ekOXA3Rg1hjy`)78&qol^p169AaX BarOWJ diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/page_white_code.png b/www/plugins/enluminures_typographiques_v3/icones_barre/page_white_code.png index 0c76bd1297751b66230f74719504b2adb02b1615..8251109800cbd93e135c00781397e0aa386872a3 100644 GIT binary patch delta 508 zcmVL}p!ov)J@9(-%9z88>Q z>TE9W2;BT=;eXn;3DXG)!ky4QY}@_^ICJ+$b^f&xt?ZbPHgqU<%%Kj9OF1Z;!(T6#(?5?D}T6vs4EG{*W=I y2EzcVbJ>CdGR6sK&vyCWJ5(nKLew!;q0C>ln~T?%SXfd30000-EbU|iI@C<1hm1nZB(mO_9n{ZGIU*sBuPwAsZ>B8NvG3I zNl>6$HJ0o_0)I*rf1kYAZV`E=Mdv;$!e7guv zby$$ss+ispLF?n0BKEQ>Ylmh+B404FEf`Bb6~s2V#(&Y7+0tV!Z((eU$NV=DqaQ9{ zS`L#CzTnC0li2V&XU}{oVq)zAoZPH{Dw+Dkf!0UX3fTRv`opF3&@zMYM7HPo;$ben z!C^d^XTiyj9A0JwBvuQMbqBRtjX}w60{RONd;6pDR35``&ROuq`vMZ_0{$8|$wAr# z-a)#JdptTja+l!hu6xjdOJ8s;8E^+=QQ$tw?%p!Hy#YapB=@+^9(46X{{RQg%9y;O RKjr`c002ovPDHLkV1kf}2u}b2 diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/page_white_code_red.png b/www/plugins/enluminures_typographiques_v3/icones_barre/page_white_code_red.png index 87a69145075afd8f8fd8b391c5da1249ec8b2889..d84cb42f735ac6a8e65a59a9e012ce1c7f0d5b32 100644 GIT binary patch delta 494 zcmVN-QtO=W9UicBR?>@iG zyfe8rQ+G6FjrAYyX;w6aDv!rwKAB7|rqd}Fq5J4`I`6KMSbr3b;}}Vj6_tz`A*3T^=7n)OSoXZtfv&J5Yh2ZzTudW^3*1U+mv28-+}TIyY$HAY zWty}SX4he!H>wby-si)m`!F|y@7Ar-kLvx?q0@kWyk}*a>}W^RLhz=Abm$?=GJ?WH z@f053URn3vHsRSDrWqbQxeW7=f&~f!`m*Ty>f5=9D+Pb3u_PC>0;-B0P(qDm!unll k{=GAGmn39ek}_rf0zYVey0c#uyZ`_I07*qoM6N<$f)3E>{Qv*} delta 563 zcmV-30?hq~1j_`FBYyw{XF*Lt006JZHwB960000PbVXQnQ*UN;cVTj606}DLVr3vn zZDD6+Qe|Oed2z{QJOBUz-AP12R5;6xlTT|CK^TW?F9i`VIo5(lFCw%dM-N3B47AjS zG)-F&(yoRUMD&vg$sylBKY#~6ggq4Pp(n8=+w7n0?96U9yMIajIq$?BHzvg{JS@z+ zzh`IOnVADHN66=aWJOZ=4-X~tI+qcw391gEXqY-8y>u5HcAF`6Hpg`du2oQ#$ z#`k@Ao`-I?t0bmrqSb0?NgBRG0{S3|BE)g5-h>bWj4@c2r3C$cAM}%UyFHd<1w-bk za0&@1z&VF)+kaC_Qawopg}V!@;^+{(yrqgkbr(UyK;+nZDURc)nRGgxNx_fDi@A%Z z`BVPt0Q}|lSg^MX(P%&%A0V=>l!RtN{cv6PufTb-xWm^=k#E$&>lGyCg(@bUOYr?F zXxuNagMa>{mP0)ukrw!+HDA0vMsK4yioSoH+_rBg@PA&Ez}~!uS1Vx<3MC=5z|7}% z*ygi{8GCSzO~h9}$1{*K@#)I4j)CofjXS_KXVbqYYK`4!0yV zIPYqRdlr%;QBZhFK)bMfe}2_^Uxig)Q$=_G`8dp69nLZ(NDtD#$kREKn*_gZx(743 z)`CBhyew=`NQK*k<+noJ-i%<0B)7QEDRlLheglw;y?aKWW;y@>002ovPDHLkV1hV8 B|C;~+ diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/petitescapitales.png b/www/plugins/enluminures_typographiques_v3/icones_barre/petitescapitales.png index 9122ea29f3172e7e7aff31ed08d38639436d4c3c..a674ecdb8a34fe72290f913fffa7f76b3a98b4ca 100644 GIT binary patch delta 85 zcmZo;>SCNA!O6tTz`&3+SNzk&$r_G2o-U3d6^zLa4EszS4!ts+Fd@NN;EZ$w%WYwW pg9jNEmxM8LYD~{&oy5Yyz#u5gR=?8GIv=Q?!PC{xWt~$(697F=7}o#* delta 213 zcmeBTY-5@rQP0B6z`*eK?xP?erB~t_QQ};bnpl#VpQjL#nVZT`mYS!hV5yLmm{+E! zU}RumqF`ujWn^w;V632RU}#_vH}m{6picG@PhVH|E3CXC%qDs6{O^E5oCO|{#S9E` z2SJ$eaArs_P>?0v(btiIVPik{pF~z5pJ$?~inp1ki(^Q|t>lCQEN)(G39}+kdPts0 z2uTn)bSNRL&8Ve^MS+J^!Np+8lqnZn9C%b!S#`P+85jygSq~Yv)>;6KVeoYIb6Mw< G&;$Sov^=Q* diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/poesie.png b/www/plugins/enluminures_typographiques_v3/icones_barre/poesie.png index 3c5bbfebfb5cae2df2c485bc180a89c44c0a1e67..f2e85edeaf0d63316df13fde7772a363d6c1de08 100644 GIT binary patch delta 146 zcmV;D0B!%m0j>d%B!6{DL_t(|0lmsC5&;1i0MIuZ81@8`WQ-!Yg5(|)(FG)hq8LB7 z&>TUda05p4+i-wycDC)yPtg(sdoOQ0O+ne#R6|MK(orxm1Z`cZr{JOr4q8@bf`=aX zIvGg>V;>9r0B!7uXL_t(|+P%@Q4nYAJhVkDN<0R1qn4KcI1<57o6wwVxlA_pf z2a@U%PLpUNo91tG6lTZSnRcG|?Rod^-AB$8^h9p%*6N?rm!g%Lj*8IUGMyjkgNByC zH7y*J!A59ioE9$H;Av}+D1S5bFh%@tOPn0`OVueWxziL_m>*;bT}NkgrJUdM0kDAIJ_pbh!>lF_r}R1v5B2yO9Ru xhm&s diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/tag.png b/www/plugins/enluminures_typographiques_v3/icones_barre/tag.png index e093032a77d0b90d3a5dc05759dd6bcc2ad51715..fffef581f77d3c8b15b224101bd7b073349d9485 100644 GIT binary patch delta 270 zcmV+p0rCEY1IPl9BQOCENkla zfAC)X{1`|MuV#^sBY(|$E%zd#SHJvTxb@Y4zgbW3sTbUkMv{{bSoG{3NG@XO^Y1{p z2o%k_4R_hXmp}hlx#JB`!L#40IoFKQEzm5#Wek!l-SqN*;LOJ#6_T#7p(s!Z5xgxuBVkz60eVuzEu=W(GCl`HD2yZ~jL|ovvEWdfoyYn7A7W}6?{9sdi=NL$CG?8Nh0M{6b U5Y|BCFaQ7m07*qoM6N<$f@Kwf*Z=?k delta 351 zcmV-l0igcK0)+#RBYyw{XF*Lt006JZHwB960000PbVXQnQ*UN;cVTj606}DLVr3vn zZDD6+Qe|Oed2z{QJOBUz7fD1xR5;6H`2YVu10|SYm>OW%^N^ox0}MJJ@O#dCdMskq z^A9kwxXrIWcrSi_3?zrw0R6UmLLRf99xK}R`oI6&r}tpuA(3Yfe*^Sd?nOkee)+v{ z>#P5Mv!32lFSsF%BqtrP=-EAxT*T7n-+^)wC@++_=2{`_O*jyFIB&wi`sTr);@ zs%H5uV~||wrkDQ%XFmR@kaUF&#RclcHzPvlKmDGy>cxMLz6bZ@<1R@f$w_-peRK~b z7c}$Hcc5GZ)-X^^RkSt>f)#WU0d$L!@z6Oqk9=Ep8p5Q$wglj!W#=R5f}I^ x%Wod@?z{(&1^+1zKiJgXIR=s&DM^_W3;;)Y*57H=t&IQx002ovPDHLkV1lSep`ic( diff --git a/www/plugins/enluminures_typographiques_v3/icones_barre/text_strikethrough.png b/www/plugins/enluminures_typographiques_v3/icones_barre/text_strikethrough.png index 612058a78eba4e3ca259aa13417fd60cd6cf2fbd..c910b5966fba19beea6655b4a6749501980a2775 100644 GIT binary patch delta 184 zcmV;p07w6g0@MMJB!8PpL_t(2&tqVqCnymtn3z=gu)rZ~&ww8?P*XvPV8P7nwAAv1nUTA(D#&}6RSu#f z$^-vnQIMOK_CL7;!uG&sLb^-B|LFfAGkuN!GuXRewIXtN=xYDK{~rHs&zPYqC@(Gl z4}x=)c?<3@hBy?8{+nng3#UF%;OQng7>^nj-R!zZ^q> rNt*6EwKMYNl4-)_yd5-(3+xa8TRQwd&^dRA00000NkvXXu0mjfctmh? diff --git a/www/plugins/enluminures_typographiques_v3/img_pack/e.gif b/www/plugins/enluminures_typographiques_v3/img_pack/e.gif index 8a27a2077ddde448febf5ed8e72488a6d2b4f7a6..3359bef61a0eb165d1d068838b8d6c088d370da1 100644 GIT binary patch delta 318 zcmV-E0m1&*0@nf%M@dFFIbj$8AOQ0Z0RQ{%kq{(*JqQ5*|M&m@{~`GV1pojK04x9i z000;OAOJuF|M1C4tF35+f`SNyQW(-f9GDgiN#~*Cbuoq}+;^bs11diVgTZ0=;6A!W z=)ov>NS#lpaJ&&16a~Q}O-u>}M+G3n{?6!%NkA}oe+Ez@&H^6_gU>)g$tV|5AR=yC zI|K`V5*a#B9)dAH08UbI1&9xiXOTKNYz71c03~<pGTS-6vgpYuf&;`Q0W4t5h#KII*RmX3e1$W@kAedPRFLdQ QR$!N_k01m?%7_2}JE1sm?*IS* delta 319 zcmV-F0l@y(0@wl&M@dFFIbj$8AOM2^06ho*kq{(*|NHO%|M&m@{~`GV0{{RI04x9i z000;OAOHXa|M1C4tG)Q8v$B5&ArMCLO^S33K`RVIVU!m#JBAPlyxszY6s2Jp6cjlE zVdv5XErtLg5gjB7g+pPW8we?fm$ns@JshFI!Gd5F5X`bcMOZ@v0|eZuFt1`*b`Nbp z3wu(3eI-jRQXMKS1%q*Y1&fSx5)1`9bBAR;Jp>FB2}=T>(j z2cuZ%DqF7-&rLfdF%9u7m=pEi*o;)taq0plgCf}0F~TFrf&&Bvcr4suB-{roSTY{? Ra-yThk01p@iX0gM06WAKZVvze diff --git a/www/plugins/enluminures_typographiques_v3/img_pack/moinecopiste.gif b/www/plugins/enluminures_typographiques_v3/img_pack/moinecopiste.gif index c16f85889127a3bb505cb5c2ddadd85a733449fd..cf44f19527bb5f511b7050ec07941f179c500b51 100644 GIT binary patch delta 1793 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 - + + - + - + - + - + + + + + + + diff --git a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_ar.php b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_ar.php index 97137ab0..5fc9a760 100644 --- a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_ar.php +++ b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_ar.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/enlumtypo?lang_cible=ar // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -41,5 +43,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'tableau_resume' => 'الخلاصة', 'tableau_titre' => 'العنوان' ); - -?> diff --git a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_en.php b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_en.php index 7a293435..32bd8d84 100644 --- a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_en.php +++ b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_en.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/enlumtypo?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -40,5 +42,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'tableau_resume' => 'Summary', 'tableau_titre' => 'Title' ); - -?> diff --git a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_es.php b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_es.php index fa3bd55a..ac005428 100644 --- a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_es.php +++ b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/enlumtypo?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -25,5 +27,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'cfg_puces' => 'Traitement des puces', 'cfg_titraille' => 'Titraille' ); - -?> diff --git a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_fr.php b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_fr.php index 1f77bf2c..07a88aad 100644 --- a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_fr.php +++ b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_fr.php @@ -1,7 +1,9 @@ 'Mettre le texte en <sc>petites capitales</sc>', 'barre_poesie' => 'Mettre en forme comme une <poesie>poésie</poesie>', 'barre_tableau' => 'Insérer/modifier (le sélectionner avant) un tableau', + 'bouton_reinitialiser' => 'Réinitialiser', // C 'cfg_insertcss' => 'Insertion CSS', @@ -38,5 +41,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'tableau_resume' => 'Résumé', 'tableau_titre' => 'Titre' ); - -?> diff --git a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_it.php b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_it.php index c6664760..a949bb91 100644 --- a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_it.php +++ b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_it.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/enlumtypo?lang_cible=it // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -25,5 +27,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'cfg_puces' => 'Traitement des puces', 'cfg_titraille' => 'Titraille' ); - -?> diff --git a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_nl.php b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_nl.php new file mode 100644 index 00000000..c453659f --- /dev/null +++ b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_nl.php @@ -0,0 +1,45 @@ + 'De paragraaf [/rechts uitlijnen/]', + 'barre_alignergauche' => 'De paragraaf [!links uitlijnen!]', + 'barre_avances' => 'Betekenisvol!', + 'barre_barre' => 'De tekst <del>doorstrepen</del>', + 'barre_boutonsavances' => 'Extra betekenisvol, gebruik met mate en inzicht!', + 'barre_cadre' => 'In een <cadre>tekstinvoerveld</cadre> plaatsen', + 'barre_centrer' => 'De paragraaf [|centreren|]', + 'barre_code' => 'In <code>programmeercode</code> plaatsen', + 'barre_encadrer' => 'De paragraaf [(omkaderen)]', + 'barre_exposant' => 'Zet de tekst in <sup>superscript</sup>', + 'barre_formatages_speciaux' => 'Speciale formattering', + 'barre_indice' => 'Zet de tekst in <sub>subscript</sub>', + 'barre_intertitre2' => 'Omzetten in {{{**tussentitel niveau 2}}}', + 'barre_intertitre3' => 'Omzetten in {{{***tussentitel niveau 3}}}', + 'barre_miseenevidence' => 'Maak de tekst [*benadrukt*]', + 'barre_miseenevidence2' => 'Maak de tekst [**benadrukt*] (2e kleur)', + 'barre_petitescapitales' => 'Zet de tekst in <sc>kleine kapitalen</sc>', + 'barre_poesie' => 'Formatteren als <poesie>poesie</poesie>', + 'barre_tableau' => 'Een tabel invoegen/aanpassen (eerst kiezen)', + 'bouton_reinitialiser' => 'Herinitialiseren', + + // C + 'cfg_insertcss' => 'CSS invoegen', + 'cfg_puces' => 'Puntsgewijs', + 'cfg_titraille' => 'Titelkoppen', + 'configuration_typoenluminee' => 'Typografische Verlichting', + + // T + 'tableau_enregistrer' => 'Opslaan', + 'tableau_prem_ligne' => 'Eerste regel', + 'tableau_resume' => 'Samenvatting', + 'tableau_titre' => 'Titel' +); diff --git a/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_ru.php b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_ru.php new file mode 100644 index 00000000..983caa23 --- /dev/null +++ b/www/plugins/enluminures_typographiques_v3/lang/enlumtypo_ru.php @@ -0,0 +1,44 @@ + '[/Выровнять вправо/] абзац', + 'barre_alignergauche' => '[!Выровнять влево!] абзац', + 'barre_avances' => 'Значение, смысл!', + 'barre_barre' => '<del>Зачеркнутый</del> текст', + 'barre_boutonsavances' => 'Эти дополнительные возможности надо использовать умеренно и со смыслом!', + 'barre_cadre' => 'Поместить текст <cadre>в кадр</cadre>', + 'barre_centrer' => '[|Центрировать|] абзац', + 'barre_code' => 'Текст как <code>программный код</code>', + 'barre_encadrer' => '[(Рамка)] вокруг абзаца', + 'barre_exposant' => '<sup>Верхнийм</sup> индекс', + 'barre_formatages_speciaux' => 'Специальные форматы', + 'barre_indice' => '<sub>Нижний</sub> индекс', + 'barre_intertitre2' => 'Заголовок {{{**второго уровня}}}', + 'barre_intertitre3' => 'Заголовок {{{***третьего уровня}}}', + 'barre_miseenevidence' => 'Текст [*подчеркнуть*]', + 'barre_miseenevidence2' => 'Текст [**подчеркнуть*] (другой цвет)', + 'barre_petitescapitales' => 'Сделать <sc>малыми прописными</sc>', + 'barre_poesie' => 'отформатировать как <poesie>поэзию</poesie>', + 'barre_tableau' => 'Вставить/изменить (сначала выберите) таблицу', + + // C + 'cfg_insertcss' => 'Вставить CSS', + 'cfg_puces' => 'Маркеры (для списков)', + 'cfg_titraille' => 'Заголовки', + 'configuration_typoenluminee' => 'Типографские озарения', + + // T + 'tableau_enregistrer' => 'Сохранить', + 'tableau_prem_ligne' => 'Первая строка', + 'tableau_resume' => 'Резюме', + 'tableau_titre' => 'Заголовок' +); diff --git a/www/plugins/enluminures_typographiques_v3/lang/paquet-typoenluminee.xml b/www/plugins/enluminures_typographiques_v3/lang/paquet-typoenluminee.xml new file mode 100644 index 00000000..3fa359fb --- /dev/null +++ b/www/plugins/enluminures_typographiques_v3/lang/paquet-typoenluminee.xml @@ -0,0 +1,4 @@ + + + + diff --git a/www/plugins/enluminures_typographiques_v3/lang/paquet-typoenluminee_fr.php b/www/plugins/enluminures_typographiques_v3/lang/paquet-typoenluminee_fr.php index bfe25838..59f4c48f 100644 --- a/www/plugins/enluminures_typographiques_v3/lang/paquet-typoenluminee_fr.php +++ b/www/plugins/enluminures_typographiques_v3/lang/paquet-typoenluminee_fr.php @@ -1,32 +1,26 @@ 'Ce plugin ajoute des raccourcis typographiques et des boutons au porte plume. Par exemple : --* Paragraphes : --** {{Sous-titres}} {{{**Texte du titre}}}, le nombre d\'étoiles (*) variant de 2 à 5, la barre de raccourcis ne proposant que 2 et 3 --** {{Centrer}} [|Paragraphe centré|] --** {{Aligner à droite}} [/Paragraphe aligné à droite/] --** {{Encadrer}} [(Paragraphe à encadrer)] --* Caractères : --** {{Mise en évidence}} [*texte en évidence*] --** {{Mise en évidence variante}} [**texte en évidence (autre couleur)*] --** {{Mise en exposant}} {<sup>}texte en exposant{</sup>} --** {{Petites capitales}} {<sc>}texte en petite capitales{</sc>} + // T + 'typoenluminee_description' => 'Ce plugin ajoute des raccourcis typographiques et des boutons au porte plume. Par exemple : +-* Paragraphes : +-** {{Sous-titres}} {{{**Texte du titre}}}, le nombre d’étoiles (*) variant de 2 à 5, la barre de raccourcis ne proposant que 2 et 3 +-** {{Centrer}} [|Paragraphe centré|] +-** {{Aligner à droite}} [/Paragraphe aligné à droite/] +-** {{Encadrer}} [(Paragraphe à encadrer)] +-* Caractères : +-** {{Mise en évidence}} [*texte en évidence*] +-** {{Mise en évidence variante}} [**texte en évidence (autre couleur)*] +-** {{Mise en exposant}} {<sup>}texte en exposant{</sup>} +-** {{Petites capitales}} {<sc>}texte en petite capitales{</sc>} -** {{Biffé}} {<del>}texte biffé{</del>} ', - 'typoenluminee_slogan' => 'Plein de raccourcis pour la mise en forme !', + 'typoenluminee_slogan' => 'Plein de raccourcis pour la mise en forme !' ); -?> \ No newline at end of file diff --git a/www/plugins/enluminures_typographiques_v3/paquet.xml b/www/plugins/enluminures_typographiques_v3/paquet.xml index 817ac361..04d9121d 100644 --- a/www/plugins/enluminures_typographiques_v3/paquet.xml +++ b/www/plugins/enluminures_typographiques_v3/paquet.xml @@ -1,12 +1,13 @@ + schema="0.1.0" +> Enluminures typographiques @@ -29,8 +30,8 @@ - + - \ No newline at end of file + diff --git a/www/plugins/enluminures_typographiques_v3/plugin.xml b/www/plugins/enluminures_typographiques_v3/plugin.xml index e9c09ec2..e4e8af74 100644 --- a/www/plugins/enluminures_typographiques_v3/plugin.xml +++ b/www/plugins/enluminures_typographiques_v3/plugin.xml @@ -4,7 +4,9 @@ [Jacques->http://contrib.spip.net/_Jacques-PYRAT_], à partir des raccourcis mis en place par [François->http://contrib.spip.net/_Francois-Schreuer_] © 2007 GNU/GPL http://contrib.spip.net/Enluminures-typographiques-V3-pour-SPIP-2-avec - 3.4.3 + 3.5.8 + 0.1.0 + base/typoenluminee_upgrade.php stable Ce plugin ajoute des raccourcis typographiques et des boutons au porte plume. Par exemple : -* Paragraphes : @@ -70,6 +72,6 @@ enluminures_typo_pipelines.php edition - + diff --git a/www/plugins/enluminures_typographiques_v3/prive/themes/spip/images/typoenluminee-16.png b/www/plugins/enluminures_typographiques_v3/prive/themes/spip/images/typoenluminee-16.png index edb0d98e950ecfb955a3a4e7535944c8e6b69441..223f52dda9a0c1392b6f2f921733e1d9904004fe 100644 GIT binary patch delta 408 zcmV;J0cZZd1hE5K~R<@22UCWUuTwt|Ya6A{Z_0BN#Oz&wvTwvRuh^`+Zp2#E4JBf*x zxbJroNu1!TZHEgSr;QM3K3w2=9+o!qxMmDj{qL}xJVR{b2$9tTc&-~Ppkw(TUhpx} zMH&aH9}y%4;hg?1GE;lO8Qx5)XFeu)CdUZXvu_8qh!Ip@sF`yB00001}xU=*{MnB5t_+1+g1sL==C4uA9Gd;7jO^D!wU6n(3Z*j? z$_5JO298cj_IfgvLO2}8KwsbJb|#am=jqplDg+({QS1nL1qg~KM9w%z%{0-~-Hlj( z|44dgCqP>tbbo)XpjtT|3rb)vfpErWkqCZnZ9x#(L?WRSzxOGqOVByP$?F$j!5}2D z$Vvt6dwD#MM(yyFxh3mpf=-V2?Eh6#T>k;<@)GA&1Huw8DLOkllxepU1T=<)jT}Bs zzp)9F%j?NJc(q~^EshN~{jdqjgXPIr;8W5wcF9#Dq<=v5qSBfmpmWTB{{y|Pjo36; zG)^UAHrd+R9+t*q_b8yGmCtei;;5tLD}`y+S`%oRj=3MZnECY9egm5FU_A#;w_(<5 zSp5>egTTFbdhhr)I|R%&I->VRZ#2&HhIEdHf%(pR3XF0&PtWtEa5}6-zSEh8VdU*; py@^QrQy>~bcsNce_uxu^0RYPC-a0_~<6{5-002ovPDHLkV1n>}1fl={ diff --git a/www/plugins/enluminures_typographiques_v3/prive/themes/spip/images/typoenluminee-32.png b/www/plugins/enluminures_typographiques_v3/prive/themes/spip/images/typoenluminee-32.png index 76fbc360e3371a541b6fd88c37184f5d12e79f83..8b267fe61268347586fbee767b0a381f5eb181cc 100644 GIT binary patch delta 1158 zcmV;11bO?l3YrO!BYy;8Nkl8VaG)V&B`foRJO-)!s1DFGB;TC35jGkG;}I z%fX}gDFI;4aew>v9a>si=}(5?Bh{UO+&k1dnE?p*oAq?k^!QGhC^}U-zbXZuROk<`X1< z#)V5DQX(@90AW#tB@;oZ1m?&^Vp?MA?i8AtfjCAA0F=uuAhEb6G)n{Lu%>1vpX$Pv zF3lIn9Dh7YPGQBhU(nPP^7Hc+5vc#l025|nQ5cvxNXzGtR8YYEBLLK9Y5n;|It`d{ zU!-(0LQ(=Vz!?-h0p}bBsRSXQ>1nW;x_|+ipAe~&)fa0i#B1z@%;lt&Ve8xJmP5y0RfnM zL0eqov;F-j2p`1pcLxB7eaNC%37qkIvZGa9ZGaGl%ptQh!N`smll2L@lU;%!2ownE z+JBn#-OlzF_Ela;pFzTx_-w|V~`P62=u?+t=PE%ulb7K#cu z$KH>|(;kQej0~^mCo`76x(Px6M1};_Djnbc!2gb%qr0Pw1d^!vz=5GPpn@e(slbHp@Btr02!A3D0g8^HqKF^Ocp}*`-lJNT&a2^e-k9)IB@FVP}cos zhGEDk-h|G3Beln}7#|S^XQq?&b+p2exiq4=e|a2akY1f$Bm6_kiobO&%WAdY+8G Y0lYE{HVHRuLjV8(07*qoM6N<$f`peCtpET3 delta 1315 zcmV+;1>E|Y3AGB4BYyxHbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$ z*GWV{RCwCFSIcW$RT%%yoktT>X#;9!l0{}h(uEscM8&3QV(p?LMM9>Xl2{tSjffkO zVo8uj3|J@%{sCIhrb*2tsRR+E)rGFyxGK1i7Nv^_)l52>$A7)|+~e;%=gxGT%K zJPH76x7xI(J^H3GmAuIlS3qq_b3U9vhlNJJtykfl%6@Wjd^avbtXB~q?K z$wVK0v9Lg|PJd3)(Xp}dg{7q%lj-!aMod%#5M|oKot?BX|1M>}xeol{=B!JX_8otP zVzU=X=6!Qo7Hw{3DHe;-*vQD}((>|e=~Su@LryaQ50Hc-lwDt@7srN4g+fgk5K_|3 z^$hjQeMHK#%z8-YBb{{b-k%hY$LYxMaQs>(bLZ5=M1P_dM126Br2QvO(v7cIF(cBP z0npxk0=@6xJ+Eq}GmGfp0DYyw|@h?SOY3?C4P2*TzjBATTEMFmJcmnT&$!aOdzJUtYT$Mkr6 zPRIZt1g8=mo%F|({Uo}&S_9A+z#dpQaO+o6c>s}h^|lGXe=1>uRERe7qh4y6^*DrT zf}lPCs|t*y>B#V40zIAmCx0jd7E|vtL0lIKa7a<~0SMZ$Ba{li zPdg<0k?~C3tC|3>3m_D-C=B7E!aK4XNh?Guy2pU16cUpO1w<<(liw|EI!n)!EYb@G zfR(@X@j4Cm_h=<9!P2<_D}8j-(``~ zHEUR~hM#t^pxNBox*v=Ij@{`GGuj7Sn0sdG2>p!HcfWK@N5wy)fWg}~CBFNSUYoy0 zgNeBA;>{g6-}&?*b7u(RgbHc*)0xvcoOA?0p2CJ)n5~^bsOK=S&t}qQ6pGnYOn<-2 zfP;o1-vNHYqR05e@M48(m%RA{P0ugV!9=`Vf+_@fPr|Q;3u5vDHb$K>zt_T36(>eKRoPuUTKDEAJR3{y!P0{!+Y)laX zdy$Cc+sQbZltF7jncEr`REq+{8GrQ5+=5A9zNd2*oSQxxyc+(S#{TyCg{i8`i%HMy zjN*R*piBg`&Dw4QXrxfI9ftlytHmWEXsZCI10-B~57-SB8nx>E>jHqv+{)V8Uaw9B zJR}AF9YN%F3|0Ld@5dtv>27idf0)LK{^DOx{x7KLtpX77e;T6n-!&Vu%^Ww)vfjT1 Z7yxb*7D=c(opt~K002ovPDHLkV1iwhhW-Em diff --git a/www/plugins/enluminures_typographiques_v3/svn.revision b/www/plugins/enluminures_typographiques_v3/svn.revision index c935c880..a02bb7ac 100644 --- a/www/plugins/enluminures_typographiques_v3/svn.revision +++ b/www/plugins/enluminures_typographiques_v3/svn.revision @@ -1,10 +1,10 @@ -Origine: file:///home/svn/repository/spip-zone/_plugins_/porte_plume_extras/enluminures_typographiques_v3 -Revision: 84614 -Dernier commit: 2014-09-14 23:33:31 +0200 +Origine: file:///home/svn/repository/spip-zone/_plugins_/porte_plume_enluminures_typographiques/trunk +Revision: 99227 +Dernier commit: 2016-08-21 06:04:02 +0200 -file:///home/svn/repository/spip-zone/_plugins_/porte_plume_extras/enluminures_typographiques_v3 -84614 -2014-09-14 23:33:31 +0200 +file:///home/svn/repository/spip-zone/_plugins_/porte_plume_enluminures_typographiques/trunk +99227 +2016-08-21 06:04:02 +0200 \ No newline at end of file diff --git a/www/plugins/enluminures_typographiques_v3/typoenluminee.php b/www/plugins/enluminures_typographiques_v3/typoenluminee.php index 377da47f..68f8788d 100644 --- a/www/plugins/enluminures_typographiques_v3/typoenluminee.php +++ b/www/plugins/enluminures_typographiques_v3/typoenluminee.php @@ -1,286 +1,317 @@ -texte : mettre en exposant le texte selectionne - * texte : mettre en indice le texte selectionne - * - * Styles pour les encadrements a rajouter dans votre feuille de style : - * .texteencadre-spip { - * background: #FFE; - * border-bottom: 2px solid #999999; - * border-left: 1px solid #EEEEEE; - * border-right: 2px solid #999999; - * border-top: 1px solid #EEEEEE; - * padding: .25em; - * } - * .caractencadre-spip { - * border: 1px solid #666; - * padding: 0px .5em 0px .5em; - * } - * - */ - -// Gerer les variables de personnalisation, fonction depreciee sous SPIP 2.0 -// A suivre sur la methode... -if(!function_exists('tester_variable')) { - function tester_variable($var, $val){ - if (!isset($GLOBALS[$var])) $GLOBALS[$var] = $val; - } -} - -function typoenluminee_pre_propre($texte) { - if(!$texte) return $texte; - - static $chercher_raccourcis=NULL; - static $remplacer_raccourcis=NULL; - - if ($chercher_raccourcis===NULL) { - - // tous les elements block doivent etre introduits ici - // pour etre pris en charge par paragrapher - - // Definition des differents intertitres possibles, si pas deja definies - if ((!function_exists('lire_config')) OR (isset($GLOBALS['config_intertitre']))) { - tester_variable('debut_intertitre', '

    '); - tester_variable('fin_intertitre', '

    '); - tester_variable('debut_intertitre_2', '

    '); - tester_variable('fin_intertitre_2', '

    '); - tester_variable('debut_intertitre_3', '
    '); - tester_variable('fin_intertitre_3', '
    '); - tester_variable('debut_intertitre_4', '
    '); - tester_variable('fin_intertitre_4', '
    '); - tester_variable('debut_intertitre_5', ''); - tester_variable('fin_intertitre_5', ''); - } else { - $GLOBALS['debut_intertitre'] = lire_config('bte/titraille1open','

    '); - $GLOBALS['fin_intertitre'] = lire_config('bte/titraille1close','

    '); - $GLOBALS['debut_intertitre_2'] = lire_config('bte/titraille2open','

    '); - $GLOBALS['fin_intertitre_2'] = lire_config('bte/titraille2close','

    '); - $GLOBALS['debut_intertitre_3'] = lire_config('bte/titraille3open','
    '); - $GLOBALS['fin_intertitre_3'] = lire_config('bte/titraille3close','
    '); - $GLOBALS['debut_intertitre_4'] = lire_config('bte/titraille4open','
    '); - $GLOBALS['fin_intertitre_4'] = lire_config('bte/titraille4close','
    '); - $GLOBALS['debut_intertitre_5'] = lire_config('bte/titraille5open',''); - $GLOBALS['fin_intertitre_5'] = lire_config('bte/titraille5close',''); - } - - tester_variable('toujours_paragrapher', false); - - global $debut_intertitre, $fin_intertitre; - global $debut_intertitre_2, $fin_intertitre_2; - global $debut_intertitre_3, $fin_intertitre_3; - global $debut_intertitre_4, $fin_intertitre_4; - global $debut_intertitre_5, $fin_intertitre_5; - - $chercher_raccourcis=array(); - $remplacer_raccourcis=array(); - - /* 9b */ $chercher_raccourcis[]="/(^|[^{])[{][{][{]\*\*\*\*\*(.*)[}][}][}]($|[^}])/SUms"; - /* 9 */ $chercher_raccourcis[]="/(^|[^{])[{][{][{]\*\*\*\*(.*)[}][}][}]($|[^}])/SUms"; - /* 7 */ $chercher_raccourcis[]="/(^|[^{])[{][{][{]\*\*\*(.*)[}][}][}]($|[^}])/SUms"; - /* 5 */ $chercher_raccourcis[]="/(^|[^{])[{][{][{]\*\*(.*)[}][}][}]($|[^}])/SUms"; - /* 3 */ $chercher_raccourcis[]="/(^|[^{])[{][{][{]\*(.*)[}][}][}]($|[^}])/SUms"; - /* 1 */ $chercher_raccourcis[]="/(^|[^{])[{][{][{](.*)[}][}][}]($|[^}])/SUms"; - /* 11 */ $chercher_raccourcis[]="/\{(�|§)\{/S"; # § Pour gerer l'unicode aussi ! - /* 12 */ $chercher_raccourcis[]="/\}(�|§)\}/S"; # ne pas sauvergarder ce fichier en utf8 ! - - /* 9b */ $remplacer_raccourcis[]="\$1\n\n$debut_intertitre_5\$2$fin_intertitre_5\n\n\$3"; - /* 9 */ $remplacer_raccourcis[]="\$1\n\n$debut_intertitre_4\$2$fin_intertitre_4\n\n\$3"; - /* 7 */ $remplacer_raccourcis[]="\$1\n\n$debut_intertitre_3\$2$fin_intertitre_3\n\n\$3"; - /* 5 */ $remplacer_raccourcis[]="\$1\n\n$debut_intertitre_2\$2$fin_intertitre_2\n\n\$3"; - /* 3 */ $remplacer_raccourcis[]="\$1\n\n$debut_intertitre\$2$fin_intertitre\n\n\$3"; - /* 1 */ $remplacer_raccourcis[]="\$1\n\n$debut_intertitre\$2$fin_intertitre\n\n\$3"; - /* 11 */ $remplacer_raccourcis[]=""; - /* 12 */ $remplacer_raccourcis[]=""; - } - - // Conversion des intertitres d'enluminures type {n{titre}n} - // ou n est un nombre en intertitres avec des etoiles type {{{* (avec n etoiles) - // {1{ sera converti en {{{* ; {2{ sera converti en {{{** ; etc. - // Ne faire la recherche que s'il y a au moins un titre ancienne mode a convertir - if (strpos($texte, '{1{')!==false - OR strpos($texte, '{2{')!==false - OR strpos($texte, '{3{')!==false - OR strpos($texte, '{4{')!==false - OR strpos($texte, '{5{')!==false) { - $texte=preg_replace_callback ("/\{(\d)\{(.*)\}(\\1)\}/Ums", - create_function ( - '$matches', - 'return "{{{".str_repeat("*",$matches[1]).trim($matches[2])."}}}";' - ), - $texte); - } - $texte = preg_replace($chercher_raccourcis, $remplacer_raccourcis, $texte); - - return $texte; -} - -function typoenluminee_post_propre($texte) { - if(!$texte) return $texte; - static $cherche1 = NULL; - static $remplace1 = NULL; - if ($cherche1===NULL) { - # Le remplacement des intertitres de premier niveau a deja ete effectue dans inc/texte.php - $cherche1 = array(); - $remplace1 = array(); - $cherche1[] = /* 15 */ ",\[/(.*)/\],Ums"; - $cherche1[] = /* 16 */ ",\[!(.*)!\],Ums"; - $cherche1[] = /* 17 */ ",\[\|(.*)\|\],Ums"; - $cherche1[] = /* 19 */ ",\[\((.*)\)\],Ums"; - $cherche1[] = /* 21 */ "/\[\*\*/S"; - $cherche1[] = /* 21b */ "/\[\*/S"; - $cherche1[] = /* 22 */ "/\*\]/S"; - - $remplace1[] = /* 15 */ "
    $1
    "; - $remplace1[] = /* 16 */ "
    $1
    "; - $remplace1[] = /* 17 */ "
    $1
    "; - $remplace1[] = /* 19 */ "
    $1
    "; - $remplace1[] = /* 21 */ ""; - $remplace1[] = /* 21b */ ""; - $remplace1[] = /* 22 */ ""; - } - $texte = preg_replace($cherche1, $remplace1, $texte); - $texte = paragrapher($texte,$GLOBALS['toujours_paragrapher']); // il faut reparagrapher a cause des raccourcis typo que l'on a ajoute (block div) - return $texte; -} - -function typoenluminee_pre_liens($texte) { - if (!isset($GLOBALS['barre_typo_pas_de_fork_typo']) OR $GLOBALS['barre_typo_pas_de_fork_typo'] === true) - return $texte; - - $texte = str_replace('<-->','↔',$texte); - $texte = str_replace('-->','→',$texte); - - return $texte; -} - -function typoenluminee_pre_typo($texte) { - if(!$texte) return $texte; - static $local_barre_typo_pas_de_fausses_puces = null; - static $chercher_raccourcis; - static $remplacer_raccourcis; - global $debut_italique, $fin_italique; - if (!isset($GLOBALS['barre_typo_pas_de_fork_typo']) OR $GLOBALS['barre_typo_pas_de_fork_typo'] === true) - return $texte; - - if ($local_barre_typo_pas_de_fausses_puces===null){ - // remplace les fausses listes a puce par de vraies ? - // (recherche en debut de lignes - suivi d'un ou plusieurs caracteres blancs, en mode multiligne) - // Mettre $GLOBALS['barre_typo_pas_de_fausses_puces'] = true; dans mes_options.php pour avoir ce comportement - if (isset($GLOBALS['barre_typo_pas_de_fausses_puces'])) { - $local_barre_typo_pas_de_fausses_puces = $GLOBALS['barre_typo_pas_de_fausses_puces']; - } else { - if (function_exists('lire_config')) { - $local_barre_typo_pas_de_fausses_puces = (lire_config('bte/puces','Non') == 'Oui')?true:false; - } - } - global $class_spip; - tester_variable('debut_italique', ""); - tester_variable('fin_italique', ''); - - $chercher_raccourcis = array( - /* 9 */ "/(?','⇔',$texte); - $texte = str_replace('==>','⇒',$texte); - $texte = str_replace('<==','⇐',$texte); - $texte = str_ireplace('(c)','©',$texte); - $texte = str_ireplace('(r)','®',$texte); - $texte = str_ireplace('(tm)','™',$texte); - $texte = str_replace('...','…',$texte); - $texte = preg_replace($chercher_raccourcis, $remplacer_raccourcis, $texte); - /* - Cas particulier pour le gras - Il ne faut pas traiter la mise en gras ici si le texte contient un tableau - */ - if (!preg_match(',.(\|([[:space:]]*{{[^}]+}}[[:space:]]*|<))+.,sS', $texte)) { - $chercher_raccourcisg = array( - /* 7 */ "/(?", - /* 8 */ "" - ); - $texte = preg_replace($chercher_raccourcisg, $remplacer_raccourcisg, $texte); - } - return $texte; -} - -function typoenluminee_post_typo($texte) { - if(!$texte) return $texte; - if (!isset($GLOBALS['barre_typo_pas_de_fork_typo']) OR $GLOBALS['barre_typo_pas_de_fork_typo'] === true) - return $texte; - $texte = str_replace('[^','',$texte); - $texte = str_replace('^]','',$texte); - $texte = str_replace('[**','',$texte); - $texte = str_replace('[*','',$texte); - $texte = str_replace('*]','',$texte); - - // Correction des & en & - $texte = preg_replace('/&([A-Za-z#0-9]*);/','@@@amp:\1:amp@@@',$texte); // echapement des entites html deja presentes - $texte = str_replace('&','&',$texte); - $texte = preg_replace('/@@@amp:([A-Za-z#0-9]*):amp@@@/','&\1;',$texte); - // Raccourci typographique - $texte = str_replace('', '', $texte); - $texte = str_replace('', '', $texte); - $texte = acronymes_traiter_raccourcis($texte); - return $texte; -} - -function typoenluminee_nettoyer_raccourcis_typo($texte){ - $texte = preg_replace(',\{[1-5]\{,','',$texte); - $texte = preg_replace(',\}[1-5]\},','',$texte); - $texte = preg_replace(',\{\{\{\*+,','{{{',$texte); - $texte = str_replace('…','...',$texte); - return $texte; -} - -// traite les raccourcis de la forme [SNCF|societe nationale...] -// reprise du plugin acronymes -if (!function_exists('acronymes_traiter_raccourcis')) { - function acronymes_traiter_raccourcis($letexte){ - $pattern="{\[([^\|\]-]+)\|([^\|\]-]+)\]}"; - preg_match_all ($pattern, $letexte, $tagMatches, PREG_SET_ORDER); - $textMatches = preg_split ($pattern, $letexte); - - $tag_attr=array(); - foreach ($tagMatches as $key => $value) { - $tag_attr[]="".$value[1].""; - } - for ($i = 0; $i < count ($textMatches); $i ++) { - $textMatches [$i] = $textMatches [$i] . $tag_attr [$i]; - } - return implode ("", $textMatches); - } -} - - -?> \ No newline at end of file +texte : mettre en exposant le texte selectionne + * texte : mettre en indice le texte selectionne + * + * Styles pour les encadrements a rajouter dans votre feuille de style : + * .texteencadre-spip { + * background: #FFE; + * border-bottom: 2px solid #999999; + * border-left: 1px solid #EEEEEE; + * border-right: 2px solid #999999; + * border-top: 1px solid #EEEEEE; + * padding: .25em; + * } + * .caractencadre-spip { + * border: 1px solid #666; + * padding: 0px .5em 0px .5em; + * } + */ + +// Gerer les variables de personnalisation, fonction depreciee sous SPIP 2.0 +// A suivre sur la methode... +if (!function_exists('tester_variable')) { + function tester_variable($var, $val) { + if (!isset($GLOBALS[$var])) { + $GLOBALS[$var] = $val; + } + } +} + +function typoenluminee_pre_propre($texte) { + if (!$texte) { + return $texte; + } + + static $chercher_raccourcis = null; + static $remplacer_raccourcis = null; + + if ($chercher_raccourcis === null) { + // tous les elements block doivent etre introduits ici + // pour etre pris en charge par paragrapher + + // Definition des differents intertitres possibles, si pas deja definies + if ((!function_exists('lire_config')) or (isset($GLOBALS['config_intertitre']))) { + tester_variable('debut_intertitre', '

    '); + tester_variable('fin_intertitre', '

    '); + tester_variable('debut_intertitre_2', '

    '); + tester_variable('fin_intertitre_2', '

    '); + tester_variable('debut_intertitre_3', '
    '); + tester_variable('fin_intertitre_3', '
    '); + tester_variable('debut_intertitre_4', '
    '); + tester_variable('fin_intertitre_4', '
    '); + tester_variable('debut_intertitre_5', ''); + tester_variable('fin_intertitre_5', ''); + } else { + $GLOBALS['debut_intertitre'] = lire_config('bte/titraille1open', '

    '); + $GLOBALS['fin_intertitre'] = lire_config('bte/titraille1close', '

    '); + $GLOBALS['debut_intertitre_2'] = lire_config('bte/titraille2open', '

    '); + $GLOBALS['fin_intertitre_2'] = lire_config('bte/titraille2close', '

    '); + $GLOBALS['debut_intertitre_3'] = lire_config('bte/titraille3open', '
    '); + $GLOBALS['fin_intertitre_3'] = lire_config('bte/titraille3close', '
    '); + $GLOBALS['debut_intertitre_4'] = lire_config('bte/titraille4open', '
    '); + $GLOBALS['fin_intertitre_4'] = lire_config('bte/titraille4close', '
    '); + $GLOBALS['debut_intertitre_5'] = lire_config('bte/titraille5open', ''); + $GLOBALS['fin_intertitre_5'] = lire_config('bte/titraille5close', ''); + } + + tester_variable('toujours_paragrapher', false); + + global $debut_intertitre, $fin_intertitre; + global $debut_intertitre_2, $fin_intertitre_2; + global $debut_intertitre_3, $fin_intertitre_3; + global $debut_intertitre_4, $fin_intertitre_4; + global $debut_intertitre_5, $fin_intertitre_5; + + $chercher_raccourcis=array(); + $remplacer_raccourcis=array(); + + /* 9b */ $chercher_raccourcis[] = '/(^|[^{])[{][{][{]\*\*\*\*\*(.*)[}][}][}]($|[^}])/SUms'; + /* 9 */ $chercher_raccourcis[] = '/(^|[^{])[{][{][{]\*\*\*\*(.*)[}][}][}]($|[^}])/SUms'; + /* 7 */ $chercher_raccourcis[] = '/(^|[^{])[{][{][{]\*\*\*(.*)[}][}][}]($|[^}])/SUms'; + /* 5 */ $chercher_raccourcis[] = '/(^|[^{])[{][{][{]\*\*(.*)[}][}][}]($|[^}])/SUms'; + /* 3 */ $chercher_raccourcis[] = '/(^|[^{])[{][{][{]\*(.*)[}][}][}]($|[^}])/SUms'; + /* 1 */ $chercher_raccourcis[] = '/(^|[^{])[{][{][{](.*)[}][}][}]($|[^}])/SUms'; + /* 11 */ $chercher_raccourcis[] = '/\{(�|§)\{/S'; # § Pour gerer l'unicode aussi ! + /* 12 */ $chercher_raccourcis[] = '/\}(�|§)\}/S'; # ne pas sauvergarder ce fichier en utf8 ! + + /* 9b */ $remplacer_raccourcis[] = "\$1\n\n$debut_intertitre_5\$2$fin_intertitre_5\n\n\$3"; + /* 9 */ $remplacer_raccourcis[] = "\$1\n\n$debut_intertitre_4\$2$fin_intertitre_4\n\n\$3"; + /* 7 */ $remplacer_raccourcis[] = "\$1\n\n$debut_intertitre_3\$2$fin_intertitre_3\n\n\$3"; + /* 5 */ $remplacer_raccourcis[] = "\$1\n\n$debut_intertitre_2\$2$fin_intertitre_2\n\n\$3"; + /* 3 */ $remplacer_raccourcis[] = "\$1\n\n$debut_intertitre\$2$fin_intertitre\n\n\$3"; + /* 1 */ $remplacer_raccourcis[] = "\$1\n\n$debut_intertitre\$2$fin_intertitre\n\n\$3"; + /* 11 */ $remplacer_raccourcis[] = ''; + /* 12 */ $remplacer_raccourcis[] = ''; + } + + // Conversion des intertitres d'enluminures type {n{titre}n} + // ou n est un nombre en intertitres avec des etoiles type {{{* (avec n etoiles) + // {1{ sera converti en {{{* ; {2{ sera converti en {{{** ; etc. + // Ne faire la recherche que s'il y a au moins un titre ancienne mode a convertir + if (strpos($texte, '{1{') !== false + or strpos($texte, '{2{') !== false + or strpos($texte, '{3{') !== false + or strpos($texte, '{4{') !== false + or strpos($texte, '{5{') !== false) { + $texte = preg_replace_callback( + '/\{(\d)\{(.*)\}(\\1)\}/Ums', + create_function( + '$matches', + 'return "{{{".str_repeat("*",$matches[1]).trim($matches[2])."}}}";' + ), + $texte + ); + } + $texte = preg_replace($chercher_raccourcis, $remplacer_raccourcis, $texte); + + return $texte; +} + +/** + * Insertion dans le pipeline post_propre (SPIP) + * + * Remplacement de caracteres apres le passage de propre + * + * @param $texte string + * Le texte a modifier + * @return $texte string + */ +function typoenluminee_post_propre($texte) { + if (!$texte) { + return $texte; + } + static $cherche1 = null; + static $remplace1 = null; + if ($cherche1=== null) { + # Le remplacement des intertitres de premier niveau a deja ete effectue dans inc/texte.php + $cherche1 = array(); + $remplace1 = array(); + $cherche1[] = /* 15 */ ',\[/(.*)/\],Ums'; + $cherche1[] = /* 16 */ ',\[!(.*)!\],Ums'; + $cherche1[] = /* 17 */ ',\[\|(.*)\|\],Ums'; + $cherche1[] = /* 19 */ ',\[\((.*)\)\],Ums'; + $cherche1[] = /* 21 */ '/\[\*\*/S'; + $cherche1[] = /* 21b */ '/\[\*/S'; + $cherche1[] = /* 22 */ '/\*\]/S'; + + $remplace1[] = /* 15 */ '
    $1
    '; + $remplace1[] = /* 16 */ '
    $1
    '; + $remplace1[] = /* 17 */ '
    $1
    '; + $remplace1[] = /* 19 */ '
    $1
    '; + $remplace1[] = /* 21 */ ''; + $remplace1[] = /* 21b */ ''; + $remplace1[] = /* 22 */ ''; + } + $texte = preg_replace($cherche1, $remplace1, $texte); + $texte = paragrapher($texte, $GLOBALS['toujours_paragrapher']); // il faut reparagrapher a cause des raccourcis typo que l'on a ajoute (block div) + return $texte; +} + +function typoenluminee_pre_liens($texte) { + if (!isset($GLOBALS['barre_typo_pas_de_fork_typo']) or $GLOBALS['barre_typo_pas_de_fork_typo'] === true) { + return $texte; + } + + $texte = str_replace('<-->', '↔', $texte); + $texte = str_replace('-->', '→', $texte); + + return $texte; +} + +function typoenluminee_pre_typo($texte) { + if (!$texte) { + return $texte; + } + static $local_barre_typo_pas_de_fausses_puces = null; + static $chercher_raccourcis; + static $remplacer_raccourcis; + + if (!isset($GLOBALS['barre_typo_pas_de_fork_typo']) or $GLOBALS['barre_typo_pas_de_fork_typo'] === true) { + return $texte; + } + + if ($local_barre_typo_pas_de_fausses_puces === null) { + // remplace les fausses listes a puce par de vraies ? + // (recherche en debut de lignes - suivi d'un ou plusieurs caracteres blancs, en mode multiligne) + // Mettre $GLOBALS['barre_typo_pas_de_fausses_puces'] = true; dans mes_options.php pour avoir ce comportement + if (isset($GLOBALS['barre_typo_pas_de_fausses_puces'])) { + $local_barre_typo_pas_de_fausses_puces = $GLOBALS['barre_typo_pas_de_fausses_puces']; + } else { + if (function_exists('lire_config')) { + $local_barre_typo_pas_de_fausses_puces = (lire_config('bte/puces', 'Non') == 'Oui') ? true : false; + } + } + } + + if ($local_barre_typo_pas_de_fausses_puces === true) { + $texte = preg_replace('/^-\s+/m', '-* ', $texte); + } + + $texte = str_replace('<--', '←', $texte); + $texte = str_replace('<==>', '⇔', $texte); + $texte = str_replace('==>', '⇒', $texte); + $texte = str_replace('<==', '⇐', $texte); + $texte = str_ireplace('(c)', '©', $texte); + $texte = str_ireplace('(r)', '®', $texte); + $texte = str_ireplace('(tm)', '™', $texte); + $texte = str_replace('...', '…', $texte); + + global $debut_italique, $fin_italique,$class_spip; + /* + Cas particulier pour le gras + Il ne faut pas traiter la mise en gras ici si le texte contient un tableau + */ + if (!preg_match(',.(\|([[:space:]]*{{[^}]+}}[[:space:]]*|<))+.,sS', $texte)) { + $chercher_raccourcisg = array( + /* 7 */ '/(?", + /* 8 */ '' + ); + $texte = preg_replace($chercher_raccourcisg, $remplacer_raccourcisg, $texte); + } + + + /** + * Remplacer les { ... } par + * On passe après les gras pour que la regexp ne matche pas {{ ... }} + */ + tester_variable('debut_italique', ""); + tester_variable('fin_italique', ''); + $chercher_raccourcis = array( + /* 9 */ '/(?', $texte); + $texte = str_replace('^]', '', $texte); + $texte = str_replace('[**', '', $texte); + $texte = str_replace('[*', '', $texte); + $texte = str_replace('*]', '', $texte); + + // Correction des & en & + $texte = preg_replace('/&([A-Za-z#0-9]*);/', '@@@amp:\1:amp@@@', $texte); // echapement des entites html deja presentes + $texte = str_replace('&', '&', $texte); + $texte = preg_replace('/@@@amp:([A-Za-z#0-9]*):amp@@@/', '&\1;', $texte); + // Raccourci typographique + $texte = str_replace('', '', $texte); + $texte = str_replace('', '', $texte); + $texte = acronymes_traiter_raccourcis($texte); + return $texte; +} + +function typoenluminee_nettoyer_raccourcis_typo($texte) { + $texte = preg_replace(',\{[1-5]\{,', '', $texte); + $texte = preg_replace(',\}[1-5]\},', '', $texte); + $texte = preg_replace(',\{\{\{\*+,', '{{{', $texte); + $texte = str_replace('…', '...', $texte); + return $texte; +} + +// traite les raccourcis de la forme [SNCF|societe nationale...] +// reprise du plugin acronymes +if (!function_exists('acronymes_traiter_raccourcis')) { + function acronymes_traiter_raccourcis($letexte) { + $pattern = '{\[([^\|\]-]+)\|([^\|\]-]+)\]}'; + if (preg_match_all($pattern, $letexte, $tagMatches, PREG_SET_ORDER)) { + $textMatches = preg_split($pattern, $letexte); + + $tag_attr=array(); + foreach ($tagMatches as $key => $value) { + $tag_attr[] = "".$value[1].''; + } + for ($i = 0; $i < count($tag_attr); $i ++) { + $textMatches [$i] = $textMatches [$i] . $tag_attr [$i]; + } + return implode('', $textMatches); + } else { + return $letexte; + } + } +} diff --git a/www/plugins/enluminures_typographiques_v3/typoenluminee_administrations.php b/www/plugins/enluminures_typographiques_v3/typoenluminee_administrations.php new file mode 100644 index 00000000..2cc27c8f --- /dev/null +++ b/www/plugins/enluminures_typographiques_v3/typoenluminee_administrations.php @@ -0,0 +1,59 @@ + $article) { + $id_article = $article['id_article']; + $article['texte'] = preg_replace('/({1{)(.*)(}1})/Uims', '{{{\\2}}}', $article['texte']); + $article['texte'] = preg_replace('/({2{)(.*)(}2})/Uims', '{{{**\\2}}}', $article['texte']); + $article['texte'] = preg_replace('/({3{)(.*)(}3})/Uims', '{{{***\\2}}}', $article['texte']); + $article['texte'] = preg_replace('/({4{)(.*)(}4})/Uims', '{{{****\\2}}}', $article['texte']); + $article['texte'] = preg_replace('/({5{)(.*)(}5})/Uims', '{{{*****\\2}}}', $article['texte']); + $article['texte'] = trim($article['texte']); + sql_updateq('spip_articles', array('texte' => $article['texte']), 'id_article='.intval($article['id_article'])); + if (time() >= _TIME_OUT) { + return; + } + } +} + + +/** + * Desinstallation + * + * @param string $nom_meta_base_version + */ +function typoenluminee_vider_tables($nom_meta_base_version) { + include_spip('inc/meta'); + effacer_meta($nom_meta_base_version); +} diff --git a/www/plugins/enluminures_typographiques_v3/typoenluminee_options.php b/www/plugins/enluminures_typographiques_v3/typoenluminee_options.php index 9f2dce06..57b58e0d 100644 --- a/www/plugins/enluminures_typographiques_v3/typoenluminee_options.php +++ b/www/plugins/enluminures_typographiques_v3/typoenluminee_options.php @@ -1,11 +1,17 @@ -, , , et
    -// dans le nom/signature d'un auteur. -// par défaut, est toujours autorisé. -// Cf : http://www.spip.net/fr_article5666.html -// Cf : http://core.spip.org/projects/spip/repository/revisions/21016 à 21018 -if (!defined('_TAGS_NOM_AUTEUR')) define('_TAGS_NOM_AUTEUR', 'b, i, em, sc, br'); - -?> \ No newline at end of file +, , , et
    + * dans le nom/signature d'un auteur. + * + * Par defaut, est toujours autorise. + * Cf : http://www.spip.net/fr_article5666.html + * Cf : http://core.spip.org/projects/spip/repository/revisions/21016 a 21018 + */ +if (!defined('_TAGS_NOM_AUTEUR')) { + define('_TAGS_NOM_AUTEUR', 'b, i, em, sc, br'); +} diff --git a/www/plugins/enluminures_typographiques_v3/typoenluminee_pipelines.php b/www/plugins/enluminures_typographiques_v3/typoenluminee_pipelines.php index cac292e8..249ed268 100644 --- a/www/plugins/enluminures_typographiques_v3/typoenluminee_pipelines.php +++ b/www/plugins/enluminures_typographiques_v3/typoenluminee_pipelines.php @@ -1,30 +1,33 @@ - du document (#INSERT_HEAD) -function TypoEnluminee_insert_head_css($flux) { - static $done = false; - if (!$done) { - $done = true; - if (isset($GLOBALS['BarreTypoEnrichie_Preserve_Header']) OR !function_exists('lire_config')) - global $BarreTypoEnrichie_Preserve_Header; - else - $BarreTypoEnrichie_Preserve_Header = lire_config('bte/insertcss','Oui'); - if ($BarreTypoEnrichie_Preserve_Header == 'Oui') - $flux .= "\n".''; - } - return $flux; -} - -// insert le css pour les styles supplementaires de la BTE dans le du document (#INSERT_HEAD) -function TypoEnluminee_insert_head($flux) { - $flux = TypoEnluminee_insert_head_css($flux); - return $flux; -} -function TypoEnluminee_header_prive($texte) { - $texte.= '' . "\n"; - $texte.= '' . "\n"; - return $texte; -} - -?> \ No newline at end of file + du document (#INSERT_HEAD) +function TypoEnluminee_insert_head_css($flux) { + static $done = false; + if (!$done) { + $done = true; + if (isset($GLOBALS['BarreTypoEnrichie_Preserve_Header']) or !function_exists('lire_config')) { + global $BarreTypoEnrichie_Preserve_Header; + } else { + $BarreTypoEnrichie_Preserve_Header = lire_config('bte/insertcss', 'Oui'); + } + if ($BarreTypoEnrichie_Preserve_Header == 'Oui') { + $flux .= "\n".''; + } + } + return $flux; +} + +// insert le css pour les styles supplementaires de la BTE dans le du document (#INSERT_HEAD) +function TypoEnluminee_insert_head($flux) { + $flux = TypoEnluminee_insert_head_css($flux); + return $flux; +} +function TypoEnluminee_header_prive($texte) { + $texte.= '' . "\n"; + $texte.= '' . "\n"; + return $texte; +} diff --git a/www/plugins/facteur/classes/facteur.php b/www/plugins/facteur/classes/facteur.php index daedf1e2..5a8decd5 100755 --- a/www/plugins/facteur/classes/facteur.php +++ b/www/plugins/facteur/classes/facteur.php @@ -19,7 +19,28 @@ if (!class_exists('PHPMailer')) { include_spip('facteur_fonctions'); +/** + * Wrapper de spip_log pour par PHPMailer + * @param $message + * @param $level + */ +function facteur_log_debug($message,$level){ + spip_log("$level: ".trim($message),"facteur"._LOG_DEBUG); +} + + class Facteur extends PHPMailer { + /** + * From force si From pas dans le bon domaine + * @var string + */ + public $ForceFrom = ''; + + /** + * FromName force si From pas dans le bon domaine + * @var string + */ + public $ForceFromName = ''; /** * @param $email @@ -29,44 +50,65 @@ class Facteur extends PHPMailer { * @param array $options * */ - function Facteur($email, $objet, $message_html, $message_texte, $options = array()) { - $defaut = array( - 'adresse_envoi' => $GLOBALS['meta']['facteur_adresse_envoi'], - 'adresse_envoi_email' => $GLOBALS['meta']['facteur_adresse_envoi_email'], - 'adresse_envoi_nom' => $GLOBALS['meta']['facteur_adresse_envoi_nom'], - 'cc' => $GLOBALS['meta']['facteur_cc'], - 'bcc' => $GLOBALS['meta']['facteur_bcc'], - 'smtp' => $GLOBALS['meta']['facteur_smtp'], - 'smtp_host' => $GLOBALS['meta']['facteur_smtp_host'], - 'smtp_port' => $GLOBALS['meta']['facteur_smtp_port'], - 'smtp_auth' => $GLOBALS['meta']['facteur_smtp_auth'], - 'smtp_username' => $GLOBALS['meta']['facteur_smtp_username'], - 'smtp_password' => $GLOBALS['meta']['facteur_smtp_password'], - 'smtp_secure' => $GLOBALS['meta']['facteur_smtp_secure'], - 'smtp_sender' => $GLOBALS['meta']['facteur_smtp_sender'], - 'filtre_images' => $GLOBALS['meta']['facteur_filtre_images'], - 'filtre_iso_8859' => $GLOBALS['meta']['facteur_filtre_iso_8859'], - ); + public function __construct($email, $objet, $message_html, $message_texte, $options = array()) { + // On récupère toutes les options par défaut depuis le formulaire de config + $defaut = array(); + foreach (array( + 'adresse_envoi', 'adresse_envoi_email', 'adresse_envoi_nom', 'forcer_from', + 'cc', 'bcc', + 'smtp', 'smtp_host', 'smtp_port', 'smtp_auth', + 'smtp_username', 'smtp_password', 'smtp_secure', 'smtp_sender', + 'filtre_images', 'filtre_iso_8859', + ) as $config) { + $defaut[$config] = isset($GLOBALS['meta']["facteur_$config"]) ? $GLOBALS['meta']["facteur_$config"] : ''; + } + // On fusionne les options avec d'éventuelles surcharges lors de l'appel $options = array_merge($defaut, $options); + // par defaut on log rien car tres verbeux + // on utilise facteur_log_debug qui filtre log SPIP en _LOG_DEBUG + $this->SMTPDebug = 0; + $this->Debugoutput = "facteur_log_debug"; + // Il est possible d'avoir beaucoup plus de logs avec 2, 3 ou 4, ce qui logs les échanges complets avec le serveur + // utiliser avec un define('_MAX_LOG',1000); car sinon on est limite a 100 lignes par hit et phpMailer est tres verbeux if (defined('_FACTEUR_DEBUG_SMTP')) { $this->SMTPDebug = _FACTEUR_DEBUG_SMTP ; } - if ($options['adresse_envoi'] == 'oui' - AND $options['adresse_envoi_email']) + $this->exceptions = false; + + + if ( + $options['adresse_envoi'] == 'oui' + and $options['adresse_envoi_email'] + ) { $this->From = $options['adresse_envoi_email']; - else - $this->From = (isset($GLOBALS['meta']["email_envoi"]) AND $GLOBALS['meta']["email_envoi"])? + } + else { + $this->From = (isset($GLOBALS['meta']["email_envoi"]) AND $GLOBALS['meta']["email_envoi"]) ? $GLOBALS['meta']["email_envoi"] - :$GLOBALS['meta']['email_webmaster']; + : $GLOBALS['meta']['email_webmaster']; + } // Si plusieurs emails dans le from, pas de Name ! - if (strpos($this->From,",")===false){ - if ($options['adresse_envoi'] == 'oui' - AND $options['adresse_envoi_nom']) + if (strpos($this->From,",") === false) { + if ( + $options['adresse_envoi'] == 'oui' + and $options['adresse_envoi_nom'] + ) { $this->FromName = $options['adresse_envoi_nom']; - else + } + // Par défaut, l'envoyeur est le nom du site + else { $this->FromName = strip_tags(extraire_multi($GLOBALS['meta']['nom_site'])); + } + } + + // si forcer_from, on sauvegarde le From et FromName par defaut, qui seront utilises + // si From n'est pas dans le meme domaine + // (utiliser le facteur avec un service externe qui necessite la validation des domaines d'envoi) + if ($options['forcer_from']=='oui'){ + $this->ForceFrom = $this->From; + $this->ForceFromName = $this->FromName; } $this->CharSet = "utf-8"; @@ -76,32 +118,38 @@ class Facteur extends PHPMailer { //Pour un envoi multiple de mail, $email doit être un tableau avec les adresses. if (is_array($email)) { foreach ($email as $cle => $adresseMail) { - if (!$this->AddAddress($adresseMail)) - spip_log("Erreur AddAddress $adresseMail : ".print_r($this->ErrorInfo,true),'facteur'); + if (!$this->AddAddress($adresseMail)) { + spip_log("Erreur AddAddress $adresseMail : ".print_r($this->ErrorInfo, true), 'facteur.'._LOG_ERREUR); + } } } - else - if (!$this->AddAddress($email)) - spip_log("Erreur AddAddress $email : ".print_r($this->ErrorInfo,true),'facteur'); + elseif (!$this->AddAddress($email)) { + spip_log("Erreur AddAddress $email : ".print_r($this->ErrorInfo, true), 'facteur.'._LOG_ERREUR); + } + // Retour des erreurs if (!empty($options['smtp_sender'])) { $this->Sender = $options['smtp_sender']; $this->AddCustomHeader("Errors-To: ".$this->Sender); } + // Destinataires en copie, seulement s'il n'y a pas de destinataire de test if (!defined('_TEST_EMAIL_DEST')){ if (!empty($options['cc'])) { - $this->AddCC( $options['cc'] ); + $this->AddCC($options['cc']); } if (!empty($options['bcc'])) { - $this->AddBCC( $options['bcc'] ); + $this->AddBCC($options['bcc']); } } + // Si on envoie avec un SMTP explicite if (isset($options['smtp']) AND $options['smtp'] == 'oui') { $this->Mailer = 'smtp'; $this->Host = $options['smtp_host']; $this->Port = $options['smtp_port']; + + // SMTP authentifié if ($options['smtp_auth'] == 'oui') { $this->SMTPAuth = true; $this->Username = $options['smtp_username']; @@ -110,55 +158,85 @@ class Facteur extends PHPMailer { else { $this->SMTPAuth = false; } - if (intval(phpversion()) == 5) { - if ($options['smtp_secure'] == 'ssl') + + if ($options['smtp_secure'] == 'ssl') { $this->SMTPSecure = 'ssl'; - if ($options['smtp_secure'] == 'tls') + } + if ($options['smtp_secure'] == 'tls') { $this->SMTPSecure = 'tls'; } + + // Pour le moment on remet l'ancien fonctionnement : + // on ne doit pas tester les certificats si pas demandé explicitement avec l'option TLS ! + $this->SMTPAutoTLS = false; } + // S'il y a un contenu HTML if (!empty($message_html)) { - $message_html = unicode_to_utf_8(charset2unicode($message_html,$GLOBALS['meta']['charset'])); + $message_html = unicode_to_utf_8(charset2unicode($message_html, $GLOBALS['meta']['charset'])); + $this->Body = $message_html; $this->IsHTML(true); - if ($options['filtre_images']) + if ($options['filtre_images']) { $this->JoindreImagesHTML(); + } + $this->UrlsAbsolues(); } + + // S'il y a un contenu texte brut if (!empty($message_texte)) { - $message_texte = unicode_to_utf_8(charset2unicode($message_texte,$GLOBALS['meta']['charset'])); + $message_texte = unicode_to_utf_8(charset2unicode($message_texte, $GLOBALS['meta']['charset'])); + + // Si pas de HTML on le remplace en tant que contenu principal if (!$this->Body) { $this->IsHTML(false); $this->Body = $message_texte; } + // Sinon on met le texte brut en contenu alternatif else { $this->AltBody = $message_texte; } } - if ($options['filtre_iso_8859']) + if ($options['filtre_iso_8859']) { $this->ConvertirUtf8VersIso8859(); + } + } + /** + * @param bool $exceptions + */ + public function SetExceptions($exceptions){ + $this->exceptions = ($exceptions?true:false); } - - /* + + /** * Transforme du HTML en texte brut, mais proprement * utilise le filtre facteur_mail_html2text * @uses facteur_mail_html2text() * * @param string $html Le HTML à transformer + * @param bool $advanced Inutilisé * @return string Retourne un texte brut formaté correctement */ - function html2text($html){ + public function html2text($html, $advanced = false){ return facteur_mail_html2text($html); } - + + /** + * Compat ascendante, obsolete + * @deprecated + */ + public function ConvertirStylesEnligne() { + $this->Body = facteur_convertir_styles_inline($this->Body); + } + /** * Transformer les urls des liens et des images en url absolues * sans toucher aux images embarquees de la forme "cid:..." */ - function UrlsAbsolues($base=null){ + protected function UrlsAbsolues($base=null){ include_spip('inc/filtres_mini'); if (preg_match_all(',(<(a|link)[[:space:]]+[^<>]*href=["\']?)([^"\' ><[:space:]]+)([^<>]*>),imsS', $this->Body, $liens, PREG_SET_ORDER)) { @@ -182,7 +260,10 @@ class Facteur extends PHPMailer { } } - function JoindreImagesHTML() { + /** + * Embed les images HTML dans l'email + */ + protected function JoindreImagesHTML() { $image_types = array( 'gif' => 'image/gif', 'jpg' => 'image/jpeg', @@ -202,6 +283,7 @@ class Facteur extends PHPMailer { $adresse_site = $GLOBALS['meta']['adresse_site'].'/'; foreach($images as $im){ + $im = array_pad($im, 6, null); $src_orig = $im[1].$im[4].$im[5]; if (!isset($src_found[$src_orig])){ // deja remplace ? rien a faire (ie la meme image presente plusieurs fois) // examiner le src et voir si embedable @@ -234,14 +316,12 @@ class Facteur extends PHPMailer { /** - * Compat ascendante, obsolete + * Conversion safe d'un texte utf en isotruc + * @param string $text + * @param string $mode + * @return string */ - function ConvertirStylesEnligne() { - $this->Body = facteur_convertir_styles_inline($this->Body); - } - - - function safe_utf8_decode($text,$mode='texte_brut') { + protected function safe_utf8_decode($text,$mode='texte_brut') { if (!is_utf8($text)) return ($text); @@ -259,7 +339,10 @@ class Facteur extends PHPMailer { } } - function ConvertirUtf8VersIso8859() { + /** + * Convertir tout le mail utf en isotruc + */ + protected function ConvertirUtf8VersIso8859() { $this->CharSet = 'iso-8859-1'; $this->Body = str_ireplace('charset=utf-8', 'charset=iso-8859-1', $this->Body); $this->Body = $this->safe_utf8_decode($this->Body,'html'); @@ -268,7 +351,10 @@ class Facteur extends PHPMailer { $this->FromName = $this->safe_utf8_decode($this->FromName); } - function ConvertirAccents() { + /** + * Convertir les accents du body en entites html + */ + protected function ConvertirAccents() { // tableau à compléter au fur et à mesure $cor = array( 'à' => 'à', @@ -292,56 +378,79 @@ class Facteur extends PHPMailer { $this->Body = strtr($this->Body, $cor); } - public function Send() { - ob_start(); - $retour = parent::Send(); - $error = ob_get_contents(); - ob_end_clean(); - if( !empty($error) ) { - spip_log("Erreur Facteur->Send : $error",'facteur.err'); + + + /** + * Une fonction wrapper pour appeler une methode de phpMailer + * en recuperant l'erreur eventuelle, en la loguant via SPIP et en lancant une exception si demandee + * @param string $function + * @param array $args + * @return bool + * @throws phpmailerException + */ + protected function callWrapper($function,$args){ + $exceptions = $this->exceptions; + $this->exceptions = true; + try { + $retour = call_user_func_array($function,$args); + $this->exceptions = $exceptions; } + catch (phpmailerException $exc) { + spip_log((is_array($function)?implode('::',$function):$function)."() : ".$exc->getMessage(),'facteur.'._LOG_ERREUR); + $this->exceptions = $exceptions; + if ($this->exceptions) { + throw $exc; + } + return false; + } + if ($this->ErrorInfo){ + spip_log($function."() : ".$this->ErrorInfo,'facteur.'._LOG_ERREUR); + } + return $retour; } - public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { - ob_start(); - $retour = parent::AddAttachment($path, $name, $encoding, $type); - $error = ob_get_contents(); - ob_end_clean(); - if( !empty($error) ) { - spip_log("Erreur Facteur->AddAttachment : $error",'facteur.err'); + + /* + * Appel des fonctions parents via le callWrapper qui se charge de loger les erreurs + */ + + /** + * Avant le Send() on force le From si besoin + * @return bool + * @throws phpmailerException + */ + public function Send() { + if ($this->ForceFrom + AND $this->From!==$this->ForceFrom){ + $forcedomain = explode('@',$this->ForceFrom); + $forcedomain = end($forcedomain); + $domain = explode('@',$this->From); + $domain = end($domain); + if ($domain!==$forcedomain){ + // le From passe en ReplyTo + $this->AddReplyTo($this->From,$this->FromName); + // on force le From + $this->From = $this->ForceFrom; + $this->FromName = $this->ForceFromName; + } } - return $retour; + $args = func_get_args(); + return $this->callWrapper(array('parent','Send'),$args); + } + public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') { + $args = func_get_args(); + return $this->callWrapper(array('parent','AddAttachment'),$args); } public function AddReplyTo($address, $name = '') { - ob_start(); - $retour = parent::AddReplyTo($address, $name); - $error = ob_get_contents(); - ob_end_clean(); - if( !empty($error) ) { - spip_log("Erreur Facteur->AddReplyTo : $error",'facteur.err'); - } - return $retour; + $args = func_get_args(); + return $this->callWrapper(array('parent','AddReplyTo'),$args); } public function AddBCC($address, $name = '') { - ob_start(); - $retour = parent::AddBCC($address, $name); - $error = ob_get_contents(); - ob_end_clean(); - if( !empty($error) ) { - spip_log("Erreur Facteur->AddBCC : $error",'facteur.err'); - } - return $retour; + $args = func_get_args(); + return $this->callWrapper(array('parent','AddBCC'),$args); } public function AddCC($address, $name = '') { - ob_start(); - $retour = parent::AddCC($address, $name); - $error = ob_get_contents(); - ob_end_clean(); - if( !empty($error) ) { - spip_log("Erreur Facteur->AddCC : $error",'facteur.err'); - } - return $retour; + $args = func_get_args(); + return $this->callWrapper(array('parent','AddCC'),$args); } } - -?> diff --git a/www/plugins/facteur/emails/test_email_html.html b/www/plugins/facteur/emails/test_email_html.html index 481b417b..75760b25 100755 --- a/www/plugins/facteur/emails/test_email_html.html +++ b/www/plugins/facteur/emails/test_email_html.html @@ -1,28 +1,27 @@ #HTTP_HEADER{Content-Type:text/html} -#INCLURE{fond=emails/inc-haut} + +

    <:facteur:corps_email_de_test:>

    -

    <:facteur:corps_email_de_test:>

    +

    <:facteur:version_html:>

    -

    <:facteur:version_html:>

    + + [(#TEXTE|image_reduire{550,0})] +
    + [(#NOTES|image_reduire{550,0})] + + + [(#TEXTE|image_reduire{550,0})] +
    + [(#NOTES|image_reduire{550,0})] + + - - [(#TEXTE|image_reduire{550,0})] -
    - [(#NOTES|image_reduire{550,0})] - - - [(#TEXTE|image_reduire{550,0})] -
    - [(#NOTES|image_reduire{550,0})] - - + + [(#MODELE{img}|image_reduire{550,0})] + - - [(#MODELE{img}|image_reduire{550,0})] - - - - [(#MODELE{doc}|image_reduire{550,0})] - - -#INCLURE{fond=emails/inc-bas} \ No newline at end of file + + [(#MODELE{doc}|image_reduire{550,0})] + + +#FILTRE{facteur_email_wrap_to_html} diff --git a/www/plugins/facteur/emails/texte.html b/www/plugins/facteur/emails/texte.html index 3ae51b65..d1694549 100644 --- a/www/plugins/facteur/emails/texte.html +++ b/www/plugins/facteur/emails/texte.html @@ -56,11 +56,11 @@ + style="margin: 0;padding: 0;width: 100% !important;background-color: #DDDDDD;">
    [
    (#ENV{intro,''})
    ] + style="margin: 0;padding: 0;height: 100% !important;width: 100% !important;background-color: #DDDDDD;"> - + diff --git a/www/plugins/gis/prive/objets/liste/gis_associer_fonctions.php b/www/plugins/gis/prive/objets/liste/gis_associer_fonctions.php index 891b756d..b3016007 100644 --- a/www/plugins/gis/prive/objets/liste/gis_associer_fonctions.php +++ b/www/plugins/gis/prive/objets/liste/gis_associer_fonctions.php @@ -1,3 +1,7 @@ \ No newline at end of file diff --git a/www/plugins/gis/prive/objets/liste/gis_lies.html b/www/plugins/gis/prive/objets/liste/gis_lies.html index d4950cf8..9065a2e0 100644 --- a/www/plugins/gis/prive/objets/liste/gis_lies.html +++ b/www/plugins/gis/prive/objets/liste/gis_lies.html @@ -24,10 +24,8 @@ diff --git a/www/plugins/gis/prive/objets/liste/gis_lies_fonctions.php b/www/plugins/gis/prive/objets/liste/gis_lies_fonctions.php index 891b756d..b3016007 100644 --- a/www/plugins/gis/prive/objets/liste/gis_lies_fonctions.php +++ b/www/plugins/gis/prive/objets/liste/gis_lies_fonctions.php @@ -1,3 +1,7 @@ \ No newline at end of file diff --git a/www/plugins/gis/prive/squelettes/contenu/gis.html b/www/plugins/gis/prive/squelettes/contenu/gis.html index 101a4a1d..486e20a2 100644 --- a/www/plugins/gis/prive/squelettes/contenu/gis.html +++ b/www/plugins/gis/prive/squelettes/contenu/gis.html @@ -3,7 +3,7 @@ [(#AUTORISER{modifier,gis,#ID_GIS}) [(#URL_ECRIRE{gis_edit,id_gis=#ID_GIS}|icone_verticale{<:gis:texte_modifier_gis:>,gis,edit,right ajax preload})] ] -

    (#TITRE|sinon{<:info_sans_titre:>})[(#CHEMIN_IMAGE{gis-24.png}|balise_img{gis,cadre-icone})]

    +

    (#TITRE|sinon{<:info_sans_titre:>})[(#CHEMIN_IMAGE{gis-24.png}|balise_img{gis,cadre-icone})]

    ],simple fiche_objet})] [(#INCLURE{fond=modeles/carte_gis_preview,id_gis})] diff --git a/www/plugins/gis/prive/style_prive_plugin_gis.html b/www/plugins/gis/prive/style_prive_plugin_gis.html index eb7ea221..271a73ef 100644 --- a/www/plugins/gis/prive/style_prive_plugin_gis.html +++ b/www/plugins/gis/prive/style_prive_plugin_gis.html @@ -8,5 +8,8 @@ #SET{right,#ENV{ltr}|choixsiegal{left,right,left}} /* liste des points exec=gis_tous */ - .gis_tous .onglets_simple .formulaire_recherche { margin-bottom: 0; } + +/* saisie carte */ +.saisie_carte .leaflet-control-layers label { float: none; width: auto; margin-#GET{left}: 0; } +.saisie_carte .leaflet-control.leaflet-draw .leaflet-draw-actions { margin-#GET{left}: 0; margin-#GET{right}: 0; } diff --git a/www/plugins/gis/prive/themes/spip/images/gis-16.png b/www/plugins/gis/prive/themes/spip/images/gis-16.png index b0e5a4cd8271e43ceb57d98fc6573022ee391753..399d41ca6b67a482f65f2b430b8db110e7dde62c 100644 GIT binary patch delta 203 zcmV;+05t!L0{a1wB!9w5L_t(|0b@V|LJW!wVhmUTCxf+Slhi`>6AYHvq$MO48J|!4 zU-UQhJ%a`|1?-$LQQyk{m;6uqBb5p(Gb}Kk+j^+N(`JeY+do@-C{~4rP6aJ_F z&-(BFfWZ{20tR=#kIDa&fY9_Zw-XixOhLZi;{V6~kN@xgpOKp%NgR%ZK&~Kx?Yz8r z6fnpso#*nzr+`^-F-H|11wh|K3d~@@r+|TnA&P+mj{=||69W^B4FFJl>Qt3-X^Q{= N002ovPDHLkV1i=WV_g6M diff --git a/www/plugins/gis/prive/themes/spip/images/gis-24.png b/www/plugins/gis/prive/themes/spip/images/gis-24.png index 6cb9f54090783c3be5461b4ebf5819b2b0f2f23f..25d1e7ef2a3fe740f6c89a68e9a2d27f570cbd3d 100755 GIT binary patch delta 334 zcmV-U0kQtd1>ORX8Gi%-002sU^>Y9K0VPR9K~#7FmD2-ICs6=^@$YQgwr$(CZQH}U z8fUx4${1t};$_j`?$OGsUO2pWB}{9i#B#xvKAQ=xP;*<-!lo=zpK#< z7>uOd*dB?-;e+@f-Z#9_3}6tFmZEzw>YZq7g^&D}Mq~e~;eWMg>0~kwk@fpp!AsH7 zqe=|vhm7Of!k&t@=6JCP8B-=WJrZplOXCwGkfD9K{Jv;wTO@`|LDGYLNw-BuyW;qS zgh7~GuDT&Q+7iVdB+Q%YaYeMXCk+Q)F&YW8C%Wy;+>x>_@<86PQvR_BS%-PcW6tqy zPcGk4VZ$6>>_-@ZVneW+AH+^n_^>IHx2UjpUI>;9M6prWjB#N)Dmw(EZ*psMAUL&X(s%#> z0zpYcK~zYIwUtdz6Hyd~pVO97i>3(;*eYhE(nQ;U5kC?(uz!OkZrm7`Ze5hM|Gt1ylHUs;B7R^3xC&eW&H**xiK@Q!B&cdj0a4%%@N|59+@7DG-vVA_GMOr{ z2n5^hJ*+^Ru79V2`*U-1lS@lW?`CIbrvVlg7Lvvor_q~d_kgd>^`F2mV~m^0WbV4I zi|e|ms`z}qzH~aB0Mb1JRP_V!aCv!o!*Lun#&B4pqoX6hjpIy!s{RJDrBbQbn4qC} zJboUSte>df0QGv4&*#58j>BR3{r-?;S!2N1aRKYuY=8D!^DQ#QkV>VJz-)h{CQcx7cJ1yq0{aCv5C<^izp z72XKxO2Bo?vTWcvFyQ6)dJkIF=JxjX=R_iL3ApBE?i!$~2f$`D8a>kYsFw)<)=Q<* z4`4z>IzGpq0l8dmD-wwe1H&f{P}O~4EgTM?0XAYM4yf0wot>Re!0ApV&!2wB%_28} j16AGlFMv8kv_r^Wd_{TA4_k;>00000NkvXXu0mjf43I=` diff --git a/www/plugins/gis/prive/themes/spip/images/gis-new-16.png b/www/plugins/gis/prive/themes/spip/images/gis-new-16.png index e84098afa5c0b831a1fbd77a593f68d7764b3a3c..19f1de2a1d764a54597b9e767c1465aa096b5deb 100644 GIT binary patch delta 432 zcmV;h0Z;zu1jz%CBYy#qNkl&KXfC` zE;$Q2cpG&4e)e5*`A3tug`=%ox4t%G#td4rWXbE{!-qc{e}4e9`!Z5|_CiKcH^cu3gjo`SWSsym_=>!2+6a z5VWNRw5lA$IJwOA_z|Daw|3H`Ni=ijOqw%i4h_mWp3gZ6T2}^YxRZUCTpqp!r|}a# z2MieSc aeB&)@-L^8Ae3#Pz0000hBYyw^b5ch_0Itp)=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2ipk<4j(TNoDv@Z00HPpL_t(I%bk$FYZGA@$3OQb zp?7IclbaF}QV=u*DvBws_+!>d(7!;PbSolc6zLQv2f>1aU4ON8Rgew^$)M>_e=M58 zdXba1Ce1bGa^>F3>ktR2huVJE=lOp4JdeiTV*!VO{?*6a4MT1W6$lMtG3FPpaZ`&Z z8NjJ>xqQKO-3ik)OOw|>Iul2^Jb4VJb5-7atMTCzbX?~50 - + <:info_rechercher:> ] diff --git a/www/plugins/gis/svn.revision b/www/plugins/gis/svn.revision index fef9aedc..8e0b7bcb 100644 --- a/www/plugins/gis/svn.revision +++ b/www/plugins/gis/svn.revision @@ -1,10 +1,10 @@ Origine: file:///home/svn/repository/spip-zone/_plugins_/gis/trunk -Revision: 95041 -Dernier commit: 2016-02-09 10:02:40 +0100 +Revision: 99295 +Dernier commit: 2016-08-31 06:04:04 +0200 file:///home/svn/repository/spip-zone/_plugins_/gis/trunk -95041 -2016-02-09 10:02:40 +0100 +99295 +2016-08-31 06:04:04 +0200 \ No newline at end of file diff --git a/www/plugins/gis/tests/gis_connect_sql.php b/www/plugins/gis/tests/gis_connect_sql.php index b40ee7eb..6db244c3 100644 --- a/www/plugins/gis/tests/gis_connect_sql.php +++ b/www/plugins/gis/tests/gis_connect_sql.php @@ -3,14 +3,15 @@ // attention avant de lancer ce test ! // le dossier du plugin ne doit pas être un lien symbolique dans /plugins // sous peine de générer un timeout... - + $test = 'gis_connect_sql'; - $remonte = "../"; - while (!is_dir($remonte."ecrire")) + $remonte = '../'; + while (!is_dir($remonte.'ecrire')) { $remonte = "../$remonte"; + } require $remonte.'tests/test.inc'; - find_in_path("./base/connect_sql.php",'',true); + find_in_path('./base/connect_sql.php', '', true); // Les tests @@ -33,14 +34,13 @@ // hop ! on y va $err = array(); - foreach($essais as $f=>$essai) - $err = array_merge(tester_fun($f, $essai),$err); - + foreach ($essais as $f => $essai) { + $err = array_merge(tester_fun($f, $essai), $err); + } + // si le tableau $err est pas vide ca va pas if ($err) { echo ('
    ' . join('', $err) . '
    '); } else { - echo "OK"; + echo 'OK'; } - -?> \ No newline at end of file diff --git a/www/plugins/menus_1/action/editer_menu.php b/www/plugins/menus_1/action/editer_menu.php index b93b43e3..8c60ee99 100644 --- a/www/plugins/menus_1/action/editer_menu.php +++ b/www/plugins/menus_1/action/editer_menu.php @@ -23,7 +23,7 @@ function action_editer_menu_dist($arg=null) { if ($id_menu > 0) $err = menu_set($id_menu); // S'il y a un fichier on tente d'importer son contenu - if ($_FILES['import']){ + if (isset($_FILES['import']) AND $_FILES['import']) { $fichier = $_FILES['import']['tmp_name']; $yaml = ''; lire_fichier($fichier, $yaml); diff --git a/www/plugins/menus_1/action/editer_menus_entree.php b/www/plugins/menus_1/action/editer_menus_entree.php index 8219c83a..80b074ac 100644 --- a/www/plugins/menus_1/action/editer_menus_entree.php +++ b/www/plugins/menus_1/action/editer_menus_entree.php @@ -42,6 +42,8 @@ function action_editer_menus_entree_dist($arg=null) { */ function insert_menus_entree($id_menu) { // Envoyer aux plugins + $champs = array(); + $champs['id_menu'] = $id_menu; $champs = pipeline('pre_insertion', array( 'args' => array( diff --git a/www/plugins/menus_1/action/generer_menus.php b/www/plugins/menus_1/action/generer_menus.php new file mode 100644 index 00000000..3a2ea8d7 --- /dev/null +++ b/www/plugins/menus_1/action/generer_menus.php @@ -0,0 +1,29 @@ + 'oui')); + } + + // Pour chaque menu qui reste, on le génère + foreach ($menus_utiles as $identifiant => $titre) { + objet_inserer('menu', 0, array('identifiant' => $identifiant, 'titre' => $titre)); + } +} diff --git a/www/plugins/menus_1/css/menuspip.css b/www/plugins/menus_1/css/menuspip.css index eeaa2853..1c784446 100644 --- a/www/plugins/menus_1/css/menuspip.css +++ b/www/plugins/menus_1/css/menuspip.css @@ -40,6 +40,7 @@ .formulaire_spip ul.menus_entrees .titre{ font-weight:bold; line-height:29px; + min-height:2em; /* si jamais une entrée est vide/ne contient qu'un seul espace, permet de faire apparaître les boutons admin pour la supprimer */ } .formulaire_spip ul.menus_entrees .infos{ font-size:0.9em; diff --git a/www/plugins/menus_1/formulaires/editer_menu.html b/www/plugins/menus_1/formulaires/editer_menu.html index 55e1a0c4..ffaa9843 100644 --- a/www/plugins/menus_1/formulaires/editer_menu.html +++ b/www/plugins/menus_1/formulaires/editer_menu.html @@ -8,11 +8,11 @@ parametre : url d'action ] #ACTION_FORMULAIRE{#ENV{action}} -
      +
      • <:menus:formulaire_partie_identification:>

        -
          +
            #SET{obli,'obligatoire'} #SET{name,titre} #SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}} @@ -64,11 +64,15 @@ ] +[(#REM) quand le formulaire n'est pas nouveau, on masque le bouton pour ne pas confuser avec les second formulaire en +dessous qui permet d'editer les entrees] +[(#ENV{nouveau}|non) \ No newline at end of file +jQuery(function(){ + jQuery('.formulaire_#ENV{form}'+' .boutons').hide(); + jQuery('.formulaire_#ENV{form}'+' input') + .change(function(){jQuery('.formulaire_#ENV{form}'+' .boutons').slideDown();}) + .keydown(function(){jQuery('.formulaire_#ENV{form}'+' .boutons').slideDown();}); +}); + +] \ No newline at end of file diff --git a/www/plugins/menus_1/formulaires/editer_menu.php b/www/plugins/menus_1/formulaires/editer_menu.php index 66e43b7c..897d4062 100644 --- a/www/plugins/menus_1/formulaires/editer_menu.php +++ b/www/plugins/menus_1/formulaires/editer_menu.php @@ -61,6 +61,8 @@ function formulaires_editer_menu_charger($id_menu, $nouveau){ $contexte['_action'] = array('editer_menu', $id_menu); // On sait toujours si on est sur un menu déjà créé ou pas $contexte['_hidden'] .= ''; + // reinjecter nouveau si besoin, sinon la page de l'espace prive ne reaffiche pas le form + $contexte['_hidden'] .= ""; } } else{ @@ -81,10 +83,10 @@ function formulaires_editer_menu_verifier($id_menu, $nouveau){ $identifiant = _request('identifiant'); // On vérifie que l'identifiant est bon - if (!$erreurs['identifiant'] and !preg_match('/^[\w]+$/', $identifiant)) + if (empty($erreurs['identifiant']) and !preg_match('/^[\w-]+$/', $identifiant)) $erreurs['identifiant'] = _T('menus:erreur_identifiant_forme'); // On vérifie que l'identifiant n'est pas déjà utilisé - if (!$erreurs['identifiant']){ + if (empty($erreurs['identifiant'])) { $deja = sql_getfetsel( 'id_menu', 'spip_menus', diff --git a/www/plugins/menus_1/formulaires/editer_menus_entree.html b/www/plugins/menus_1/formulaires/editer_menus_entree.html index 5c5b3a1f..806a7a95 100644 --- a/www/plugins/menus_1/formulaires/editer_menus_entree.html +++ b/www/plugins/menus_1/formulaires/editer_menus_entree.html @@ -9,7 +9,7 @@ parametre : url d'action ] #ACTION_FORMULAIRE{#ENV{action}} -
              +
              • <:menus:formulaire_partie_construction:>

                @@ -25,7 +25,7 @@ \ No newline at end of file + })(jQuery); + diff --git a/www/plugins/menus_1/formulaires/editer_menus_entree.php b/www/plugins/menus_1/formulaires/editer_menus_entree.php index 474976c1..bde8b15e 100644 --- a/www/plugins/menus_1/formulaires/editer_menus_entree.php +++ b/www/plugins/menus_1/formulaires/editer_menus_entree.php @@ -33,6 +33,17 @@ function formulaires_editer_menus_entree_charger($id_menu,$id_menus_entree='new' // On sait toujours si on est sur un menu déjà créé ou pas $valeurs['_hidden'] .= ''; + // les valeurs retournées par _verifier + $valeurs['entrees'] = ''; + $valeurs['donnees'] = ''; + $valeurs['id_menus_entree'] = ''; + $valeurs['type'] = ''; + $valeurs['type_entree'] = ''; + if( $type_entree = _request('type_entree') ) { + $valeurs['infos_' . $type_entree] = ''; + } + + return $valeurs; } @@ -45,20 +56,20 @@ function formulaires_editer_menus_entree_verifier($id_menu,$id_menus_entree='new // S'il n'y a pas encore de type d'entree de choisi if (!($type_entree = _request('type_entree'))){ include_spip('inc/config'); - $erreurs['id_menu_nouvelle_entree'] = $id_menu; + set_request('id_menu_nouvelle_entree', $id_menu); // On charge les différents types d'entrées disponibles $masque = array_flip(lire_config('menus/entrees_masquees', array())); - $erreurs['entrees'] = array_diff_key(menus_lister_disponibles(), $masque); + set_request('entrees', array_diff_key(menus_lister_disponibles(), $masque)); if (_request('suivant')) - $erreurs['type'] = _T('menus:erreur_type_menu'); + $erreur['type'] = _T('menus:erreur_type_menu'); } // Si on a choisi un type d'entree else{ - $erreurs['id_menu_nouvelle_entree'] = $id_menu; - $erreurs['type_entree'] = $type_entree; + set_request('id_menu_nouvelle_entree', $id_menu); + set_request('type_entree', $type_entree); // On charge les infos du type choisi $entrees = menus_lister_disponibles(); - $erreurs['infos_'.$type_entree] = $entrees[$type_entree]; + set_request('infos_'.$type_entree, $entrees[$type_entree]); } } @@ -74,12 +85,12 @@ function formulaires_editer_menus_entree_verifier($id_menu,$id_menus_entree='new $type_entree = $entree['type_entree']; $parametres = unserialize($entree['parametres']); - $erreurs = array_merge($erreurs, $parametres); - $erreurs['id_menus_entree'] = $id_menus_entree; - $erreurs['type_entree'] = $type_entree; + set_request('donnees', $parametres); + set_request('id_menus_entree', $id_menus_entree); + set_request('type_entree', $type_entree); // On charge les infos du type choisi $entrees = menus_lister_disponibles(); - $erreurs['infos_'.$type_entree] = $entrees[$type_entree]; + set_request('infos_'.$type_entree, $entrees[$type_entree]); } // Si on valide une entree pour un menu ------------------------------------ @@ -94,11 +105,11 @@ function formulaires_editer_menus_entree_verifier($id_menu,$id_menus_entree='new if ($parametre['obligatoire']){ if (!$parametres_envoyes[$nom]){ if ($id_menu) - $erreurs['id_menu_nouvelle_entree'] = $id_menu; + set_request('id_menu_nouvelle_entree', $id_menu); if ($id_menus_entree) - $erreurs['id_menus_entree'] = $id_menus_entree; - $erreurs['type_entree'] = $type_entree; - $erreurs['infos_'.$type_entree] = $infos; + set_request('id_menus_entree', $id_menus_entree); + set_request('type_entree', $type_entree); + set_request('infos_'.$type_entree, $infos); $erreurs['parametres'][$nom] = _T('info_obligatoire'); } } @@ -115,6 +126,8 @@ function formulaires_editer_menus_entree_traiter($id_menu,$id_menus_entree='new' if (($id_menu = intval(_request('id_menu_nouvelle_entree')) or $id_menus_entree = intval(_request('id_menus_entree'))) and _request('enregistrer')){ $res = formulaires_editer_objet_traiter('menus_entree', $id_menus_entree, 0, 0, '', '', '', ''); + set_request('id_menu_nouvelle_entree', ''); + set_request('id_menus_entree', ''); if (!$res['id_menus_entree']) $retours['message_erreur'] = _T('menus:erreur_mise_a_jour'); } @@ -244,6 +257,12 @@ function formulaires_editer_menus_entree_traiter($id_menu,$id_menus_entree='new' if ($ok and !$sous_menu) $retours['redirect'] = generer_url_ecrire('menus_tous'); } + // Bouton annuler --------------------------------------------------------- + + if(_request('annuler')){ + set_request('id_menus_entree', ''); + } + $retours['editable'] = true; return $retours; diff --git a/www/plugins/menus_1/formulaires/inc-menus_entrees.html b/www/plugins/menus_1/formulaires/inc-menus_entrees.html index c1a40081..c6969f34 100644 --- a/www/plugins/menus_1/formulaires/inc-menus_entrees.html +++ b/www/plugins/menus_1/formulaires/inc-menus_entrees.html @@ -1,8 +1,8 @@ #SET{rang_suivant,1} -
              • @@ -157,4 +186,4 @@

                - \ No newline at end of file + diff --git a/www/plugins/notifications2/lang/notifications.xml b/www/plugins/notifications2/lang/notifications.xml index 6f620d7e..462f387b 100644 --- a/www/plugins/notifications2/lang/notifications.xml +++ b/www/plugins/notifications2/lang/notifications.xml @@ -1,22 +1,27 @@ - + + + + + + - + - + - + - + - + diff --git a/www/plugins/notifications2/lang/notifications_de.php b/www/plugins/notifications2/lang/notifications_de.php new file mode 100644 index 00000000..63dbd2b4 --- /dev/null +++ b/www/plugins/notifications2/lang/notifications_de.php @@ -0,0 +1,135 @@ + '--------------', + + // A + 'alt_logo_conf' => 'Logo des Plugins Benachrichtigungen', + 'article_prive' => 'Artikel veröffentlichen', + 'article_prive_admins_restreints' => 'Rubrikadmins : Rubrikadmins erhalten eine Nachricht wenn Artikel in den von ihnen verwalteten Rubriken vorgeschlagen werden. Die Einstellung für Haupt-Admins werden im SPIP-eigenen Konfigurationsmodul gemacht.', + 'article_prive_auteurs' => 'Autoren : Autoren werden benachrichtigt, wenn ihre Artikel vorgeschlagen oder gelöscht werden.', + 'article_prive_auteurs_refus' => 'Autoren : Autoren werden benachrichtigt, wenn ihre Artikel abgelehnt werden.', + 'article_prive_publieur' => 'Autor nicht benachrichtigen, wenn er seinen Artikel selber veröffentlicht.', + 'article_propose_detail' => 'Der Artikel "@titre@" wurde zur Veröffentlichung vorgeschlagen.', + 'article_propose_sujet' => '[@nom_site_spip@] vorgeschlagen : @titre@', + 'article_propose_titre' => 'Artikel vorgeschlagen + ---------------', + 'article_propose_url' => 'Bitte lesen und kommentieren Sie den Artikel in seinem internen Forum. +Sie finden ihn unter folgender Adresse:', + 'article_publie_detail' => 'Der Artikel "@titre@" wurde von @connect_nom@ veröffentlicht.', + 'article_publie_sujet' => '[@nom_site_spip@] VERÖFFENTLICHT : @titre@', + 'article_publie_titre' => 'Artikel veröffentlicht + --------------', + 'article_refuse_detail' => 'Der Artikel "@titre@" wurde von @connect_nom@ abgelehnt.', + 'article_refuse_sujet' => '[@nom_site_spip@] ABGELEHNT : @titre@', + 'article_refuse_titre' => 'Artikel abgelehnt', + 'article_valide_date' => 'Dieser Artikel wird mit möglichen Änderungen veröffentlicht.', + 'article_valide_detail' => 'Der Artikel "@titre@" wurde von @connect_nom@ bestätigt.', + 'article_valide_sujet' => '[@nom_site_spip@] BESTÄTIGT : @titre@', + 'article_valide_titre' => 'Artikel bestätigt + --------------', + 'article_valide_url' => 'Bis dahin ist er unter dieser Adresse zu lesen :', + + // B + 'bouton_changer_pass' => 'Mein Passwort ändern', + 'bouton_finir_inscription' => 'Mein Abonnement beenden', + 'breve_propose_detail' => 'Die Meldung "@titre@" wurde zur Veröffentlichung vorgeschlagen. + depuis', + 'breve_propose_sujet' => '[@nom_site_spip@] vorgeschlagen : @titre@', + 'breve_propose_titre' => 'Meldung vorgeschlagen + ---------------', + 'breve_propose_url' => 'Bitte lesen und kommentieren Sie die Meldung in ihrem internen Forum. +Sie hat folgende Adresse :', + 'breve_publie_detail' => 'Die Meldung "@titre@" wurde von @connect_nom@ veröffentlicht.', + 'breve_publie_sujet' => '[@nom_site_spip@] VERÖFFENTLICHT : @titre@', + 'breve_publie_titre' => 'Meldung veröffentlicht + --------------', + + // E + 'evenement_notification' => 'Folgende Ereignisse können Benachrichtigungen per Mail auslösen.', + + // F + 'form_forum_confirmer_email' => 'Bitte bestätigen Sie Ihre E-Mail-Adresse indem Sie auf die Schaltfläche klicken : ', + 'forum_prives_auteur' => 'AutAutorenurs : Autoren werden über neue Beiträge in den öffentlichen und privaten Foren ihrer Artikel benachrichtigt.', + 'forum_prives_moderateur' => 'Geben Sie die Mailadresse des Moderators der privaten Foren an (mehrere Angaben mit Komma trennen).', + 'forum_prives_thread' => 'Diskussionsstrang (Thread) : Teilnehmer des selben Diskussionsstrangs werden über neue Beiträge informiert (privat).', + 'forums_admins_restreints' => 'Admins : Rubrikadmins erhalten Benachrichtigungen, wenn neue Nachrichten in dieser Haupt-Rubrik veröffentlicht werden.', + 'forums_limiter_rubriques_explication' => 'Bitte geben Sie hier die ID jeder Rubrik ein, für die Sie Benachrichtigungen aktivieren wollen. Trennen Sie die Ziffern mit einem Komma : "11,26"', + 'forums_limiter_rubriques_label' => 'Auf diese Rubriken beschränken :', + 'forums_prives' => 'Private Foren', + 'forums_public' => 'Öffentliche Foren', + 'forums_public_a_noter' => 'Anmerkung : In vorab moderierten Foren werden nur die Autoren benachrichtigt, die berechtigt sind, Beiträge freizuschalten. Die anderen Empfänger erhalten eine Nachricht, wenn ein Beitrag freigeschaltet wird.', + 'forums_public_article' => 'Antwort auf Artikel : Verfasser, die öffentlich auf Artikel reagiert haben, erhalten Benachrichtigungen über Neuigkeiten im öffentlichen Forum des Artikels (geeignet für Foren ohne « Thread-Anzeige »). Über gelöschte und als SPAM markierte Beiträge wird nicht informiert,', + 'forums_public_auteurs' => 'Autoren : Autoren werden über neue Beiträge in den öffentlichen Foren ihrer Artikel benachrichtigt.', + 'forums_public_liste' => 'Zusatzadresse : Mailadresse/n (mehrere mit Komma trennen) welche über im öffentlichen Bereich veröffentlichte Beiträge informiert werden. Besonders geeignet für unmoderierte Foren.', + 'forums_public_moderateur' => 'Geben Sie hier die Adresse des Moderators der öffentlichen Foren an (mehrere mit Komma trennen).', + 'forums_public_thread' => 'Diskussionsstrang (Thread): Teilnehmer eines Diskussionsstrangs erhalten Benachrichtigungen aus öffentlichen Foren. Gelöschte und als SPAM markierte Beiträge werden nicht berücksichtigt', + + // I + 'info_lien_publier_commentaire' => 'Beitrag veröffentlichen', + 'info_lien_signaler_spam_commentaire' => 'Als SPAM markieren', + 'info_lien_supprimer_commentaire' => 'Beitrag löschen', + 'info_moderation_confirmee_off' => 'Beitrag #@id_forum@ wurde gelöscht.', + 'info_moderation_confirmee_publie' => 'Beitrag #@id_forum@ wurde veröffentlicht.', + 'info_moderation_confirmee_spam' => 'Beitrag #@id_forum@ wurde als SPAM markiert.', + 'info_moderation_deja_faite' => 'Status des Beitrags #@id_forum@ wurde auf "@statut@" gesetzt.', + 'info_moderation_interdite' => 'Sie sind nicht berechtigt, diesen Beitrag zu moderieren.', + 'info_moderation_lien_titre' => 'Diesen Beitrag mit dem Redaktionssystem moderieren.', + 'info_moderation_url_perimee' => 'Dieser Modrationslink ist nicht mehr gültig.', + 'info_nouveau_commentaire' => 'Neuer Beitrag', + 'inscription' => 'Anmeldung der Redakteure', + 'inscription_admins' => 'Administratoren', + 'inscription_explication' => 'Welche Autoren sollen über neu angemeldete Redakteure benachrichtigt werden ?', + 'inscription_label' => 'Status', + 'inscription_statut_aucun' => 'Kein', + 'inscription_statut_webmestres' => 'Webmaster', + + // L + 'lien_documentation' => 'siehe Dokumentation', + 'limiter_rubriques_explication' => 'Geben Sie hier die IDs der Rubriken an, für die Benachrichtigungen aktiviert werden. Trennen Sie mehrer Angaben mit Komma : "11,26"', + 'limiter_rubriques_label' => 'Auf diese Rubriken beschränken :', + + // M + 'message_a_valider' => 'Nachricht bestätigen : ', + 'message_spam_a_confirmer' => 'SPAM bestätigen : ', + 'message_voir_configuration' => 'Konfiguration der Benachrichtigungen anzeigen', + 'messagerie_interne' => 'Internes Nachrichtensystem', + 'messagerie_interne_signaler' => 'Über neue private Nachrichten informieren : Aktivieren Sie diese Option, damit Redakteure per Mail über ungelesene Nachrichten im Redaktionssystem benachrichtigt werden. Das System wartet 20 Minuten bis zum Versand der Mail, damit im Redaktionssystem eingelogte Redakteure nicht mit sinnlosen Mails belästigt werden.', + 'moderateur' => 'Moderator', + + // N + 'notifications' => 'Benachrichtigungen', + + // P + 'pass_mail_passcookie_1' => 'Zur Neuanmeldung bei @nom_site_spip@, klicken Sie bitte auf die Schaltfläche : ', + 'pass_mail_passcookie_2' => 'Sie können dann ein neues Passwort eingeben, und sich wieder einloggen.', + + // S + 'signature_petition' => 'Petition/Unterschriften', + 'signature_petition_moderateur' => 'Geben Sie hier die Mailadresse des Moderators für Petitionen ein (mehrere Adressen mit Komma trennen).', + 'suivi_texte_acces_page' => 'Meine Abonnements und Diskussionen ändern', + 'suivis_perso' => 'Personalisierte Benachrichtigungen', + 'suivis_perso_activer_option' => 'Wenn Sie diese Option aktivieren, wird jeder Besucher, der sich mit diesem Benachrichtigungslink anmeldet, in der Tabelle spip_auteurs als 6visiteur eingetragen. Er kann dann alle von ihm signierten Forumsbeiträge sehen, seine Einstellungen zu Benachrichtigungen ändern u.s.w.', + 'suivis_perso_non' => 'Keine Benachrichtigungen', + 'suivis_perso_oui' => 'Benachrichtigungen aktiviert', + 'suivis_perso_url_suivis' => 'In jede Email einen personalisierten Benachrichtigungs-URL einfügen. Unter diesem URL können Benutzer ihre individuellen Einstellungen für Benachrichtigungen wählen.', + 'suivis_public_article_thread' => 'TODO : jeden Artikel/Thread mit eigener Checkbox versehen', + 'suivis_public_changer_email' => 'TODO : Email ändern', + 'suivis_public_description' => 'Hier können Sie (nach Fertigstellung der Funktionen...) alle Ihre Forenbeiträge einsehen, einen RSS-Stream der Beiträge dazu abonnieren, Ihre Benachrichtigungseinstellungen ändern, u.s.w.', + 'suivis_public_notif_desactiver' => 'TODO : Checkbox zum Abbestellen der Benachrichtigungen', + 'suivis_public_vos_forums' => 'Ihre Foren', + 'suivis_public_vos_forums_date' => 'Ihre Foren nach Datum', + 'suivis_public_votre_page' => 'Die ist Ihre persönliche Seite zu Benachrichtigungen', + + // T + 'titre_moderation' => 'Moderation' +); diff --git a/www/plugins/notifications2/lang/notifications_en.php b/www/plugins/notifications2/lang/notifications_en.php index f0b77c36..c441b276 100644 --- a/www/plugins/notifications2/lang/notifications_en.php +++ b/www/plugins/notifications2/lang/notifications_en.php @@ -3,15 +3,24 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/notifications?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( + // 0 + '0' => '--------------', + // A 'alt_logo_conf' => 'Notifications plugin logo', 'article_prive' => 'Articles publishing', - 'article_prive_admins_restreints' => 'Administrators: Administrators get notified when article(s) is(are) proposed in their section', + 'article_prive_admins_restreints' => 'Restricted Administrators: Restricted Administrators get notified when article(s) is(are) proposed in their section. +For General Administrators see + default tool of SPIP.', 'article_prive_auteurs' => 'Authors: Authors get notified when their article(s) is(are) proposed, published or deleted.', + 'article_prive_auteurs_refus' => 'Authors : authors receive notifications when the publications of their(s) article(s) is rejected.', + 'article_prive_publieur' => 'If one of the authors is the one publishing the article he will not be notified.', 'article_propose_detail' => 'The article "@titre@" is submitted for publication.', 'article_propose_sujet' => '[@nom_site_spip@] Submitted: @titre@', 'article_propose_titre' => 'Article submitted @@ -22,6 +31,9 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'article_publie_sujet' => '[@nom_site_spip@] PUBLISHED: @titre@', 'article_publie_titre' => 'Article published --------------', + 'article_refuse_detail' => 'The article "@titre@" has been rejected by @connect_nom@.', + 'article_refuse_sujet' => '[@nom_site_spip@] REJECTED: @titre@', + 'article_refuse_titre' => 'Article rejected', 'article_valide_date' => 'Without change, this article will be published', 'article_valide_detail' => 'The article "@titre@" is validated by @connect_nom@.', 'article_valide_sujet' => '[@nom_site_spip@] VALIDATED: @titre@', @@ -51,13 +63,18 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'forum_prives_auteur' => 'Authors: Authors get notified when comments are posted to their article(s) or comment(s) on the private area.', 'forum_prives_moderateur' => 'Please indicate the moderator’s email address for private forums, (comma-separated in case of multiple addresses).', 'forum_prives_thread' => 'Forum thread: Posters to the same thread get notified when a new comment is posted to the (private) thread.', + 'forums_admins_restreints' => 'Administrators : +Restricted administrators get notified when new posts are published in the sector.', + 'forums_limiter_rubriques_explication' => 'Specify the identifiers of each section where you want to activate the notifications, separated with a comma. example: "11,26"', + 'forums_limiter_rubriques_label' => 'Limit to these sections:', 'forums_prives' => 'Forums in private area', 'forums_public' => 'Public forums', 'forums_public_a_noter' => 'Note: if forums are awaiting validation from moderators before publication, only authors with rights to validate forums get notified when the comment is posted ; other recipients get notified only when moderators validate the comment.', - 'forums_public_article' => 'Reply to an article: persons who have publicly replied to an article will receive forum notifications for that article (useful for «flat» forums).', + 'forums_public_article' => 'Reply to an article: persons who have publicly replied to an article will receive forum notifications for that article (useful for «flat» forums). Posts tagged as deleted or spam will be excluded.', 'forums_public_auteurs' => 'Authors: Authors get notified when new comments are posted to their article(s) on the public area.', + 'forums_public_liste' => 'additional adress: an email adress which will receive the posts publicly published (or several separated by commas), useful for example for non-moderated forums.', 'forums_public_moderateur' => 'Please indicate the moderator’s email address for public forums, (comma-separated in case of multiple addresses).', - 'forums_public_thread' => 'Forum thread: Posters to the same thread get notified when a new comment is posted to the (public) thread.', + 'forums_public_thread' => 'Forum thread: Posters to the same thread get notified when a new comment is posted to the (public) thread. Posts tagged as deleted or spam are excluded.', // I 'info_lien_publier_commentaire' => 'Publish this comment online', @@ -118,5 +135,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // T 'titre_moderation' => 'Moderation' ); - -?> diff --git a/www/plugins/notifications2/lang/notifications_es.php b/www/plugins/notifications2/lang/notifications_es.php index ce27a426..bd9cf141 100644 --- a/www/plugins/notifications2/lang/notifications_es.php +++ b/www/plugins/notifications2/lang/notifications_es.php @@ -3,18 +3,20 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/notifications?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // A 'alt_logo_conf' => 'Logo del plugin Notificaciones', 'article_prive' => 'Publicación de artículos', - 'article_prive_admins_restreints' => 'Administradores: Los administradores -limitados- reciben notificaciones cuando llegan propuestas de artículos a su sección', - 'article_prive_auteurs' => 'Autores: los autores reciben notificaciones cuando su(s) artículo(s) son propuestos, publicados o eliminados', + 'article_prive_admins_restreints' => 'Administradores: Los administradores -limitados- reciben notificaciones cuando llegan propuestas de artículos a su sección', # MODIF + 'article_prive_auteurs' => 'Autores: los autores reciben notificaciones cuando su(s) artículo(s) son propuestos, publicados o eliminados', # MODIF 'article_propose_detail' => 'El artículo "@titre@" ha sido propuesto para publicación desde', - 'article_propose_sujet' => '[@nom_site_spip@] Propone: @titre@', + 'article_propose_sujet' => '[@nom_site_spip@] Propone: @titre@', # MODIF 'article_propose_titre' => 'Artículo propuesto ---------------', 'article_propose_url' => 'Le invitamos a consultarlo y a dar su opinión en el foro asociado. El mismo está disponible en la dirección:', @@ -51,13 +53,15 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'forum_prives_auteur' => 'Autores: los autores reciben notificaciones de los foros derivados de sus artículos o de sus mensajes en el sitio privado. ', 'forum_prives_moderateur' => 'Indique a continuación el correo electrónico del moderador de los foros privados (si son varios, separe con comas).', 'forum_prives_thread' => 'Hilo de discusión: los participantes de un mismo hilo de discusión reciben notificaciones de los foros (privados).', + 'forums_limiter_rubriques_explication' => 'Especifique aquí los identificadores de cada sección donde quiere activar las notificaciones, separados por una coma. Por ej. "11,26"', + 'forums_limiter_rubriques_label' => 'Limitar a estas secciones:', 'forums_prives' => 'Foros privados', 'forums_public' => 'Foros públicos', 'forums_public_a_noter' => 'Nota: en el caso de los foros moderados a priori, sólo aquellos autores que tienen derecho de aprobar los foros son notificados cuando se crea un foro; los otros destinatarios son notificados cuando el mensaje ha sido aprobado por el moderador.', - 'forums_public_article' => 'Respuesta al artículo: las personas que hayan respondido públicamente al artículos reciben notificaciones de los foros (públicos) del artículo (útil para los foros «planos»).', + 'forums_public_article' => 'Respuesta al artículo: las personas que hayan respondido públicamente al artículos reciben notificaciones de los foros (públicos) del artículo (útil para los foros «planos»).', # MODIF 'forums_public_auteurs' => 'Autores: los autores reciben notificaciones de aquellos foros derivados de sus artículos en en el sitio públicos.', 'forums_public_moderateur' => 'Indique a continuación el correo electrónico del moderador de los foros públicos (si son varios, separe con comas).', - 'forums_public_thread' => 'Hilo de discusión: los participantes de un mismo hilo de discusión reciben notificaciones de los foros (públicos).', + 'forums_public_thread' => 'Hilo de discusión: los participantes de un mismo hilo de discusión reciben notificaciones de los foros (públicos).', # MODIF // I 'info_lien_publier_commentaire' => 'Publicar este comentario', @@ -118,5 +122,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // T 'titre_moderation' => 'Moderación' ); - -?> diff --git a/www/plugins/notifications2/lang/notifications_fa.php b/www/plugins/notifications2/lang/notifications_fa.php index 9579d52e..cc0e4b17 100644 --- a/www/plugins/notifications2/lang/notifications_fa.php +++ b/www/plugins/notifications2/lang/notifications_fa.php @@ -3,17 +3,19 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/notifications?lang_cible=fa // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // A 'alt_logo_conf' => 'لوگوي پلاگين اطلاعيه‌ها', 'article_prive' => 'نشر مقاله‌ها', - 'article_prive_admins_restreints' => 'ادمين‌ها  : ادمين‌ها وقتي مقاله‌ها داخل بخش‌ آن‌ها پيشنهاد شود با خبر خواهند شد', + 'article_prive_admins_restreints' => 'ادمين‌ها  : ادمين‌ها وقتي مقاله‌ها داخل بخش‌ آن‌ها پيشنهاد شود با خبر خواهند شد', # MODIF 'article_prive_auteurs' => 'نويسندگان :نويسندگان هنگام نشر مقاله‌ (ها) با خبر مي‌شوند', # MODIF 'article_propose_detail' => 'مقاله "@titre@" براي نشر پيشنهاد شده', - 'article_propose_sujet' => '[@nom_site_spip@] پيشنهاد شده: @titre@', + 'article_propose_sujet' => '[@nom_site_spip@] پيشنهاد شده: @titre@', # MODIF 'article_propose_titre' => 'مقاله پيشنهادي ---------------', 'article_propose_url' => 'دعوت مي‌شويد كه در فرم پيوست مشورت و نظر خود را اعلام كنيد. اين فرم در اين شناني در دسترس است: ', @@ -52,7 +54,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( ', 'forums_public_auteurs' => 'نويسندگان: نويسندگان اطلاعيه‌هايي در سخنگاه‌هاي پست شده روي مقاله‌هايشان در سايت همگاني دريافت مي‌كنند.', 'forums_public_moderateur' => 'در زير نشاني ايميل گرداننده‌ (يا گردانندگان - جدا شده با ويرگول) سخنگاههاي عمومي را قيد كنند.', # MODIF - 'forums_public_thread' => 'خط گفتگو: شركت‌كنندگان در همان خط گفتگو اطلاعيه‌هايي از سخنگاه‌ها (همگاني) دريافت مي‌كنند.', + 'forums_public_thread' => 'خط گفتگو: شركت‌كنندگان در همان خط گفتگو اطلاعيه‌هايي از سخنگاه‌ها (همگاني) دريافت مي‌كنند.', # MODIF // I 'inscription' => 'ثبت سردبيران', @@ -92,5 +94,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'suivis_public_vos_forums_date' => 'سخنگاه‌هاي شما، به ترتيب تاريخ', 'suivis_public_votre_page' => 'اين صفحه‌ي شخصي شما براي پيگيري سايت است' ); - -?> diff --git a/www/plugins/notifications2/lang/notifications_fr.php b/www/plugins/notifications2/lang/notifications_fr.php index dfce2ed8..9447e22b 100644 --- a/www/plugins/notifications2/lang/notifications_fr.php +++ b/www/plugins/notifications2/lang/notifications_fr.php @@ -1,18 +1,25 @@ '--------------', + // A 'alt_logo_conf' => 'Logo du plugin Notifications', 'article_prive' => 'Publication d’articles', - 'article_prive_admins_restreints' => 'Administrateurs : Les administrateurs restreints reçoivent les notifications lors de proposition d’articles dans leur rubrique', - 'article_prive_auteurs' => 'Auteurs : les auteurs reçoivent les notifications lors de la proposition,publication ou suppression de leur(s) article(s)', + 'article_prive_admins_restreints' => 'Administrateurs restreints : Les administrateurs restreints reçoivent les notifications lors de proposition d’articles dans leur rubrique. Pour les administrateurs généralistes, voir l’outil par défaut de SPIP.', + 'article_prive_auteurs' => 'Auteurs : les auteurs reçoivent les notifications lors de la proposition, publication ou suppression de leur(s) article(s).', + 'article_prive_auteurs_refus' => 'Auteurs : les auteurs reçoivent les notifications lors du refus de publications de leur(s) article(s).', + 'article_prive_publieur' => 'Si l’un des auteurs est celui qui publie l’article, ne pas le prévenir.', 'article_propose_detail' => 'L’article "@titre@" est proposé à la publication depuis', - 'article_propose_sujet' => '[@nom_site_spip@] Propose : @titre@', + 'article_propose_sujet' => '[@nom_site_spip@] Proposé : @titre@', 'article_propose_titre' => 'Article proposé ---------------', 'article_propose_url' => 'Vous êtes invité à venir le consulter et à donner votre opinion @@ -21,6 +28,9 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'article_publie_sujet' => '[@nom_site_spip@] PUBLIE : @titre@', 'article_publie_titre' => 'Article publié --------------', + 'article_refuse_detail' => 'L’article "@titre@" vient d’être refusé par @connect_nom@.', + 'article_refuse_sujet' => '[@nom_site_spip@] REFUSE : @titre@', + 'article_refuse_titre' => 'Article refusé', 'article_valide_date' => 'Sous réserve de changement, cet article sera publié', 'article_valide_detail' => 'L’article "@titre@" a été validé par @connect_nom@.', 'article_valide_sujet' => '[@nom_site_spip@] VALIDE : @titre@', @@ -51,13 +61,17 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'forum_prives_auteur' => 'Auteurs : les auteurs reçoivent les notifications des forums postés sous leurs articles ou leurs messages dans le site privé.', 'forum_prives_moderateur' => 'Indiquez ci-dessous l’adresse email du modérateur des forums privés (ou plusieurs, séparées par des virgules).', 'forum_prives_thread' => 'Fil de discussion : les participants au même fil de discussion reçoivent les notifications des forums (privés).', + 'forums_admins_restreints' => 'Administrateurs : les administrateurs restreints reçoivent les notifications lors de nouveaux messages publiés sur la branche.', + 'forums_limiter_rubriques_explication' => 'Renseignez ici les identifiants de chaque rubrique où vous voulez déclencher les notifications, séparé par une virgule. ex : "11,26"', + 'forums_limiter_rubriques_label' => 'Limiter à ces rubriques :', 'forums_prives' => 'Forums privés', 'forums_public' => 'Forums publics', 'forums_public_a_noter' => 'À noter : dans le cas des forums modérés à priori, seuls les auteurs ayant le droit de valider les forums sont notifiés lors de l’envoi du forum ; les autres destinataires sont notifiés lors de la validation du message par le modérateur.', - 'forums_public_article' => 'Réponse à l’article : les personnes ayant répondu publiquement à l’article recoivent les notifications des forums (publics) de l’article (utile pour les forums « à plat »).', + 'forums_public_article' => 'Réponse à l’article : les personnes ayant répondu publiquement à l’article recoivent les notifications des forums (publics) de l’article (utile pour les forums « à plat »). Sont exclus les messages supprimés ou marqués comme SPAM.', 'forums_public_auteurs' => 'Auteurs : les auteurs reçoivent les notifications des forums postés sous leurs articles dans le site public.', + 'forums_public_liste' => 'Adresse supplémentaire : une adresse email qui recevra les messages publiés en public (ou plusieurs séparées par des virgules), utile par exemple pour les forums non modérés.', 'forums_public_moderateur' => 'Indiquez ci-dessous l’adresse email du modérateur des forums publics (ou plusieurs, séparées par des virgules).', - 'forums_public_thread' => 'Fil de discussion : les participants au même fil de discussion reçoivent les notifications des forums (publics).', + 'forums_public_thread' => 'Fil de discussion : les participants au même fil de discussion reçoivent les notifications des forums (publics). Sont exclus les messages supprimés ou marqués comme SPAM.', // I 'info_lien_publier_commentaire' => 'Publier ce commentaire', @@ -118,5 +132,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // T 'titre_moderation' => 'Modération' ); - -?> diff --git a/www/plugins/notifications2/lang/notifications_nl.php b/www/plugins/notifications2/lang/notifications_nl.php index 5c001561..5de07a3e 100644 --- a/www/plugins/notifications2/lang/notifications_nl.php +++ b/www/plugins/notifications2/lang/notifications_nl.php @@ -3,15 +3,22 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/notifications?lang_cible=nl // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( + // 0 + '0' => '--------------', + // A 'alt_logo_conf' => 'Logo van plugin Notifications', 'article_prive' => 'Publicatie van artikelen', - 'article_prive_admins_restreints' => 'Beheerders: Beperkte beheerders ontvangen notificaties bij voorstellen voor publicatie in hun rubriek', - 'article_prive_auteurs' => 'Auteurs: Auteurs ontvangen notificaties bij het voorstellen, publiceren of verwijderen van hun artikel(en)', + 'article_prive_admins_restreints' => 'Beperkte beheerders: Beperkte beheerders ontvangen notificaties bij voorstellen voor publicatie in hun rubriek. Voor algehele beheerders kijk je bij de standaard tool van SPIP.', + 'article_prive_auteurs' => 'Auteurs: Auteurs ontvangen notificaties bij het voorstellen, publiceren of verwijderen van hun artikel(en).', + 'article_prive_auteurs_refus' => 'Auteurs: auteurs ontvangen bericht bij weigering van hun artikel(en).', + 'article_prive_publieur' => 'Als een van de auteurs degene is die het artikel publiceert wordt geen bericht gestuurd.', 'article_propose_detail' => 'Artikel "@titre@" is ter publicatie voorgesteld sinds', 'article_propose_sujet' => '[@nom_site_spip@] Stelt voor: @titre@', 'article_propose_titre' => 'Voorgesteld artikel @@ -22,6 +29,9 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'article_publie_sujet' => '[@nom_site_spip@] GEPUBLICEERD: @titre@', 'article_publie_titre' => 'Gepubliceerd artikel --------------------', + 'article_refuse_detail' => 'Artikel "@titre@" wordt geweigerd door @connect_nom@.', + 'article_refuse_sujet' => '[@nom_site_spip@] GEWEIGERD: @titre@', + 'article_refuse_titre' => 'Geweigerd artikel', 'article_valide_date' => 'Onder voorbehoud van wijzigingen zal dit artikel worden gepubliceerd', 'article_valide_detail' => 'Artikel "@titre@" werd gevalideerd door @connect_nom@.', 'article_valide_sujet' => '[@nom_site_spip@] GEVALIDEERD: @titre@', @@ -51,13 +61,17 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'forum_prives_auteur' => 'Auteurs: Auteurs ontvangen notificaties uit een forum dat onder hun artikel is geplaatst of van hun berichten in de privé-omgeving.', 'forum_prives_moderateur' => 'Geef hieronder het e-mailadres van de moderator van de forums in het privé-gedeelte (of meerdere, gescheiden door een komma).', 'forum_prives_thread' => 'Draad van de discussie: deelnemers aan dezelfde discussie in het privé-forum ontvangen notificaties.', + 'forums_admins_restreints' => 'Beheerders: beperkte beheerders ontvangen berichten wanneer nieuwe berichten aan de root worden gepubliceerd.', + 'forums_limiter_rubriques_explication' => 'Vermeld hier de identificatie van iedere rubriek waarvoor de notificaties moeten worden geactiveerd, gescheiden door een komma. bv: "11,26"', + 'forums_limiter_rubriques_label' => 'Uitsluitend deze rubrieken:', 'forums_prives' => 'Privé forums', 'forums_public' => 'Publieke forums', 'forums_public_a_noter' => 'Let op: bij een gemodeeerd forum ontvangen alleen de auteurs die mogen goedkeuren een noticifatie bij een nieuw bericht; anderen ontvangen pas een bericht na goedkeuring.', - 'forums_public_article' => 'Reactie op een artikel: personen die via de publieke site op een artikel reageren, ontvangen een notificatie (zinvol bij een "plat" forum).', + 'forums_public_article' => 'Reactie op een artikel: personen die via de publieke site op een artikel reageren, ontvangen een notificatie (zinvol bij een "plat" forum). Uitgezonderd zijn verwijderde of als SPAM aangeduide berichten.', 'forums_public_auteurs' => 'Auteurs: auteurs ontvangen notificaties van publieke forumberichten onder hun artikel.', + 'forums_public_liste' => 'Extra adres: een mailadres (of meerdere door een komma gescheiden) dat berichten over geplaatste publieke berichten ontvangt, wat bijvoorbeeld nuttig kan zijn voor een niet gemodereerd forum.', 'forums_public_moderateur' => 'Geef hieronder het e-mailadres van de moderator van de publieke forums (of meerdere, gescheiden door een komma).', - 'forums_public_thread' => 'Draad van een discussie: deelnemers aan dezelfde publieke discussie ontvangen notificaties.', + 'forums_public_thread' => 'Draad van een discussie: deelnemers aan dezelfde publieke discussie ontvangen forumnotificaties. Uitgezonderd zijn verwijderde of als SPAM aangeduide berichten.', // I 'info_lien_publier_commentaire' => 'Dit commentaar plaatsen', @@ -118,5 +132,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // T 'titre_moderation' => 'Opvolgen' ); - -?> diff --git a/www/plugins/notifications2/lang/notifications_sk.php b/www/plugins/notifications2/lang/notifications_sk.php index 1cd01e22..5ee66ad3 100644 --- a/www/plugins/notifications2/lang/notifications_sk.php +++ b/www/plugins/notifications2/lang/notifications_sk.php @@ -3,18 +3,20 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/notifications?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // A 'alt_logo_conf' => 'Logo zásuvného modulu Oznamy', 'article_prive' => 'Publikovanie článkov', - 'article_prive_admins_restreints' => 'Administrátori: administrátori s obmedzeniami dostávajú oznamy pri odoslaní článkov do ich rubriky', - 'article_prive_auteurs' => 'Autori: autori dostávajú oznamy pri odoslaní svojich článkov na schválenie, pri ich publikovaní alebo odstránení', + 'article_prive_admins_restreints' => 'Administrátori: administrátori s obmedzeniami dostávajú oznamy pri odoslaní článkov do ich rubriky', # MODIF + 'article_prive_auteurs' => 'Autori: autori dostávajú oznamy pri odoslaní svojich článkov na schválenie, pri ich publikovaní alebo odstránení', # MODIF 'article_propose_detail' => 'Článok "@titre@" bol odoslaný na publikovanie z(o)', - 'article_propose_sujet' => '[@nom_site_spip@] Odoslaný: @titre@', + 'article_propose_sujet' => '[@nom_site_spip@] Odoslaný: @titre@', # MODIF 'article_propose_titre' => 'Článok bol odoslaný ---------------', 'article_propose_url' => 'Pozvali vás, aby ste si prečítali tento článok a svoj názor naň napísali do diskusného fóra, ktoré je k nemu pripojené. Článok nájdete na adrese:', @@ -51,13 +53,15 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'forum_prives_auteur' => 'Autori: autori dostávajú oznamy odoslané z diskusných fór pod ich článkami alebo správami v súkromnej zóne.', 'forum_prives_moderateur' => 'Zadajte e-mailovú adresu moderátora súkromných diskusných fór (alebo viac adries, oddeľte ich čiarkami).', 'forum_prives_thread' => 'Téma: diskutujúci v rovnakom vlánke dostávajú oznami z (verejných) diskusných fór.', + 'forums_limiter_rubriques_explication' => 'Sem zadajte identifikačné číslo každej rubriky, pre ktorú chcete spúšťať oznamy, oddeľte ich čiarkami. Napr. "11,26"', + 'forums_limiter_rubriques_label' => 'Obmedziť na tieto rubriky:', 'forums_prives' => 'Súkromné diskusné fóra', 'forums_public' => 'Verejné diskusné fóra', 'forums_public_a_noter' => 'Poznámka: v prípade, že sa príspevky do diskusných fór kontrolujú pred ich zverejnením, o odoslaní príspevkov sú informovaní iba autori, ktorí majú právo schvaľovať príspevky; ostatní sú informovaní, až keď príspevky schvália títo moderátori.', - 'forums_public_article' => 'Reakcia na článok: ľudia, ktorí verejne reagovali na článok, dostanú oznamy z–(verejných) diskusných fór článku (je to užitočné pre jednoduché diskusné fóra).', + 'forums_public_article' => 'Reakcia na článok: ľudia, ktorí verejne reagovali na článok, dostanú oznamy z–(verejných) diskusných fór článku (je to užitočné pre jednoduché diskusné fóra).', # MODIF 'forums_public_auteurs' => 'Autori: autori dostávajú oznamy odoslané z diskusných fór pod ich článkami na verejne prístupnej stránke.', 'forums_public_moderateur' => 'Zadajte e-mailovú adresu moderátora verejných diskusných fór (alebo viac adries, oddeľte ich čiarkami).', - 'forums_public_thread' => 'Téma: diskutujúci v rovnakom vlákne dostávajú oznamy z (verejných) diskusných fór.', + 'forums_public_thread' => 'Téma: diskutujúci v rovnakom vlákne dostávajú oznamy z (verejných) diskusných fór.', # MODIF // I 'info_lien_publier_commentaire' => 'Publikovať tento komentár', @@ -118,5 +122,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // T 'titre_moderation' => 'Kontrola' ); - -?> diff --git a/www/plugins/notifications2/lang/paquet-notifications.xml b/www/plugins/notifications2/lang/paquet-notifications.xml index ce0ff785..1cb70c3c 100644 --- a/www/plugins/notifications2/lang/paquet-notifications.xml +++ b/www/plugins/notifications2/lang/paquet-notifications.xml @@ -1,4 +1,7 @@ + + + diff --git a/www/plugins/notifications2/lang/paquet-notifications_de.php b/www/plugins/notifications2/lang/paquet-notifications_de.php new file mode 100644 index 00000000..10d16ea5 --- /dev/null +++ b/www/plugins/notifications2/lang/paquet-notifications_de.php @@ -0,0 +1,15 @@ + 'Aktiviert Mail-Benachrichtigungen über bestimmte Ereignisse speziell in Foren und dem internen Nachrichtensystem. Autoren können über die Veröffentlichung ihrer Artikel informiert werden.', + 'notifications_slogan' => 'Benachrichtigungsmails senden' +); diff --git a/www/plugins/notifications2/lang/paquet-notifications_en.php b/www/plugins/notifications2/lang/paquet-notifications_en.php index 1123b680..b445b7f7 100644 --- a/www/plugins/notifications2/lang/paquet-notifications_en.php +++ b/www/plugins/notifications2/lang/paquet-notifications_en.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-notifications?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'notifications_description' => 'Sends mail notifications for certain actions : forums posts and answers notified to users, private messages notified to redactors or articles publication notified to their authors.', 'notifications_slogan' => 'Report changes by mail ' ); - -?> diff --git a/www/plugins/notifications2/lang/paquet-notifications_es.php b/www/plugins/notifications2/lang/paquet-notifications_es.php index be7e54e5..ec0a86ea 100644 --- a/www/plugins/notifications2/lang/paquet-notifications_es.php +++ b/www/plugins/notifications2/lang/paquet-notifications_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-notifications?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'notifications_description' => 'Activa las notificaciones por correo electrónico de ciertas acciones, incluyendo las referidas a foros y mensajería del espacio privado. Permite igualmente el envío de un correo electrónico a los autores cuando sus artículos son publicados.', 'notifications_slogan' => 'Advertir por correo electrónico de las modificaciones' ); - -?> diff --git a/www/plugins/notifications2/lang/paquet-notifications_fa.php b/www/plugins/notifications2/lang/paquet-notifications_fa.php index fa79a739..9b8b1edc 100644 --- a/www/plugins/notifications2/lang/paquet-notifications_fa.php +++ b/www/plugins/notifications2/lang/paquet-notifications_fa.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-notifications?lang_cible=fa // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( ', 'notifications_slogan' => 'خبردهي از اصلاحات با ايميل' ); - -?> diff --git a/www/plugins/notifications2/lang/paquet-notifications_fr.php b/www/plugins/notifications2/lang/paquet-notifications_fr.php index f222b32d..2d99e7d3 100644 --- a/www/plugins/notifications2/lang/paquet-notifications_fr.php +++ b/www/plugins/notifications2/lang/paquet-notifications_fr.php @@ -1,7 +1,9 @@ 'Active les notifications par email de certaines actions, notamment des forums et de la messagerie de l’espace privé, permet également l’envoi d’un mail aux auteurs lors de la publication de leurs articles.', 'notifications_slogan' => 'Signaler par mail des modifications' ); - -?> diff --git a/www/plugins/notifications2/lang/paquet-notifications_nl.php b/www/plugins/notifications2/lang/paquet-notifications_nl.php index f31c7cde..bf818b1c 100644 --- a/www/plugins/notifications2/lang/paquet-notifications_nl.php +++ b/www/plugins/notifications2/lang/paquet-notifications_nl.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-notifications?lang_cible=nl // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'notifications_description' => 'Notificatie per email wanneer bepaalde handelingen worden verricht, zoals in het forum of het privé berichtensysteem. Ook kan een email naar auteurs worden gestuurd bij publicatie van hun artikelen.', 'notifications_slogan' => 'Berichten per email over aanpassingen' ); - -?> diff --git a/www/plugins/notifications2/lang/paquet-notifications_sk.php b/www/plugins/notifications2/lang/paquet-notifications_sk.php index d4b7d462..df79da79 100644 --- a/www/plugins/notifications2/lang/paquet-notifications_sk.php +++ b/www/plugins/notifications2/lang/paquet-notifications_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-notifications?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'notifications_description' => 'Aktivuje oznamy e-mailom pri určitých akciách, vrátane diskusných fór a odkazovača v súkromnej zóne, ako aj odoslania e-mailov autorom pri publikovaní ich článkov.', 'notifications_slogan' => 'Oznámiť zmeny e-mailom' ); - -?> diff --git a/www/plugins/notifications2/notifications/article_refuse.html b/www/plugins/notifications2/notifications/article_refuse.html new file mode 100644 index 00000000..4cb79361 --- /dev/null +++ b/www/plugins/notifications2/notifications/article_refuse.html @@ -0,0 +1,25 @@ +[(#REM) + + Squelette + (c) 2009 SPIP + Distribue sous licence GPL + +] + +#SET{auteurs,#LESAUTEURS} +[(#VAL{notifications:article_refuse_sujet}|_T{#ARRAY{nom_site_spip,#NOM_SITE_SPIP,titre,#TITRE}}|nettoyer_titre_email)] + + +
                +

                <:notifications:article_refuse_titre|trim|trim{-}:>

                +

                +[(#SET{titre,[(#TITRE)]})] +[(#VAL{notifications:article_refuse_detail}|_T{#ARRAY{titre,#GET{titre},connect_nom,#SESSION{nom}}})] +

                +
                +
                + + + + +#FILTRE{facteur_email_wrap_to_html} diff --git a/www/plugins/notifications2/notifications/forum_poste.html b/www/plugins/notifications2/notifications/forum_poste.html index 40af3e5d..878718e0 100644 --- a/www/plugins/notifications2/notifications/forum_poste.html +++ b/www/plugins/notifications2/notifications/forum_poste.html @@ -13,7 +13,7 @@ Mail HTML simplifie mis en forme complete par le filtre |facteur_email_wrap_to_h [

                <:forum:titre_cadre_forum_interne:>

                (#STATUT|=={privrac}|oui)] [

                <:forum:titre_cadre_forum_administrateur:>

                (#STATUT|=={priadm}|oui)] [ - (#ENV{par_auteur}) + (#ENV{indiquer_email_auteur,oui}|=={non}|?{#ENV{par_auteur}|replace{'<.+> ','','U'},#ENV{par_auteur}})
                ] [[(#NOM_SITE|sinon{#ENV{url_site}})]]
                diff --git a/www/plugins/notifications2/notifications/forumvalide.php b/www/plugins/notifications2/notifications/forumvalide.php index c7a1a479..994f880c 100644 --- a/www/plugins/notifications2/notifications/forumvalide.php +++ b/www/plugins/notifications2/notifications/forumvalide.php @@ -62,6 +62,48 @@ function notifications_forumvalide_dist($quoi, $id_forum, $options) { } } } + + +// Prevenir les admins restreints de la rubrique et des parentes lors de messages de forum d'article ou de rubrique +// c'est ici because dans notifications_pipelines la fonction de dédoublonnage le fait sauter (?) + +if ($GLOBALS['notifications']['forums_admins_restreints']) { + if ($t['objet']=='rubrique'){ + $id_rubrique = $t['id_objet']; + } + if ($t['objet']=='article'){ + include_spip('base/abstract_sql'); + $t = sql_fetsel("id_rubrique", "spip_articles", "id_article=" . intval($t['id_objet'])); + $id_rubrique = $t['id_rubrique']; + } + if ($GLOBALS['notifications']['forums_limiter_rubriques']){ + $limites = $GLOBALS['notifications']['forums_limiter_rubriques']; + $forums_limiter_rubriques = explode(",",$limites); + } else { + $forums_limiter_rubriques = array($id_rubrique); + } + if (in_array($id_rubrique,$forums_limiter_rubriques)){ + while ($id_rubrique){ + $hierarchie[] = $id_rubrique; + $res = sql_fetsel("id_parent", "spip_rubriques", "id_rubrique=" . intval($id_rubrique)); + if (!$res){ // rubrique inexistante + $id_rubrique = 0; + break; + } + $id_parent = $res['id_parent']; + $id_rubrique = $id_parent; + } + //les admins de la rub et de ses parents + $result = sql_select( + "auteurs.email,auteurs.id_auteur,lien.id_objet as id_rubrique", + "spip_auteurs AS auteurs JOIN spip_auteurs_liens AS lien ON auteurs.id_auteur=lien.id_auteur ", + "lien.objet='rubrique' AND ".sql_in('lien.id_objet',sql_quote($hierarchie))." AND auteurs.statut='0minirezo'"); + while ($qui = sql_fetch($result)) { + $tous[] = $qui['email']; + } + } + } +///////////////////////////// $options['forum'] = $t; $destinataires = pipeline('notifications_destinataires', @@ -80,10 +122,38 @@ function notifications_forumvalide_dist($quoi, $id_forum, $options) { // $email_notification_forum = charger_fonction('email_notification_forum','inc'); foreach ($destinataires as $email) { - $contexte = array('notification_email'=>$email); + $contexte = array('notification_email'=>$email,'indiquer_email_auteur'=>'non'); $texte = $email_notification_forum($t, $email, $contexte); notifications_envoyer_mails_texte_ou_html($email, $texte); - } + } + +// une liste d'adresses renseignées dans config possiblement liste de diffusion + if ($GLOBALS['notifications']['forums_liste']){ + + //construction du mail pour envoyer_mail + $titre="$t[titre]"; + $sujet=""._T('forum:info_1_message_forum')." '$titre'"; + $charset = lire_meta('charset'); + + if ($GLOBALS['meta']['facteur_adresse_envoi'] == 'oui' AND $GLOBALS['meta']['facteur_adresse_envoi_email']) + $from_email = $GLOBALS['meta']['facteur_adresse_envoi_email']; + else + $from_email = $email_webmaster; + // nom denvoi depuis config facteur + if ($GLOBALS['meta']['facteur_adresse_envoi'] == 'oui' AND $GLOBALS['meta']['facteur_adresse_envoi_nom']) + $from_nom = $GLOBALS['meta']['facteur_adresse_envoi_nom']; + + foreach (explode(',', $GLOBALS['notifications']['forums_liste']) as $to_email) { + $email_notification_forum = charger_fonction('email_notification_forum','inc'); + $body = $email_notification_forum($t, $to_email); + include_spip('classes/facteur'); + $body = Facteur::html2text($body); + $envoyer_mail = charger_fonction('envoyer_mail','inc/'); + $envoyer_mail($to_email, $sujet, $body, $from_email, $headers); + } + } +/////////////////////////// + } diff --git a/www/plugins/notifications2/notifications/instituerarticle.php b/www/plugins/notifications2/notifications/instituerarticle.php index bd4b7c39..183ee9b0 100644 --- a/www/plugins/notifications2/notifications/instituerarticle.php +++ b/www/plugins/notifications2/notifications/instituerarticle.php @@ -32,6 +32,10 @@ function notifications_instituerarticle_dist($quoi, $id_article, $options) { if ($options['statut'] == 'prop' AND $options['statut_ancien'] != 'publie') $modele = "notifications/article_propose"; + if ($options['statut'] == 'refuse' AND in_array($options['statut_ancien'],array('prop','publie'))) { + $modele = "notifications/article_refuse"; + } + if ($modele){ $destinataires = array(); if ($GLOBALS['meta']["suivi_edito"] == "oui") diff --git a/www/plugins/notifications2/notifications_pipelines.php b/www/plugins/notifications2/notifications_pipelines.php index 4b7f75f1..31fa6006 100644 --- a/www/plugins/notifications2/notifications_pipelines.php +++ b/www/plugins/notifications2/notifications_pipelines.php @@ -39,6 +39,7 @@ function notifications_go($x){ function notifications_post_edition($x){ #spip_log($x,'notifications'); if (isset($x['args']['table']) + AND isset($GLOBALS['notifications_post_edition'][$x['args']['table']]) AND $quoi = $GLOBALS['notifications_post_edition'][$x['args']['table']] ){ // repasser par l'entree principale @@ -60,7 +61,7 @@ function notifications_notifications_destinataires($flux){ $quoi = $flux['args']['quoi']; $options = $flux['args']['options']; - // proposition d'article prevenir les admins restreints + // proposition d'article prevenir les admins restreints pour le passage de proposé à publié if ($quoi=='instituerarticle' AND $GLOBALS['notifications']['prevenir_admins_restreints'] AND $options['statut']=='prop' AND $options['statut_ancien']!='publie' // ligne a commenter si vous voulez prevenir de la publication ){ @@ -104,6 +105,50 @@ function notifications_notifications_destinataires($flux){ } + // notification d'article pour le passage de proposé à refusé + if ($quoi=='instituerarticle' AND $GLOBALS['notifications']['prevenir_auteurs_articles_refus'] + AND $options['statut']=='refuse' AND in_array($options['statut_ancien'], array('prop','publie')) // ligne a commenter si vous voulez prevenir de la publication + ){ + + $id_article = $flux['args']['id']; + include_spip('base/abstract_sql'); + $t = sql_fetsel("id_rubrique", "spip_articles", "id_article=" . intval($id_article)); + $id_rubrique = $t['id_rubrique']; + if ($GLOBALS['notifications']['limiter_rubriques']){ + $limites = $GLOBALS['notifications']['limiter_rubriques']; + $limiter_rubriques = explode(",",$limites); + } else { + $limiter_rubriques = array($id_rubrique); + } + + if (in_array($id_rubrique,$limiter_rubriques)) + { + while ($id_rubrique){ + $hierarchie[] = $id_rubrique; + $res = sql_fetsel("id_parent", "spip_rubriques", "id_rubrique=" . intval($id_rubrique)); + if (!$res){ // rubrique inexistante + $id_rubrique = 0; + break; + } + $id_parent = $res['id_parent']; + $id_rubrique = $id_parent; + } + spip_log("Refuse article > admin restreint de " . join(',', $hierarchie), 'notifications'); + + //les admins de la rub et de ses parents + $result_email = sql_select( + "auteurs.email,auteurs.id_auteur,lien.id_objet as id_rubrique", + "spip_auteurs AS auteurs JOIN spip_auteurs_liens AS lien ON auteurs.id_auteur=lien.id_auteur ", + "lien.objet='rubrique' AND ".sql_in('lien.id_objet',sql_quote($hierarchie))." AND auteurs.statut='0minirezo'"); + + while ($qui = sql_fetch($result_email)){ + spip_log($options['statut'] . " article > admin restreint " . $qui['id_auteur'] . " de la rubrique" . $qui['id_rubrique'] . " prevenu", 'notifications'); + $flux['data'][] = $qui['email']; + } + } + + } + // publication d'article : prevenir les auteurs if ($quoi=='instituerarticle' AND $GLOBALS['notifications']['prevenir_auteurs_articles'] @@ -126,7 +171,7 @@ function notifications_notifications_destinataires($flux){ // Qui va-t-on prevenir en plus ? $result_email = sql_select( - "auteurs.email", + array('auteurs.email', 'auteurs.id_auteur'), "spip_auteurs AS auteurs JOIN spip_auteurs_liens AS lien ON auteurs.id_auteur=lien.id_auteur", "lien.id_objet=".intval($id_article)." AND lien.objet='article'"); @@ -137,10 +182,16 @@ function notifications_notifications_destinataires($flux){ } } - + //publication d'article : ne pas prévenir l'auteur s'il est le validateur + if ($quoi == "instituerarticle" and $GLOBALS['notifications']['pas_prevenir_publieur']){ + $publieur_email=$GLOBALS["visiteur_session"]["email"]; + if(($key = array_search($publieur_email,$flux['data'])) !== false){ + unset($flux['data'][$key]); + } + } // forum valide ou prive : prevenir les autres contributeurs du thread ou ceux qui ont déjà répondu à l'article if (($quoi=='forumprive' AND $GLOBALS['notifications']['thread_forum_prive']) - OR ($quoi=='forumvalide' AND ($GLOBALS['notifications']['thread_forum'] or $GLOBALS['notifications']['forum'])) + OR ($quoi=='forumvalide' AND ($GLOBALS['notifications']['thread_forum'] OR $GLOBALS['notifications']['forum'] OR $GLOBALS['notifications']['forum_article'])) ){ $id_forum = $flux['args']['id']; @@ -150,14 +201,15 @@ function notifications_notifications_destinataires($flux){ // Tous les participants a ce *thread*, abonnes // on prend les emails parmi notification_email (prioritaire si rempli) email_auteur ou email de l'auteur qd id_auteur connu + // note : on exclut les forums refusé ou marqué comme spam $s = sql_select("F.email_auteur, F.notification_email, A.email", "spip_forum AS F LEFT JOIN spip_auteurs AS A ON F.id_auteur=A.id_auteur", - "notification=1 AND id_thread=" . intval($t['id_thread']) . " AND (email_auteur != '' OR notification_email != '' OR A.email IS NOT NULL )"); + "notification=1 AND id_thread=" . intval($t['id_thread']) . " AND (email_auteur != '' OR notification_email != '' OR A.email IS NOT NULL) AND F.statut NOT IN ('off','spam')") ; // Eventuellement tout ceux qui ont répondu à cet article if ($GLOBALS['notifications']['forum_article']){ $s = sql_select("F.email_auteur, F.notification_email, A.email", "spip_forum AS F LEFT JOIN spip_auteurs AS A ON F.id_auteur=A.id_auteur", - "notification=1 AND objet=".sql_quote($t['objet'])." AND id_objet=" . intval($t['id_objet']) . " AND (email_auteur != '' OR notification_email != '' OR A.email IS NOT NULL )"); + "notification=1 AND objet=".sql_quote($t['objet'])." AND id_objet=" . intval($t['id_objet']) . " AND (email_auteur != '' OR notification_email != '' OR A.email IS NOT NULL) AND F.statut NOT IN ('off','spam')"); } while ($r = sql_fetch($s)){ if ($r['notification_email']) @@ -168,19 +220,6 @@ function notifications_notifications_destinataires($flux){ $flux['data'][] = $r['email']; } - /* - // 3. Tous les auteurs des messages qui precedent (desactive egalement) - // (possibilite exclusive de la possibilite precedente) - // TODO: est-ce utile, par rapport au thread ? - else if (defined('_SUIVI_FORUMS_REPONSES') - AND _SUIVI_FORUMS_REPONSES) { - $id_parent = $id_forum; - while ($r = spip_fetch_array(spip_query("SELECT email_auteur, id_parent FROM spip_forum WHERE id_forum=$id_parent AND statut='publie'"))) { - $tous[] = $r['email_auteur']; - $id_parent = $r['id_parent']; - } - } - */ } } diff --git a/www/plugins/notifications2/paquet.xml b/www/plugins/notifications2/paquet.xml index bc159c8f..bf4a1ab6 100644 --- a/www/plugins/notifications2/paquet.xml +++ b/www/plugins/notifications2/paquet.xml @@ -1,9 +1,9 @@ - - + + - \ No newline at end of file + diff --git a/www/plugins/notifications2/svn.revision b/www/plugins/notifications2/svn.revision index 9e6e7d92..8b1839a8 100644 --- a/www/plugins/notifications2/svn.revision +++ b/www/plugins/notifications2/svn.revision @@ -1,10 +1,10 @@ Origine: file:///home/svn/repository/spip-zone/_plugins_/notifications/trunk -Revision: 84941 -Dernier commit: 2014-10-01 13:00:23 +0200 +Revision: 99183 +Dernier commit: 2016-08-17 12:19:01 +0200 file:///home/svn/repository/spip-zone/_plugins_/notifications/trunk -84941 -2014-10-01 13:00:23 +0200 +99183 +2016-08-17 12:19:01 +0200 \ No newline at end of file diff --git a/www/plugins/odt2spip_30/action/odt2spip_importe.php b/www/plugins/odt2spip_30/action/odt2spip_importe.php index 893a8654..4d6485bb 100644 --- a/www/plugins/odt2spip_30/action/odt2spip_importe.php +++ b/www/plugins/odt2spip_30/action/odt2spip_importe.php @@ -10,7 +10,7 @@ * @subpackage odt2spip * @category import * - * @version $Id: odt2spip_importe.php 81585 2014-03-22 17:15:03Z root $ + * @version $Id: odt2spip_importe.php 81585 2014-03-22 17:08:08Z cy_altern@yahoo.fr $ * */ if (!defined("_ECRIRE_INC_VERSION")) return; diff --git a/www/plugins/odt2spip_30/paquet.xml b/www/plugins/odt2spip_30/paquet.xml index 228a7d32..00c4abd3 100644 --- a/www/plugins/odt2spip_30/paquet.xml +++ b/www/plugins/odt2spip_30/paquet.xml @@ -1,10 +1,10 @@ diff --git a/www/plugins/odt2spip_30/svn.revision b/www/plugins/odt2spip_30/svn.revision index b8c28324..cb57ed35 100644 --- a/www/plugins/odt2spip_30/svn.revision +++ b/www/plugins/odt2spip_30/svn.revision @@ -1,10 +1,10 @@ Origine: file:///home/svn/repository/spip-zone/_plugins_/odt2spip/trunk -Revision: 84608 -Dernier commit: 2014-09-14 20:53:11 +0200 +Revision: 92767 +Dernier commit: 2015-11-09 09:50:10 +0100 file:///home/svn/repository/spip-zone/_plugins_/odt2spip/trunk -84608 -2014-09-14 20:53:11 +0200 +92767 +2015-11-09 09:50:10 +0100 \ No newline at end of file diff --git a/www/plugins/redirhttps/images/redirhttps-128.png b/www/plugins/redirhttps.bak/images/redirhttps-128.png similarity index 100% rename from www/plugins/redirhttps/images/redirhttps-128.png rename to www/plugins/redirhttps.bak/images/redirhttps-128.png diff --git a/www/plugins/redirhttps/lang/paquet-redirhttps.xml b/www/plugins/redirhttps.bak/lang/paquet-redirhttps.xml similarity index 100% rename from www/plugins/redirhttps/lang/paquet-redirhttps.xml rename to www/plugins/redirhttps.bak/lang/paquet-redirhttps.xml diff --git a/www/plugins/redirhttps/lang/paquet-redirhttps_en.php b/www/plugins/redirhttps.bak/lang/paquet-redirhttps_en.php similarity index 100% rename from www/plugins/redirhttps/lang/paquet-redirhttps_en.php rename to www/plugins/redirhttps.bak/lang/paquet-redirhttps_en.php diff --git a/www/plugins/redirhttps/lang/paquet-redirhttps_es.php b/www/plugins/redirhttps.bak/lang/paquet-redirhttps_es.php similarity index 100% rename from www/plugins/redirhttps/lang/paquet-redirhttps_es.php rename to www/plugins/redirhttps.bak/lang/paquet-redirhttps_es.php diff --git a/www/plugins/redirhttps/lang/paquet-redirhttps_fr.php b/www/plugins/redirhttps.bak/lang/paquet-redirhttps_fr.php similarity index 100% rename from www/plugins/redirhttps/lang/paquet-redirhttps_fr.php rename to www/plugins/redirhttps.bak/lang/paquet-redirhttps_fr.php diff --git a/www/plugins/redirhttps/lang/paquet-redirhttps_sk.php b/www/plugins/redirhttps.bak/lang/paquet-redirhttps_sk.php similarity index 100% rename from www/plugins/redirhttps/lang/paquet-redirhttps_sk.php rename to www/plugins/redirhttps.bak/lang/paquet-redirhttps_sk.php diff --git a/www/plugins/redirhttps/lang/redirhttps.xml b/www/plugins/redirhttps.bak/lang/redirhttps.xml similarity index 100% rename from www/plugins/redirhttps/lang/redirhttps.xml rename to www/plugins/redirhttps.bak/lang/redirhttps.xml diff --git a/www/plugins/redirhttps/paquet.xml b/www/plugins/redirhttps.bak/paquet.xml similarity index 100% rename from www/plugins/redirhttps/paquet.xml rename to www/plugins/redirhttps.bak/paquet.xml diff --git a/www/plugins/redirhttps/plugin.xml b/www/plugins/redirhttps.bak/plugin.xml similarity index 100% rename from www/plugins/redirhttps/plugin.xml rename to www/plugins/redirhttps.bak/plugin.xml diff --git a/www/plugins/redirhttps/redirhttps_options.php b/www/plugins/redirhttps.bak/redirhttps_options.php similarity index 100% rename from www/plugins/redirhttps/redirhttps_options.php rename to www/plugins/redirhttps.bak/redirhttps_options.php diff --git a/www/plugins/redirhttps/svn.revision b/www/plugins/redirhttps.bak/svn.revision similarity index 100% rename from www/plugins/redirhttps/svn.revision rename to www/plugins/redirhttps.bak/svn.revision diff --git a/www/plugins/rss_article_3_0/base/rssarticle.php b/www/plugins/rss_article_3_0/base/rssarticle.php index c74ba2b3..155c3521 100644 --- a/www/plugins/rss_article_3_0/base/rssarticle.php +++ b/www/plugins/rss_article_3_0/base/rssarticle.php @@ -1,5 +1,7 @@ "bigint(21) NOT NULL", - "id_syndic" => "bigint(21) NOT NULL"); - + "id_article" => "bigint(21) NOT NULL", + "id_syndic" => "bigint(21) NOT NULL"); + $spip_rssarticle_key = array( "INDEX" => "id_article"); $tables_auxiliaires['spip_articles_syndic'] = array( - 'field' => &$spip_rssarticle, - 'key' => &$spip_rssarticle_key); - + 'field' => &$spip_rssarticle, + 'key' => &$spip_rssarticle_key); + return $tables_auxiliaires; } @@ -27,20 +29,16 @@ function rssarticle_declarer_tables_auxiliaires($tables_auxiliaires){ * @return array */ function rssarticle_declarer_tables_interfaces($interface){ - + $interface['table_des_tables']['articles_syndic']='articles_syndic'; - + // permet au compilateur de determiner explicitement les jointures possibles - // lorsqu’une boucle sur une table demande un champ inconnu + // lorsqu'une boucle sur une table demande un champ inconnu $interface['tables_jointures']['spip_articles'][] = 'articles_syndic'; return $interface; } - - -if (!defined("_ECRIRE_INC_VERSION")) return; - /** * Ajouter des champs a la table syndic * @param array $tables_principales @@ -49,7 +47,7 @@ if (!defined("_ECRIRE_INC_VERSION")) return; function rssarticle_declarer_tables_principales($tables_principales){ // Extension de la table syndic $tables_principales['spip_syndic']['field']['rssarticle'] = "varchar(3) DEFAULT 'non' NOT NULL"; - + return $tables_principales; } diff --git a/www/plugins/rss_article_3_0/exec/rss_article.php b/www/plugins/rss_article_3_0/exec/rss_article.php index 12d55363..c2d82599 100644 --- a/www/plugins/rss_article_3_0/exec/rss_article.php +++ b/www/plugins/rss_article_3_0/exec/rss_article.php @@ -1,44 +1,44 @@

                \n"; // outch ! aie aie aie ! au secours ! - echo gros_titre(_T('rssarticle:activer_recopie_intro'),'', false); + // titre + echo "


                \n"; // outch ! aie aie aie ! au secours ! + echo gros_titre(_T('rssarticle:activer_recopie_intro'),'', false); // colonne gauche echo debut_gauche('', true); - echo debut_droite('', true); + echo debut_droite('', true); // centre de la page genie_rssarticle_copie_dist("manuel"); - echo '
                '.date('Y/m/d H:i:s').'
                '._T('rssarticle:maj_manuelle').'
                '; - echo ''; - + echo '
                '.date('Y/m/d H:i:s').'
                '._T('rssarticle:maj_manuelle').'
                '; + echo ''; // pied echo fin_gauche() . fin_page(); diff --git a/www/plugins/rss_article_3_0/formulaires/configurer_rssarticle.html b/www/plugins/rss_article_3_0/formulaires/configurer_rssarticle.html index 7bd31970..f04338f1 100644 --- a/www/plugins/rss_article_3_0/formulaires/configurer_rssarticle.html +++ b/www/plugins/rss_article_3_0/formulaires/configurer_rssarticle.html @@ -9,66 +9,60 @@ #ACTION_FORMULAIRE{#ENV{action}}
                  -
                • -

                  <:rssarticle:statut_article_importe:>

                  -
                    - -
                  - -
                • -
                • -

                  <:rssarticle:mode:>

                  -
                    -
                    - - -
                    -
                    - - -
                    -
                  -
                • -
                • -

                  <:rssarticle:cron_interval:>

                  - - - -
                • -
                • -

                  <:rssarticle:suivi_syndic:>

                  -
                    -
                  • - - -
                  • -
                  • - - -
                  • -
                  -
                • -
                • -

                  <:rssarticle:copie_logo:>

                  - - - -
                • -
                • -

                  <:rssarticle:html2spip:>

                  - - - -
                • +
                • +

                  <:rssarticle:statut_article_importe:>

                  +
                    + +
                  +
                • +
                • +

                  <:rssarticle:mode:>

                  +
                    +
                    + + +
                    +
                    + + +
                    +
                  +
                • +
                • +

                  <:rssarticle:cron_interval:>

                  + + +
                • +
                • +

                  <:rssarticle:suivi_syndic:>

                  +
                    +
                  • + + +
                  • +
                  • + + +
                  • +
                  +
                • + +
                • +

                  <:rssarticle:html2spip:>

                  + + +
                - [(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ] - -

                  -

                - - ] + [(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ] + +

                 

                + ] \ No newline at end of file diff --git a/www/plugins/rss_article_3_0/formulaires/editer_rssarticle.html b/www/plugins/rss_article_3_0/formulaires/editer_rssarticle.html index d523609d..a4f14050 100644 --- a/www/plugins/rss_article_3_0/formulaires/editer_rssarticle.html +++ b/www/plugins/rss_article_3_0/formulaires/editer_rssarticle.html @@ -1,22 +1,20 @@ - -
                - - [

                (#ENV*{message_ok})

                ] +
                + [

                (#ENV*{message_ok})

                ] [

                (#ENV*{message_erreur})

                ] -
                +
                #ACTION_FORMULAIRE{#ENV{action}}
                  #SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}#SET{obli,'obligatoire'} -
                • -
                  - [(#CHEMIN_IMAGE{rssarticle-32.png}|balise_img{RSS})] - - -
                  - [(#ENV*{erreurs}|table_valeur{rssarticle})] -
                • +
                • +
                  + [(#CHEMIN_IMAGE{rssarticle-32.png}|balise_img{RSS})] + + +
                  + [(#ENV*{erreurs}|table_valeur{rssarticle})] +
                - [(#ENV{editable}|oui)

                ] + [(#ENV{editable}|oui)

                ]
                \ No newline at end of file diff --git a/www/plugins/rss_article_3_0/formulaires/editer_rssarticle.php b/www/plugins/rss_article_3_0/formulaires/editer_rssarticle.php index 1c7fcf25..00bf6728 100644 --- a/www/plugins/rss_article_3_0/formulaires/editer_rssarticle.php +++ b/www/plugins/rss_article_3_0/formulaires/editer_rssarticle.php @@ -1,11 +1,13 @@ true, 'message_ok'=>''); - - if (_request('rssarticle')=='oui') { - sql_updateq('spip_syndic',array( - 'rssarticle'=> 'oui', - 'resume'=>'non', - 'oubli'=>'oui' - ),'id_syndic='.intval($id_syndic)); - - // on force le site en mode oubli et pas resume - // on rensynchronise la syndic pour passer les anciens articles (qui etaient ss doute en mode resume) en mode complet HTML - //sql_delete("spip_syndic_articles", "id_syndic=".sql_quote($id_syndic)); // alternative ;) - include_spip('genie/syndic'); - $t = syndic_a_jour($id_syndic); - } else { - sql_updateq('spip_syndic',array('rssarticle'=> 'non'),'id_syndic='.intval($id_syndic)); - } - - $message = _T("rssarticle:site_maj"); + if (_request('rssarticle')=='oui') { + sql_updateq('spip_syndic',array( + 'rssarticle'=> 'oui', + 'resume'=>'non', + 'oubli'=>'oui' + ),'id_syndic='.intval($id_syndic)); + + // on force le site en mode oubli et pas resume + // on rensynchronise la syndic pour passer les anciens articles (qui etaient ss doute en mode resume) en mode complet HTML + // sql_delete("spip_syndic_articles", "id_syndic=".sql_quote($id_syndic)); // alternative ;) + include_spip('genie/syndic'); + $t = syndic_a_jour($id_syndic); + } else { + sql_updateq('spip_syndic',array('rssarticle'=> 'non'),'id_syndic='.intval($id_syndic)); + } + $message = array('editable'=>true, 'message_ok'=>_T("rssarticle:site_maj")); return $message; - } ?> \ No newline at end of file diff --git a/www/plugins/rss_article_3_0/genie/rssarticle_copie.php b/www/plugins/rss_article_3_0/genie/rssarticle_copie.php index 5f5a1e8b..10d6576b 100644 --- a/www/plugins/rss_article_3_0/genie/rssarticle_copie.php +++ b/www/plugins/rss_article_3_0/genie/rssarticle_copie.php @@ -15,167 +15,178 @@ include_spip('inc/chercher_logo'); include_spip('inc/rubriques'); include_spip('inc/config'); -function genie_rssarticle_copie_dist($t){ +function genie_rssarticle_copie_dist($t){ - // configuration (ou valeurs par defaut) - if (lire_config('rssarticle/import_statut')=="publie") $import_statut="publie"; else $import_statut="prop"; - if (lire_config('rssarticle/mode')=="auto") $mode_auto=true; else $mode_auto=false; - if (lire_config('rssarticle/email_alerte')=="on") $email_alerte=true; else $email_alerte=false; - if (lire_config('rssarticle/copie_logo')=="on") $copie_logo=true; else $copie_logo=false; - if (lire_config('rssarticle/html2spip')=="on") $html2spip=true; else $html2spip=false; - $email_suivi = lire_config('rssarticle/email_suivi'); - - // autres valeurs - $accepter_forum = substr($GLOBALS['meta']['forums_publics'],0,3); - - // principe de pile: - // on boucle sur les derniers articles syndiques pour les retirer ensuite - // bourrin voir les requetes avec jointure du Miroir ou du site Rezo - $log = ""; - $log_c = 0; - - // boucle sur les sites publies - if ($mode_auto) $u = sql_select("id_syndic,id_rubrique,id_secteur","spip_syndic","statut='publie'"); // tous - else $u = sql_select("id_syndic,id_rubrique,id_secteur","spip_syndic","statut='publie' AND rssarticle='oui'"); - - while ($b = sql_fetch($u)) { - $id_syndic = (int) $b['id_syndic']; - $id_rubrique = (int) $b['id_rubrique']; - $id_secteur = (int) $b['id_secteur']; - - // sur chaque site copie les derniers syndication - $s = sql_select("*", "spip_syndic_articles", "statut='publie' AND id_syndic='$id_syndic'","","maj DESC","10"); // par flot de 10 articles / site pour limiter la charge - while ($a = sql_fetch($s)) { - $titre = $a['titre']; - $url = $a['url']; - $id_syndic_article = $a['id_syndic_article']; - - // article avec mm titre existe ? (test doublons sur l'url plutot que sr le titre) - if (!$row = sql_fetsel("id_article","spip_articles","url_site=".sql_quote($url))) { - - $texte = $a['descriptif']; - //traitement pour syntaxe SPIP - if($html2spip) - $texte = html2spip($texte); - $lang = $a['lang']; - $url = $a['url']; - $tags = $a['tags']; - $lsDate = $a['date']; - - - if ($lang=="") - $lang = $GLOBALS['spip_lang']; - - // cas particulier: - // site multilingue avec la configuration: 1 lang par rubrique - // on force l'article a avoir la langue de la rubrique ds lequel il est importee(pour omaidi) - if ($GLOBALS['meta']['multi_rubriques']=='oui') { - $s_lang = sql_select("lang", "spip_rubriques", "id_rubrique=$id_rubrique"); - while ($a_lang = sql_fetch($s_lang)) - $lang = $a_lang['lang']; - } - - //$lsDate = date('Y-m-d H:i:s'); - // creation de l'article - $id_article = sql_insertq( 'spip_articles', array( - 'titre'=>$titre, 'id_rubrique'=>$id_rubrique, - 'texte'=>$texte, 'statut'=>$import_statut, 'id_secteur'=>$id_secteur, - 'date'=> $lsDate, 'accepter_forum'=>$accepter_forum, 'lang'=>$lang, 'url_site'=>$url)); - - // lier article et site - sql_insertq( 'spip_articles_syndic', array('id_article'=>$id_article, 'id_syndic'=>$id_syndic)); - - // gestion auteur - $auteurs= explode(", ",$a['lesauteurs']); - foreach ($auteurs as $k => $auteur) { - if ($current_id_auteur = rssarticle_get_id_auteur($auteur)) - sql_insertq( 'spip_auteurs_liens', array('id_auteur'=>$current_id_auteur, 'id_objet'=>$id_article, 'objet'=>'article')); - } - - // tags a convertir en documents distants - $doc_distants = extraire_enclosures($tags); - foreach ($doc_distants as $k=>$doc_distant) { - $infos = recuperer_infos_distantes($doc_distant); - if ($infos['extension']) { - $ext = $infos['extension']; - $taille = $infos['tailles']; - $row = sql_fetsel("inclus", "spip_types_documents", "extension=" . sql_quote($ext) . " AND upload='oui'"); // extension autorisee ? - if ($row) { - $id_document = sql_insertq( 'spip_documents', array( - 'extension'=>$ext, - 'date'=> $lsDate, - 'fichier'=> $doc_distant, - 'taille'=> $taille, - 'mode' => 'document', - 'distant' => 'oui')); - - sql_insertq( 'spip_documents_liens', array( - 'id_document' =>$id_document, - 'id_objet'=> $id_article, - 'objet'=> 'article', - 'vu'=> 'non')); - } - } - - } - - // logo - if ($copie_logo) { - if ($logo_site = inc_chercher_logo_dist($id_syndic,"id_syndic")) { - $logo_article = "arton$id_article.".$logo_site[3]; - @copy($logo_site[0],_DIR_LOGOS."$logo_article"); - } - } - - $log_c++; - $log .= "\n - $titre"; - - // on "depublie" l'article syndique qui vient d'etre copie - sql_update("spip_syndic_articles", array('statut' => '"refuse"'), "id_syndic_article=$id_syndic_article"); + // configuration (ou valeurs par defaut) + if (lire_config('rssarticle/import_statut')=="publie") + $import_statut="publie"; + else + $import_statut="prop"; + if (lire_config('rssarticle/mode')=="auto") + $mode_auto=true; + else + $mode_auto=false; + if (lire_config('rssarticle/email_alerte')=="on") + $email_alerte=true; + else + $email_alerte=false; + if (lire_config('rssarticle/copie_logo')=="on") + $copie_logo=true; + else + $copie_logo=false; + if (lire_config('rssarticle/html2spip')=="on") + $html2spip=true; + else + $html2spip=false; + $email_suivi = lire_config('rssarticle/email_suivi'); + + // autres valeurs + $accepter_forum = substr($GLOBALS['meta']['forums_publics'],0,3); + + // principe de pile: + // on boucle sur les derniers articles syndiques pour les retirer ensuite + // bourrin voir les requetes avec jointure du Miroir ou du site Rezo + $log = ""; + $log_c = 0; + + // boucle sur les sites publies + if ($mode_auto) + $u = sql_select("id_syndic,id_rubrique,id_secteur","spip_syndic","statut='publie'"); // tous + else + $u = sql_select("id_syndic,id_rubrique,id_secteur","spip_syndic","statut='publie' AND rssarticle='oui'"); + + while ($b = sql_fetch($u)) { + $id_syndic = (int) $b['id_syndic']; + $id_rubrique = (int) $b['id_rubrique']; + $id_secteur = (int) $b['id_secteur']; + + // sur chaque site copie les derniers syndication + $s = sql_select("*", "spip_syndic_articles", "statut='publie' AND id_syndic='$id_syndic'","","maj DESC","10"); // par flot de 10 articles / site pour limiter la charge + while ($a = sql_fetch($s)) { + $titre = $a['titre']; + $url = $a['url']; + $id_syndic_article = $a['id_syndic_article']; + + // article avec mm titre existe ? (test doublons sur l'url plutot que sr le titre) + if (!$id_article = sql_getfetsel("id_article","spip_articles","url_site=".sql_quote($url))) { + $texte = $a['descriptif']; + //traitement pour syntaxe SPIP + if($html2spip) + $texte = html2spip($texte); + $lang = $a['lang']; + $url = $a['url']; + $tags = $a['tags']; + $lsdate = $a['date']; + + if ($lang=="") + $lang = $GLOBALS['spip_lang']; + + // cas particulier: + // site multilingue avec la configuration: 1 lang par rubrique + // on force l'article a avoir la langue de la rubrique ds lequel il est importee(pour omaidi) + if ($GLOBALS['meta']['multi_rubriques']=='oui') { + $s_lang = sql_select("lang", "spip_rubriques", "id_rubrique=$id_rubrique"); + while ($a_lang = sql_fetch($s_lang)) + $lang = $a_lang['lang']; + } + + //$lsdate = date('Y-m-d H:i:s'); + // creation de l'article + $id_article = sql_insertq( 'spip_articles', array( + 'titre'=>$titre, 'id_rubrique'=>$id_rubrique, + 'texte'=>$texte, 'statut'=>$import_statut, 'id_secteur'=>$id_secteur, + 'date'=> $lsdate, 'accepter_forum'=>$accepter_forum, 'lang'=>$lang, 'url_site'=>$url)); + + // lier article et site + sql_insertq( 'spip_articles_syndic', array('id_article'=>$id_article, 'id_syndic'=>$id_syndic)); + + // gestion auteur + $auteurs= explode(", ",$a['lesauteurs']); + foreach ($auteurs as $k => $auteur) { + if ($current_id_auteur = rssarticle_get_id_auteur($auteur)) + sql_insertq( 'spip_auteurs_liens', array('id_auteur'=>$current_id_auteur, 'id_objet'=>$id_article, 'objet'=>'article')); + } + + // tags a convertir en documents distants + $doc_distants = extraire_enclosures($tags); + foreach ($doc_distants as $k=>$doc_distant) { + $infos = recuperer_infos_distantes($doc_distant); + if ($infos['extension']) { + $ext = $infos['extension']; + $taille = $infos['tailles']; + $inclus = sql_getfetsel("inclus", "spip_types_documents", "extension=" . sql_quote($ext) . " AND upload='oui'"); // extension autorisee ? + if ($inclus) { + $id_document = sql_insertq( 'spip_documents', array( + 'extension'=>$ext, + 'date'=> $lsdate, + 'fichier'=> $doc_distant, + 'taille'=> $taille, + 'mode' => 'document', + 'distant' => 'oui')); + + sql_insertq( 'spip_documents_liens', array( + 'id_document' =>$id_document, + 'id_objet'=> $id_article, + 'objet'=> 'article', + 'vu'=> 'non')); + } + } + } + + // logo + if ($copie_logo) { + if ($logo_site = inc_chercher_logo_dist($id_syndic,"id_syndic")) { + $logo_article = "arton$id_article.".$logo_site[3]; + @copy($logo_site[0],_DIR_LOGOS."$logo_article"); + } + } + + $log_c++; + $log .= "\n - $titre"; + + // on "depublie" l'article syndique qui vient d'etre copie + sql_update("spip_syndic_articles", array('statut' => '"refuse"'), "id_syndic_article=".intval($id_syndic_article)); + + // Mise à jour des dates de rubriques après création d'un article dedans + if ($id_article) { + if (function_exists('calculer_rubriques')) + calculer_rubriques(); + if (function_exists('calculer_langues_rubriques')) + calculer_langues_rubriques(); + if (function_exists('propager_les_secteurs')) + propager_les_secteurs(); + } + } // test doublons + } + } // FIN PILE - // Mise à jour des dates de rubriques après création d'un article dedans - if ($id_article) { - if (function_exists('calculer_rubriques')) - calculer_rubriques(); - if (function_exists('calculer_langues_rubriques')) - calculer_langues_rubriques(); - if (function_exists('propager_les_secteurs')) - propager_les_secteurs(); - } - - } // test doublons - } - } // FIN PILE - - // log et alerte email - $log .= "\n\n---------\nPlugin Copie RSS en Articles: $log_c articles copies\n"; - spip_log($log); - $log .= $GLOBALS['meta']['adresse_site']."/ecrire/?exec=accueil"; - - if ($email_alerte && $email_suivi !="" && $log_c > 0) - envoyer_mail($email_suivi,"Copie RSS en Articles", $log); - + $log .= "\n\n---------\nPlugin Copie RSS en Articles: $log_c articles copies\n"; + spip_log($log); + $log .= $GLOBALS['meta']['adresse_site']."/ecrire/?exec=accueil"; + + if ($email_alerte && $email_suivi !="" && $log_c > 0) + envoyer_mail($email_suivi,"Copie RSS en Articles", $log); // maintenance generale - // mode auto: on efface les syndic_articles de plus de 2 mois pour soulager le systeme (cf genie/syndic) - // attention: on efface sur l'ensemble des sites syndiques ss tenir compte de l'option + // mode auto: on efface les syndic_articles de plus de 2 mois pour soulager le systeme (cf genie/syndic) + // attention: on efface sur l'ensemble des sites syndiques ss tenir compte de l'option if ($mode_auto) sql_delete('spip_syndic_articles', "maj < DATE_SUB(NOW(), INTERVAL 2 MONTH) AND date < DATE_SUB(NOW(), INTERVAL 2 MONTH)"); - + return 1; } // // recupere id d'un auteur selon son nom sinon le creer -function rssarticle_get_id_auteur($nom) { - if (trim($nom)=="") - return false; - - if ($row = sql_fetsel(array("id_auteur"),"spip_auteurs","nom=".sql_quote($nom))) - return $row['id_auteur']; +function rssarticle_get_id_auteur($nom) { + if (trim($nom)=="") + return false; + + if ($id_auteur = sql_getfetsel("id_auteur","spip_auteurs","nom=".sql_quote($nom))) + return $id_auteur; - // auteur inconnu, on le cree ... - return sql_insertq('spip_auteurs',array('nom'=>$nom,'statut'=>'1comite')); + // auteur inconnu, on le cree ... + return sql_insertq('spip_auteurs',array('nom'=>$nom,'statut'=>'1comite')); } // @@ -196,7 +207,7 @@ function extraire_enclosures($tags) { * * Nettoyer l'utf-8 et ses accents * -**/ + */ function clean_utf8($t) { if (!preg_match('!\S!u', $t)) $t = preg_replace_callback(',&#x([0-9a-f]+);,i', 'utf8_do', utf8_encode(utf8_decode($t))); @@ -234,7 +245,6 @@ function html2spip($lapage){ // images (cf ressource) $lapage = preg_replace(",]*src=[^<>]*(http[^<>'\"]*)[^<>]*>,uims","[img]\\1[//img]", $lapage); - // intertitres $lapage = preg_replace(",<(h[1-3])( [^>]*)?".">(.+),Uims", "\r{{{ \\3 }}}\r", $lapage); // tableaux diff --git a/www/plugins/rss_article_3_0/lang/rssarticle_ar.php b/www/plugins/rss_article_3_0/lang/rssarticle_ar.php index 726711cd..99692319 100644 --- a/www/plugins/rss_article_3_0/lang/rssarticle_ar.php +++ b/www/plugins/rss_article_3_0/lang/rssarticle_ar.php @@ -1,37 +1,37 @@ 'هذا المقال منقول عن موقع', - 'activer_recopie_intro' => 'تدفق RSS الى المقالات', - 'activer_recopie' => 'نسخ المقالات الناتحة عن تدفق RSS الى مقالات SPIP', + // A + 'article_origine' => 'هذا المقال منقول عن موقع', + 'activer_recopie_intro' => 'تدفق RSS الى المقالات', + 'activer_recopie' => 'نسخ المقالات الناتحة عن تدفق RSS الى مقالات SPIP', - // C - 'citer_source' => 'كر المصدر', - 'citer_source_oui' => 'ذكر عنوان المقال المصدر في المقال المستورد', - 'copie_logo' => 'نسخ شعار الموقع وجعله سعار المقال', + // C + 'citer_source' => 'كر المصدر', + 'citer_source_oui' => 'ذكر عنوان المقال المصدر في المقال المستورد', + 'copie_logo' => 'نسخ شعار الموقع وجعله سعار المقال', - // S - 'statut_article_importe' => 'وضعية المقالات المستوردة', - 'suivi_syndic' => 'متابعة الترخيص', + // S + 'statut_article_importe' => 'وضعية المقالات المستوردة', + 'suivi_syndic' => 'متابعة الترخيص', - // E - 'email_alerte' => 'إنذار بالبريد الإلكتروني عند كل ترخيص في مقال؟', - 'email_alerte_email' => 'في حال الموافقة، على أي عنوان يتم إرسال الإنذار؟', + // E + 'email_alerte' => 'إنذار بالبريد الإلكتروني عند كل ترخيص في مقال؟', + 'email_alerte_email' => 'في حال الموافقة، على أي عنوان يتم إرسال الإنذار؟', - // I - 'install_rssarticle' => 'إنشاء جدول spip_articles_syndic', + // I + 'install_rssarticle' => 'إنشاء جدول spip_articles_syndic', - // M - 'mode' => 'وضعية التشغيل', - 'mode_auto' => 'الوضعية الآلية: نسخ كل المواقع المبوبة كمقالات', - 'mode_manuel' => 'الوضعية اليدوية: تحدد يدوياً المواقع المبوبة التي تريد نسخها كمقالات' + // M + 'mode' => 'وضعية التشغيل', + 'mode_auto' => 'الوضعية الآلية: نسخ كل المواقع المبوبة كمقالات', + 'mode_manuel' => 'الوضعية اليدوية: تحدد يدوياً المواقع المبوبة التي تريد نسخها كمقالات' ); - + ?> diff --git a/www/plugins/rss_article_3_0/lang/rssarticle_fr.php b/www/plugins/rss_article_3_0/lang/rssarticle_fr.php index c8686b1c..7b6b3d15 100644 --- a/www/plugins/rss_article_3_0/lang/rssarticle_fr.php +++ b/www/plugins/rss_article_3_0/lang/rssarticle_fr.php @@ -1,48 +1,47 @@ 'Cet article est repris du site', + 'activer_recopie_intro' => 'Flux RSS en Articles', + 'activer_recopie' => 'Copier les articles issus de ce flux RSS en articles SPIP', - // A - 'article_origine' => 'Cet article est repris du site', - 'activer_recopie_intro' => 'Flux RSS en Articles', - 'activer_recopie' => 'Copier les articles issus de ce flux RSS en articles SPIP', + // C + 'citer_source' => 'Citer la source', + 'citer_source_oui' => 'Citer l\'URL de l\'article d\'origine dans l\'article importé', + 'configuration_rssarticle' => 'Flux RSS en articles', + 'copie_logo' => 'Recopier le logo du site comme logo d\'article', + 'cron_interval' => 'Fréquence de la copie des flux RSS en articles', + 'cron_interval_timer' => 'Intervalle en seconde ', + + //R + 'html2spip' => 'Passer le HTML en syntaxe SPIP. Utilisez le plugin "ressource" pour afficher ensuite les images.', - // C - 'citer_source' => 'Citer la source', - 'citer_source_oui' => 'Citer l\'URL de l\'article d\'origine dans l\'article importé', - 'configuration_rssarticle' => 'Flux RSS en articles', - 'copie_logo' => 'Recopier le logo du site comme logo d\'article', - 'cron_interval' => 'Fréquence de la copie des flux RSS en articles', - 'cron_interval_timer' => 'Intervalle en seconde ', - - //R - 'html2spip' => 'Passer le HTML en syntaxe SPIP. Utilisez le plugin "ressource" pour afficher ensuite les images.', - - // S - 'statut_article_importe' => 'Statut des articles importés', - 'suivi_syndic' => 'Suivi de la syndication', - 'site_maj' => 'Option enregistrée', - - // E - 'email_alerte' => 'Prévenir par email à chaque nouvelle syndication en articles ?', - 'email_alerte_email' => 'Si oui, sur quel email ? ', - - // I - 'install_rssarticle' => 'Création de la table spip_articles_syndic', - - // M - 'maj_manuelle' => 'La copie manuelle des derniers flux RSS en articles a été effectuée', - 'maj_recharge' => 'Relancer la copie manuelle', - 'mode' => 'Mode de fonctionnement', - 'mode_auto' => 'Mode automatique: tous les sites référencés sont recopiés en articles', - 'mode_manuel' => 'Mode manuel: vous selectionnez manuellement les sites référencés qui doivent être recopiés en articles', - - // T - 'titre_page_configurer_rssarticle' => 'Copie RSS en articles' - + // S + 'statut_article_importe' => 'Statut des articles importés', + 'suivi_syndic' => 'Suivi de la syndication', + 'site_maj' => 'Option enregistrée', + + // E + 'email_alerte' => 'Prévenir par email à chaque nouvelle syndication en articles ?', + 'email_alerte_email' => 'Si oui, sur quel email ? ', + + // I + 'install_rssarticle' => 'Création de la table spip_articles_syndic', + + // M + 'maj_manuelle' => 'La copie manuelle des derniers flux RSS en articles a été effectuée', + 'maj_recharge' => 'Relancer la copie manuelle', + 'mode' => 'Mode de fonctionnement', + 'mode_auto' => 'Mode automatique: tous les sites référencés sont recopiés en articles', + 'mode_manuel' => 'Mode manuel: vous selectionnez manuellement les sites référencés qui doivent être recopiés en articles', + + // T + 'titre_page_configurer_rssarticle' => 'Copie RSS en articles' ); diff --git a/www/plugins/rss_article_3_0/paquet.xml b/www/plugins/rss_article_3_0/paquet.xml index f7dc1f69..5224eeb8 100644 --- a/www/plugins/rss_article_3_0/paquet.xml +++ b/www/plugins/rss_article_3_0/paquet.xml @@ -1,21 +1,21 @@ Flux RSS en articles erational - LudoRA + LudoRA GNU/GPL v3 - - - - - + + + + + diff --git a/www/plugins/rss_article_3_0/prive/contenu/rssarticle.html b/www/plugins/rss_article_3_0/prive/contenu/rssarticle.html index 6de56858..45278ce8 100644 --- a/www/plugins/rss_article_3_0/prive/contenu/rssarticle.html +++ b/www/plugins/rss_article_3_0/prive/contenu/rssarticle.html @@ -1,3 +1,3 @@
                - #FORMULAIRE_EDITER_RSSARTICLE{#ID_SYNDIC} + #FORMULAIRE_EDITER_RSSARTICLE{#ID_SYNDIC}
                \ No newline at end of file diff --git a/www/plugins/rss_article_3_0/prive/themes/spip/images/rssarticle-128.png b/www/plugins/rss_article_3_0/prive/themes/spip/images/rssarticle-128.png index edf816601d56f9790e86a12a9b03810e6d1ebf23..ff38077375d9513f7b8e6da4b9e9a32f0f25e4a4 100644 GIT binary patch delta 1883 zcmV-h2c-C{7T*q#8Gi!+005o0f$RVP0{~D=R7K3p%>V!YV`F2_&(G-S=<Cd#h$`!TF@O1(IQf}5;Nalko^!jq zyWL?b$jHdy;oqB6HtmW(?u|k7?dt#j|MikL_mnntbad>3I_rl& z>whx)ojS+I$K!A=<#ssZt&81}UjO>`-kfs%>DBp~Ir^bS>B+X)StaRpCGw3t`MZPi zj5F@s(%oDidVhL)=e?ofXC&ZfEd8KA>PT zl0eVU(Cx>q<$yKpdnWLPGyBr3^_D^7fIR)`*!1-D`pl*6*U9I>s_%g)`Qy{@h%>~* z#QVaB{qX44eMIz;J^aj^`lwU(_V($8KK}dp`O>xa;(yla&ARX4*7f!E%*@Q=rhD>~ zLj2pj{_Wf3{{H{|{n)klk~00`$N&BO(9qA#UKj3;J#ley|NZ;acs!Jpl+I-!_071r zxVZI=F7~2T<7*?(&(HDY-SX+=;fhV=<>mGE_5c3;;--Jp)YSUdyZWtRgs+u?v6+6(ZKZG&G4UT=(Uvcl}Yu#nDn@g_QQ4A1NtGOY7^KH?OR$%*@Pehkwg5-2He>s8qUw@4(~Lb!M=AgMvAZPCgO& zl{aGU14@gevZ4T#^7eKO`*eB}5So%K7m#})et;*e+g_PrUtApAA4e3XC+#Kna$X5`Kq%ML zFHdNBSE*7B+(}-Dw=%dwp2OR?0slI#Mt2eS+@jScB>=!&jgS}455*2}+4j>wr`yuf zj68<ma4SAQu_-vH2|;LD_Q@B_X8I>l0N^oe zX%u$gF5Tl_tX0h>ZhO&ujl2io{xeaMXzW06Fh?vNxZP4q7FybCUjXQdmgHdvDpzsD zN&AjW9}p||0SrHt`YZsvk(+lnZeXg|QB_YqfH$2SN1Ak6VD)MfO zYsk=a0NiJ7{V>3ZEVnx_1BFw4e6-!(*B-Qlei+gt7C#6v*6=PrQC8AGPn4^TJnHpUIU-KFG>Su}CS(A^v(> z>Ek(w+N71+^PP0hUmo%Jm48M_Bzc?N+=v5M8h`@g3x}UENk##b1*_OYW~<1(!=*hj zx7ZxLArocB+W^29CdtRoQx^&v{r&y@{KCS9hK6Pmmdu&i7@LX44t@uu>Qb8+L|sUZ znWE1oXB@Se{0Ns+v?2PoJ@^h>cJwv+`(-AhSN6juR*1fWDOUocM}LW*SzWIBOc6D! z_yV}3IuJd153g`p|2PYXAoVAlqp!xbsyN`9Bbw9b&39M(C&(LGeS|3R#Ao4c62Hv7BIsw)M zKBE(u;j!9TpNDxloxo~!qye?5E1iJpJ;qMr2fP@}uWmA8$5de92J9HN0`-9dOy=3D zswyT^{k@ubR^65Dg>Z>N7xBFlLKrVA*;7q_@ttos51DKLepd Viet6C{Vo6i002ovPDHLkV1kj^Fqi-U literal 2860 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 KMNUMnLSTZfk#Jl9 diff --git a/www/plugins/rss_article_3_0/prive/themes/spip/images/rssarticle-16.png b/www/plugins/rss_article_3_0/prive/themes/spip/images/rssarticle-16.png index ce2267478739e6b22d9dd82448244e5f9c555ba3..7e3d9e7ceb5ba668a3ecc5c38788929f4e0d903a 100644 GIT binary patch delta 552 zcmV+@0@wZ32et%|8Gi-<001BJ|6u?C0sTotK~#7FjnFfkT}vDX@ZZcFT;H{>Hnxo> zP7~W|(?n%dM%7l?`qpv!Pw?_$+s3suXU|Vz#eQhfOAkyavmB2bJ=m@qbqf%l<$8A22e2eo)F2 zE?EUpUBh6Ww-55z<h1WV3--955p9L0oen{sd6?_#8UJfGATK zSndxHehX4E3jEIp5bu0w!UU1a4;+BXjL;Gf1PAgT{zpC(1CK?a!vtPZTRN*+8a2Gu z!q5j2xO}qC6n}cUQ%fdUA*F$50ijU>*NC5%*(-lgCb^S;zt!bNEUJHW|9_5dq^x(* z@eD1#uA2j@QEC{vro)iTCYyKE{-RMc7g5HL&!iVVe);U3!{M;BCC=ybQLEMZjQIV2 zbZ2&rrnBWA$Lv+U!vuQn>653Q^~#aH^0G23S|t*R!hi4Izt8sw&}O>JS|b~Lsv^sg z%a6XS+q7-R!LqV4v`HqDxYMXDK))I@o!GKv%WdZ?okYquItb= zt^Eig&}2{nnzA+pXnNcJZD&vcnzE(SX{1uAE{Agt34#bUK6RS_000045bDP46hOx7_4S6Fo+k-*%fF5)Hfr* zC&cyUiM>EI&z2Uwni}%FKln*!;Dv2-Zl6AQlZQ&GYHn`tuLIJf0H&W_sL*c_ELN*FEhIeAn;va$4kz zDM2rqY@bbvd_61lNxkdiuAsN`BOcZJ-kVc&d+&-9N7lXC*!XE~;JXPfFIpTPS35i? zcX}`>{ne?hZ_e(#zjfC2TX!FxKk{Jnqebt}ZCktl%+n+5KixU^`OcZctLGd%bm-c(YbQ>eShsH7js5HI?pyWv@cJne`gZKt z(bd(pbLY;^&d%-Ix3{&m0nO;{?q0TR*@_h_=FguG^y$2L^XAN%^Lb({UU|NsB#)2GLeAAkJ#@ztwW4<9~!_wL=>w{M?6e}4b| z{WovkJbn7~%9Se*9z3{t^XC5j`_G&?bNKLKhgZwC03#;0B*+gG=_o+2Z9;#4Um(lc ze;33~JeGl=laKY)nJ0hz^5x6dn|p3#vkH0m`}u_(TI=HHZ^zHn@a4^^mtWqsOZiy! z9&I=Qf^}P*51!cXCp|;)A<%TjByV?@GQ;GPz@){%S>O>_45U54*zIJt9guOz)5S4F z;&QTpfQXQopr~+qLJI>M=gAv8ez0g}s?BKdNeU|R+OtN+*vG-nRM*zh*>NJP+JY%F zr_P5AGE^a^!Fs{2W!skV zDIO3GiNAf}f&`EF1K!M4d3kx9t=u14w{F|Ib!+=!)*s4Bi-9RQnc?qOo#xE;ckh9| zQ7v(eC`m~yNwrEYN(E93Mh1pPx&~&tMn)lqMpj1VRwm}!21Zr}24;C`O(+_2^HVa@ WDsgLYH=YLyF9uInKbLh*2~7Z`Pv#8( diff --git a/www/plugins/rss_article_3_0/prive/themes/spip/images/rssarticle-32.png b/www/plugins/rss_article_3_0/prive/themes/spip/images/rssarticle-32.png index 391ac79ecb46ab1a01b75f17e16a6e827aee6efb..37b5d4f3e4e3f60fa308b73c270fb0d9b676dfb1 100644 GIT binary patch delta 1084 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 D3zQ-S literal 2860 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 KMNUMnLSTZfk#Jl9 diff --git a/www/plugins/rss_article_3_0/rssarticle_administrations.php b/www/plugins/rss_article_3_0/rssarticle_administrations.php index 5548c826..fbdd1c0b 100644 --- a/www/plugins/rss_article_3_0/rssarticle_administrations.php +++ b/www/plugins/rss_article_3_0/rssarticle_administrations.php @@ -1,48 +1,47 @@ "._T('rssarticle:install_rssarticle')."

    "; - ecrire_meta('rssarticle_base_version',$current_version=$version_base,'non'); - } - - if (version_compare($current_version,"0.3","<")){ - include_spip('base/create'); - maj_tables('spip_syndic'); - echo "

    "._T('rssarticle:mise_a_jour_v03')."

    "; - ecrire_meta('rssarticle_base_version',$current_version="0.3",'non'); - } +function rssarticle_upgrade(){ + $version_base = $GLOBALS['rssarticle_base_version']; + $current_version = 0.0; + if ((!isset($GLOBALS['meta']['rssarticle_base_version']) ) + || (($current_version = $GLOBALS['meta']['rssarticle_base_version'])!=$version_base)){ + include_spip('base/rssarticle'); + if ($current_version==0.0){ + include_spip('base/create'); + include_spip('base/abstract_sql'); + creer_base(); + maj_tables('spip_syndic'); + echo "

    "._T('rssarticle:install_rssarticle')."

    "; + ecrire_meta('rssarticle_base_version',$current_version=$version_base,'non'); + } - ecrire_metas(); + if (version_compare($current_version,"0.3","<")){ + include_spip('base/create'); + maj_tables('spip_syndic'); + echo "

    "._T('rssarticle:mise_a_jour_v03')."

    "; + ecrire_meta('rssarticle_base_version',$current_version="0.3",'non'); } + ecrire_metas(); + } } - - function rssarticle_install($action){ - $version_base = $GLOBALS['rssarticle_base_version']; - switch ($action){ - case 'test': - return (isset($GLOBALS['meta']['rssarticle_base_version']) AND ($GLOBALS['meta']['rssarticle_base_version']>=$version_base)); - break; - case 'install': - rssarticle_upgrade(); - break; - case 'uninstall': - rssarticle_vider_tables(); - break; - } + $version_base = $GLOBALS['rssarticle_base_version']; + switch ($action){ + case 'test': + return (isset($GLOBALS['meta']['rssarticle_base_version']) AND ($GLOBALS['meta']['rssarticle_base_version']>=$version_base)); + break; + case 'install': + rssarticle_upgrade(); + break; + case 'uninstall': + rssarticle_vider_tables(); + break; + } } /** @@ -52,9 +51,9 @@ function rssarticle_install($action){ */ function rssarticle_vider_tables() { - sql_alter("TABLE spip_syndic DROP rssarticle"); - spip_query("DROP TABLE spip_articles_syndic"); - effacer_meta('rssarticle_base_version'); - ecrire_metas(); + sql_alter("TABLE spip_syndic DROP rssarticle"); + spip_query("DROP TABLE spip_articles_syndic"); + effacer_meta('rssarticle_base_version'); + ecrire_metas(); } ?> diff --git a/www/plugins/rss_article_3_0/rssarticle_pipelines.php b/www/plugins/rss_article_3_0/rssarticle_pipelines.php index 491da0c8..ed9d1486 100644 --- a/www/plugins/rss_article_3_0/rssarticle_pipelines.php +++ b/www/plugins/rss_article_3_0/rssarticle_pipelines.php @@ -1,21 +1,20 @@ "; - $out .= "\n". recuperer_fond('prive/contenu/rssarticle',$contexte,array('ajax'=>false)); - $out .= "\n"; - //$out .= "\n". fin_cadre_relief(true); - if ($p=strpos($flux['data'],'')) - $flux['data'] = substr_replace($flux['data'],$out,$p,0); - - - } - } - return $flux; + if ($flux['args']['exec'] == 'site'){ + include_spip('inc/config'); + if (lire_config('rssarticle/mode') == "auto") + $mode_auto=true; + else + $mode_auto=false; + + if (!$mode_auto) { + $out .= "\n
    "; + $out .= "\n". recuperer_fond('prive/contenu/rssarticle',array('id_syndic' => $flux["args"]["id_syndic"]),array('ajax'=>false)); + $out .= "\n
    "; + if ($p=strpos($flux['data'],'')) + $flux['data'] = substr_replace($flux['data'],$out,$p,0); + } + } + return $flux; } - - -?> +?> \ No newline at end of file diff --git a/www/plugins/rss_article_3_0/svn.revision b/www/plugins/rss_article_3_0/svn.revision index dbd1b87e..96a99b78 100644 --- a/www/plugins/rss_article_3_0/svn.revision +++ b/www/plugins/rss_article_3_0/svn.revision @@ -1,10 +1,10 @@ Origine: file:///home/svn/repository/spip-zone/_plugins_/rss_article/trunk -Revision: 83421 -Dernier commit: 2014-06-23 09:03:15 +0200 +Revision: 94788 +Dernier commit: 2016-01-28 13:23:37 +0100 file:///home/svn/repository/spip-zone/_plugins_/rss_article/trunk -83421 -2014-06-23 09:03:15 +0200 +94788 +2016-01-28 13:23:37 +0100 \ No newline at end of file diff --git a/www/plugins/saisies/action/deplacer_saisie.php b/www/plugins/saisies/action/deplacer_saisie.php index 5bee2b1a..eeea9ee6 100644 --- a/www/plugins/saisies/action/deplacer_saisie.php +++ b/www/plugins/saisies/action/deplacer_saisie.php @@ -5,8 +5,10 @@ * * @package SPIP\Saisies\Action */ - -if (!defined("_ECRIRE_INC_VERSION")) return; + +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} /** * Action de déplacement de saisies dans le constructeur de formulaires @@ -24,19 +26,19 @@ function action_deplacer_saisie_dist() { $formulaire_actuel = session_get($session); if (!$formulaire_actuel) { - return ""; + return ''; } include_spip('inc/saisies'); - + $saisies_actuelles = saisies_lister_par_identifiant($formulaire_actuel); if (!isset($saisies_actuelles[$identifiant])) { - return ""; + return ''; } // tester @id et [@id] (fieldset) - if ($ou and !isset($saisies_actuelles[$ou]) and !isset($saisies_actuelles[ substr($ou,1,-1) ])) { - return ""; + if ($ou and !isset($saisies_actuelles[$ou]) and !isset($saisies_actuelles[ substr($ou, 1, -1) ])) { + return ''; } // on deplace ou c'est demande... @@ -45,4 +47,3 @@ function action_deplacer_saisie_dist() { // On sauve tout ca $formulaire_actuel = session_set($session, $formulaire_actuel); } - diff --git a/www/plugins/saisies/balise/configurer_saisie.php b/www/plugins/saisies/balise/configurer_saisie.php index f362eed3..75dabf45 100644 --- a/www/plugins/saisies/balise/configurer_saisie.php +++ b/www/plugins/saisies/balise/configurer_saisie.php @@ -6,7 +6,9 @@ */ // Sécurité -if (!defined("_ECRIRE_INC_VERSION")) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} /** * Compile la balise `#CONFIGURER_SAISIE` @@ -14,11 +16,11 @@ if (!defined("_ECRIRE_INC_VERSION")) return; * @uses Pile::recuperer_et_supprimer_argument_balise() * @uses Pile::creer_et_ajouter_argument_balise() * @see balise_INCLURE_dist() - * + * * @param Champ $p * @return Champ **/ -function balise_CONFIGURER_SAISIE_dist($p){ +function balise_CONFIGURER_SAISIE_dist($p) { // On recupere le premier argument : le nom de la saisie $saisie = Pile::recuperer_et_supprimer_argument_balise(1, $p); @@ -40,5 +42,3 @@ function balise_CONFIGURER_SAISIE_dist($p){ } } - - diff --git a/www/plugins/saisies/balise/generer_saisies.php b/www/plugins/saisies/balise/generer_saisies.php index 6a37f128..cf8242d6 100644 --- a/www/plugins/saisies/balise/generer_saisies.php +++ b/www/plugins/saisies/balise/generer_saisies.php @@ -1,4 +1,4 @@ -param[0]`. - * + * * `param[0][0]` vaut toujours '' (ou presque ?) * * @see balise_SAISIE_dist() Pour un exemple d'utilisation @@ -34,7 +36,7 @@ class Pile { /** * Récupère un argument de balise - * + * * @param int $pos * @param Champ $p * @return mixed|null Élément de l'AST représentant l'argument s'il existe @@ -62,7 +64,7 @@ class Pile { } if (!isset($p->param[0][$pos])) { return null; - } + } if ($pos == 0) { array_shift($p->param[0]); } else { @@ -79,7 +81,7 @@ class Pile { * * @uses Pile::recuperer_argument_balise() * @uses Pile::supprimer_argument_balise() - * + * * @param int $pos * @param Champ $p * @return mixed|null Élément de l'AST représentant l'argument s'il existe @@ -95,7 +97,7 @@ class Pile { * Ajoute un argument de balise * * Empile l'argument à la suite des arguments déjà existants pour la balise - * + * * @param mixed $element Élément de l'AST représentant l'argument à ajouter * @param Champ $p * @return Champ @@ -122,11 +124,11 @@ class Pile { * ``` * $nom = Pile::creer_argument_balise(nom); // {nom} * $nom = Pile::creer_argument_balise(nom, 'coucou'); // {nom=coucou} - * + * * $balise = Pile::creer_balise('BALISE'); * $nom = Pile::creer_argument_balise(nom, $balise); // {nom=#BALISE} * ``` - * + * * @param string $nom * Nom de l'argument * @param string|object $valeur @@ -138,26 +140,24 @@ class Pile { $s = new Texte; $s->texte = $nom; $s->ligne=0; - + // si #BALISE cree avec Pile::creer_balise(), le mettre en array, comme les autres if (is_object($valeur)) { $valeur = array($valeur); } - + $res = null; - + // {nom} if (is_null($valeur)) { $res = array($s); - } - // {nom=coucou} - elseif (is_string($valeur)) { + } elseif (is_string($valeur)) { + // {nom=coucou} $s->texte .= "=$valeur"; $res = array($s); - } - // {nom=#BALISE} - elseif (is_array($valeur)) { - $s->texte .= "="; // /!\ sans cette toute petite chose, ça ne fait pas d'egalite :) + } elseif (is_array($valeur)) { + // {nom=#BALISE} + $s->texte .= '='; // /!\ sans cette toute petite chose, ça ne fait pas d'egalite :) $res = array_merge(array($s), $valeur); } @@ -170,7 +170,7 @@ class Pile { * * @uses Pile::creer_argument_balise() * @uses Pile::ajouter_argument_balise() - * + * * @param Champ $p * @param string $nom * Nom de l'argument @@ -179,7 +179,7 @@ class Pile { * @return Champ **/ static function creer_et_ajouter_argument_balise($p, $nom, $valeur = null) { - $new = Pile::creer_argument_balise($nom, $valeur); + $new = Pile::creer_argument_balise($nom, $valeur); return Pile::ajouter_argument_balise($new, $p); } @@ -191,10 +191,10 @@ class Pile { * @example * ``` * // Crée : #ENV*{titre} - * $titre = Pile::recuperer_argument_balise(1, $p); // $titre, 1er argument de la balise actuelle + * $titre = Pile::recuperer_argument_balise(1, $p); // $titre, 1er argument de la balise actuelle * $env = Pile::creer_balise('ENV', array('param' => array($titre), 'etoile' => '*')); * ``` - * + * * @param string $nom * Nom de la balise * @param array $opt @@ -205,8 +205,8 @@ class Pile { include_spip('public/interfaces'); $b = new Champ; $b->nom_champ = strtoupper($nom); - foreach ($opt as $o=>$val) { - if (property_exists($b,$o)) { + foreach ($opt as $o => $val) { + if (property_exists($b, $o)) { if ($o == 'param') { array_unshift($val, ''); $b->$o = array($val); @@ -229,7 +229,7 @@ class Pile { * La balise `#SAISIE` est un raccourci pour une écriture plus compliquée de la balise `#INCLURE`. * La balise calcule une série de paramètre récupérer et à transmettre à `#INCLURE`, * en fonction des valeurs des 2 premiers paramètres transmis. - * + * * Les autres arguments sont transmis tels quels à la balise `#INCLURE`. * * Ainsi `#SAISIE{input,nom,label=Nom,...}` exécutera l'équivalent de @@ -270,5 +270,3 @@ function balise_SAISIE_dist($p) { return balise_INCLURE_dist($p); } } - - diff --git a/www/plugins/saisies/balise/voir_saisie.php b/www/plugins/saisies/balise/voir_saisie.php index 8ed9f945..f2030033 100644 --- a/www/plugins/saisies/balise/voir_saisie.php +++ b/www/plugins/saisies/balise/voir_saisie.php @@ -8,23 +8,25 @@ // Sécurité -if (!defined("_ECRIRE_INC_VERSION")) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} /** * Compile la balise `#VOIR_SAISIE` qui retourne le code HTML de la vue d'une saisie indiquée * * Cette balise incluera le squelette `saisies-vues/_base.html` et lui-même `saisies-vues/{type}.html` - * + * * @syntaxe `#VOIR_SAISIE{type,nom[,option=valeur,...]}` * @uses Pile::recuperer_et_supprimer_argument_balise() * @uses Pile::creer_et_ajouter_argument_balise() * @uses Pile::creer_balise() * @see balise_INCLURE_dist() - * + * * @param Champ $p * @return Champ */ -function balise_VOIR_SAISIE_dist ($p) { +function balise_VOIR_SAISIE_dist($p) { // on recupere les parametres sans les traduire en code d'execution php $type_saisie = Pile::recuperer_et_supprimer_argument_balise(1, $p); @@ -42,7 +44,7 @@ function balise_VOIR_SAISIE_dist ($p) { // on appelle la balise #INCLURE // avec les arguments ajoutes - if(function_exists('balise_INCLURE')) { + if (function_exists('balise_INCLURE')) { return balise_INCLURE($p); } else { return balise_INCLURE_dist($p); diff --git a/www/plugins/saisies/balise/voir_saisies.php b/www/plugins/saisies/balise/voir_saisies.php index 482c418d..ed8fd939 100644 --- a/www/plugins/saisies/balise/voir_saisies.php +++ b/www/plugins/saisies/balise/voir_saisies.php @@ -1,4 +1,4 @@ -}|replace{"<(\S*).*>",$1,i})]').eq(0).hide().text(); + var titre = $(this).find('[(#VAL{"{{{ titre }}}"}|propre|replace{"<(\S*).*>",$1,i})]').eq(0).hide().text(); + // On crée un onglet var $onglet = $('
  • '+titre+'
  • '); $onglet diff --git a/www/plugins/saisies/formulaires/construire_formulaire.php b/www/plugins/saisies/formulaires/construire_formulaire.php index 21b934ed..f389534f 100644 --- a/www/plugins/saisies/formulaires/construire_formulaire.php +++ b/www/plugins/saisies/formulaires/construire_formulaire.php @@ -1,68 +1,70 @@ $formulaire_config)); $formulaire_config = $formulaire_config['saisies']; - + // Si la saisie possede un identifiant, on l'ajoute // au formulaire de configuration pour ne pas le perdre en route if (isset($saisie['identifiant']) and $saisie['identifiant']) { @@ -117,11 +119,10 @@ function formulaires_construire_formulaire_verifier($identifiant, $formulaire_in ) ); } - + // S'il y a l'option adéquat, on ajoute le champ pour modifier le nom if (isset($options['modifier_nom']) and $options['modifier_nom'] - and $chemin_nom = saisies_chercher($formulaire_config, "saisie_modifiee_${nom}[options][description]", true)) - { + and $chemin_nom = saisies_chercher($formulaire_config, "saisie_modifiee_${nom}[options][description]", true)) { $chemin_nom[] = 'saisies'; $chemin_nom[] = '0'; @@ -151,12 +152,12 @@ function formulaires_construire_formulaire_verifier($identifiant, $formulaire_in $verif_options = array(); // S'il y a un groupe "validation" alors on va construire le formulaire des vérifications - if ($chemin_validation = saisies_chercher($formulaire_config, "saisie_modifiee_${nom}[options][validation]", true)){ + if ($chemin_validation = saisies_chercher($formulaire_config, "saisie_modifiee_${nom}[options][validation]", true)) { include_spip('inc/verifier'); $liste_verifications = verifier_lister_disponibles(); $chemin_validation[] = 'saisies'; $chemin_validation[] = 1000000; // à la fin - + // On construit la saisie à insérer et les fieldset des options $saisie_liste_verif = array( 'saisie' => 'selection', @@ -169,10 +170,10 @@ function formulaires_construire_formulaire_verifier($identifiant, $formulaire_in ) ); - foreach ($liste_verifications as $type_verif => $verif){ + foreach ($liste_verifications as $type_verif => $verif) { $saisie_liste_verif['options']['datas'][$type_verif] = $verif['titre']; // Si le type de vérif a des options, on ajoute un fieldset - if (isset($verif['options']) and $verif['options'] and is_array($verif['options'])){ + if (isset($verif['options']) and $verif['options'] and is_array($verif['options'])) { $groupe = array( 'saisie' => 'fieldset', 'options' => array( @@ -188,34 +189,47 @@ function formulaires_construire_formulaire_verifier($identifiant, $formulaire_in } $verif_options = array_merge(array($saisie_liste_verif), $verif_options); } - - - if ($enregistrer_saisie){ + + + // Permettre d'intégrer des saisies et fieldset au formulaire de configuration. + // Si des vérifications sont à faire, elles seront prises en compte + // lors des tests de vérifications à l'enregistrement. + $formulaire_config = pipeline('saisies_construire_formulaire_config', array( + 'data' => $formulaire_config, + 'args' => array( + 'identifiant' => $identifiant, + 'action' => $enregistrer_saisie ? 'enregistrer' : 'configurer', + 'options' => $options, + 'nom' => $nom, + 'saisie' => $saisie, + ), + )); + + if ($enregistrer_saisie) { // La saisie modifié $saisie_modifiee = _request("saisie_modifiee_${nom}"); // On cherche les erreurs de la configuration $vraies_erreurs = saisies_verifier($formulaire_config); // Si on autorise à modifier le nom ET qu'il doit être unique : on vérifie if (isset($options['modifier_nom']) and $options['modifier_nom'] - and isset($options['nom_unique']) and $options['nom_unique']) - { + and isset($options['nom_unique']) and $options['nom_unique']) { $nom_modifie = $saisie_modifiee['options']['nom']; - if ($nom_modifie != $enregistrer_saisie and saisies_chercher($formulaire_actuel, $nom_modifie)) + if ($nom_modifie != $enregistrer_saisie and saisies_chercher($formulaire_actuel, $nom_modifie)) { $vraies_erreurs["saisie_modifiee_${nom}[options][nom]"] = _T('saisies:erreur_option_nom_unique'); + } } // On regarde s'il a été demandé un type de vérif if (isset($saisie_modifiee['verifier']['type']) - and (($type_verif = $saisie_modifiee['verifier']['type']) != '') - and $verif_options[$type_verif]) - { + and (($type_verif = $saisie_modifiee['verifier']['type']) != '') + and $verif_options[$type_verif]) { // On ne vérifie que les options du type demandé $vraies_erreurs = array_merge($vraies_erreurs, saisies_verifier($verif_options[$type_verif]['saisies'])); } } // On insère chaque saisie des options de verification - if ($verif_options){ - foreach ($verif_options as $saisie_verif){ + if ($verif_options) { + foreach ($verif_options as $saisie_verif) { $formulaire_config = saisies_inserer($formulaire_config, $saisie_verif, $chemin_validation); } } @@ -225,6 +239,7 @@ function formulaires_construire_formulaire_verifier($identifiant, $formulaire_in if ($enregistrer_saisie) { if ($vraies_erreurs) { $erreurs = array_merge($erreurs, $vraies_erreurs); + $erreurs['message_erreur'] = singulier_ou_pluriel(count($vraies_erreurs), 'avis_1_erreur_saisie', 'avis_nb_erreurs_saisie'); } else { $erreurs = array(); } @@ -235,23 +250,23 @@ function formulaires_construire_formulaire_verifier($identifiant, $formulaire_in return $erreurs; } -function formulaires_construire_formulaire_traiter($identifiant, $formulaire_initial=array(), $options=array()){ +function formulaires_construire_formulaire_traiter($identifiant, $formulaire_initial = array(), $options = array()) { include_spip('inc/saisies'); $retours = array(); $saisies_disponibles = saisies_lister_disponibles(); - + // On ajoute un préfixe devant l'identifiant $identifiant = 'constructeur_formulaire_'.$identifiant; // On récupère le formulaire à son état actuel $formulaire_actuel = session_get($identifiant); - + // Si on demande à ajouter un groupe - if ($ajouter_saisie = _request('ajouter_groupe_saisie')){ + if ($ajouter_saisie = _request('ajouter_groupe_saisie')) { $formulaire_actuel = saisies_groupe_inserer($formulaire_actuel, $ajouter_saisie); } - + // Si on demande à ajouter une saisie - if ($ajouter_saisie = _request('ajouter_saisie')){ + if ($ajouter_saisie = _request('ajouter_saisie')) { $nom = saisies_generer_nom($formulaire_actuel, $ajouter_saisie); $saisie = array( 'saisie' => $ajouter_saisie, @@ -260,49 +275,40 @@ function formulaires_construire_formulaire_traiter($identifiant, $formulaire_ini ) ); // S'il y a des valeurs par défaut pour ce type de saisie, on les ajoute - if (($defaut = $saisies_disponibles[$ajouter_saisie]['defaut']) and is_array($defaut)){ + if (($defaut = $saisies_disponibles[$ajouter_saisie]['defaut']) and is_array($defaut)) { $defaut = _T_ou_typo($defaut, 'multi'); - //Compatibilite PHP<5.3.0 + //Compatibilite PHP<5.3.0 //source : http://www.php.net/manual/en/function.array-replace-recursive.php#92574 - if (!function_exists('array_replace_recursive')) - { - function array_replace_recursive($array, $array1) - { - function recurse($array, $array1) - { - foreach ($array1 as $key => $value) - { + if (!function_exists('array_replace_recursive')) { + function array_replace_recursive($array, $array1) { + function recurse($array, $array1) { + foreach ($array1 as $key => $value) { // create new key in $array, if it is empty or not an array - if (!isset($array[$key]) || (isset($array[$key]) && !is_array($array[$key]))) - { + if (!isset($array[$key]) || (isset($array[$key]) && !is_array($array[$key]))) { $array[$key] = array(); } // overwrite the value in the base array - if (is_array($value)) - { + if (is_array($value)) { $value = recurse($array[$key], $value); } $array[$key] = $value; } return $array; } - + // handle the arguments, merge one by one $args = func_get_args(); $array = $args[0]; - if (!is_array($array)) - { + if (!is_array($array)) { return $array; } - for ($i = 1; $i < count($args); $i++) - { - if (is_array($args[$i])) - { + for ($i = 1; $i < count($args); $i++) { + if (is_array($args[$i])) { $array = recurse($array, $args[$i]); } } - return $array; + return $array; } } $saisie = array_replace_recursive($saisie, $defaut); @@ -312,38 +318,37 @@ function formulaires_construire_formulaire_traiter($identifiant, $formulaire_ini // Si on demande à dupliquer une saisie if ($dupliquer_saisie = _request('dupliquer_saisie')) { - $formulaire_actuel = saisies_dupliquer($formulaire_actuel, $dupliquer_saisie); + $formulaire_actuel = saisies_dupliquer($formulaire_actuel, $dupliquer_saisie); } - + // Si on demande à supprimer une saisie - if ($supprimer_saisie = _request('supprimer_saisie')){ + if ($supprimer_saisie = _request('supprimer_saisie')) { $formulaire_actuel = saisies_supprimer($formulaire_actuel, $supprimer_saisie); } - + // Si on enregistre la conf d'une saisie - if ($nom = _request('enregistrer_saisie')){ + if ($nom = _request('enregistrer_saisie')) { // On récupère ce qui a été modifié $saisie_modifiee = _request("saisie_modifiee_$nom"); - + // On regarde s'il y a une position à modifier - if (isset($saisie_modifiee['position'])){ + if (isset($saisie_modifiee['position'])) { $position = $saisie_modifiee['position']; unset($saisie_modifiee['position']); // On ne déplace que si ce n'est pas la même chose - if ($position != $nom) + if ($position != $nom) { $formulaire_actuel = saisies_deplacer($formulaire_actuel, $nom, $position); + } } - + // On regarde s'il y a des options de vérification à modifier if (isset($saisie_modifiee['verifier']['type']) - and ($type_verif = $saisie_modifiee['verifier']['type']) != '') - { + and ($type_verif = $saisie_modifiee['verifier']['type']) != '') { $saisie_modifiee['verifier'] = array( 'type' => $type_verif, 'options' => $saisie_modifiee['verifier'][$type_verif] ); - } - else { + } else { unset($saisie_modifiee['verifier']); } @@ -352,17 +357,18 @@ function formulaires_construire_formulaire_traiter($identifiant, $formulaire_ini if (isset($saisie_modifiee['verifier']['options']) and $saisie_modifiee['verifier']['options']) { $saisie_modifiee['verifier']['options'] = array_filter($saisie_modifiee['verifier']['options'], 'saisie_option_contenu_vide'); } - + // On désinfecte à la main - if (is_array($saisie_modifiee['options'])) + if (is_array($saisie_modifiee['options'])) { spip_desinfecte($saisie_modifiee['options']); - + } + // On modifie enfin $formulaire_actuel = saisies_modifier($formulaire_actuel, $nom, $saisie_modifiee); } // Si on demande à réinitialiser - if (_request('reinitialiser') == 'oui'){ + if (_request('reinitialiser') == 'oui') { $formulaire_actuel = $formulaire_initial; } @@ -377,26 +383,26 @@ function formulaires_construire_formulaire_traiter($identifiant, $formulaire_ini // À utiliser avec un array_walk_recursive() // Applique une transformation à la @valeur@ de tous les champs "nom" d'un formulaire, y compris loin dans l'arbo -function formidable_transformer_nom(&$valeur, $cle, $transformation){ - if ($cle == 'nom' and is_string($valeur)){ +function formidable_transformer_nom(&$valeur, $cle, $transformation) { + if ($cle == 'nom' and is_string($valeur)) { $valeur = str_replace('@valeur@', $valeur, $transformation); } } // Préparer une saisie pour la transformer en truc configurable -function formidable_generer_saisie_configurable($saisie, $env){ +function formidable_generer_saisie_configurable($saisie, $env) { // On récupère le nom $nom = $saisie['options']['nom']; - $identifiant = isset($saisie['identifiant']) ? $saisie['identifiant'] : ""; + $identifiant = isset($saisie['identifiant']) ? $saisie['identifiant'] : ''; // On cherche si ya un formulaire de config - $formulaire_config = isset($env['erreurs']['configurer_'.$nom]) ? $env['erreurs']['configurer_'.$nom] : ""; + $formulaire_config = isset($env['erreurs']['configurer_'.$nom]) ? $env['erreurs']['configurer_'.$nom] : ''; // On ajoute une classe if (!isset($saisie['options']['conteneur_class'])) { $saisie['options']['conteneur_class'] = ''; // initialisation } // Compat ancien nom li_class if (isset($saisie['options']['li_class'])) { - $saisie['options']['conteneur_class'] .= " " . $saisie['options']['li_class']; // initialisation + $saisie['options']['conteneur_class'] .= ' ' . $saisie['options']['li_class']; // initialisation } $saisie['options']['conteneur_class'] .= ' configurable'; @@ -411,7 +417,7 @@ function formidable_generer_saisie_configurable($saisie, $env){ 'formulaires/inc-construire_formulaire-actions', array( 'nom' => $nom, - 'identifiant' => $identifiant, + 'identifiant' => $identifiant, 'formulaire_config' => $formulaire_config, 'deplacable' => $env['_chemin_ui'] ) @@ -428,7 +434,7 @@ function formidable_generer_saisie_configurable($saisie, $env){ ); // Si ya un form de config on l'ajoute à la fin - if (is_array($formulaire_config)){ + if (is_array($formulaire_config)) { // On double l'environnement $env2 = $env; // On ajoute une classe @@ -436,9 +442,9 @@ function formidable_generer_saisie_configurable($saisie, $env){ // Si possible on met en readonly $saisie['options']['readonly'] = 'oui'; - + // On vire les sous-saisies s'il y en a - if (isset($saisie['saisies']) and $saisie['saisies'] and is_array($saisie['saisies'])){ + if (isset($saisie['saisies']) and $saisie['saisies'] and is_array($saisie['saisies'])) { $nb_champs_masques = count(saisies_lister_champs($saisie['saisies'])); $saisie['saisies'] = array( array( @@ -450,9 +456,9 @@ function formidable_generer_saisie_configurable($saisie, $env){ ) ); } - + // On va ajouter le champ pour la position - if (!($chemin_description = saisies_chercher($formulaire_config, "saisie_modifiee_${nom}[options][description]", true))){ + if (!($chemin_description = saisies_chercher($formulaire_config, "saisie_modifiee_${nom}[options][description]", true))) { $chemin_description = array(0); $formulaire_config = saisies_inserer( $formulaire_config, @@ -483,22 +489,21 @@ function formidable_generer_saisie_configurable($saisie, $env){ ), $chemin_description ); - + $env2['saisies'] = $formulaire_config; - + // Un test pour savoir si on prend le _request ou bien $erreurs_test = $env['erreurs']; unset($erreurs_test['configurer_'.$nom]); unset($erreurs_test['positionner']); unset($erreurs_test['message_erreur']); - if ($erreurs_test){ + if ($erreurs_test) { // Là aussi on désinfecte à la main if (isset($env2["saisie_modifiee_$nom"]['options']) and is_array($env2["saisie_modifiee_$nom"]['options'])) { spip_desinfecte($env2["saisie_modifiee_$nom"]['options']); } - } - else{ + } else { $env2["saisie_modifiee_$nom"] = $env2['_saisies_par_nom'][$nom]; // il n'y a pas toujours de verification... if (isset($env2["saisie_modifiee_$nom"]['verifier'])) { @@ -506,7 +511,7 @@ function formidable_generer_saisie_configurable($saisie, $env){ = $env2["saisie_modifiee_$nom"]['verifier']['options']; } } - + $env2['fond_generer'] = 'inclure/generer_saisies'; $saisie = saisies_inserer_html( $saisie, @@ -539,7 +544,7 @@ function formidable_generer_saisie_configurable($saisie, $env){ **/ function saisie_option_contenu_vide($var) { if (!$var) { - if (is_string($var) AND strlen($var)) { + if (is_string($var) and strlen($var)) { return true; } return false; @@ -547,29 +552,29 @@ function saisie_option_contenu_vide($var) { return true; } -function saisies_groupe_inserer($formulaire_actuel, $saisie){ +function saisies_groupe_inserer($formulaire_actuel, $saisie) { include_spip('inclure/configurer_saisie_fonctions'); - + //le groupe de saisies - $saisies_charger_infos = saisies_charger_infos($saisie,$saisies_repertoire = "saisies/groupes"); - + $saisies_charger_infos = saisies_charger_infos($saisie, $saisies_repertoire = 'saisies/groupes'); + //le tableau est-il en options ou en saisies ? $classique_yaml=count($saisies_charger_infos['options']); $formidable_yaml=count($saisies_charger_infos['saisies']); - if($classique_yaml>0) { + if ($classique_yaml>0) { $champ_options = 'options'; } - if($formidable_yaml>0) { + if ($formidable_yaml>0) { $champ_options = 'saisies'; } - - //les champs du groupe - foreach($saisies_charger_infos[$champ_options] as $info_saisie){ + + //les champs du groupe + foreach ($saisies_charger_infos[$champ_options] as $info_saisie) { unset($info_saisie['identifiant']); $saisies_disponibles = saisies_lister_disponibles(); $construire_nom = $info_saisie[$champ_options]['nom'] ? $info_saisie[$champ_options]['nom'] : $info_saisie['saisie']; - $nom = $info_saisie[$champ_options]['nom'] = saisies_generer_nom($formulaire_actuel,$construire_nom); - + $nom = $info_saisie[$champ_options]['nom'] = saisies_generer_nom($formulaire_actuel, $construire_nom); + $formulaire_actuel = saisies_inserer($formulaire_actuel, $info_saisie); } return $formulaire_actuel; diff --git a/www/plugins/saisies/formulaires/saisies_cvt.php b/www/plugins/saisies/formulaires/saisies_cvt.php index ac5eb147..c71bb7bc 100644 --- a/www/plugins/saisies/formulaires/saisies_cvt.php +++ b/www/plugins/saisies/formulaires/saisies_cvt.php @@ -1,9 +1,11 @@ 'input', @@ -37,4 +39,3 @@ function formulaires_saisies_cvt_saisies_dist(){ ) ); } - diff --git a/www/plugins/saisies/images/formulaire-annuler-16.png b/www/plugins/saisies/images/formulaire-annuler-16.png index 1af591c2acefc4ae059b2711f608c8a140747b69..a62df55bae8b76faafa9fbf9f30e3aa008834d89 100644 GIT binary patch delta 483 zcmV<90UZ9y1^fe$BYy$INkl{4;1$3(I;p2Z1#D}7T)&e z4Yl0APi=4C($^h3x&ZK&2M-9|mn~aFWYIy_Yb0y>boOz>2C@0c6KcG1gIbDAgbA!@#R{SN@@1;Nc+m!M zXz)VbZX7$7oRlC+N?iLxg|s z+_?hasUd@`*NArbaE*29RPpEDz4T+}PWriTAK|PSHe8GW;Lv{T+C|9VjE-v{eaH}v zX~G2Y%jV4lm?fSuc(Cmj036zvEn8eZI$lpm?cbm2M~@Z(aA=YGu26FC-WtH$4DZMF ZbpvtxK+1nD;8*|v002ovPDHLkV1iJY_zeI6 delta 691 zcmV;k0!;n<1Ih)EBYyw{b3#c}2nYxWd|a<$qb)2ZWH*2ZuW1Wr-cTe7aVND!=X5dipPVk@dVjMifpZKx9W%PWw*mYX0U)Ck*>Z_&u|O7v&<#TxoSvG|aOePls_Uk1 z7!vh;2%7fFWefm7IOlK)5z|J)Q7aX*-fT))6hY85+*RSGU4Vp6X=YNcZQI69KE`5ZY_1pu%xgnyu_7+hS$(Rl0?`u(=aIbCnC zHj5B(q3e#eyZftpc&LE>4?+|%y1JT&qtT@_9Ih{K#JDO(Dd=(ux>x{N_S#HS&?Et) z^gSIL62hGwM=qC*>cN4WB?)qp^g8tA1wuZL(e-s4KR$ZeWU?v2B}9DM-ge}zE#v$C zzRZ_Pkbit04>vb+0QkDMr>uH^d%ZY*dh)h{plxza1po+2B|Bd%8s$bqPG>VPN-^wq z>%;(;>BrI9${0QGLah%K908nA< z4Nr6o4ED>$cX!E)uRJ&L#M6&n3(!+qn%19}w-CSpcz@!lN935JPN09F7eDaP zqS5-lBfu~WCdVD}a`XA<sV1hhBi))57SmMbG!2k#xkZkhwLsZ4=FiOaUUA0m`&sw3dZs z2VfSTjDM3-Md!C4Gq%eOj4Ud`bv-0%@l@LC{}c?M_LndC?X!P4a$z=I|D1Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L z01ejw01ejxLMWSf00007bV*G`2iXN2104=ASbtIg00PTNL_t(I%WacOXjEqyhM#lJ zKgrA(V#Y>nl-wqx@tRm%SP>P4A|g==UZ9J%OQ{=?3L>_}t$&Il3hGj;7;gwdz=hf> zqDUkVG4+yYlP20+%#691%sF$;_jPfGiB;d#zxf~D=llQ9QdKTpy|Br$IH{tu6hIXv zAJv>?+kXUsf8@LE-{0ips45pPpMR6i4D09Odae!(^y{_jS0>IkpWUab3@%z!GMq}4 zswxJ+_x*~p>3<2{4iDl7KB9t%AQE6%7L)H?Hf{Vi_UD~j`=4%ZT3-PxBo^~C4Gnt? zfT*G>Km-6k$bZq*^$Jx%RZ$5++188XBD0yC z80Y!3r;KKE^i7OweGu#@D1-o^s;Uyu0>EqejhOq4jVsG|+54L7-5!Z)#pv7Ma-yT- z+>}E8`MO{Ijaq;Rr4No$u0zzUTZcQ;Lz!1ZL|vl6n5LIB`~YBos9;$ZwRK7AlC{if zKgCQZO@GbWHMm1PjE_d>e{`3ouN%=swTOmy@_x&0of)39_rM{llM9K*;}{d+b9whJgE7v4>v}GLrK%h|eq@6& z<}S47d6ge-Y5s&x?KZ{~^#y^yWB0B-Edc)kU@oa9mAU~R00000NkvXXu0mjf^tFi& diff --git a/www/plugins/saisies/images/formulaire-deplacer-16.png b/www/plugins/saisies/images/formulaire-deplacer-16.png index 6e13dd3d6f0400d367a6f55e559cea5173dd13c8..ae1f378f9ac3ba51eff37d19492e3da50ae22060 100644 GIT binary patch delta 365 zcmV-z0h0c|1cw8VBYy!-Nkl-1fm)5T}?uNF|D67VCjUztKZv!?>^zaOQ5)=aivdiLoUnNEHetwr#^l4mEJVeRWj#z;cDM2D!j5Vj$s8d>^9*PT&LQxw-R^ z$W$R;-Y4Q)H)h2Y_pyI|rvZ)-zh&08b{_T)uHNQqy&WS*w{KER$Cl{Gxvu-)VZ3iH zQk@o0X500000 LNkvXXu0mjf=pM8E delta 551 zcmV+?0@(eB1HS~2BYyxHbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz z;Ymb6RCwBA{Qv(y14RIz0glZ({(~?+y)3vS?HjlM&-T^>v;Y0u{{LXTCnGj>SPgJ) z+4(=y$B<#grFUR{uD>w@3-iwZdu!Y=3}Hg%xVP^H^Z$JPuzzdn#xo4k5+V#TKn!97 z#r6;k1CY(GtvjCqnMy!x9Jl!9f2XExAO*%CF`(QkkQ!vYOvrvN@Hb-k`Rk7)kb4h^ z&oTfV%mi`tS&$e|E)=8&q!uL%oLhGM4|CFESbFs%Lz2HagRIhx|I9$0AP90`{E}P$ z|NQ;O;HoPERDbhCMJ*@8RS&d z7#`od1B{7(3}?lK!D?Q7`T^F190tZtP22zHZ+!6IxoJDh&&CPM?)-OY*#YM}L)ADz z)gXt#*?o1MCfBaq1p4{^Yp9>k{{R0E>O{t1r;S*B*7w*4u4zstDuf?`NMet=>DwAA6!FlnQ=ZY>MLsgb?-7PgMk(p$tKB zG#`sKO`En_lYiT8?Ts>r0fK5ZH)#$A? z02u@#jR;`_ni)ah!z-`D+h$JX(ZVQ2XR1D5k7HnK3-*Q5lOo7EdTljO;831*~*G z-g@Zldrvv&yp40Yxb5D_?@i*?ss z*UM$|?CUD^+>et9#T30$t-(ieIucTX4o(I$pnnnxF4vqNjWoR_%xF}dpVGUhh2uba z@MRiIJqo~3>y4ca5k^vtAfGFt&Q+w-so?XcS`Vd1+D{?GZHu+prJJq;f@IR;lC^ga ze7{4A32HQZxFCkm>w45|HQ@U`5Wsd@V&hNh&APFXZK}{cqd0UVO9(>LefQn_AYw=i z!!d{|ak0^8&f$N&_`>u3O1bu8_|Kf@xr$i~g!~SIHqgNizR*Dc0000e!wd|}Hl8kyAr_~7C!fuZ36*J^U;KXN`^>aiKF8Ij9#QEw;ce9m5@glZ5OZfR=e1X?#r0|!8yGr_W%%Utw%(T4kKcFaNqy!2X8zTyvwJruO2`H(G%W}S zJAdYk9%Bc`f)9J{zBS<4Cp&jZr1WZr3ok2dg4X+%RNei)>E<2J16>?Si@yB1Bh#e7 zxo6&Fkah%g%R3)a|eS-z8shfB%m|r#G(1*>&rUr-_ef!@jMT)J(k!sh@OF)a$5~>}|E_rxLYPNJ|PI{x2E4nMH!jG>exT1RFtK4$WNi5r4X6Wx!bg=Px`Nis7$cxuOE8kq< zv(0~c!0yXZZ*lwI+Z|+%D|Q`9+kU$`!REuBFZOfS$NpWm|K_b-&n(V0TgYW)A7%Ve z&mMZ`<^un@OWp$Wm1>D=L`h0wNvc(HQ7VvPFfuSS&^0jCHLwUVG_o?aurf5zHZZa> zFgQ2Cb_t4x-29Zxv`X9>_MdH)0BVo~*$|wcR#Ki=l*&+EUM{PbnU`IhoLG>mmtT}V T`<;yxP!)rxtDnm{r-UW|TS(Y& diff --git a/www/plugins/saisies/images/formulaire-enregistrer-16.png b/www/plugins/saisies/images/formulaire-enregistrer-16.png index 06b2491722d51465520942fa828328411b15b42b..a16058a0cd5067697218f7f1a9ad61c72b3af86a 100644 GIT binary patch delta 536 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 diff --git a/www/plugins/saisies/images/formulaire-saisie-defaut.png b/www/plugins/saisies/images/formulaire-saisie-defaut.png index 6a0e70ae0687b0e9b453ef76fdcf2a6b0d32d433..7bc466f5b6c8b3f31cce756b6736c10beda20df7 100644 GIT binary patch delta 290 zcmV+-0p0%p1F`~;8Gi%-002sU^>Y9K0QpHoK~#7Fz0*Zv0xr8BnFRRliW%Y7xE;dKaqFk+!sG%4OgPjY1rR z*B#2z(xVVZ`qK}lHAs`9GzdPL*2{$pP$w@n0-sxHKUH#4#{ap%M~RFS@qI3^D3F&N o)~5oecjRSHGaK`bQ}n;b2NVy1yS^;1ssI2007*qoM6N<$fJUHvj+ue@R3^R7l6& zm9dV3KoExi72;xZSCNPXv6q6z7upBg7qYRy#>&EkGuWIlQGW_%u93@vBjV{5ciSu( zVE&o;eiq=bFLmz$YwbG#4Pel^MF2`;%xBm8evcybd_K%j%#lU|A7!fu0K5NjogLcw~JFwQi0SF|~I+?rI z*Vfu`m%H2%>3=j$CAUB+RT7bQN2HW0(=^S6qKoBnnMe#gW)9;xhEl3sy(XdtgUMu~ z+Z{18@;q<2%a`18JRaTZ8#@4;PA746!{P9XjW5BxjNm(_l)4GkjaOCGEl{^V8jZwc zb>&)X5xP`_D^M|WvE6P($WatEAn$g&l9{yx`QoH2foU?!vP81!Y&OfQs%k(cBE4Fz zBI$bsP+kcbV-5fg!f85o+0+8{IE*nLFFA|cq!P@h1==Hexd0Kt^Soc_fS9@1@AqMs mTb>ap*Xwn1>z9dtzrFxSlPdeiGnl;q00004oAgcfX002ovPDHLk FV1jg$T;>1( delta 292 zcmaFPxSwf)NRa3zzYfJ=OTGh@ewz>Y}C zS@ym1E#|@(ChM#?W3f9{E^W`+Pl@^R(p|ekZ0lbv^A##qJCpUFzu|A5nflIh`QUuM zT*Wz$AJ@I#wp+G^AuTi@_7FpPyIQX@53>{--|t#+Z?7r0duwcx(jqt_m~V2kc`$K$ zo|t>I%Ga|qqDbw#?aQjQ4V|AvQUsHkm$S;n3CskL8Gir(002w1#jpSX0uxC@K~#7Foz8=@Ja-ht@o%4VW^QcTw(XQs zjGZ^g)8r{qj8h8!wyoGU7UyDiE4#It$*1^3SGPVo*b#Mgi;H5%t4?jnbCF(BUn|4I zsV^0{QJ*X1P6PiZU`BmO;7&!5j1rKelhEJ)Di04v{MkiEXn$mqemn2FqrYAE`<#*i z>im7+9E2tFV{6}7V;iCAG!W}>| z^96R;=TyEoAAe+@T$8O<>*{}hjp_o!79IKdE*5?IabW{=%<}VJI{vt4?%4cu*`K7U z>zM5)pJ?q*m;F;P$XjdgyPIO;IyV+c{eXY@`e}##`sF_*!)){Cr}5p_S=Z-0sz za_+b;q!t7I_0MO5XO}7T_1|Z8NCH#*_{i1p_nesK&-YtK%H-|=@Xju#iet^)t4T_r z+hwXQZoNrn01`8pk-Y}$Fdq)IXG}_kK!IZl;Edy#%47mUj+X~7>~a%-G0mU2Kp`hD z{bGAEOE+fFYvAZBTFmCqYk&;u3XDd=L=y^}CbDUu9Y_Bz>dRy10ePX6x+^V|rvLx| M07*qoM6N<$g2n?U1^@s6 delta 1211 zcmV;s1VsDH1jGrD8Gi!+003D4YF+>U00d`2O+f$vugEtAis=9V02y>eSaefwW^{L9 za%BKPWN%_+AW3auXJt}lVPtu6$z?nM00FR2OjJdqqobgppkQENX=!Pjo14hU$g8WX zc6N5k%F36Qmy?r|d3kyE_V%Qtq>he`k&%&mdwYIU3U$;rULz^JIGcXxNZyu7}?zK@TO_xJbG($cuNxV^o-ySuy7)6=rDvc<*4wzjse zuCA@Et-rs&kdTnV!os<^xxvA~v$L~@hlj_<$ET;KjEs!6wY93Ms*;kD&CShvdU}9> zfX~m*ZEbDK%YVz^;o-!@#IdolUteExa&mlpe9+L)goK1|Z*Tee`QP8)h=_=p`oFrrKOFHjn&oF zsi~=beSMUalwDn2*4EaTn3&z&-Q(lqm6es9ot=Mwe}80TWc>X6XJ=>f^74X$g8lvd zXlQ8W=H{QDpIcj7baZrDT3T>$aO~{txG4d_4W1o`ughX>S}6g;^N|p zii&G%Yo4B-adB~OZf>TgrgL+1*VosUmX^A@y3Wqd(b3V=)YN8XW|^6p%*@RH|Nmg9 zPH+GK0)LuGL_t(|+LY5}ciM0ifbrXIltOWf0m0p+#kJJkWtF+Rdv!<)`N~UxZFJiK z{=Zkb_uS{?O#)LoU!`v*a|Qy3gZ<0rD_|SEL@?`v=!0tr)+!KvbcEoU1sq>b5gh4Y zF?E9A)C{JHa|CbLpulg_YPJ0T(01<6_263{X@80rHc}hy=PM>ssnfY%1K$l5t&CHg zpxq5e;+3o@>r@;$nU5tYzP3Hju|ZtUx?iBS7>0SQOYF<9IIl8yzA?|w;;m6ef@NRD zDh5{>&ck_`suO>R5$5xe&mWZX<}CMvE}_wAN?Iq=;+JbWl-8%Pg|)Q>8#CY9C)hxv zR)4F5BY}2+KT&rG&b^~vUS1yFV#2ECqT~g=TES8Y+JUX4=?=xcxWvA(BgRgLsV|eYg!V7MtgrlIoJY`mIzi3T=D9A~XXtgmGX^jyK zNQtybva+mm9_&j0;-SSlU6^hkN$D(*9)Dqrl$OwA!hd;aiRbrTngzeGjNrfy{&F3G zzz*K}bp&-Bu$5y3Db(CVwRt zI4`;flUObgur**f>aav=?Bcz#dtktp9gZj)ESk&`E^t|U1rC#GF$U?1g{1om>^_U7 zQiXyg*_F;}0ZOn6e_hAoEjz Z0RR``ma-Cjq0ImQ002ovPDHLkV1gD zqkV;!G)RM2=vKHxMV6Vc&pkKieAn`4Ci!=E#9+f(JJ)-E4K%#30Z*Pg=eLf?JFIg% zqhPH@g7*M-5Y3!(`;*0$Qq!FGcWP10_o5aJ{WoLGjwAz-Wq+$FG!QgL3y&rllq;33 zu?^k_(CCG8(ZCp6O)@Bz%G;uW^L^7{VA2eV#S#pnSfE&6&_HV~k_^rk3Y#bb6ZW}* zM0H~0cM=eWW2r%!Ev35L>@!U|Fn}q-_m8Ms0!F47j47APd%X95KKY&#eXPli~*Ld;q#ZhZEdSlci(Y})2GkuX5Ssqng%Auv{I>_!2BeTZ%8Sx zFqRai0il`F`cW=nA+q^dCR-81UyLeR1@Q>m6=;b0gV?}^VG4`oh~7O2y@$|Wwuhql z1~h4!xBz&fFPM8HGr4O(;c~e$39-Du#f+gbHc$*Z1b?a_RS)o;ch;dkU>)C|AXzK> z>-B9Gfk445qwt_~)L}C)G2G1iJ`GSRY177B$+;9?FgpE+~p x1oS3?&M48+(lQdasbB$En3EYRR;=hq(LWR?1h@abb@~7R002ovPDHLkV1h4_4Fv!I delta 719 zcmV;=0xhBYyw^b5ch_0Itp)=>Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2ipq_4KFptT&MT|00L%7L_t(Y$E8*=Yg1tqJ?FkW z!B)CR6{geNdBZ!sno^-SX*10Dy3=5$Xk+n6G=(h4A@%K40!c`i8Vf+KZc!D_DGq%M0O>ecfLL&@@B#y8 z;PPA&NKonu=;RS1J(8rou>hW~tbEV1{B`8HTQxp{KvE(2&f?J9;PS zcaqpYVlq+^nC009fFDJJC<4frmzOuQEZ+i1vOAYZ4}U|*ciZiD13*3&MKN{`4h~jb zjuWclLLVL;HJXh^dzg%d0pydD6Y~V&?#J>6B%~M8djNio?M3zav#TWMlf<4UN$Fyq z=VUx>W|G7_4=W_zR;$&|BLmdy_3KHJY>+IQ*=3OCA;i6iPDj8j5dgaTuH<`iJ*+NO zHwOaLYJaN}X_~$;;{%!jg4~^wcaO2xDnKH!L?9q{y0qo)cONe;ee2oeG%dX`<81&6 zd0^MfPT7I_t}%|OBTYuT3E~5QD?I=bZYbXR^d(1$?*2KA6rgDU34n0Miv-Cjj99gw zy~GbuRA)HbL8M}QfH;;xZYsEjx-b6Mx=(kIMM(ENR|ipUJPTl*PN!BXB{S#j!QB08 z9P-~in46nptJS&$U~<@>#t6|Vm&^Ox+uH#E{r~}EN@<{N7Bm0=002ovPDHLkV1mLR BJk|gJ diff --git a/www/plugins/saisies/images/saisies_case.png b/www/plugins/saisies/images/saisies_case.png index 71565b0b1f7108b3c225816043c4b83fb1502043..5d5851353ad983128f1157e3ba7a4c6b10b6c1a7 100644 GIT binary patch delta 168 zcmV;Z09XI$0=WT@8Gi%-002sU^>Y9K0DwtEK~#7F?b5LU0bvjY;jKXddVwCU13&~M zKq|ThHoFSsAkzXs5t|QWfc<0M#9#L0$ET6^kOPZMn7)4Syl*fEvPjVw;C%6@pWg+7M8(vKb{Zb@>`|k{d W!6KQFD{ImK0000VYbIJes65U8~+|3k0wv2(+;R6=%k0kA$zni>wnl#Z8n=x%ElP9*5AM+ z0{|?`>J`6UudG%pwAP)R&u4q9lp+knLEh{caVaI|^BF1S>kXuoD5YqchV^j}qPPcMmL;}rv)yh-SKMomBnh|Mjk>Pc@Am+B zo`>T&qYVaI6j8@9d7iUaECBF*e^O?HAupFpf*_!6TbiaJ2!hub7-N{v=l8J?0wKiY qE8S)ArM0g5Ug&TB`&)nG@9+c6D^Mc3YyU<70000Y9K0GdfeK~#7F?a?Jr1pxp>(d`*c5b;D$^h!p0 zrC0jk)`vbrkGS{Yr*-$;%XfE6`))qz3Dep2?lq0w>~{w!sYEFm1uZ>SdH@Nhm`%VD z3a5X406SmEVII&MXngWZ!ai$g{eU-CS>m2q9tipYCRZ#XuscP9)en%dcw(7j-2Q-; w0_em5ke({t!OppMnyX8>+s@w4-kiW00001Pf0{UR7l6w zlQC)nK@^6+nH_{#*2d0GEWChMFr>8*7QxD3W$7&p9>G)=vVSS}41%R65IjT{oZ?L? zgBy~N852kz49pvb`QU%^!GAAx*{s*=9N2z&S*eHVbovwmFjxESa5(fLqTW4ilTTHk(W>IT5Iinw8`JCP~%NRtU<=>n8Ae@uQ_k|A>T3HM18#gY9K0$oW&K~#7FmCOUwCS?GC(aG9eN7=5UY^-hD zw!Oc(wr$(CZQC|(uK9A$=+&Lz?;D(^^P9o{DeAq{g%|JphXbiaTRt70zxG(WQ>Wh8 zb=TPk{{|$i8(;O;@uf7QULBl2@%-e)6F2qTo$-^u1kDCb8GkbVl|DuL$M>4tZ%5y& zL&a!stj;p_2>#fJ9Pyo+?dg3Z@k*j3sXtt8bk#zfAwOJ2*2LZxge#u5>WwC9tEQ&L znrW_;B<+5PQnCU5Qt5LF?w29_9Z zl_aH=R96d4wSPC&B73crH!%YAOq)@v{@Q9PRkDF*JLkJ^;p3pd;D5j?cGp8qTbRu3r2bIn-FkY!L^IQaV6ZX zIiST47qCv|ra`zoLq~vZYRE4qxZw-a0H;)+907{Pc7O3}!@cPm_Iuqn+;Y`ry^aJA zg+PNUQGRWO=j_K?&)9`)&e?Cut*DPfpypQ%+yWf+q-j{~HT$vMSe>*`rdkN}f3?Py z(|~J=n1xF=T56cSCfj3$9DPFI$b+T#?!vE~w%T;l%(mW6D~(c9#?7N136YXZm*9*a z{$-}I#($Y?tS%ZTD4j2*RcyuZFeux6$B}I*+Nb?3o~3 z?f43ssi>fwvdgF3)tZ}H4DVWhd|FQje^u)u`DIh^ROPh|M|Ey8GRN*$+#UQ=eV=YU jyMN1NpL!_x$G!)C{vKPeWyw_l00008VI delta 1469 zcmV;u1w#6k1;h)G8Gi-<007{3J@^0s00eVFNmK|32nc)#WQYI&010qNS#tmY8@vDj z8@vI!x1hTK0010xMObuGZ)S9NVRB^vL1b@YWgtdra%FdKa%*!SLsK*cveTdd000(r zMObu0a%Ew3X>V>IRB3Hx05LKzGcYeOI1G~nH2?qw97#k$RDVc`os>^Z6L}QJzr)NF zrVOR6Q0P!fYoVkigwSl)E}p@J5MvWgCMLQ!6R#Y+89nHYBZp1)q6r5@F2-Fqk>F}r z+#qoQ1=fNo{kQE*>69|lPN$vO1ECSEtL{tY@cYht@AJO-<^7=RI==OrotWnXeRuozZQ}a%>-vX1 z30*%rU%q^K)MPUK(%RZe7K=rwstS@MVKf>+k|d5H48x$Yu@L}j|5%pA)2C16_4Re% zix)5U>VG;Q2qF-V$4QoDK~WSaih|qi#`g9$XqpB|l4xmZK|@0WG)+S~od(OYplKSi zEW=W>l+Ha2yA( z*Nc{x7IbxWAruPX&Ye4F0L;||a2&UzX&P)c8-L!tdx!n~eXOmm!D6w%=kvjCw}az2 z`2Btu3eVZVq6nVn@%Zs$ghC-0jYjnJ^!N#aXxDX}{{+z4*_oy&Dtqzb z#ea^To}Lp^jE#-q{Q2{^di5%FUB~3)B--2CF*`d8zu#ZWb2^>Y)2B}l0$4cKYKt~J zJe&iNPNh<{0znXP<;oR2d-e>1Ab=!E%*@PSYHAA6XcQwOBQTjvwfx@RUif^zvmXxk z;U?>YxQmH^u6bOOy84u=Dprom`5f~IKzKr|Y~+qZ9#NFj)K6A%O;P}jle=xAzj zaWS3C<(y`-xu(-Jjk|a6LKH>3et-QMf*?TGbX&U8n8N0i?c=F^4 zqR}X_*(?-Afx%#a-ENnv)#|4X0Dz*Xzc)5Ez9&f%sZoxo$z-qNFhC-pmwzjt4`}_NU3kHMh01m#US-tod X)DmWKsEB0V00000NkvXXu0mjf6g99? diff --git a/www/plugins/saisies/images/saisies_explication.png b/www/plugins/saisies/images/saisies_explication.png index be5c13408d12536b31df0c144f2398c605d943f5..6bc994857f49bb15806b2dcd28300ec022b49740 100644 GIT binary patch delta 231 zcmV+2De6on3#D{X-tOlkynoX@PsGG%Xhu0*2ac>nDFZ3pMJZ`4y+kPk zsd5~pEZMfH75||Vr8Jxx8tO+0iyr()mCLAS-K&(+NH6MG_FyDkd6zycL_K?UZ1^?y z7^R%4R75HF#wu&(b)ufOPw7q9jce0U$CfYY*{yV8HtOgZNtJYNChFOh(zku>C}GZ_ h6RW18l%`fp%pabXZdR$cq@4f&002ovPDHLkV1iyRX(|8! delta 363 zcmV-x0hIoO0)_*SB!2;OQb$4nuFf3k00002VoOIv0RM-N%)bBt010qNS#tmY3ljhU z3ljkVnw%H_000McNliru+Xn~;A_w$*Fo*yE0SZY(K~y-)#nd57Ltzxg@!xjGCK?1m zG|1XS5Q`$BMT=dF**x$Y2roB?K`;p7f-V0b8OFD&i{A8PL&J_Cx1Qtfpl4SMrT_aJegTpwI`(~?DvbaD002ov JPDHLkV1o8`o@4+3 diff --git a/www/plugins/saisies/images/saisies_fieldset.png b/www/plugins/saisies/images/saisies_fieldset.png index f9efaca86e2ee4f64dfc5a77edb23ae000e891e8..3648cf0fd6f31ea0b2ef9a990c918773a362925f 100644 GIT binary patch delta 110 zcmaFK*uXeJGMxbkj>;sd04aA*7srqa#^fKZ%mxk~8b_ww;1k)`tM;+t@5}hxlH2}A z9o+EfdX>eFgCDYOLyqUR-S&{W=B(Nv&~ZUEAtAuK$IB+JpZ5*}LlYzS`HKn8ULd1A MUHx3vIVCg!04a|u&j0`b delta 216 zcmV;}04M)|0qFsd8Gix*003_ls;>Y500v@9M??Vs0RI60puMM)00019mqh^feeZcGoG?MsorQsc!K?0TF_2RCba4!+U`&>nlHjK*@L!!Nd{XY=`lPG8`O*^XxAw3vb6ppzccUnhf?KrIZOu6{1-oD!M4Otpku5e+B>m0N{5$_y7O^0drDELIAGL9O(c600v@9M??Vs0RI60puMM) z00009a7bBm000XU000XU0RWnu7ytkO2XskIMF-jf4h=dtaH3hC0003kNklkF zx~_Yj=Q$3C0|4OdM!;i}`@RpuFtA#!9`2i_K~+^K%Mx)Mb5&LM0z@Rn7D$o=%jI$~ zX1m?~Y9K0NzPNK~#7F?TZ6w#bFdj@4Us?M#i#@Ia^E1 zZJEnsnwNWVVG47a(rnwdb$0vrFnjUc)9>qi)se5B{dzHdiEhk+iDAZ>eUoeiW9lYr zpr3tZoM=LsFkBP|!l^`Er#ubjI8;i=Ae~afMYm5I9%fgb27im3Dyh^^MVjHFJEo3A zvnx-76)rf!n?1JiQoBG5oTx!vr#uZ-xuOv<)1*JqozsS&*_Efk26tpq$eof)mcF99 zq@G~2D^G(hAeK=828jbiaVDN_!;O0xynV%pc~63F)vwTj{Lk6%5v8+z9L@o==>Px# M07*qoM6N<$f)`bK>Hq)$ delta 595 zcmV-Z0<8U)0^tOZ8Gi-<007{3J@^0s00DDSM?wIu&K&6g000JJOGiWi{{a60|De66 zlK=n!32;bRa{vGf6951U69E94oEQKA00(qQO+^RV0uBu}5P2P=_y7O_;Ymb6R7l6| zl`pGeQ5400=icKBf<*O_Wm1=X1Ku5BpH=B)iuv)EjEEdyRYYk{XODT0Ck+riH+Xsx;5@2plUmdhnV2%60%LI_%|)>ALx{0EE0LhtwcFT3POBtkl! h7UK2cyafJ#fgjMF;lqQlut@*_002ovPDHLkV1oGh6DR-x diff --git a/www/plugins/saisies/images/saisies_oui_non.png b/www/plugins/saisies/images/saisies_oui_non.png index a32b6072c0cb26a458dec53346d952456d9c8f9d..9445412e02d352488d8dd1e8ee813d1ab1512bf8 100644 GIT binary patch delta 300 zcmV+{0n`4b1I7Z7BYy!6NklcPwQDNHjkT77FRppt9vG8Q^D}RPO#i@sf22&VdSPPKO z#+qu<3~vCpCnqQ8H+L_e?|8YpId{gl;7Bv6u4(Kffi=LN$WjJ}hQ}smlspWt#gk#D zmetuz3}NCirv<86%NXwKv&&axuG_O)7*6Y1Xh}5Px#32;bRa{vGf6951U69E94oEQKA00(qQ zO+^RW2M7o@8oAVq1ONa5I7vi7R4C7NlFdrPKoG}gH<@&8un0C*Y7s$1K@Tl>@FaK? zK}7H+d=cM3&{q&d5WH3K;7P$=3W5mYM=3O-G|lHEyIv|}A%D(gV1E4PKgVZF8{bn}D~BEsrR3p53eqEu$;{brx*Q$2NJibzfShl)WE0vO0G z1DJv=k(2>Ulz&07WBZGtz*2LCX-m94-(t+*rnovX^L5$YcKX~j(I(Ig9~WIhL<=p@ zKy=sbRnW4~DgoqM1+ZgFG}TCkHssBtvmQE2(Q9K;&d+I6N$Fp%-tX2J=&gYBm=F1^ rcJpy$;$aVpz|^2w{oB<)@AC^k7I&CV75)(b0000k diff --git a/www/plugins/saisies/images/saisies_radio.png b/www/plugins/saisies/images/saisies_radio.png index c85d9492ad8444e2087cef880a83868b6028a6f4..c4d45d191b61f3caf11030e09ced89486f56b2a8 100644 GIT binary patch delta 249 zcmVY9K0MSWAK~y-)?b5$W!*CSE@gJRqK1iLjban}y z&8uYd3A$&=7$}-#ats-)ub^ZSBBc;lDINUtaTbgb=YHpNIQQOjLpTva2z}g?#gHq8 zrtITM`8KCp2Y;+S1(2-1*cF zeO!V1uU86To3*~vPFGjy9B|N0H~o)aI`IQvBD?1{n2bJ@00000NkvXXu0mjfV`X&v delta 546 zcmV+-0^R+J0j(-vafxz>;D~cj36be7{ z`TYBr1dOrnZntY^G8rV3NyK6?0D$lNFijJJApB4i<@;Zi#~AAlheKK}m*l!GolYmZ zTrPAzpXqwN5)qMM7{nOs-pb%UYs+@KZI?Y?N2%3TYmz}vRc_}797W6GMS*)>p_-fl*?s!o`+7S0|2Pk>nIkBuq>+u;QiqW z9LG^osT2~41aw`8EX#O%d&6inf?*h#&1UHL`v8DkE(gbPl&4x01c4BX#SjjMv0kr{ zPNy-QPT{&PeBa06aKLJ{0sus#Q3OFCJSE_H-sLzBk$*@8k|e?NypM3(wh@oVAxRPd z;CMWO=Xv)jfhdY>zu$x7IH;-$#uyfh1x(XKC=^02mxHRR0D#SA15p&&QzL5Ic1_bX z`i-vZq^c^F%Vknkm2_SIc+)hEZcWkMJunP|KI7gVJS5RHjpp+?`Mys?M85CSd_E^l k)9!}<^BY_A;>Fkb1qNO_dHmKZ_Z=je z)>OS@@O%{DUhSZ?>LY{4ZHI1NrVIHUYG0Sv$1%^__Cm1AQGMz=kQ+Q*{an^LB{Ts5 DxcEEI delta 240 zcmZ3%*uXSFqMnJFfq`MJeF10a_tz$e7@|Ns9hSFUt+b~ZLP zUMjS%9VpIH666=m0F>CQ>(Bw@a~60+7BevL34k!;&kF&TKtY)j*NBqf{Irtt#G+IN z$CUh}R0X%pqSW&IqU>S?=U@}IO_vuiFk~_Wd%8G=aLi0jIKZ_eEJK$uh|`C6j>D?V ztEi}Z5-r` jnFIRf&-~9ECd@GZi*R~i@9H-|cQAOm`njxgN@xNAlyp%I diff --git a/www/plugins/saisies/images/saisies_selecteur_rubrique.png b/www/plugins/saisies/images/saisies_selecteur_rubrique.png index 026a114419c095ff34a3c77d2eb3c48a72a38624..3ddb98447e03a41bd25329bb4a57503e39e24ba9 100644 GIT binary patch delta 152 zcmeyzxPozlL_G%s5FC|BQUOv-B|(0{4F97iDs2Vw5Vn42?mB)B55qwG*!1b>}+7XX0mc-^^S|vXO}N`dL$^dUgPa8kQ+Q*{an^LB{Ts5 D^#VED delta 238 zcmZ3%_>XadL_HHT0|Ucc$*b8win-XyGlYYK}+go zyi{miJ5ZdZB*-tA0VuIq*P#Q*=PdAuEM{Qf698expBDlwfr2t6t`Q}{`DrEPiAAXl zjw$&`sS0kHMXBZaMcKs)&cP;Zn=UV4U`S^O^mK6y;h346aDZz`ScWcR5T_6C9EVkz zS68ViT)lW;S<3^}4ZaUtRvh8xnZf^|K|_vNn(g=DZ#-=25ev}L*7#fyM9ZKYd}{pc)I$ztaD0e0sv(9P$B>T diff --git a/www/plugins/saisies/images/saisies_selecteur_rubrique_article.png b/www/plugins/saisies/images/saisies_selecteur_rubrique_article.png index 77acfe3e5422c39ad38f8284490f29b738618475..e9767781f93c42b4ba1abf4e69e44e6989d2f194 100644 GIT binary patch delta 177 zcmZ3&bdYg^L_G%s5FC|BQUOv-B|(0{4F97iDs2VwsytmBLn;`1``a0t12|YWU+z7y zMJLnxpvpJ(zkl8u>z#@)>04H!a$-ZDmyqNC+pqT>IKOq;d2OSf(sxqt^Ges*CKR&l zo+-)L(71?KXGJ7C;~eHP?GnfJD-;i`E>Bo;Np3@$7=zZ0S+h9*y-&4b+$tuuVR@6_ dh4SrIS6MW-?dE&=b%GVhah|SzF6*2UngH5TNBjT) delta 277 zcmX@exP)nfL_HHT0|Ucc$*b8win-XyGlYYK}+go zyi{miJ5ZdZB*-tA0VuIq*P#Q*=PdAuEM{Qf698expBDlwfr2t6t`Q}{`DrEPiAAXl zjw$&`sS0kHMXBZaMcKs)&cP;Zn=UV4V5ny(_jGX#;h5>#ZOGMNAiyHd&veMK%G-N2 zbF^aoN6mw$F1bf^tmjyAHkn0!!E}vXM|lswV?29pEyJ->*Sj+Bs~>&i`}=mrv^#rG z>$^DWM~mI~ti*A_Sh3+8Qou@@R75oXGu4Te)*q@p+@?Y$Y9K0M$uEK~#7Fos`u90x=W>(=aZ@;2q=(e(3`$ zz};op2|@A2OI9$g z%pzGr!mWU?)9i7;k(_YG1+apM63V1vsgfEog3ts7C;ep8uXeau;Tzp0H`}DwtuS>6 z2qyjPq~D1W<_-bjpYHzsk=%mmx%cl+AYocf&qlYjpt zPOFptwCNvw6Bo`&Z)#ekowPNUh_0AH%Te~5K+gIBIDIFwNvk;{00000NkvXXu0mjf D|6_Gv delta 441 zcmV;q0Y?6g0>}f98Gi-<007{3J@^0s00v@9M??Vs0RI60puMM)0004fNkl@{yOpkUIWnN#`%0E zilVeWEQ%uHIL2%?WA;4H!*aP4xFwQh`Kdq<@~1kVOeSTuf&fBDvj>~aCO=RGD2}Jo ziMv-M;Sy}O+kcW$p86_zmSxOZErDfOjIydq+qU!dD2i%*;u7q3yH4t-(ztk8i{;7MOu@Z~rgw00000NkvXXu0mjfc>&EF diff --git a/www/plugins/saisies/images/saisies_selection_multiple.png b/www/plugins/saisies/images/saisies_selection_multiple.png index d682108ad8dc666c7064012b67b2b5638f8c2580..b353ba2635619100e5f672252d736d6e2c0b67f4 100644 GIT binary patch delta 297 zcmV+^0oMNY1Gxf_8Gi%-002sU^>Y9K0RTxvK~#7FosCc;)a|oQR$bUkhp5<|f>J_M+c7_3cw*z(~LuFu_hJv}xPslZ3)R v_>?-|CT9W?s3OFV@byW5qJRGr`1^SW{aRYw8?P4300000NkvXXu0mjf4qu8n delta 486 zcmVuTRlr_%ty4*@Eb z3aZs=a;rqfCjdO3PY@AmwHksTQ0mHYp!s}m1dhgXxm3;>8~`lK!t3=)CRi*MnW{~s zK@b?f8#^!o#0yue6#$^oXyAIiCXTio2k<;EmwJ9a9uIW8T}{O8c2fz62t-AbWlTyNQ9Nh1BbUK}6 z57@j+(C5Kc}&jzAFz2v zHYsyNM1=8poVr0mh++gBX(KVIw{07~@8|DeG#aIDkY5l&$$j64>$(WTP&wC3W}xkM zTgZb_sr2(6hN0d8D;N%kng0O*?Du;m=lUqPLQt>Q0RV@?q3|Uf2agi$-gjuB;CaU{ cef&p!1NY9K0KG{>K~#7FmC}Vxg<%Xv;itF^@Q=eZtbn`Q z2Cxi65#_oyDf*qH@zXaItpu+R_Wh5?-GdeE@7VS?AKv#(1RJ(WY*x|(D*)$!K;=fV z5H4$Pp->Y-5?~;?O##9cqSj9dA)M72z@21G3b^{Se@QqMC0--+BoB3lo0b^}CzOor z|5Sy*P3sINWk>hF3546$I~M1%u4j?*}U^&b;s5I5j54&_m1Uv@;kZ|1`;+kY=iqpDj?^#BhC0l+wp zEr94|>@Ez$FY9L!1wjDM^KL<2mId=XM*ubgIF19?b+aQ#@MOq&vs$$!HEb(QJmJGX&PZ2^nj8*H5q@wTp<6oo<^QZ=@0~3%C z;`c@)qRl9e`5;ZxOS7o!x@)6?bN;LbNs@frL9a9DQU^o?A;dEpNGU-?h~xOs2Uj%N w2z=iM01U(M=Oa^L?FqVRnr=Vz@gMOG@-a;h!9@J%01E&B07*qoM6N<$f)}c(5&!@I diff --git a/www/plugins/saisies/inc/saisies.php b/www/plugins/saisies/inc/saisies.php index 53853efd..ad7a3e8d 100644 --- a/www/plugins/saisies/inc/saisies.php +++ b/www/plugins/saisies/inc/saisies.php @@ -1,517 +1,512 @@ - array('form' => $form, 'args' => $args), - 'data' => $saisies - ) - ) - // Si c'est toujours un tableau après le pipeline - and is_array($saisies) - ){ - return $saisies; - } - else{ - return false; - } -} - -/** - * Cherche une saisie par son id, son nom ou son chemin et renvoie soit la saisie, soit son chemin - * - * @param array $saisies Un tableau décrivant les saisies - * @param unknown_type $id_ou_nom_ou_chemin L'identifiant ou le nom de la saisie à chercher ou le chemin sous forme d'une liste de clés - * @param bool $retourner_chemin Indique si on retourne non pas la saisie mais son chemin - * @return array Retourne soit la saisie, soit son chemin, soit null - */ -function saisies_chercher($saisies, $id_ou_nom_ou_chemin, $retourner_chemin=false){ - - if (is_array($saisies) and $id_ou_nom_ou_chemin){ - if (is_string($id_ou_nom_ou_chemin)){ - $nom = $id_ou_nom_ou_chemin; - // identifiant ? premier caractere @ - $id = ($nom[0] == '@'); - - foreach($saisies as $cle => $saisie){ - $chemin = array($cle); - // notre saisie est la bonne ? - if ($nom == ($id ? $saisie['identifiant'] : $saisie['options']['nom'])) { - return $retourner_chemin ? $chemin : $saisie; - // sinon a telle des enfants ? et si c'est le cas, cherchons dedans - } elseif (isset($saisie['saisies']) and is_array($saisie['saisies']) and $saisie['saisies'] - and ($retour = saisies_chercher($saisie['saisies'], $nom, $retourner_chemin))) { - return $retourner_chemin ? array_merge($chemin, array('saisies'), $retour) : $retour; - } - - } - } - elseif (is_array($id_ou_nom_ou_chemin)){ - $chemin = $id_ou_nom_ou_chemin; - $saisie = $saisies; - // On vérifie l'existence quand même - foreach ($chemin as $cle){ - if (isset($saisie[$cle])) $saisie = $saisie[$cle]; - else return null; - } - // Si c'est une vraie saisie - if ($saisie['saisie'] and $saisie['options']['nom']) - return $retourner_chemin ? $chemin : $saisie; - } - } - - return null; -} - -/** - * Génère un nom unique pour un champ d'un formulaire donné - * - * @param array $formulaire - * Le formulaire à analyser - * @param string $type_saisie - * Le type de champ dont on veut un identifiant - * @return string - * Un nom unique par rapport aux autres champs du formulaire - */ -function saisies_generer_nom($formulaire, $type_saisie){ - $champs = saisies_lister_champs($formulaire); - - // Tant que type_numero existe, on incrémente le compteur - $compteur = 1; - while (array_search($type_saisie.'_'.$compteur, $champs) !== false) - $compteur++; - - // On a alors un compteur unique pour ce formulaire - return $type_saisie.'_'.$compteur; -} - -/** - * Crée un identifiant Unique - * pour toutes les saisies donnees qui n'en ont pas - * - * @param Array $saisies Tableau de saisies - * @param Bool $regenerer Régénère un nouvel identifiant pour toutes les saisies ? - * @return Array Tableau de saisies complété des identifiants - */ -function saisies_identifier($saisies, $regenerer = false) { - if (!is_array($saisies)) { - return array(); - } - foreach ($saisies as $k => $saisie) { - $saisies[$k] = saisie_identifier($saisie, $regenerer); - } - return $saisies; -} - -/** - * Crée un identifiant Unique - * pour la saisie donnee si elle n'en a pas - * (et pour ses sous saisies éventuels) - * - * @param Array $saisie Tableau d'une saisie - * @param Bool $regenerer Régénère un nouvel identifiant pour la saisie ? - * @return Array Tableau de la saisie complété de l'identifiant -**/ -function saisie_identifier($saisie, $regenerer = false) { - if (!isset($saisie['identifiant']) OR !$saisie['identifiant']) { - $saisie['identifiant'] = uniqid('@'); - } elseif ($regenerer) { - $saisie['identifiant'] = uniqid('@'); - } - if (isset($saisie['saisies']) AND is_array($saisie['saisies'])) { - $saisie['saisies'] = saisies_identifier($saisie['saisies'], $regenerer); - } - return $saisie; -} - -/** - * Vérifier tout un formulaire tel que décrit avec les Saisies - * - * @param array $formulaire Le contenu d'un formulaire décrit dans un tableau de Saisies - * @param bool $saisies_masquees_nulles Si TRUE, les saisies masquées selon afficher_si ne seront pas verifiées, leur valeur étant forcée a NULL. Cette valeur NULL est transmise à traiter (via set_request). - * @return array Retourne un tableau d'erreurs - */ -function saisies_verifier($formulaire, $saisies_masquees_nulles=true){ - include_spip('inc/verifier'); - $erreurs = array(); - $verif_fonction = charger_fonction('verifier','inc',true); - - if ($saisies_masquees_nulles) - $formulaire = saisies_verifier_afficher_si($formulaire); - - $saisies = saisies_lister_par_nom($formulaire); - foreach ($saisies as $saisie){ - $obligatoire = isset($saisie['options']['obligatoire']) ? $saisie['options']['obligatoire'] : ''; - $champ = $saisie['options']['nom']; - $file = ($saisie['saisie'] == 'input' and isset($saisie['options']['type']) and $saisie['options']['type'] == 'file'); - $verifier = isset($saisie['verifier']) ? $saisie['verifier'] : false; - - // Si le nom du champ est un tableau indexé, il faut parser ! - if (preg_match('/([\w]+)((\[[\w]+\])+)/', $champ, $separe)){ - $valeur = _request($separe[1]); - preg_match_all('/\[([\w]+)\]/', $separe[2], $index); - // On va chercher au fond du tableau - foreach($index[1] as $cle){ - $valeur = isset($valeur[$cle]) ? $valeur[$cle] : null; - } - } - // Sinon la valeur est juste celle du nom - else - $valeur = _request($champ); - - // Pour la saisie "destinataires" il faut filtrer si jamais on a mis un premier choix vide - if ($saisie['saisie'] == 'destinataires') { - $valeur = array_filter($valeur); - } - - // On regarde d'abord si le champ est obligatoire - if ($obligatoire - and $obligatoire != 'non' - and ( - ($file and !$_FILES[$champ]['name']) - or (!$file and ( - is_null($valeur) - or (is_string($valeur) and trim($valeur) == '') - or (is_array($valeur) and count($valeur) == 0) - )) - ) - ) { - $erreurs[$champ] = - (isset($saisie['options']['erreur_obligatoire']) and $saisie['options']['erreur_obligatoire']) - ? $saisie['options']['erreur_obligatoire'] - : _T('info_obligatoire'); - } - - // On continue seulement si ya pas d'erreur d'obligation et qu'il y a une demande de verif - if ((!isset($erreurs[$champ]) or !$erreurs[$champ]) and is_array($verifier) and $verif_fonction){ - $normaliser = null; - // Si le champ n'est pas valide par rapport au test demandé, on ajoute l'erreur - $options = isset($verifier['options']) ? $verifier['options'] : array(); - if ($erreur_eventuelle = $verif_fonction($valeur, $verifier['type'], $options, $normaliser)) { - $erreurs[$champ] = $erreur_eventuelle; - // S'il n'y a pas d'erreur et que la variable de normalisation a été remplie, on l'injecte dans le POST - } elseif (!is_null($normaliser)) { - set_request($champ, $normaliser); - } - } - } - - return $erreurs; -} - -/** - * Applatie une description tabulaire - * @param string $tab Le tableau à aplatir - * @return $nouveau_tab - */ -function saisies_aplatir_tableau($tab){ - $nouveau_tab = array(); - foreach($tab as $entree=>$contenu){ - if (is_array($contenu)) { - foreach ($contenu as $cle => $valeur) { - $nouveau_tab[$cle] = $valeur; - } - } else { - $nouveau_tab[$entree] = $contenu; - } - } - return $nouveau_tab; -} - -/** - * Applatie une description chaînée, en supprimant les sous-groupes. - * @param string $chaine La chaîne à aplatir - * @return $chaine - */ -function saisies_aplatir_chaine($chaine){ - return trim(preg_replace("#(?:^|\n)(\*(?:.*)|/\*)\n#i","\n",$chaine)); -} - -/** - * Transforme une chaine en tableau avec comme principe : - * - * - une ligne devient une case - * - si la ligne est de la forme truc|bidule alors truc est la clé et bidule la valeur - * - si la ligne commence par * alors on commence un sous-tableau - * - si la ligne est égale à /*, alors on fini le sous-tableau - * - * @param string $chaine Une chaine à transformer - * @param string $separateur Séparateur utilisé - * @return array Retourne un tableau PHP - */ -function saisies_chaine2tableau($chaine, $separateur="\n"){ - if ($chaine and is_string($chaine)){ - $tableau = array(); - $soustab = False; - // On découpe d'abord en lignes - $lignes = explode($separateur, $chaine); - foreach ($lignes as $i=>$ligne){ - $ligne = trim(trim($ligne), '|'); - // Si ce n'est pas une ligne sans rien - if ($ligne !== ''){ - // si ca commence par * c'est qu'on va faire un sous tableau - if (strpos($ligne,"*")===0) { - $soustab=True; - $soustab_cle = _T_ou_typo(substr($ligne,1), 'multi'); - if (!isset($tableau[$soustab_cle])){ - $tableau[$soustab_cle] = array(); - } - } - elseif ($ligne=="/*") {//si on finit sous tableau - $soustab=False; - } - else{//sinon c'est une entrée normale - // Si on trouve un découpage dans la ligne on fait cle|valeur - if (strpos($ligne, '|') !== false) { - list($cle,$valeur) = explode('|', $ligne, 2); - // permettre les traductions de valeurs au passage - if ($soustab == True){ - $tableau[$soustab_cle][$cle] = _T_ou_typo($valeur, 'multi'); - } else { - $tableau[$cle] = _T_ou_typo($valeur, 'multi'); - } - } - // Sinon on génère la clé - else{ - if ($soustab == True) { - $tableau[$soustab_cle][$i] = _T_ou_typo($ligne,'multi'); - } else { - $tableau[$i] = _T_ou_typo($ligne,'multi'); - } - } - } - } - } - return $tableau; - } - // Si c'est déjà un tableau on lui applique _T_ou_typo (qui fonctionne de manière récursive avant de le renvoyer - elseif (is_array($chaine)){ - return _T_ou_typo($chaine, 'multi'); - } else { - return array(); - } -} - -/** - * Transforme un tableau en chaine de caractères avec comme principe : - * - * - une case de vient une ligne de la chaine - * - chaque ligne est générée avec la forme cle|valeur - * - si une entrée du tableau est elle même un tableau, on met une ligne de la forme *clef - * - pour marquer que l'on quitte un sous-tableau, on met une ligne commencant par /*, sauf si on bascule dans un autre sous-tableau. - * - * @param array $tableau Tableau à transformer - * @return string Texte représentant les données du tableau - */ -function saisies_tableau2chaine($tableau){ - if ($tableau and is_array($tableau)){ - $chaine = ''; - $avant_est_tableau = False; - foreach($tableau as $cle=>$valeur){ - if (is_array($valeur)){ - $avant_est_tableau = True; - $ligne=trim("*$cle"); - $chaine .= "$ligne\n"; - $chaine .= saisies_tableau2chaine($valeur)."\n"; - } - else{ - if ($avant_est_tableau == True){ - $avant_est_tableau = False; - $chaine.="/*\n"; - } - $ligne = trim("$cle|$valeur"); - $chaine .= "$ligne\n"; - } - } - $chaine = trim($chaine); - - return $chaine; - } - // Si c'est déjà une chaine on la renvoie telle quelle - elseif (is_string($tableau)){ - return $tableau; - } - else{ - return ''; - } -} - - - - -/** - * Transforme une valeur en tableau d'élements si ce n'est pas déjà le cas - * - * @param mixed $valeur - * @return array Tableau de valeurs -**/ -function saisies_valeur2tableau($valeur) { - if (is_array($valeur)) { - return $valeur; - } - - if (!strlen($valeur)) { - return array(); - } - - $t = saisies_chaine2tableau($valeur); - if (count($t) > 1) { - return $t; - } - - // qu'une seule valeur, c'est qu'elle a peut etre un separateur a virgule - // et a donc une cle est 0 dans ce cas la d'ailleurs - if (isset($t[0])) { - $t = saisies_chaine2tableau($t[0], ','); - } - - return $t; -} - - -/** - * Pour les saisies multiples (type checkbox) proposant un choix alternatif, - * retrouve à partir des data de choix proposés - * et des valeurs des choix enregistrés - * le texte enregistré pour le choix alternatif. - * - * @param array $data - * @param array $valeur - * @return string choix_alternatif -**/ -function saisies_trouver_choix_alternatif($data,$valeur) { - if (!is_array($valeur)) { - $valeur = saisies_chaine2tableau($valeur) ; - } - if (!is_array($data)) { - $data = saisies_chaine2tableau($data) ; - } - $choix_theorique = array_keys($data); - $choix_alternatif = array_values(array_diff($valeur,$choix_theorique)); - return $choix_alternatif[0];//on suppose que personne ne s'est amusé à proposer deux choix alternatifs -} - -/** - * Génère une page d'aide listant toutes les saisies et leurs options - * - * Retourne le résultat du squelette `inclure/saisies_aide` auquel - * on a transmis toutes les saisies connues. - * - * @return string Code HTML - */ -function saisies_generer_aide(){ - // On a déjà la liste par saisie - $saisies = saisies_lister_disponibles(); - - // On construit une liste par options - $options = array(); - foreach ($saisies as $type_saisie=>$saisie){ - $options_saisie = saisies_lister_par_nom($saisie['options'], false); - foreach ($options_saisie as $nom=>$option){ - // Si l'option n'existe pas encore - if (!isset($options[$nom])){ - $options[$nom] = _T_ou_typo($option['options']); - } - // On ajoute toujours par qui c'est utilisé - $options[$nom]['utilisee_par'][] = $type_saisie; - } - ksort($options_saisie); - $saisies[$type_saisie]['options'] = $options_saisie; - } - ksort($options); - - return recuperer_fond( - 'inclure/saisies_aide', - array( - 'saisies' => $saisies, - 'options' => $options - ) - ); -} - -/** - * Le tableau de saisies a-t-il une option afficher_si ? - * - * @param array $saisies Un tableau de saisies - * @return boolean - */ - -function saisies_afficher_si($saisies) { - $saisies = saisies_lister_par_nom($saisies,true); - // Dès qu'il y a au moins une option afficher_si, on l'active - foreach ($saisies as $saisie) { - if (isset($saisie['options']['afficher_si'])) - return true; - } - return false; -} - - -/** - * Le tableau de saisies a-t-il une option afficher_si_remplissage ? - * - * @param array $saisies Un tableau de saisies - * @return boolean - */ -function saisies_afficher_si_remplissage($saisies) { - $saisies = saisies_lister_par_nom($saisies,true); - // Dès qu'il y a au moins une option afficher_si_remplissage, on l'active - foreach ($saisies as $saisie) { - if (isset($saisie['options']['afficher_si_remplissage'])) - return true; - } - return false; -} - + array('form' => $form, 'args' => $args), + 'data' => $saisies + ) + ) + // Si c'est toujours un tableau après le pipeline + and is_array($saisies) + ) { + return $saisies; + } else { + return false; + } +} + +/** + * Cherche une saisie par son id, son nom ou son chemin et renvoie soit la saisie, soit son chemin + * + * @param array $saisies Un tableau décrivant les saisies + * @param unknown_type $id_ou_nom_ou_chemin L'identifiant ou le nom de la saisie à chercher ou le chemin sous forme d'une liste de clés + * @param bool $retourner_chemin Indique si on retourne non pas la saisie mais son chemin + * @return array Retourne soit la saisie, soit son chemin, soit null + */ +function saisies_chercher($saisies, $id_ou_nom_ou_chemin, $retourner_chemin = false) { + if (is_array($saisies) and $id_ou_nom_ou_chemin) { + if (is_string($id_ou_nom_ou_chemin)) { + $nom = $id_ou_nom_ou_chemin; + // identifiant ? premier caractere @ + $id = ($nom[0] == '@'); + + foreach ($saisies as $cle => $saisie) { + $chemin = array($cle); + // notre saisie est la bonne ? + if ($nom == ($id ? $saisie['identifiant'] : $saisie['options']['nom'])) { + return $retourner_chemin ? $chemin : $saisie; + // sinon a telle des enfants ? et si c'est le cas, cherchons dedans + } elseif (isset($saisie['saisies']) and is_array($saisie['saisies']) and $saisie['saisies'] + and ($retour = saisies_chercher($saisie['saisies'], $nom, $retourner_chemin))) { + return $retourner_chemin ? array_merge($chemin, array('saisies'), $retour) : $retour; + } + } + } elseif (is_array($id_ou_nom_ou_chemin)) { + $chemin = $id_ou_nom_ou_chemin; + $saisie = $saisies; + // On vérifie l'existence quand même + foreach ($chemin as $cle) { + if (isset($saisie[$cle])) { + $saisie = $saisie[$cle]; + } else { + return null; + } + } + // Si c'est une vraie saisie + if ($saisie['saisie'] and $saisie['options']['nom']) { + return $retourner_chemin ? $chemin : $saisie; + } + } + } + + return null; +} + +/** + * Génère un nom unique pour un champ d'un formulaire donné + * + * @param array $formulaire + * Le formulaire à analyser + * @param string $type_saisie + * Le type de champ dont on veut un identifiant + * @return string + * Un nom unique par rapport aux autres champs du formulaire + */ +function saisies_generer_nom($formulaire, $type_saisie) { + $champs = saisies_lister_champs($formulaire); + + // Tant que type_numero existe, on incrémente le compteur + $compteur = 1; + while (array_search($type_saisie.'_'.$compteur, $champs) !== false) { + $compteur++; + } + + // On a alors un compteur unique pour ce formulaire + return $type_saisie.'_'.$compteur; +} + +/** + * Crée un identifiant Unique + * pour toutes les saisies donnees qui n'en ont pas + * + * @param Array $saisies Tableau de saisies + * @param Bool $regenerer Régénère un nouvel identifiant pour toutes les saisies ? + * @return Array Tableau de saisies complété des identifiants + */ +function saisies_identifier($saisies, $regenerer = false) { + if (!is_array($saisies)) { + return array(); + } + foreach ($saisies as $k => $saisie) { + $saisies[$k] = saisie_identifier($saisie, $regenerer); + } + return $saisies; +} + +/** + * Crée un identifiant Unique + * pour la saisie donnee si elle n'en a pas + * (et pour ses sous saisies éventuels) + * + * @param Array $saisie Tableau d'une saisie + * @param Bool $regenerer Régénère un nouvel identifiant pour la saisie ? + * @return Array Tableau de la saisie complété de l'identifiant +**/ +function saisie_identifier($saisie, $regenerer = false) { + if (!isset($saisie['identifiant']) or !$saisie['identifiant']) { + $saisie['identifiant'] = uniqid('@'); + } elseif ($regenerer) { + $saisie['identifiant'] = uniqid('@'); + } + if (isset($saisie['saisies']) and is_array($saisie['saisies'])) { + $saisie['saisies'] = saisies_identifier($saisie['saisies'], $regenerer); + } + return $saisie; +} + +/** + * Vérifier tout un formulaire tel que décrit avec les Saisies + * + * @param array $formulaire Le contenu d'un formulaire décrit dans un tableau de Saisies + * @param bool $saisies_masquees_nulles Si TRUE, les saisies masquées selon afficher_si ne seront pas verifiées, leur valeur étant forcée a NULL. Cette valeur NULL est transmise à traiter (via set_request). + * @return array Retourne un tableau d'erreurs + */ +function saisies_verifier($formulaire, $saisies_masquees_nulles = true) { + include_spip('inc/verifier'); + $erreurs = array(); + $verif_fonction = charger_fonction('verifier', 'inc', true); + + if ($saisies_masquees_nulles) { + $formulaire = saisies_verifier_afficher_si($formulaire); + } + + $saisies = saisies_lister_par_nom($formulaire); + foreach ($saisies as $saisie) { + $obligatoire = isset($saisie['options']['obligatoire']) ? $saisie['options']['obligatoire'] : ''; + $champ = $saisie['options']['nom']; + $file = ($saisie['saisie'] == 'input' and isset($saisie['options']['type']) and $saisie['options']['type'] == 'file'); + $verifier = isset($saisie['verifier']) ? $saisie['verifier'] : false; + + // Si le nom du champ est un tableau indexé, il faut parser ! + if (preg_match('/([\w]+)((\[[\w]+\])+)/', $champ, $separe)) { + $valeur = _request($separe[1]); + preg_match_all('/\[([\w]+)\]/', $separe[2], $index); + // On va chercher au fond du tableau + foreach ($index[1] as $cle) { + $valeur = isset($valeur[$cle]) ? $valeur[$cle] : null; + } + } else { + // Sinon la valeur est juste celle du nom + $valeur = _request($champ); + } + + // Pour la saisie "destinataires" il faut filtrer si jamais on a mis un premier choix vide + if ($saisie['saisie'] == 'destinataires') { + $valeur = array_filter($valeur); + } + + // On regarde d'abord si le champ est obligatoire + if ($obligatoire + and $obligatoire != 'non' + and ( + ($file and !$_FILES[$champ]['name']) + or (!$file and ( + is_null($valeur) + or (is_string($valeur) and trim($valeur) == '') + or (is_array($valeur) and count($valeur) == 0) + )) + ) + ) { + $erreurs[$champ] = + (isset($saisie['options']['erreur_obligatoire']) and $saisie['options']['erreur_obligatoire']) + ? $saisie['options']['erreur_obligatoire'] + : _T('info_obligatoire'); + } + + // On continue seulement si ya pas d'erreur d'obligation et qu'il y a une demande de verif + if ((!isset($erreurs[$champ]) or !$erreurs[$champ]) and is_array($verifier) and $verif_fonction) { + $normaliser = null; + // Si le champ n'est pas valide par rapport au test demandé, on ajoute l'erreur + $options = isset($verifier['options']) ? $verifier['options'] : array(); + if ($erreur_eventuelle = $verif_fonction($valeur, $verifier['type'], $options, $normaliser)) { + $erreurs[$champ] = $erreur_eventuelle; + // S'il n'y a pas d'erreur et que la variable de normalisation a été remplie, on l'injecte dans le POST + } elseif (!is_null($normaliser)) { + set_request($champ, $normaliser); + } + } + } + + return $erreurs; +} + +/** + * Applatie une description tabulaire + * @param string $tab Le tableau à aplatir + * @return $nouveau_tab + */ +function saisies_aplatir_tableau($tab) { + $nouveau_tab = array(); + foreach ($tab as $entree => $contenu) { + if (is_array($contenu)) { + foreach ($contenu as $cle => $valeur) { + $nouveau_tab[$cle] = $valeur; + } + } else { + $nouveau_tab[$entree] = $contenu; + } + } + return $nouveau_tab; +} + +/** + * Applatie une description chaînée, en supprimant les sous-groupes. + * @param string $chaine La chaîne à aplatir + * @return $chaine + */ +function saisies_aplatir_chaine($chaine) { + return trim(preg_replace("#(?:^|\n)(\*(?:.*)|/\*)\n#i", "\n", $chaine)); +} + +/** + * Transforme une chaine en tableau avec comme principe : + * + * - une ligne devient une case + * - si la ligne est de la forme truc|bidule alors truc est la clé et bidule la valeur + * - si la ligne commence par * alors on commence un sous-tableau + * - si la ligne est égale à /*, alors on fini le sous-tableau + * + * @param string $chaine Une chaine à transformer + * @param string $separateur Séparateur utilisé + * @return array Retourne un tableau PHP + */ +function saisies_chaine2tableau($chaine, $separateur = "\n") { + if ($chaine and is_string($chaine)) { + $tableau = array(); + $soustab = false; + // On découpe d'abord en lignes + $lignes = explode($separateur, $chaine); + foreach ($lignes as $i => $ligne) { + $ligne = trim(trim($ligne), '|'); + // Si ce n'est pas une ligne sans rien + if ($ligne !== '') { + // si ca commence par * c'est qu'on va faire un sous tableau + if (strpos($ligne, '*') === 0) { + $soustab=true; + $soustab_cle = _T_ou_typo(substr($ligne, 1), 'multi'); + if (!isset($tableau[$soustab_cle])) { + $tableau[$soustab_cle] = array(); + } + } elseif ($ligne == '/*') {//si on finit sous tableau + $soustab=false; + } else { + //sinon c'est une entrée normale + // Si on trouve un découpage dans la ligne on fait cle|valeur + if (strpos($ligne, '|') !== false) { + list($cle,$valeur) = explode('|', $ligne, 2); + // permettre les traductions de valeurs au passage + if ($soustab == true) { + $tableau[$soustab_cle][$cle] = _T_ou_typo($valeur, 'multi'); + } else { + $tableau[$cle] = _T_ou_typo($valeur, 'multi'); + } + } else { + // Sinon on génère la clé + if ($soustab == true) { + $tableau[$soustab_cle][$i] = _T_ou_typo($ligne, 'multi'); + } else { + $tableau[$i] = _T_ou_typo($ligne, 'multi'); + } + } + } + } + } + return $tableau; + } elseif (is_array($chaine)) { + // Si c'est déjà un tableau on lui applique _T_ou_typo (qui fonctionne de manière récursive avant de le renvoyer + return _T_ou_typo($chaine, 'multi'); + } else { + return array(); + } +} + +/** + * Transforme un tableau en chaine de caractères avec comme principe : + * + * - une case de vient une ligne de la chaine + * - chaque ligne est générée avec la forme cle|valeur + * - si une entrée du tableau est elle même un tableau, on met une ligne de la forme *clef + * - pour marquer que l'on quitte un sous-tableau, on met une ligne commencant par /*, sauf si on bascule dans un autre sous-tableau. + * + * @param array $tableau Tableau à transformer + * @return string Texte représentant les données du tableau + */ +function saisies_tableau2chaine($tableau) { + if ($tableau and is_array($tableau)) { + $chaine = ''; + $avant_est_tableau = false; + foreach ($tableau as $cle => $valeur) { + if (is_array($valeur)) { + $avant_est_tableau = true; + $ligne=trim("*$cle"); + $chaine .= "$ligne\n"; + $chaine .= saisies_tableau2chaine($valeur)."\n"; + } else { + if ($avant_est_tableau == true) { + $avant_est_tableau = false; + $chaine.="/*\n"; + } + $ligne = trim("$cle|$valeur"); + $chaine .= "$ligne\n"; + } + } + $chaine = trim($chaine); + + return $chaine; + } elseif (is_string($tableau)) { + // Si c'est déjà une chaine on la renvoie telle quelle + return $tableau; + } else { + return ''; + } +} + +/** + * Transforme une valeur en tableau d'élements si ce n'est pas déjà le cas + * + * @param mixed $valeur + * @return array Tableau de valeurs +**/ +function saisies_valeur2tableau($valeur) { + if (is_array($valeur)) { + return $valeur; + } + + if (!strlen($valeur)) { + return array(); + } + + $t = saisies_chaine2tableau($valeur); + if (count($t) > 1) { + return $t; + } + + // qu'une seule valeur, c'est qu'elle a peut etre un separateur a virgule + // et a donc une cle est 0 dans ce cas la d'ailleurs + if (isset($t[0])) { + $t = saisies_chaine2tableau($t[0], ','); + } + + return $t; +} + +/** + * Pour les saisies multiples (type checkbox) proposant un choix alternatif, + * retrouve à partir des data de choix proposés + * et des valeurs des choix enregistrés + * le texte enregistré pour le choix alternatif. + * + * @param array $data + * @param array $valeur + * @return string choix_alternatif +**/ +function saisies_trouver_choix_alternatif($data, $valeur) { + if (!is_array($valeur)) { + $valeur = saisies_chaine2tableau($valeur) ; + } + if (!is_array($data)) { + $data = saisies_chaine2tableau($data) ; + } + $choix_theorique = array_keys($data); + $choix_alternatif = array_values(array_diff($valeur, $choix_theorique)); + return $choix_alternatif[0];//on suppose que personne ne s'est amusé à proposer deux choix alternatifs +} + +/** + * Génère une page d'aide listant toutes les saisies et leurs options + * + * Retourne le résultat du squelette `inclure/saisies_aide` auquel + * on a transmis toutes les saisies connues. + * + * @return string Code HTML + */ +function saisies_generer_aide() { + // On a déjà la liste par saisie + $saisies = saisies_lister_disponibles(); + + // On construit une liste par options + $options = array(); + foreach ($saisies as $type_saisie => $saisie) { + $options_saisie = saisies_lister_par_nom($saisie['options'], false); + foreach ($options_saisie as $nom => $option) { + // Si l'option n'existe pas encore + if (!isset($options[$nom])) { + $options[$nom] = _T_ou_typo($option['options']); + } + // On ajoute toujours par qui c'est utilisé + $options[$nom]['utilisee_par'][] = $type_saisie; + } + ksort($options_saisie); + $saisies[$type_saisie]['options'] = $options_saisie; + } + ksort($options); + + return recuperer_fond( + 'inclure/saisies_aide', + array( + 'saisies' => $saisies, + 'options' => $options + ) + ); +} + +/** + * Le tableau de saisies a-t-il une option afficher_si ? + * + * @param array $saisies Un tableau de saisies + * @return boolean + */ + +function saisies_afficher_si($saisies) { + $saisies = saisies_lister_par_nom($saisies, true); + // Dès qu'il y a au moins une option afficher_si, on l'active + foreach ($saisies as $saisie) { + if (isset($saisie['options']['afficher_si'])) { + return true; + } + } + return false; +} + + +/** + * Le tableau de saisies a-t-il une option afficher_si_remplissage ? + * + * @param array $saisies Un tableau de saisies + * @return boolean + */ +function saisies_afficher_si_remplissage($saisies) { + $saisies = saisies_lister_par_nom($saisies, true); + // Dès qu'il y a au moins une option afficher_si_remplissage, on l'active + foreach ($saisies as $saisie) { + if (isset($saisie['options']['afficher_si_remplissage'])) { + return true; + } + } + return false; +} diff --git a/www/plugins/saisies/inc/saisies_afficher.php b/www/plugins/saisies/inc/saisies_afficher.php index 4e7e3488..f90c820a 100644 --- a/www/plugins/saisies/inc/saisies_afficher.php +++ b/www/plugins/saisies/inc/saisies_afficher.php @@ -155,9 +155,8 @@ function saisies_generer_html($champ, $env = array()) { } $contexte = array_merge($env, $contexte); - } - // Sinon on ne sélectionne que quelques éléments importants - else { + } else { + // Sinon on ne sélectionne que quelques éléments importants // On récupère la liste des erreurs $contexte['erreurs'] = $env['erreurs']; // On récupère la langue de l'objet si existante @@ -170,20 +169,19 @@ function saisies_generer_html($champ, $env = array()) { // Dans tous les cas on récupère de l'environnement la valeur actuelle du champ // Si le nom du champ est un tableau indexé, il faut parser ! - if (isset($contexte['nom']) and preg_match('/([\w]+)((\[[\w]+\])+)/', $contexte['nom'], $separe)) { + if (isset($contexte['nom']) and preg_match('/([\w]+)((\[[\w]+\])+)/', $contexte['nom'], $separe) + and isset($env[$separe[1]])) { $contexte['valeur'] = $env[$separe[1]]; preg_match_all('/\[([\w]+)\]/', $separe[2], $index); // On va chercher au fond du tableau foreach ($index[1] as $cle) { $contexte['valeur'] = isset($contexte['valeur'][$cle]) ? $contexte['valeur'][$cle] : null; } - } - // Sinon la valeur est juste celle du nom si elle existe - elseif (isset($contexte['nom']) and isset($env[$contexte['nom']])) { + } elseif (isset($contexte['nom']) and isset($env[$contexte['nom']])) { + // Sinon la valeur est juste celle du nom si elle existe $contexte['valeur'] = $env[$contexte['nom']]; - } - // Sinon rien - else { + } else { + // Sinon rien $contexte['valeur'] = null; } @@ -266,20 +264,18 @@ function saisies_generer_vue($saisie, $env = array(), $env_obligatoire = array() // Dans tous les cas on récupère de l'environnement la valeur actuelle du champ // On regarde en priorité s'il y a un tableau listant toutes les valeurs - if ($env['valeurs'] and is_array($env['valeurs']) and isset($env['valeurs'][$contexte['nom']])) { + if (!empty($env['valeurs']) and is_array($env['valeurs']) and isset($env['valeurs'][$contexte['nom']])) { $contexte['valeur'] = $env['valeurs'][$contexte['nom']]; - } - // Si le nom du champ est un tableau indexé, il faut parser ! - elseif (preg_match('/([\w]+)((\[[\w]+\])+)/', $contexte['nom'], $separe)) { + } elseif (preg_match('/([\w]+)((\[[\w]+\])+)/', $contexte['nom'], $separe)) { + // Si le nom du champ est un tableau indexé, il faut parser ! $contexte['valeur'] = $env[$separe[1]]; preg_match_all('/\[([\w]+)\]/', $separe[2], $index); // On va chercher au fond du tableau foreach ($index[1] as $cle) { $contexte['valeur'] = $contexte['valeur'][$cle]; } - } - // Sinon la valeur est juste celle du nom - else { + } else { + // Sinon la valeur est juste celle du nom // certains n'ont pas de nom (fieldset) $contexte['valeur'] = isset($env[$contexte['nom']]) ? $env[$contexte['nom']] : ''; } @@ -334,7 +330,12 @@ function saisies_generer_js_afficher_si($saisies, $id_form) { $class_li = 'explication_'.$saisie['options']['nom']; break; default: - $class_li = 'editer_'.$saisie['options']['nom']; + // Les [] dans le nom de la saisie sont transformés en _ dans le + // nom de la classe, il faut faire pareil + $class_li = 'editer_' . rtrim( + preg_replace('/[][]\[?/', '_', $saisie['options']['nom']), + '_' + ); } $afficher_si = isset($saisie['options']['afficher_si']) ? $saisie['options']['afficher_si'] : ''; $afficher_si_remplissage = isset($saisie['options']['afficher_si_remplissage']) ? $saisie['options']['afficher_si_remplissage'] : ''; diff --git a/www/plugins/saisies/inc/saisies_lister.php b/www/plugins/saisies/inc/saisies_lister.php index 6dc3b80f..d66a8b72 100644 --- a/www/plugins/saisies/inc/saisies_lister.php +++ b/www/plugins/saisies/inc/saisies_lister.php @@ -255,12 +255,13 @@ function saisies_comparer_rappel($a, $b) { * * @param array $saisies_anciennes Un tableau décrivant des saisies * @param array $saisies_nouvelles Un autre tableau décrivant des saisies - * @param bool $avec_conteneur Indique si on veut prendre en compte dans la comparaison les conteneurs comme les fieldsets + * @param bool $avec_conteneur Indique si on veut prendre en compte dans la comparaison + * les conteneurs comme les fieldsets * * @return array Retourne le tableau des saisies supprimées, ajoutées et modifiées */ function saisies_comparer_par_identifiant($saisies_anciennes, $saisies_nouvelles, $avec_conteneur = true) { - return saisies_comparer($saisies_anciennes, $saisies_nouvelles, $avec_conteneur, $tri = 'identifiant'); + return saisies_comparer($saisies_anciennes, $saisies_nouvelles, $avec_conteneur, 'identifiant'); } /** @@ -268,7 +269,7 @@ function saisies_comparer_par_identifiant($saisies_anciennes, $saisies_nouvelles * * @return array Un tableau listant des saisies et leurs options */ -function saisies_lister_disponibles($saisies_repertoire = "saisies") { +function saisies_lister_disponibles($saisies_repertoire = 'saisies') { static $saisies = null; if (is_null($saisies)) { @@ -299,7 +300,7 @@ function saisies_lister_disponibles($saisies_repertoire = "saisies") { * * @return array Un tableau listant des saisies et leurs options */ -function saisies_groupes_lister_disponibles($saisies_repertoire = "saisies") { +function saisies_groupes_lister_disponibles($saisies_repertoire = 'saisies') { static $saisies = null; if (is_null($saisies)) { @@ -311,7 +312,7 @@ function saisies_groupes_lister_disponibles($saisies_repertoire = "saisies") { $type_saisie = preg_replace(',[.]yaml$,i', '', $fichier); $dossier = str_replace($fichier, '', $chemin); // On ne garde que les saisies qui ont bien le HTML avec ! - if (is_array($saisie = saisies_charger_infos($type_saisie,$saisies_repertoire))) { + if (is_array($saisie = saisies_charger_infos($type_saisie, $saisies_repertoire))) { $saisies[$type_saisie] = $saisie; } } @@ -325,7 +326,7 @@ function saisies_groupes_lister_disponibles($saisies_repertoire = "saisies") { * * @return array Un tableau listant des saisies et leurs options */ -function saisies_lister_disponibles_sql($saisies_repertoire = "saisies") { +function saisies_lister_disponibles_sql($saisies_repertoire = 'saisies') { $saisies = array(); $saisies_disponibles = saisies_lister_disponibles($saisies_repertoire); foreach ($saisies_disponibles as $type => $saisie) { @@ -344,7 +345,7 @@ function saisies_lister_disponibles_sql($saisies_repertoire = "saisies") { * * @return array Un tableau contenant le YAML décodé */ -function saisies_charger_infos($type_saisie,$saisies_repertoire = "saisies") { +function saisies_charger_infos($type_saisie, $saisies_repertoire = 'saisies') { if (defined('_DIR_PLUGIN_YAML')) { include_spip('inc/yaml'); $fichier = find_in_path("$saisies_repertoire/$type_saisie.yaml"); diff --git a/www/plugins/saisies/inc/saisies_manipuler.php b/www/plugins/saisies/inc/saisies_manipuler.php index e4983902..0894e067 100644 --- a/www/plugins/saisies/inc/saisies_manipuler.php +++ b/www/plugins/saisies/inc/saisies_manipuler.php @@ -140,17 +140,15 @@ function saisies_deplacer($saisies, $id_ou_nom_ou_chemin, $ou) { if (!$ou) { $saisies = saisies_supprimer($saisies, $id_ou_nom_ou_chemin); $chemin = array(count($saisies)); - } - // Si l'endroit est entre crochet, c'est un conteneur - elseif (preg_match('/^\[(@?[\w]*)\]$/', $ou, $match)) { + } elseif (preg_match('/^\[(@?[\w]*)\]$/', $ou, $match)) { + // Si l'endroit est entre crochet, c'est un conteneur $parent = $match[1]; // Si dans les crochets il n'y a rien, on met à la fin du formulaire if (!$parent) { $saisies = saisies_supprimer($saisies, $id_ou_nom_ou_chemin); $chemin = array(count($saisies)); - } - // Sinon on vérifie que ce conteneur existe - elseif (saisies_chercher($saisies, $parent, true)) { + } elseif (saisies_chercher($saisies, $parent, true)) { + // Sinon on vérifie que ce conteneur existe // S'il existe on supprime la saisie et on recherche la nouvelle position $saisies = saisies_supprimer($saisies, $id_ou_nom_ou_chemin); $parent = saisies_chercher($saisies, $parent, true); @@ -158,9 +156,8 @@ function saisies_deplacer($saisies, $id_ou_nom_ou_chemin, $ou) { } else { $chemin = false; } - } - // Sinon ça sera devant un champ - else { + } else { + // Sinon ça sera devant un champ // On vérifie que le champ existe if (saisies_chercher($saisies, $ou, true)) { // S'il existe on supprime la saisie @@ -205,8 +202,7 @@ function saisies_modifier($saisies, $id_ou_nom_ou_chemin, $modifs) { $modifs['options']['nom'] = $parent[$position]['options']['nom']; } // On récupère les enfants tels quels s'il n'y a pas des enfants dans la modif - if ( - !isset($modifs['saisies']) + if (!isset($modifs['saisies']) and isset($parent[$position]['saisies']) and is_array($parent[$position]['saisies']) ) { diff --git a/www/plugins/saisies/inclure/configurer_saisie_fonctions.php b/www/plugins/saisies/inclure/configurer_saisie_fonctions.php index da20293d..07e988f6 100644 --- a/www/plugins/saisies/inclure/configurer_saisie_fonctions.php +++ b/www/plugins/saisies/inclure/configurer_saisie_fonctions.php @@ -1,17 +1,20 @@ 'input', 'options' => array( @@ -28,10 +31,9 @@ function construire_configuration_saisie($saisie, $avec_nom='non'){ ) ) ); - } - else + } + } else { $configuration_saisie = array(); - + } return $configuration_saisie; } - diff --git a/www/plugins/saisies/lang/paquet-saisies_ar.php b/www/plugins/saisies/lang/paquet-saisies_ar.php index 138397a4..bfc7b82b 100644 --- a/www/plugins/saisies/lang/paquet-saisies_ar.php +++ b/www/plugins/saisies/lang/paquet-saisies_ar.php @@ -16,5 +16,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'saisies_slogan' => 'إنشاء حقول استمارات بسهولة', 'saisies_titre' => 'إدخال للاستمارات' ); - -?> diff --git a/www/plugins/saisies/lang/paquet-saisies_de.php b/www/plugins/saisies/lang/paquet-saisies_de.php index 7ba1e402..4d645204 100644 --- a/www/plugins/saisies/lang/paquet-saisies_de.php +++ b/www/plugins/saisies/lang/paquet-saisies_de.php @@ -15,5 +15,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'saisies_slogan' => 'Unkompliziertes Erstellen von Eingabefeldern für Formulare.', 'saisies_titre' => 'Eingabefelder für Formulare' ); - -?> diff --git a/www/plugins/saisies/lang/paquet-saisies_en.php b/www/plugins/saisies/lang/paquet-saisies_en.php index 4da860b0..bf6a2e78 100644 --- a/www/plugins/saisies/lang/paquet-saisies_en.php +++ b/www/plugins/saisies/lang/paquet-saisies_en.php @@ -17,5 +17,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'saisies_slogan' => 'Create easily forms fields.', 'saisies_titre' => 'Entries for forms' ); - -?> diff --git a/www/plugins/saisies/lang/paquet-saisies_es.php b/www/plugins/saisies/lang/paquet-saisies_es.php index 4e4684b6..8f279fe7 100644 --- a/www/plugins/saisies/lang/paquet-saisies_es.php +++ b/www/plugins/saisies/lang/paquet-saisies_es.php @@ -15,5 +15,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'saisies_slogan' => 'Escribir fácilmente los campos de formularios.', 'saisies_titre' => 'Entradas para formularios' ); - -?> diff --git a/www/plugins/saisies/lang/paquet-saisies_fr.php b/www/plugins/saisies/lang/paquet-saisies_fr.php index 4107b51e..d3e0dab6 100644 --- a/www/plugins/saisies/lang/paquet-saisies_fr.php +++ b/www/plugins/saisies/lang/paquet-saisies_fr.php @@ -15,5 +15,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'saisies_slogan' => 'Écrire facilement des champs de formulaires.', 'saisies_titre' => 'Saisies pour formulaires' ); - -?> diff --git a/www/plugins/saisies/lang/paquet-saisies_fr_tu.php b/www/plugins/saisies/lang/paquet-saisies_fr_tu.php index a6c03172..cda4f4b5 100644 --- a/www/plugins/saisies/lang/paquet-saisies_fr_tu.php +++ b/www/plugins/saisies/lang/paquet-saisies_fr_tu.php @@ -17,5 +17,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'saisies_slogan' => 'Écrire facilement des champs de formulaires.', 'saisies_titre' => 'Saisies pour formulaires' ); - -?> diff --git a/www/plugins/saisies/lang/paquet-saisies_nl.php b/www/plugins/saisies/lang/paquet-saisies_nl.php index e16d00fa..c7826bb5 100644 --- a/www/plugins/saisies/lang/paquet-saisies_nl.php +++ b/www/plugins/saisies/lang/paquet-saisies_nl.php @@ -15,5 +15,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'saisies_slogan' => 'Eenvoudig formuliervelden maken.', 'saisies_titre' => 'Invoer voor formulieren' ); - -?> diff --git a/www/plugins/saisies/lang/paquet-saisies_pt_br.php b/www/plugins/saisies/lang/paquet-saisies_pt_br.php index 057c563b..a2729f2e 100644 --- a/www/plugins/saisies/lang/paquet-saisies_pt_br.php +++ b/www/plugins/saisies/lang/paquet-saisies_pt_br.php @@ -15,5 +15,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'saisies_slogan' => 'Facilitar a entrada de dados em campos de formulários.', 'saisies_titre' => 'Entrada de dados para formulários' ); - -?> diff --git a/www/plugins/saisies/lang/paquet-saisies_ru.php b/www/plugins/saisies/lang/paquet-saisies_ru.php index b0ed5973..7913aa72 100644 --- a/www/plugins/saisies/lang/paquet-saisies_ru.php +++ b/www/plugins/saisies/lang/paquet-saisies_ru.php @@ -15,5 +15,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'saisies_slogan' => 'Упрощение работы по созданию форм', 'saisies_titre' => 'Поля для форм (saises)' ); - -?> diff --git a/www/plugins/saisies/lang/paquet-saisies_sk.php b/www/plugins/saisies/lang/paquet-saisies_sk.php index c8e22873..443e7414 100644 --- a/www/plugins/saisies/lang/paquet-saisies_sk.php +++ b/www/plugins/saisies/lang/paquet-saisies_sk.php @@ -15,5 +15,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'saisies_slogan' => 'Jednoduchý zápis polí formulárov.', 'saisies_titre' => 'Vstupy pre formuláre' ); - -?> diff --git a/www/plugins/saisies/lang/saisies.xml b/www/plugins/saisies/lang/saisies.xml index d5b0a847..36886a57 100644 --- a/www/plugins/saisies/lang/saisies.xml +++ b/www/plugins/saisies/lang/saisies.xml @@ -1,47 +1,47 @@ - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/www/plugins/saisies/lang/saisies_ca.php b/www/plugins/saisies/lang/saisies_ca.php index 959fc0b4..9c686e43 100644 --- a/www/plugins/saisies/lang/saisies_ca.php +++ b/www/plugins/saisies/lang/saisies_ca.php @@ -117,5 +117,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_de.php b/www/plugins/saisies/lang/saisies_de.php index c2d8dfe0..4e6dce03 100644 --- a/www/plugins/saisies/lang/saisies_de.php +++ b/www/plugins/saisies/lang/saisies_de.php @@ -177,5 +177,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'Zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_en.php b/www/plugins/saisies/lang/saisies_en.php index b4818bed..a5826173 100644 --- a/www/plugins/saisies/lang/saisies_en.php +++ b/www/plugins/saisies/lang/saisies_en.php @@ -23,6 +23,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'construire_action_dupliquer_copie' => '(copy)', 'construire_action_supprimer' => 'Delete', 'construire_ajouter_champ' => 'Add a field', + 'construire_ajouter_groupe' => 'Add a group', 'construire_attention_enregistrer' => 'Remember to save your changes!', 'construire_attention_modifie' => 'The form below is different from the initial form. You can reset it to the state before the changes.', 'construire_attention_supprime' => 'Your changes include deletions of fields. Please confirm the registration of the new version of the form.', @@ -107,6 +108,8 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'option_label_case_label' => 'Label located beside the check box', 'option_label_explication' => 'The title that will be displayed.', 'option_label_label' => 'Label', + 'option_limite_branche_explication' => 'Limit the choice to one specific branch of the site', + 'option_limite_branche_label' => 'Limit to one branch', 'option_maxlength_explication' => 'The user can not type more characters than this number.', 'option_maxlength_label' => 'Maximum number of characters', 'option_multiple_explication' => 'The user will be able to select several values', @@ -198,5 +201,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_es.php b/www/plugins/saisies/lang/saisies_es.php index 0ecef177..35b671e3 100644 --- a/www/plugins/saisies/lang/saisies_es.php +++ b/www/plugins/saisies/lang/saisies_es.php @@ -191,5 +191,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_fa.php b/www/plugins/saisies/lang/saisies_fa.php index 34d2550c..1ccba8bb 100644 --- a/www/plugins/saisies/lang/saisies_fa.php +++ b/www/plugins/saisies/lang/saisies_fa.php @@ -133,5 +133,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_fr.php b/www/plugins/saisies/lang/saisies_fr.php index ed7e2206..0beef4aa 100644 --- a/www/plugins/saisies/lang/saisies_fr.php +++ b/www/plugins/saisies/lang/saisies_fr.php @@ -106,6 +106,8 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'option_label_case_label' => 'Label placé à côté de la case', 'option_label_explication' => 'Le titre qui sera affiché.', 'option_label_label' => 'Label', + 'option_limite_branche_explication' => 'Limitera le choix à une branche spécifique du site', + 'option_limite_branche_label' => 'Limiter à une branche', 'option_maxlength_explication' => 'L’utilisateur ne pourra pas taper plus de caractères que ce nombre.', 'option_maxlength_label' => 'Nombre de caractères maximum', 'option_multiple_explication' => 'L’utilisateur pourra sélectionner plusieurs valeurs', @@ -197,5 +199,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_fr_tu.php b/www/plugins/saisies/lang/saisies_fr_tu.php index cb888bc6..3b442a8c 100644 --- a/www/plugins/saisies/lang/saisies_fr_tu.php +++ b/www/plugins/saisies/lang/saisies_fr_tu.php @@ -188,5 +188,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_it.php b/www/plugins/saisies/lang/saisies_it.php index 1b24b970..974106b0 100644 --- a/www/plugins/saisies/lang/saisies_it.php +++ b/www/plugins/saisies/lang/saisies_it.php @@ -171,5 +171,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_nl.php b/www/plugins/saisies/lang/saisies_nl.php index 2678a15e..61ec0166 100644 --- a/www/plugins/saisies/lang/saisies_nl.php +++ b/www/plugins/saisies/lang/saisies_nl.php @@ -23,6 +23,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'construire_action_dupliquer_copie' => '(copy)', 'construire_action_supprimer' => 'Verwijder', 'construire_ajouter_champ' => 'Voeg veld toe', + 'construire_ajouter_groupe' => 'Een groep toevoegen', 'construire_attention_enregistrer' => 'Sla je wijzingen op!', 'construire_attention_modifie' => 'Het onderstaande formulier wijkt van het oorspronkelijke af. Je kunt het naar de oorspronkelijke staat herstellen.', 'construire_attention_supprime' => 'Je wijzigingen bevatten verwijderingen van velden. Bevestig de nieuwe formulierversie.', @@ -107,6 +108,8 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'option_label_case_label' => 'Label staat naast de checkbox', 'option_label_explication' => 'De titel die zal worden weergegeven.', 'option_label_label' => 'Label', + 'option_limite_branche_explication' => 'Beperk de keuze tot een specifieke tak van de site', + 'option_limite_branche_label' => 'Tot één tak (hoofdrubriek) beperken', 'option_maxlength_explication' => 'De gebruikers kan niet meer tekens invoeren dan dit aantal.', 'option_maxlength_label' => 'Maximum aantal tekens', 'option_multiple_explication' => 'De gebruiker kan meerdere waardes kiezen', @@ -138,6 +141,10 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'option_type_label' => 'Veldtype', 'option_type_password' => 'Verborgen tekst tijdens invoer (bv: wachtwoord)', 'option_type_text' => 'Normaal', + 'option_valeur_non_explication' => 'Geposte waarde wanneer de checkbox niet wordt geselecteerd', + 'option_valeur_non_label' => 'Waarde non', + 'option_valeur_oui_explication' => 'Geposte waarde wanneer de checkbox is geselecteerd', + 'option_valeur_oui_label' => 'Waarde oui', // S 'saisie_auteurs_explication' => 'Laat je een of meer auteurs kiezen', @@ -194,5 +201,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_pt_br.php b/www/plugins/saisies/lang/saisies_pt_br.php index 315dbd43..9705f87c 100644 --- a/www/plugins/saisies/lang/saisies_pt_br.php +++ b/www/plugins/saisies/lang/saisies_pt_br.php @@ -23,6 +23,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'construire_action_dupliquer_copie' => '(cópia)', 'construire_action_supprimer' => 'Excluir', 'construire_ajouter_champ' => 'Incluir um campo', + 'construire_ajouter_groupe' => 'Incluir um grupo', 'construire_attention_enregistrer' => 'Lembre-se de gravar as suas alterações!', 'construire_attention_modifie' => 'O formulário abaixo é diferente do formulário inicial.Você tem a possibilidade de revertê-lo ao estado em que estava, antes das suas alterações.', 'construire_attention_supprime' => 'As suas alterações incluem exclusões de campos. Por favor, confirme a gravação desta nova versão do formulário.', @@ -200,5 +201,3 @@ Você pode indicar o início de um subgrupo, no formato "*Título do subgrupo". // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_ru.php b/www/plugins/saisies/lang/saisies_ru.php index 6594de7f..0f19484e 100644 --- a/www/plugins/saisies/lang/saisies_ru.php +++ b/www/plugins/saisies/lang/saisies_ru.php @@ -187,5 +187,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/lang/saisies_sk.php b/www/plugins/saisies/lang/saisies_sk.php index 37b305b4..a2d89dd6 100644 --- a/www/plugins/saisies/lang/saisies_sk.php +++ b/www/plugins/saisies/lang/saisies_sk.php @@ -191,5 +191,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'z' => 'zzz' ); - -?> diff --git a/www/plugins/saisies/paquet.xml b/www/plugins/saisies/paquet.xml index 579e54bf..5fe2150e 100644 --- a/www/plugins/saisies/paquet.xml +++ b/www/plugins/saisies/paquet.xml @@ -1,7 +1,7 @@ + diff --git a/www/plugins/saisies/saisies-vues/selecteur_article_fonctions.php b/www/plugins/saisies/saisies-vues/selecteur_article_fonctions.php index 5556cf98..9dbb831c 100644 --- a/www/plugins/saisies/saisies-vues/selecteur_article_fonctions.php +++ b/www/plugins/saisies/saisies-vues/selecteur_article_fonctions.php @@ -1,3 +1,7 @@ <[(#ENV{saisies_base_conteneur,[(#VAL{li}|saisie_balise_structure_formulaire)]})] class="editer editer_[(#ENV{nom}|saisie_nom2classe)][ (#GET{obligatoire})][ (#GET{erreurs}|oui)erreur][ (#GET{conteneur_class})][ (#ENV{conteneur_class,#ENV{li_class}})][ saisie_(#ENV{type_saisie})]"[ data-id="(#ENV{id_saisie})"]> #ENV*{inserer_debut} - [(#ENV*{label})[(#GET{obligatoire}|oui)[(#ENV*{info_obligatoire}|is_null|?{<:info_obligatoire_02:>,#ENV*{info_obligatoire}})]]] + [(#ENV*{label})[(#GET{obligatoire}|oui)[(#ENV*{info_obligatoire}|is_null|?{<:info_obligatoire_02:>,#ENV*{info_obligatoire}})]]] [(#GET{erreurs})] [

    (#ENV*{explication})

    ] [(#ENV*{attention})] diff --git a/www/plugins/saisies/saisies/checkbox.html b/www/plugins/saisies/saisies/checkbox.html index c14e0a9d..1dbc3351 100644 --- a/www/plugins/saisies/saisies/checkbox.html +++ b/www/plugins/saisies/saisies/checkbox.html @@ -38,23 +38,23 @@ [(#GET{disabled}|oui) #SET{disabled,#ARRAY|push{#GET{disabled}}} ] ] [(#ENV{tout_selectionner}|oui) -
    +
    - +
    ] -
    [(#SET{id,champ_[(#ENV{id,#ENV{nom}}|saisie_nom2classe)]_[(#COMPTEUR_BOUCLE|concat{'-',#CLE}|md5)]})] +
    [(#SET{id,champ_[(#ENV{id,#ENV{nom}}|saisie_nom2classe)]_[(#COMPTEUR_BOUCLE|concat{'-',#CLE}|md5)]})]
    [(#ENV{choix_alternatif}|oui) -
    +
    -
    diff --git a/www/plugins/facteur/facteur_fonctions.php b/www/plugins/facteur/facteur_fonctions.php index 7eb20877..54a2d258 100755 --- a/www/plugins/facteur/facteur_fonctions.php +++ b/www/plugins/facteur/facteur_fonctions.php @@ -8,6 +8,19 @@ if (!defined("_ECRIRE_INC_VERSION")) return; +function facteur_affiche_password_masque($pass){ + $l = strlen($pass); + if ($l<=8){ + return str_pad('',$l,'*'); + } + $e = intval(ceil($l/10)); + $mid = str_pad('',$l-2*$e,'*'); + if (strlen($mid)>8){ + $mid = '***...***'; + } + return substr($pass,0,$e) . $mid . substr($pass,-$e); +} + /** * Transformer un mail texte ou HTML simplifie en mail HTML complet avec le wrapper emails/texte.html * Si le mail est un mail texte : @@ -283,12 +296,15 @@ function facteur_addstyle($matches) { * @return string */ function facteur_nl2br_si_pas_autobr($texte){ - return (_AUTOBR?$texte:nl2br($texte)); + if (_AUTOBR) return $texte; + include_spip("inc/filtres"); + $texte = post_autobr($texte); + return $texte; } /** * Transformer un mail HTML en mail Texte proprement : - * - les tableaux de mise en page sont utilisés pour structurer le mail texte + * - les tableaux de mise en page sont utilis�s pour structurer le mail texte * - le reste du HTML est markdownifie car c'est un format texte lisible et conventionnel * * @param string $html diff --git a/www/plugins/facteur/facteur_pipelines.php b/www/plugins/facteur/facteur_pipelines.php index 2bdbdce4..9c45c196 100644 --- a/www/plugins/facteur/facteur_pipelines.php +++ b/www/plugins/facteur/facteur_pipelines.php @@ -20,8 +20,8 @@ if (!defined("_ECRIRE_INC_VERSION")) return; * @return array $flux * Le contexte du pipeline modifé */ -function facteur_recuperer_fond($flux){ - if(($flux['args']['fond'] == 'formulaires/configurer_identite') +function facteur_formulaire_fond($flux){ + if(($flux['args']['form'] == 'configurer_identite') && (isset($GLOBALS['meta']['facteur_adresse_envoi']) && $GLOBALS['meta']['facteur_adresse_envoi'] == 'oui') && (isset($GLOBALS['meta']['facteur_adresse_envoi_email']) && strlen($GLOBALS['meta']['facteur_adresse_envoi_email']) > 0)){ $ajout = '

    '._T('facteur:message_identite_email').'

    '; diff --git a/www/plugins/facteur/formulaires/configurer_facteur.html b/www/plugins/facteur/formulaires/configurer_facteur.html index 6f7122ba..08c19cf8 100644 --- a/www/plugins/facteur/formulaires/configurer_facteur.html +++ b/www/plugins/facteur/formulaires/configurer_facteur.html @@ -2,21 +2,21 @@ [

    (#ENV*{message_ok})

    ] [

    (#ENV*{message_erreur})

    ] - [(#ENV{tester,''}|oui) + [(#ENV{tester,''}|et{#ENV*{message_erreur}|non}) ]
    #ACTION_FORMULAIRE{#ENV{action}} -
      +
      • <:facteur:configuration_adresse_envoi:> -
          +
          • [(#ENV**{erreurs}|table_valeur{facteur_adresse_envoi})]
            - +
            @@ -33,13 +33,25 @@ (#ENV**{erreurs}|table_valeur{facteur_adresse_envoi_email})]
          • + #SET{name,facteur_forcer_from}#SET{obli,''}#SET{defaut,''}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}} +
          • [ + (#GET{erreurs}) + ] +
            + #SET{val,non} + + #SET{val,oui} + + +
            +
      • <:facteur:configuration_mailer:> -
          +
          • <:facteur:configuration_smtp_descriptif:>

            @@ -74,16 +86,17 @@
    -
      -
    • +
        +
      • [ (#ENV**{erreurs}|table_valeur{facteur_smtp_username})]
      • -
      • +
      • [ (#ENV**{erreurs}|table_valeur{facteur_smtp_password})] - +
    • @@ -95,14 +108,14 @@ -
      - - -
      +
      + + +
      ]
    • [ @@ -116,7 +129,7 @@
    • <:facteur:facteur_filtres:> -
        +
        • [(#ENV**{erreurs}|table_valeur{facteur_smtp_secure})]

          <:facteur:facteur_filtres_descriptif:>

          @@ -135,7 +148,7 @@
        • <:facteur:facteur_copies:> -
            +
            • <:facteur:facteur_copies_descriptif:>

            • @@ -156,13 +169,17 @@

              -
                +
                • <:facteur:tester_la_configuration:>

                  -
                    -
                  • -

                    <:facteur:note_test_configuration:>

                    +
                      + #SET{name,email_test}#SET{obli,''}#SET{defaut,''}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}} +
                    • + [ + (#GET{erreurs}) + ] +

                      <:facteur:note_test_configuration:>

                  diff --git a/www/plugins/facteur/formulaires/configurer_facteur.php b/www/plugins/facteur/formulaires/configurer_facteur.php index 0aa321b5..aa46e78b 100644 --- a/www/plugins/facteur/formulaires/configurer_facteur.php +++ b/www/plugins/facteur/formulaires/configurer_facteur.php @@ -9,31 +9,44 @@ if (!defined("_ECRIRE_INC_VERSION")) return; function formulaires_configurer_facteur_charger_dist(){ + include_spip('inc/config'); $valeurs = array( - 'facteur_adresse_envoi' => $GLOBALS['meta']['facteur_adresse_envoi'], - 'facteur_adresse_envoi_nom' => $GLOBALS['meta']['facteur_adresse_envoi_nom'], - 'facteur_adresse_envoi_email' => $GLOBALS['meta']['facteur_adresse_envoi_email'], - 'facteur_smtp' => $GLOBALS['meta']['facteur_smtp'], - 'facteur_smtp_host' => $GLOBALS['meta']['facteur_smtp_host'], - 'facteur_smtp_port' => $GLOBALS['meta']['facteur_smtp_port']?$GLOBALS['meta']['facteur_smtp_port']:'25', - 'facteur_smtp_auth' => $GLOBALS['meta']['facteur_smtp_auth'], - 'facteur_smtp_username' => $GLOBALS['meta']['facteur_smtp_username'], - 'facteur_smtp_password' => $GLOBALS['meta']['facteur_smtp_password'], - 'facteur_smtp_secure' => $GLOBALS['meta']['facteur_smtp_secure'], - 'facteur_smtp_sender' => $GLOBALS['meta']['facteur_smtp_sender'], - 'facteur_filtre_images' => $GLOBALS['meta']['facteur_filtre_images'], - 'facteur_filtre_iso_8859' => $GLOBALS['meta']['facteur_filtre_iso_8859'], - '_enable_smtp_secure' => (intval(phpversion()) == 5)?' ':'', - 'facteur_cc' => $GLOBALS['meta']['facteur_cc'], - 'facteur_bcc' => $GLOBALS['meta']['facteur_bcc'], - 'tester' => '', + 'facteur_adresse_envoi' => lire_config('facteur_adresse_envoi'), + 'facteur_adresse_envoi_nom' => lire_config('facteur_adresse_envoi_nom'), + 'facteur_adresse_envoi_email' => lire_config('facteur_adresse_envoi_email'), + 'facteur_forcer_from' => lire_config('facteur_forcer_from'), + 'facteur_smtp' => lire_config('facteur_smtp'), + 'facteur_smtp_host' => lire_config('facteur_smtp_host'), + 'facteur_smtp_port' => lire_config('facteur_smtp_port', 25), + 'facteur_smtp_auth' => lire_config('facteur_smtp_auth'), + 'facteur_smtp_username' => lire_config('facteur_smtp_username'), + 'facteur_smtp_password' => '', + '_facteur_smtp_password' => lire_config('facteur_smtp_password'), + 'facteur_smtp_secure' => lire_config('facteur_smtp_secure'), + 'facteur_smtp_sender' => lire_config('facteur_smtp_sender'), + 'facteur_filtre_images' => lire_config('facteur_filtre_images'), + 'facteur_filtre_iso_8859' => lire_config('facteur_filtre_iso_8859'), + 'facteur_cc' => lire_config('facteur_cc'), + 'facteur_bcc' => lire_config('facteur_bcc'), + '_enable_smtp_secure' => (intval(phpversion()) == 5)?' ':'', + 'email_test' => lire_config('facteur_adresse_envoi')=='oui'?lire_config('facteur_adresse_envoi_email'):$GLOBALS['meta']['email_webmaster'], + 'tester' => '', ); + // recuperer le from par defaut actuel pour l'indiquer dans le formulaire + include_spip('classes/facteur'); + $facteur = new Facteur('test@example.org','Test','','',array('adresse_envoi'=>'non')); + $valeurs['_from_defaut'] = $facteur->From; + if ($facteur->FromName){ + $valeurs['_from_defaut'] = $facteur->FromName . ' <'.$valeurs['_from_defaut'].'>'; + } + return $valeurs; } function formulaires_configurer_facteur_verifier_dist(){ $erreurs = array(); + include_spip('inc/config'); if ($email = _request('facteur_adresse_envoi_email') AND !email_valide($email)) { $erreurs['facteur_adresse_envoi_email'] = _T('form_email_non_valide'); @@ -43,17 +56,19 @@ function formulaires_configurer_facteur_verifier_dist(){ if (!($h=_request('facteur_smtp_host'))) $erreurs['facteur_smtp_host'] = _T('info_obligatoire'); else { + $h = trim($h); $regexp_ip_valide = '#^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))|((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$#'; // Source : http://www.d-sites.com/2008/10/09/regex-ipv4-et-ipv6/ if (!preg_match($regexp_ip_valide,$h)){ // ce n'est pas une IP - if(!preg_match(';^([^.\s/?:]+[.]){0,2}[^.\s/?:]+$;',$h) + if(!preg_match(';^([^.\s/?:]+[.])*[^.\s/?:]+$;',$h) OR gethostbyname($h)==$h) $erreurs['facteur_smtp_host'] = _T('facteur:erreur_invalid_host'); } else { if (gethostbyaddr($h)==$h) - $erreurs['facteur_smtp_host'] = _T('facteur:erreur_invalid_host'); + $erreurs['facteur_smtp_host'] = _T('facteur:erreur_invalid_host'); } + set_request('facteur_smtp_host',$h); } if (!($p=_request('facteur_smtp_port'))) $erreurs['facteur_smtp_port'] = _T('info_obligatoire'); @@ -66,7 +81,7 @@ function formulaires_configurer_facteur_verifier_dist(){ if (_request('facteur_smtp_auth')=='oui'){ if (!_request('facteur_smtp_username')) $erreurs['facteur_smtp_username'] = _T('info_obligatoire'); - if (!_request('facteur_smtp_password')) + if (!_request('facteur_smtp_password') AND !lire_config('facteur_smtp_password')) $erreurs['facteur_smtp_password'] = _T('info_obligatoire'); } } @@ -78,6 +93,16 @@ function formulaires_configurer_facteur_verifier_dist(){ AND !email_valide($emailbcc)) { $erreurs['facteur_bcc'] = _T('form_email_non_valide'); } + + if (_request('tester')){ + if (!$email = _request('email_test')){ + $erreurs['email_test'] = _T('info_obligatoire'); + } + elseif (!email_valide($email)) { + $erreurs['email_test'] = _T('form_email_non_valide'); + } + } + if(count($erreurs)>0){ $erreurs['message_erreur'] = _T('facteur:erreur_generale'); @@ -97,6 +122,9 @@ function formulaires_configurer_facteur_traiter_dist(){ $facteur_adresse_envoi_email = _request('facteur_adresse_envoi_email'); ecrire_meta('facteur_adresse_envoi_email', $facteur_adresse_envoi_email?$facteur_adresse_envoi_email:''); + $facteur_forcer_from = _request('facteur_forcer_from'); + ecrire_meta('facteur_forcer_from', ($facteur_forcer_from=='oui')?'oui':'non'); + $facteur_smtp = _request('facteur_smtp'); ecrire_meta('facteur_smtp', ($facteur_smtp=='oui')?'oui':'non'); @@ -112,8 +140,9 @@ function formulaires_configurer_facteur_traiter_dist(){ $facteur_smtp_username = _request('facteur_smtp_username'); ecrire_meta('facteur_smtp_username', $facteur_smtp_username); - $facteur_smtp_password = _request('facteur_smtp_password'); - ecrire_meta('facteur_smtp_password', $facteur_smtp_password); + if ($facteur_smtp_password = _request('facteur_smtp_password')) { + ecrire_meta('facteur_smtp_password', $facteur_smtp_password); + } if (intval(phpversion()) == 5) { $facteur_smtp_secure = _request('facteur_smtp_secure'); @@ -137,35 +166,54 @@ function formulaires_configurer_facteur_traiter_dist(){ // faut-il envoyer un message de test ? if (_request('tester')){ - - if ($GLOBALS['meta']['facteur_adresse_envoi'] == 'oui' - AND $GLOBALS['meta']['facteur_adresse_envoi_email']) - $destinataire = $GLOBALS['meta']['facteur_adresse_envoi_email']; - else - $destinataire = $GLOBALS['meta']['email_webmaster']; - - if ((facteur_envoyer_mail_test($destinataire,_T('facteur:corps_email_de_test')))===true){ - // OK - $res = array('message_ok'=>_T('facteur:email_test_envoye')); + $res = array(); + $destinataire = _request('email_test'); + $err = facteur_envoyer_mail_test($destinataire,_T('facteur:corps_email_de_test')); + if ($err) { + $res['message_erreur'] = $err; } else { - // erreur - $res = array('message_erreur'=>_T('facteur:erreur')._T('facteur:erreur_dans_log')); + $res['message_ok'] = _T('facteur:email_test_envoye'); } } return $res; } +/** + * Fonction pour tester un envoi de mail ver sun destinataire + * renvoie une erreur eventuelle ou rien si tout est OK + * @param string $destinataire + * @param string $titre + * @return string + * message erreur ou vide si tout est OK + */ function facteur_envoyer_mail_test($destinataire,$titre){ + include_spip('classes/facteur'); $message_html = recuperer_fond('emails/test_email_html', array()); $message_texte = recuperer_fond('emails/test_email_texte', array()); + $corps = array( + 'html' => $message_html, + 'texte' => $message_texte, + 'exceptions' => true, + ); // passer par envoyer_mail pour bien passer par les pipeline et avoir tous les logs $envoyer_mail = charger_fonction('envoyer_mail','inc'); - $retour = $envoyer_mail($destinataire, $titre, array('html'=>$message_html,'texte'=>$message_texte)); + try { + $retour = $envoyer_mail($destinataire, $titre, $corps); + } + catch (Exception $e) { + return $e->getMessage(); + } + + // si echec mais pas d'exception, on signale de regarder dans les logs + if (!$retour) { + return _T('facteur:erreur').' '._T('facteur:erreur_dans_log'); + } - return $retour?true:false; + // tout est OK, pas d'erreur + return ""; } ?> diff --git a/www/plugins/facteur/inc/envoyer_mail.php b/www/plugins/facteur/inc/envoyer_mail.php index 66b28a04..d485eb2c 100644 --- a/www/plugins/facteur/inc/envoyer_mail.php +++ b/www/plugins/facteur/inc/envoyer_mail.php @@ -32,6 +32,7 @@ include_once _DIR_RESTREINT."inc/envoyer_mail.php"; * string encodage : encodage a utiliser, parmi 'base64', '7bit', '8bit', 'binary', 'quoted-printable' * string mime : mime type du document * array headers : tableau d'en-tetes personalises, une entree par ligne d'en-tete + * bool exceptions : lancer une exception en cas d'erreur (false par defaut) * @param string $from (deprecie, utiliser l'entree from de $corps) * @param string $headers (deprecie, utiliser l'entree headers de $corps) * @return bool @@ -39,20 +40,22 @@ include_once _DIR_RESTREINT."inc/envoyer_mail.php"; function inc_envoyer_mail($destinataire, $sujet, $corps, $from = "", $headers = "") { $message_html = ''; $message_texte = ''; + $nom_envoyeur = $cc = $bcc = $repondre_a = ''; + $pieces_jointes = array(); // si $corps est un tableau -> fonctionnalites etendues // avec entrees possible : html, texte, pieces_jointes, nom_envoyeur, ... if (is_array($corps)) { - $message_html = $corps['html']; - $message_texte = nettoyer_caracteres_mail($corps['texte']); - $pieces_jointes = $corps['pieces_jointes']; - $nom_envoyeur = $corps['nom_envoyeur']; - $from = (isset($corps['from'])?$corps['from']:$from); - $cc = $corps['cc']; - $bcc = $corps['bcc']; - $repondre_a = $corps['repondre_a']; - $adresse_erreur = $corps['adresse_erreur']; - $headers = (isset($corps['headers'])?$corps['headers']:$headers); + $message_html = isset($corps['html']) ? $corps['html'] : ""; + $message_texte = isset($corps['texte']) ? nettoyer_caracteres_mail($corps['texte']) : ""; + $pieces_jointes = isset($corps['pieces_jointes']) ? $corps['pieces_jointes'] : array(); + $nom_envoyeur = isset($corps['nom_envoyeur']) ? $corps['nom_envoyeur'] : ""; + $from = isset($corps['from']) ? $corps['from']: $from; + $cc = isset($corps['cc']) ? $corps['cc'] : ""; + $bcc = isset($corps['bcc']) ? $corps['bcc'] : ""; + $repondre_a = isset($corps['repondre_a']) ? $corps['repondre_a'] : ""; + $adresse_erreur = isset($corps['adresse_erreur']) ? $corps['adresse_erreur'] : ""; + $headers = isset($corps['headers']) ? $corps['headers'] : $headers; if (is_string($headers)){ $headers = array_map('trim',explode("\n",$headers)); $headers = array_filter($headers); @@ -114,10 +117,20 @@ function inc_envoyer_mail($destinataire, $sujet, $corps, $from = "", $headers = $message_texte = facteur_mail_html2text($message_html); } + $exceptions = false; + if (is_array($corps) AND isset($corps['exceptions'])){ + $exceptions = $corps['exceptions']; + } + // mode TEST : forcer l'email if (defined('_TEST_EMAIL_DEST')) { - if (!_TEST_EMAIL_DEST) + if (!_TEST_EMAIL_DEST){ + spip_log($e="Envois bloques par la constante _TEST_EMAIL_DEST", 'mail.' . _LOG_ERREUR); + if ($exceptions) { + throw new Exception($e); + } return false; + } else $destinataire = _TEST_EMAIL_DEST; } @@ -126,28 +139,50 @@ function inc_envoyer_mail($destinataire, $sujet, $corps, $from = "", $headers = // c'est un format standard dans l'envoi de mail // les passer au format array pour phpMailer // mais ne pas casser si on a deja un array en entree - // si aucun destinataire du courriel on renvoie false (eviter les warning PHP) + // si pas destinataire du courriel on renvoie false (eviter les warning PHP : ligne 464 de phpmailer-php5/class.phpmailer.php + // suppression des adresses de courriels invalides, si aucune valide, renvoyer false (eviter un warning PHP : ligne 464 de phpmailer-php5/class.phpmailer.php) if (is_array($destinataire)) $destinataire = implode(", ",$destinataire); - if(strlen($destinataire) > 0) + if(strlen($destinataire) > 0){ $destinataire = array_map('trim',explode(",",$destinataire)); + foreach ($destinataire as $key => $value) { + if(!email_valide($value)) + unset($destinataire[$key]); + } + if(count($destinataire) == 0) { + spip_log($e="Aucune adresse email de destination valable pour l'envoi du courriel.", 'mail.' . _LOG_ERREUR); + if ($exceptions) { + throw new Exception($e); + } + return false; + } + } else { - spip_log("Aucune adresse email de destination valable pour l'envoi du courriel.", 'mail.' . _LOG_ERREUR); + spip_log($e="Aucune adresse email de destination valable pour l'envoi du courriel.", 'mail.' . _LOG_ERREUR); + if ($exceptions) { + throw new Exception($e); + } return false; } // On crée l'objet Facteur (PHPMailer) pour le manipuler ensuite $facteur = new Facteur($destinataire, $sujet, $message_html, $message_texte); + if (is_array($corps) AND isset($corps['exceptions'])){ + $facteur->SetExceptions($corps['exceptions']); + } // On ajoute le courriel de l'envoyeur s'il est fournit par la fonction if (empty($from) AND empty($facteur->From)) { $from = $GLOBALS['meta']["email_envoi"]; if (empty($from) OR !email_valide($from)) { spip_log("Meta email_envoi invalide. Le mail sera probablement vu comme spam.", 'mail.' . _LOG_ERREUR); - $from = $destinataire; + if(is_array($destinataire) && count($destinataire) > 0) + $from = $destinataire[0]; + else + $from = $destinataire; } - } + } // "Marie Toto " if (preg_match(",^([^<>\"]*)<([^<>\"]+)>$,i",$from,$m)){ @@ -234,14 +269,13 @@ function inc_envoyer_mail($destinataire, $sujet, $corps, $from = "", $headers = $head = $facteur->CreateHeader(); // Et c'est parti on envoie enfin - spip_log("mail via facteur\n$head"."Destinataire:".print_r($destinataire,true),'mail.' . _LOG_ERREUR); + spip_log("mail via facteur\n$head"."Destinataire:".print_r($destinataire,true),'mail'); spip_log("mail\n$head"."Destinataire:".print_r($destinataire,true),'facteur'); $retour = $facteur->Send(); - if (!$retour) - spip_log("Erreur Envoi mail via Facteur : ".print_r($facteur->ErrorInfo,true),'facteur'); + if (!$retour){ + spip_log("Erreur Envoi mail via Facteur : ".print_r($facteur->ErrorInfo,true),'mail.'._LOG_ERREUR); + } return $retour ; } - -?> diff --git a/www/plugins/facteur/lang/facteur.xml b/www/plugins/facteur/lang/facteur.xml index ceab0c38..e9d736f4 100644 --- a/www/plugins/facteur/lang/facteur.xml +++ b/www/plugins/facteur/lang/facteur.xml @@ -1,31 +1,41 @@ - + - + - + - + - + - + - + + + + - + + + + + + + + diff --git a/www/plugins/facteur/lang/facteur_de.php b/www/plugins/facteur/lang/facteur_de.php index 21158e74..41e17cfb 100644 --- a/www/plugins/facteur/lang/facteur_de.php +++ b/www/plugins/facteur/lang/facteur_de.php @@ -3,15 +3,17 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/facteur?lang_cible=de // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // C 'config_info_enregistree' => 'Die Konfiguration des Briefträgers wurde gespeichert.', - 'configuration_adresse_envoi' => 'Absenderadresse einstellen', + 'configuration_adresse_envoi' => 'Absenderadresse einstellen', # MODIF 'configuration_facteur' => 'Briefträger', - 'configuration_mailer' => 'Konfiguration des Mailers', + 'configuration_mailer' => 'Konfiguration des Mailers', # MODIF 'configuration_smtp' => 'Auswahl der Versandmethode', 'configuration_smtp_descriptif' => 'Im Zweifel hier die mail() Funktion von PHP eintragen.', 'corps_email_de_test' => 'Das ist ein Versandtest mit Sondärzeichen: Bär Größe Maß accentué', @@ -30,7 +32,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_adresse_envoi_nom' => 'Name:', 'facteur_bcc' => 'Blindkopie (BCC) :', 'facteur_cc' => 'Kopie (CC) :', - 'facteur_copies' => 'Kopien:', + 'facteur_copies' => 'Kopien:', # MODIF 'facteur_copies_descriptif' => 'Eine Kopie der E-Mails wird an die angegebenen Adressen geschickt. Geben sie eine Adresse als Empfänger der Kopie bzw. Blindkopie an.', 'facteur_filtre_accents' => 'Sonderzeichen in HTML-Entitäten umwandeln (z.B. für Hotmail).', 'facteur_filtre_css' => 'Stile zwischen und zu "inline" Stilen umwandeln, sinnvoll für Webmail die inline-Stile externen vorzieht.', @@ -46,17 +48,17 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_smtp_port' => 'Port:', 'facteur_smtp_secure' => 'Verschlüsselte Verbindung:', 'facteur_smtp_secure_non' => 'nein', - 'facteur_smtp_secure_ssl' => 'SSL', - 'facteur_smtp_secure_tls' => 'TLS', - 'facteur_smtp_sender' => 'Fehlercodes (optional)', - 'facteur_smtp_sender_descriptif' => 'Legt im Kopf der Mail die Empfängeradresse für Fehlermeldungen fest (bzw. den Return-Path), bestimmt ebenfalls die Absenderadresse bei Versand per SMTP.', + 'facteur_smtp_secure_ssl' => 'SSL (obsolet)', + 'facteur_smtp_secure_tls' => 'TLS (empfohlen)', + 'facteur_smtp_sender' => 'Fehlercodes (optional)', # MODIF + 'facteur_smtp_sender_descriptif' => 'Legt im Kopf der Mail die Empfängeradresse für Fehlermeldungen fest (bzw. den Return-Path), bestimmt ebenfalls die Absenderadresse bei Versand per SMTP.', # MODIF 'facteur_smtp_username' => 'Benutzername:', // M 'message_identite_email' => 'Die Konfiguration des Plugins Briefträger (facteur) überschreibt diese Adresse für den Mailversand.', // N - 'note_test_configuration' => 'Eine Mail wird an die Absendeadresse geschickt (oder an den Webmaster).', + 'note_test_configuration' => 'Eine Mail wird an die Absendeadresse geschickt (oder an den Webmaster).', # MODIF // P 'personnaliser' => 'Individuelle Einstellungen', @@ -67,7 +69,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'utiliser_mail' => 'Funktion mail() von PHP verwenden', - 'utiliser_reglages_site' => 'Einstellungen von SPIP verwenden: als Name wird die Bezeichnung der SPIP-Website verwendet und als Adresse die des Webmasters.', + 'utiliser_reglages_site' => 'Einstellungen von SPIP verwenden: als Name wird die Bezeichnung der SPIP-Website verwendet und als Adresse die des Webmasters.', # MODIF 'utiliser_smtp' => 'SMTP verwenden', // V @@ -75,5 +77,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'version_html' => 'HTML-Version.', 'version_texte' => 'Textversion.' ); - -?> diff --git a/www/plugins/facteur/lang/facteur_en.php b/www/plugins/facteur/lang/facteur_en.php index 3c9c75a1..172067f8 100755 --- a/www/plugins/facteur/lang/facteur_en.php +++ b/www/plugins/facteur/lang/facteur_en.php @@ -3,15 +3,17 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/facteur?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // C 'config_info_enregistree' => 'Postman’s configuration is now saved', - 'configuration_adresse_envoi' => 'Sender’s address configuration', + 'configuration_adresse_envoi' => 'Sender’s address configuration', # MODIF 'configuration_facteur' => 'Postman', - 'configuration_mailer' => 'Mailer’s configuration', + 'configuration_mailer' => 'Mailer’s configuration', # MODIF 'configuration_smtp' => 'Choose your mailer', 'configuration_smtp_descriptif' => 'If you’re not sure about the settings, leave them set to "PHP mail".', 'corps_email_de_test' => 'This is a test email', @@ -30,7 +32,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_adresse_envoi_nom' => 'Name:', 'facteur_bcc' => 'Blind Carbon Copy (BCC):', 'facteur_cc' => 'Carbon Copy (CC):', - 'facteur_copies' => 'Copies:', + 'facteur_copies' => 'Copies:', # MODIF 'facteur_copies_descriptif' => 'An email will be sent to specified adresses. One Carbon Copy and/or one Blind Carbon Copy.', 'facteur_filtre_accents' => 'Transform accents into their html entities (useful for Hotmail).', 'facteur_filtre_css' => 'Transform styles present between <head> and </head> into inline styles, useful for webmails because inline styles overwrite external styles.', @@ -46,17 +48,17 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_smtp_port' => 'Port:', 'facteur_smtp_secure' => 'Secure:', 'facteur_smtp_secure_non' => 'no', - 'facteur_smtp_secure_ssl' => 'SSL', - 'facteur_smtp_secure_tls' => 'TLS', - 'facteur_smtp_sender' => 'Return-Path (optional)', - 'facteur_smtp_sender_descriptif' => 'Define the Return-Path in the mail header, useful for error feedback, also in SMTP mode it defines the sender’s email.', + 'facteur_smtp_secure_ssl' => 'SSL (depreciated)', + 'facteur_smtp_secure_tls' => 'TLS (recommended)', + 'facteur_smtp_sender' => 'Return-Path (optional)', # MODIF + 'facteur_smtp_sender_descriptif' => 'Define the Return-Path in the mail header, useful for error feedback, also in SMTP mode it defines the sender’s email.', # MODIF 'facteur_smtp_username' => 'Username:', // M 'message_identite_email' => 'The configuration of the plugin "factor" preset this email address for sending emails.', // N - 'note_test_configuration' => 'A test email will be sent to the "sender".', + 'note_test_configuration' => 'A test email will be sent to the "sender".', # MODIF // P 'personnaliser' => 'Customize', @@ -67,7 +69,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'utiliser_mail' => 'Use mail function from PHP', - 'utiliser_reglages_site' => 'Use the site’s settings: the email address is the webmaster’s one and the name of the website is the name of the sender', + 'utiliser_reglages_site' => 'Use the site’s settings: the email address is the webmaster’s one and the name of the website is the name of the sender', # MODIF 'utiliser_smtp' => 'Use SMTP', // V @@ -75,5 +77,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'version_html' => 'HTML version.', 'version_texte' => 'Text version.' ); - -?> diff --git a/www/plugins/facteur/lang/facteur_es.php b/www/plugins/facteur/lang/facteur_es.php index 3cef7c9f..795e48b7 100644 --- a/www/plugins/facteur/lang/facteur_es.php +++ b/www/plugins/facteur/lang/facteur_es.php @@ -3,15 +3,17 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/facteur?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // C 'config_info_enregistree' => 'La configuración del cartero fue guardada correctamente', - 'configuration_adresse_envoi' => 'Configuración de la dirección de envío', + 'configuration_adresse_envoi' => 'Configuración de la dirección de envío', # MODIF 'configuration_facteur' => 'Cartero', - 'configuration_mailer' => 'Configuración del "mailer"', + 'configuration_mailer' => 'Configuración del "mailer"', # MODIF 'configuration_smtp' => 'Elección del método de envío del correo electrónico', 'configuration_smtp_descriptif' => 'Si no estás seguro, elige la función de correo electrónico de PHP.', 'corps_email_de_test' => 'Éste es un mensaje de prueba acentuado', @@ -30,7 +32,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_adresse_envoi_nom' => 'Nombre:', 'facteur_bcc' => 'Copia Oculta (CCO):', 'facteur_cc' => 'Copia (CC) :', - 'facteur_copies' => 'Copias:', + 'facteur_copies' => 'Copias:', # MODIF 'facteur_copies_descriptif' => 'Un correo electrónico será enviado en copia a las direcciones definidas. Una sola dirección en copia y/o una sola dirección en copia oculta.', 'facteur_filtre_accents' => 'Transformar los acentos en su versión html (especialmente útil para Hotmail).', 'facteur_filtre_css' => 'Transformar los estilos contenidos entre y en estilos en línea, útil para los webmails porque los estilos lineales tienen prioridad sobre los estilos externos. ', @@ -46,17 +48,17 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_smtp_port' => 'Puerto:', 'facteur_smtp_secure' => 'Conexión segura:', 'facteur_smtp_secure_non' => 'no', - 'facteur_smtp_secure_ssl' => 'SSL', - 'facteur_smtp_secure_tls' => 'TLS', - 'facteur_smtp_sender' => 'Rebote de errores (opcional)', - 'facteur_smtp_sender_descriptif' => 'Indica en el encabezado del correo electrónico la dirección de correo electrónico de rebote de errores (o "Return-Path"), y en caso de un envío a través del método SMTP indica, también, la dirección del remitente.', + 'facteur_smtp_secure_ssl' => 'SSL (obsoleto)', + 'facteur_smtp_secure_tls' => 'TLS (recomendado)', + 'facteur_smtp_sender' => 'Rebote de errores (opcional)', # MODIF + 'facteur_smtp_sender_descriptif' => 'Indica en el encabezado del correo electrónico la dirección de correo electrónico de rebote de errores (o "Return-Path"), y en caso de un envío a través del método SMTP indica, también, la dirección del remitente.', # MODIF 'facteur_smtp_username' => 'Nombre de usuario:', // M 'message_identite_email' => 'La configuración del plugin "cartero" sobrecarga esta dirección de correo para el envío de correos.', // N - 'note_test_configuration' => 'Un correo electrónico se enviará a la dirección de envío definida (o aquélla del webmaster).', + 'note_test_configuration' => 'Un correo electrónico se enviará a la dirección de envío definida (o aquélla del webmaster).', # MODIF // P 'personnaliser' => 'Personalizar esta configuración', @@ -67,7 +69,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'utiliser_mail' => 'Utilizar la función de correo electrónico de PHP', - 'utiliser_reglages_site' => 'Utilizar la configuración del sitio SPIP: el nombre mostrado será el nombre del sitio SPIP y la dirección de correo electrónico será la del webmaster', + 'utiliser_reglages_site' => 'Utilizar la configuración del sitio SPIP: el nombre mostrado será el nombre del sitio SPIP y la dirección de correo electrónico será la del webmaster', # MODIF 'utiliser_smtp' => 'Utilizar SMTP', // V @@ -75,5 +77,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'version_html' => 'Versión HTML.', 'version_texte' => 'Versión texto.' ); - -?> diff --git a/www/plugins/facteur/lang/facteur_fa.php b/www/plugins/facteur/lang/facteur_fa.php index 45866b6c..691d3316 100644 --- a/www/plugins/facteur/lang/facteur_fa.php +++ b/www/plugins/facteur/lang/facteur_fa.php @@ -3,15 +3,17 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/facteur?lang_cible=fa // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // C 'config_info_enregistree' => 'پيكربندي پستجي ثبت شده است.', - 'configuration_adresse_envoi' => 'پيكربندي نشاني نامه ', + 'configuration_adresse_envoi' => 'پيكربندي نشاني نامه ', # MODIF 'configuration_facteur' => 'پستچي', - 'configuration_mailer' => 'پيكربندي نامه‌ رسان', + 'configuration_mailer' => 'پيكربندي نامه‌ رسان', # MODIF 'configuration_smtp' => 'انتخاب روش ارسال نامه', 'configuration_smtp_descriptif' => 'اگر در مورد تنظيمات مطمئن نيستيد، بگذاريد «پي.اچ.پي ميل» تنظيم كند. ', 'corps_email_de_test' => 'اين يك ايميل آزمايشي است.', @@ -30,7 +32,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_adresse_envoi_nom' => 'نام:‌', 'facteur_bcc' => 'كپي مخفي (بي.سي.سي): ', 'facteur_cc' => 'كپي غيرمخفي (سي.سي): ', - 'facteur_copies' => 'كپي‌ها:‌', + 'facteur_copies' => 'كپي‌ها:‌', # MODIF 'facteur_copies_descriptif' => 'يك ايميل به نشاني مشخص شده ارسال خواهد شد. يك كپي غير مخفي و/يا يك كپي مخفي.', 'facteur_filtre_accents' => 'تبديل اكسان‌ها به اچ.تي.ام.ال (براي هاتميل مفيد است)', 'facteur_filtre_css' => 'تبديل استايل‌هاي مطالب بين و به استايل‌هاي درخط، مفيد براي وب‌ميل‌ها، زيرا استايل‌هاي درخط بر استايل‌هاي بيروني اولويت مي‌يابند.', @@ -46,17 +48,17 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_smtp_port' => 'پورت:‌', 'facteur_smtp_secure' => 'ارتباط امن:‌', 'facteur_smtp_secure_non' => 'نه', - 'facteur_smtp_secure_ssl' => 'اس.اس.ال', - 'facteur_smtp_secure_tls' => 'تي.ال.اس', - 'facteur_smtp_sender' => 'برگشت خطاها (دلبخواه)', - 'facteur_smtp_sender_descriptif' => 'تعيين مسير برگشت در بالاي ايميل مفيد براي خطاي فيدبك، همچنين در حالت اس.ام.تي.پي (پروتكل انتقال ساده نامه) فرستنده نامه را مشخص مي‌كمند. ', + 'facteur_smtp_secure_ssl' => 'اس.اس.ال', # MODIF + 'facteur_smtp_secure_tls' => 'تي.ال.اس', # MODIF + 'facteur_smtp_sender' => 'برگشت خطاها (دلبخواه)', # MODIF + 'facteur_smtp_sender_descriptif' => 'تعيين مسير برگشت در بالاي ايميل مفيد براي خطاي فيدبك، همچنين در حالت اس.ام.تي.پي (پروتكل انتقال ساده نامه) فرستنده نامه را مشخص مي‌كمند. ', # MODIF 'facteur_smtp_username' => 'نام كاربر:‌', // M 'message_identite_email' => 'پيكربندي پلاگين «پستچي» نشاني اين ايميل را براي ارسال ايميل‌ها تنظيم مي‌كند', // N - 'note_test_configuration' => 'يك ايميل به نشاني مرسوله تعيين شده (يا به نشاني وب مستر) ارسال خواهد شد', + 'note_test_configuration' => 'يك ايميل به نشاني مرسوله تعيين شده (يا به نشاني وب مستر) ارسال خواهد شد', # MODIF // P 'personnaliser' => 'شخصي سازي اين تنظيمات ', @@ -67,7 +69,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'utiliser_mail' => 'ار كاركرد نامه پي.اچ.پي استفاده كنيد', - 'utiliser_reglages_site' => 'استفاده از تنظيمات سايت اسپيپ: نام وب سايت نام فرستنده خواهد بود و نشاني ايميل نشاني ايميل وب مستر خواهد بود. ', + 'utiliser_reglages_site' => 'استفاده از تنظيمات سايت اسپيپ: نام وب سايت نام فرستنده خواهد بود و نشاني ايميل نشاني ايميل وب مستر خواهد بود. ', # MODIF 'utiliser_smtp' => 'از اس.ام.تي.پي (پروتكل ارسال ساده نامه)‌ اسفتاده كنيد', // V @@ -75,5 +77,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'version_html' => 'نسخه اچ.تي.ام.ال', 'version_texte' => 'نسخه متني.' ); - -?> diff --git a/www/plugins/facteur/lang/facteur_fr.php b/www/plugins/facteur/lang/facteur_fr.php index 5610ec6e..0e5c8acf 100755 --- a/www/plugins/facteur/lang/facteur_fr.php +++ b/www/plugins/facteur/lang/facteur_fr.php @@ -1,15 +1,17 @@ 'La configuration du facteur a bien été enregistrée', - 'configuration_adresse_envoi' => 'Configuration de l’adresse d’envoi', + 'configuration_adresse_envoi' => 'Adresse d’envoi par défaut', 'configuration_facteur' => 'Facteur', - 'configuration_mailer' => 'Configuration du mailer', + 'configuration_mailer' => 'Méthode d’envoi', 'configuration_smtp' => 'Choix de la méthode d’envoi de mail', 'configuration_smtp_descriptif' => 'Si vous n’êtes pas sûrs, choisissez la fonction mail de PHP.', 'corps_email_de_test' => 'Ceci est un email de test accentué', @@ -28,8 +30,9 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_adresse_envoi_nom' => 'Nom :', 'facteur_bcc' => 'Copie Cachée (BCC) :', 'facteur_cc' => 'Copie (CC) :', - 'facteur_copies' => 'Copies :', + 'facteur_copies' => 'Copies', 'facteur_copies_descriptif' => 'Un email sera envoyé en copie aux adresses définies. Une seule adresse en copie et/ou une seule adresse en copie cachée.', + 'facteur_email_test' => 'Envoyer un email de test à :', 'facteur_filtre_accents' => 'Transformer les accents en leur entités html (utile pour Hotmail notamment).', 'facteur_filtre_css' => 'Transformer les styles contenus entre et en des styles "en ligne", utile pour les webmails car les styles en ligne ont la priorité sur les styles externes.', 'facteur_filtre_images' => 'Embarquer les images référencées dans les emails', @@ -44,17 +47,20 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_smtp_port' => 'Port :', 'facteur_smtp_secure' => 'Connexion sécurisée :', 'facteur_smtp_secure_non' => 'non', - 'facteur_smtp_secure_ssl' => 'SSL', - 'facteur_smtp_secure_tls' => 'TLS', - 'facteur_smtp_sender' => 'Retour des erreurs (optionnel)', - 'facteur_smtp_sender_descriptif' => 'Définit dans l’entête du mail l’adresse email de retour des erreurs (ou Return-Path), et lors d’un envoi via la méthode SMTP cela définit aussi l’adresse de l’envoyeur.', + 'facteur_smtp_secure_ssl' => 'SSL (déprécié)', + 'facteur_smtp_secure_tls' => 'TLS (recommandé)', + 'facteur_smtp_sender' => 'Adresse de retour des erreurs (optionnel)', + 'facteur_smtp_sender_descriptif' => 'Définit dans l’entête du mail l’adresse email de retour des erreurs (ou Return-Path)', 'facteur_smtp_username' => 'Nom d’utilisateur :', + // L + 'label_facteur_forcer_from' => 'Forcer cette adresse d’envoi quand le From n’est pas sur le même domaine', + // M 'message_identite_email' => 'La configuration du plugin "facteur" surcharge cette adresse email pour l’envoi de courriels.', // N - 'note_test_configuration' => 'Un email sera envoyé à l’adresse d’envoi définie (ou celle du webmaster).', + 'note_test_configuration' => 'Un email sera envoyé à cette adresse.', // P 'personnaliser' => 'Personnaliser ces réglages', @@ -65,7 +71,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'utiliser_mail' => 'Utiliser la fonction mail de PHP', - 'utiliser_reglages_site' => 'Utiliser les réglages du site SPIP : le nom affiché sera le nom du site SPIP et l’adresse email sera celle du webmaster', + 'utiliser_reglages_site' => 'Utiliser les réglages du site SPIP :
                  @from@', 'utiliser_smtp' => 'Utiliser SMTP', // V @@ -73,5 +79,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'version_html' => 'Version HTML.', 'version_texte' => 'Version texte.' ); - -?> diff --git a/www/plugins/facteur/lang/facteur_fr_tu.php b/www/plugins/facteur/lang/facteur_fr_tu.php index eae3378f..4ad5edf7 100644 --- a/www/plugins/facteur/lang/facteur_fr_tu.php +++ b/www/plugins/facteur/lang/facteur_fr_tu.php @@ -3,15 +3,17 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/facteur?lang_cible=fr_tu // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // C 'config_info_enregistree' => 'La configuration du facteur a bien été enregistrée', - 'configuration_adresse_envoi' => 'Configuration de l’adresse d’envoi', + 'configuration_adresse_envoi' => 'Configuration de l’adresse d’envoi', # MODIF 'configuration_facteur' => 'Facteur', - 'configuration_mailer' => 'Configuration du mailer', + 'configuration_mailer' => 'Configuration du mailer', # MODIF 'configuration_smtp' => 'Choix de la méthode d’envoi de mail', 'configuration_smtp_descriptif' => 'Si tu n’es pas sûr, choisis la fonction mail de PHP.', 'corps_email_de_test' => 'Ceci est un email de test accentué', @@ -30,7 +32,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_adresse_envoi_nom' => 'Nom :', 'facteur_bcc' => 'Copie Cachée (BCC) :', 'facteur_cc' => 'Copie (CC) :', - 'facteur_copies' => 'Copies :', + 'facteur_copies' => 'Copies :', # MODIF 'facteur_copies_descriptif' => 'Un email sera envoyé en copie aux adresses définies. Une seule adresse en copie et/ou une seule adresse en copie cachée.', 'facteur_filtre_accents' => 'Transformer les accents en leur entités html (utile pour Hotmail notamment).', 'facteur_filtre_css' => 'Transformer les styles contenus entre et en des styles "en ligne", utile pour les webmails car les styles en ligne ont la priorité sur les styles externes.', @@ -46,17 +48,17 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_smtp_port' => 'Port :', 'facteur_smtp_secure' => 'Connexion sécurisée :', 'facteur_smtp_secure_non' => 'non', - 'facteur_smtp_secure_ssl' => 'SSL', - 'facteur_smtp_secure_tls' => 'TLS', - 'facteur_smtp_sender' => 'Retour des erreurs (optionnel)', - 'facteur_smtp_sender_descriptif' => 'Définit dans l’entête du mail l’adresse email de retour des erreurs (ou Return-Path), et lors d’un envoi via la méthode SMTP cela définit aussi l’adresse de l’envoyeur.', + 'facteur_smtp_secure_ssl' => 'SSL', # MODIF + 'facteur_smtp_secure_tls' => 'TLS', # MODIF + 'facteur_smtp_sender' => 'Retour des erreurs (optionnel)', # MODIF + 'facteur_smtp_sender_descriptif' => 'Définit dans l’entête du mail l’adresse email de retour des erreurs (ou Return-Path), et lors d’un envoi via la méthode SMTP cela définit aussi l’adresse de l’envoyeur.', # MODIF 'facteur_smtp_username' => 'Nom d’utilisateur :', // M 'message_identite_email' => 'La configuration du plugin "facteur" surcharge cette adresse email pour l’envoi de courriels.', // N - 'note_test_configuration' => 'Un email sera envoyé à l’adresse d’envoi définie (ou celle du webmaster).', + 'note_test_configuration' => 'Un email sera envoyé à l’adresse d’envoi définie (ou celle du webmaster).', # MODIF // P 'personnaliser' => 'Personnaliser ces réglages', @@ -67,7 +69,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'utiliser_mail' => 'Utiliser la fonction mail de PHP', - 'utiliser_reglages_site' => 'Utiliser les réglages du site SPIP : le nom affiché sera le nom du site SPIP et l’adresse email sera celle du webmaster', + 'utiliser_reglages_site' => 'Utiliser les réglages du site SPIP : le nom affiché sera le nom du site SPIP et l’adresse email sera celle du webmaster', # MODIF 'utiliser_smtp' => 'Utiliser SMTP', // V @@ -75,5 +77,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'version_html' => 'Version HTML.', 'version_texte' => 'Version texte.' ); - -?> diff --git a/www/plugins/facteur/lang/facteur_it.php b/www/plugins/facteur/lang/facteur_it.php new file mode 100644 index 00000000..0a92e76b --- /dev/null +++ b/www/plugins/facteur/lang/facteur_it.php @@ -0,0 +1,78 @@ + 'La configurazione di Facteur è stata registrata', + 'configuration_adresse_envoi' => 'Configurazione dell’indirizzo emittente', # MODIF + 'configuration_mailer' => 'Configurazione del mailer', # MODIF + 'configuration_smtp' => 'Scelta del metodo d’invio di mail', + 'configuration_smtp_descriptif' => 'Se no siete sicuri, scegliete la funzione mail di PHP.', + 'corps_email_de_test' => 'Questo è un mail di prova con accento', + + // E + 'email_envoye_par' => 'Inviato da @site@', + 'email_test_envoye' => 'La mail di prova è stata correttamente inviata. Se non la ricevete correttamente, verficate la configurazione del server o contattate un amministratore del server.', + 'erreur' => 'Errorr', + 'erreur_dans_log' => ': consultate il file log per maggiori dettagli', + 'erreur_generale' => 'Ci sono uno o più errori di configurazione. Verificate il contenuto del formulario.', + 'erreur_invalid_host' => 'Questo nome di host non è corretto', + 'erreur_invalid_port' => 'Questu numero di porta non è corretto', + + // F + 'facteur_adresse_envoi_email' => 'Email:', + 'facteur_adresse_envoi_nom' => 'Cognome:', + 'facteur_bcc' => 'Copia nascosta (CCN):', + 'facteur_cc' => 'Copia (CC):', + 'facteur_copies' => 'Copie:', # MODIF + 'facteur_copies_descriptif' => 'Una mail sarà mandata in copia agli indirizzi definiti. Un solo indirizzo in copia e/o un solo indirizzo in copia nascosta.', + 'facteur_filtre_accents' => 'Trasformate gli accenti nella loro entity html (utile sopratutto per Hotmail).', + 'facteur_filtre_css' => 'Trasformare gli stili contenuti tra e negli stili "in linea", utile per le webmail perché gli stili in linea hanno la precedenza sugli stili estermi.', + 'facteur_filtre_images' => 'Integrate le immagini citate nelle mail', + 'facteur_filtre_iso_8859' => 'Convertire in ISO-8859-1', + 'facteur_filtres' => 'Filtri', + 'facteur_filtres_descriptif' => 'Alcuni filtri possono essere applicati alle mail al momento dell’invio.', + 'facteur_smtp_auth' => 'Richiede un’autenticazione:', + 'facteur_smtp_auth_non' => 'no', + 'facteur_smtp_auth_oui' => 'si', + 'facteur_smtp_host' => 'Host:', + 'facteur_smtp_password' => 'Password:', + 'facteur_smtp_port' => 'Porta:', + 'facteur_smtp_secure' => 'Connessione sicura:', + 'facteur_smtp_secure_non' => 'no', + 'facteur_smtp_secure_ssl' => 'SSL', # MODIF + 'facteur_smtp_secure_tls' => 'TLS', # MODIF + 'facteur_smtp_sender' => 'Resoconto degli errori (opzionale)', # MODIF + 'facteur_smtp_sender_descriptif' => 'Definisce nella testata della mail l’indirizzo mail di resoconto degli errori (o Return-Path), e durante l’invio tramite il metodo SMTP definisce anche l’indirizzo del mittente.', # MODIF + 'facteur_smtp_username' => 'Nome dell’utente:', + + // M + 'message_identite_email' => 'La configurazione del plugin "facteur" sovraccarica questo indirizzo mail per l’invio della posta.', + + // N + 'note_test_configuration' => 'Una mail sarà inviata all’indirizzo definito (o all’indirizzo del webmaster).', # MODIF + + // P + 'personnaliser' => 'Personnalizzate questi impostazioni', + + // T + 'tester' => 'Provare', + 'tester_la_configuration' => 'Provare la configurazione', + + // U + 'utiliser_mail' => 'Usare la funzione mail di PHP', + 'utiliser_reglages_site' => 'Usare le impostazioni del sito SPIP: il nome visualizzato sarà il nome del sito SPIP e l’indirizzo mail sarà quello del webmaster', # MODIF + 'utiliser_smtp' => 'Utilisare SMTP', + + // V + 'valider' => 'Confermare', + 'version_html' => 'Versione HTML.', + 'version_texte' => 'Versione testo.' +); diff --git a/www/plugins/facteur/lang/facteur_nl.php b/www/plugins/facteur/lang/facteur_nl.php index 1d2c1305..0fbb2a14 100644 --- a/www/plugins/facteur/lang/facteur_nl.php +++ b/www/plugins/facteur/lang/facteur_nl.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/facteur?lang_cible=nl // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -32,6 +34,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_cc' => 'Kopie (CC) :', 'facteur_copies' => 'Kopieën:', 'facteur_copies_descriptif' => 'Deze adressen worden in kopie van de email gezet. Niet meer dan één adres in kopie en/of in verborgen kopie.', + 'facteur_email_test' => 'Een test email sturen naar:', 'facteur_filtre_accents' => 'Zet tekens met accenten om in hun html-code (met name voor Hotmail).', 'facteur_filtre_css' => 'Zet de stijlen binnen <head> en </head> om in "inline" stijlen, wat zinvol is voor webmails.', 'facteur_filtre_images' => 'Voeg afbeeldingen in', @@ -46,12 +49,15 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_smtp_port' => 'Poort:', 'facteur_smtp_secure' => 'Beveiligde verbinding:', 'facteur_smtp_secure_non' => 'nee', - 'facteur_smtp_secure_ssl' => 'SSL', - 'facteur_smtp_secure_tls' => 'TLS', + 'facteur_smtp_secure_ssl' => 'SSL (gedeprecieerd)', + 'facteur_smtp_secure_tls' => 'TLS (aanbevolen)', 'facteur_smtp_sender' => 'Return-Path (optioneel)', 'facteur_smtp_sender_descriptif' => 'Geef het Return-Path voor de mail aan, bv voor feedback. In SMTP bepaalt het het emailadres van de verzender.', 'facteur_smtp_username' => 'Naam van de gebruiker:', + // L + 'label_facteur_forcer_from' => 'Forceer dit verzendadres wanneer de From niet tot hetzelfde domein behoort', + // M 'message_identite_email' => 'De configuratie van plugin "facteur" laadt dit e-mailadres voor het verzenden van mails.', @@ -67,7 +73,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'utiliser_mail' => 'Gebruik de PHP mail functie', - 'utiliser_reglages_site' => 'Gebruik de instellingen van SPIP: de getoonde naam is die van de site en het adres dat van de webmaster', + 'utiliser_reglages_site' => 'Gebruik de instellingen van SPIP:
                  @from@
                  De getoonde naam is die van de site en het adres dat van de webmaster', 'utiliser_smtp' => 'Gebruik SMTP', // V @@ -75,5 +81,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'version_html' => 'HTML-versie.', 'version_texte' => 'Tekstversie.' ); - -?> diff --git a/www/plugins/facteur/lang/facteur_oc_ni_mis.php b/www/plugins/facteur/lang/facteur_oc_ni_mis.php new file mode 100644 index 00000000..b2618f2c --- /dev/null +++ b/www/plugins/facteur/lang/facteur_oc_ni_mis.php @@ -0,0 +1,79 @@ + 'La counfiguracioun dóu fatour es ben estada registrada', + 'configuration_adresse_envoi' => 'Counfiguracioun de l’adressa de spedissioun', # MODIF + 'configuration_facteur' => 'Fatour', + 'configuration_mailer' => 'Counfiguracioun dóu mailer', # MODIF + 'configuration_smtp' => 'Chausida de la mètodou de spedissioun de mail', + 'configuration_smtp_descriptif' => 'Se noun sias segur, chaussissès la founcioun mail de PHP.', + 'corps_email_de_test' => 'Aiçòt es un e-mail de prova achentat', + + // E + 'email_envoye_par' => 'Mandat da @site@', + 'email_test_envoye' => 'L’e-mail de prova es ben estat mandat. Se noun lou recevès courretamen, verificàs la counfiguracioun dóu vouòstre servidou o countatàs un aministratour dóu servidou.', + 'erreur' => 'Errour', + 'erreur_dans_log' => ' : counsultàs lou fichié log per mai de detai', + 'erreur_generale' => 'Lì a, au màncou, un errour de counfiguracioun. Vourguès verificà lou countengut dóu fourmulari.', + 'erreur_invalid_host' => 'Aquestou noum d’oste es pas courret', + 'erreur_invalid_port' => 'Aquestou nùmero de pouòrt es pas courret', + + // F + 'facteur_adresse_envoi_email' => 'E-mail :', + 'facteur_adresse_envoi_nom' => 'Noum :', + 'facteur_bcc' => 'Còpia Escounduda (BCC) :', + 'facteur_cc' => 'Còpia (CC) :', + 'facteur_copies' => 'Còpia :', # MODIF + 'facteur_copies_descriptif' => 'Un e-mail serà mandat en còpia ai adressa definidi. Basta una adressa en còpia e/o basta una adressa en còpia escounduda.', + 'facteur_filtre_accents' => 'Trasfourmà lu achent en li siéu entità html (utile per Hotmail per isemple).', + 'facteur_filtre_css' => 'Trasfourmà lu estil countengut tra e en dei estil "en ligna", utile per lu webmail perqué lu estil en ligna an la priourità soubre lu estil estèrnou.', + 'facteur_filtre_images' => 'Embarcà li image referençadi en lu e-mail', + 'facteur_filtre_iso_8859' => 'Counvertì en ISO-8859-1', + 'facteur_filtres' => 'Filtre', + 'facteur_filtres_descriptif' => 'Dei filtre pouòdon estre aplicat ai e-mail au moumen de la spedissioun.', + 'facteur_smtp_auth' => 'Necessita una autentificacioun :', + 'facteur_smtp_auth_non' => 'noun', + 'facteur_smtp_auth_oui' => 'ahì', + 'facteur_smtp_host' => 'Oste :', + 'facteur_smtp_password' => 'Mot de passa :', + 'facteur_smtp_port' => 'Pouòrt :', + 'facteur_smtp_secure' => 'Counessioun seguritada :', + 'facteur_smtp_secure_non' => 'noun', + 'facteur_smtp_secure_ssl' => 'SSL (oussoulet)', + 'facteur_smtp_secure_tls' => 'TLS (racoumandat)', + 'facteur_smtp_sender' => 'Retour dei errour (oupciounal)', # MODIF + 'facteur_smtp_sender_descriptif' => 'Definit en l’entestacioun dóu e-mail de retour dei errour (o Return-Path), e dóu tems d’una spedissioun vìa lou mètodou SMTP acò definit finda l’adressa de l’espeditour.', # MODIF + 'facteur_smtp_username' => 'Noum d’utilisaire :', + + // M + 'message_identite_email' => 'Lou counfiguracioun dóu plugin "fatour" soubre-scriéu aquela adressa e-mail per la spedissioun.', + + // N + 'note_test_configuration' => 'Un e-mail serà mandat a l’adressa de spedissioun definida (o aquela dóu webmèstre).', # MODIF + + // P + 'personnaliser' => 'Persounalisà aquestu reglage', + + // T + 'tester' => 'Prouvà', + 'tester_la_configuration' => 'Prouvà la counfiguracioun', + + // U + 'utiliser_mail' => 'Utilisà la founcioun mail de PHP', + 'utiliser_reglages_site' => 'Utilisà lu reglage dóu sit SPIP : lou noum afichat serà lou noum dóu sit SPIP et l’adressa e-mail serà aquela dóu webmèstre', # MODIF + 'utiliser_smtp' => 'Utilisà SMTP', + + // V + 'valider' => 'Validà', + 'version_html' => 'Versioun HTML.', + 'version_texte' => 'Versioun tèst.' +); diff --git a/www/plugins/facteur/lang/facteur_pt_br.php b/www/plugins/facteur/lang/facteur_pt_br.php new file mode 100644 index 00000000..c7e547f5 --- /dev/null +++ b/www/plugins/facteur/lang/facteur_pt_br.php @@ -0,0 +1,83 @@ + 'A configuração do Carteiro foi gravada corretamente', + 'configuration_adresse_envoi' => 'Endereço de envio padrão', + 'configuration_facteur' => 'Carteiro', + 'configuration_mailer' => 'Método de envio', + 'configuration_smtp' => 'Seleção do método de envio de e-mail', + 'configuration_smtp_descriptif' => 'Se tiver dúvida, escolha a função mail do PHP.', + 'corps_email_de_test' => 'Este é um e-mail de teste acentuado', + + // E + 'email_envoye_par' => 'Enviado por @site@', + 'email_test_envoye' => 'O e-mail de teste foi enviado corretamente. Se você não o receber, verifique a configuração do seu servidor ou contate o administrador do servidor.', + 'erreur' => 'Erro', + 'erreur_dans_log' => ' : consulte o arquivo de log para obter mais detalhes', + 'erreur_generale' => 'Há um ou mais erros de configuração. Por favor, verifique o conteúdo do formulário.', + 'erreur_invalid_host' => 'Este nome de host não está correto', + 'erreur_invalid_port' => 'Este número de porta não está correto', + + // F + 'facteur_adresse_envoi_email' => 'E-mail:', + 'facteur_adresse_envoi_nom' => 'Nome:', + 'facteur_bcc' => 'Cópia Oculta (BCC):', + 'facteur_cc' => 'Cópia (CC):', + 'facteur_copies' => 'Cópias', + 'facteur_copies_descriptif' => 'Um e-mail será enviado em cópia para os endereços especificados. Um único endereço em cópia e/ou um único endereço em cópia oculta.', + 'facteur_email_test' => 'Enviar um e-mail de teste para:', + 'facteur_filtre_accents' => 'Transformar os acentos em entidades HTML (útil especialmente para o Hotmail).', + 'facteur_filtre_css' => 'Transformaros estílos contidos entre e em estilos "em linha", útil para os webmails, já que os estilos em linha têm prioridade sobre os estilos externos.', + 'facteur_filtre_images' => 'Embutir as imagens referenciadas no próprio e-mail', + 'facteur_filtre_iso_8859' => 'Converter em ISO-8859-1', + 'facteur_filtres' => 'Filtros', + 'facteur_filtres_descriptif' => 'Filtros podem ser aplicados aos e-mails, no momento do envio.', + 'facteur_smtp_auth' => 'Requer autenticação:', + 'facteur_smtp_auth_non' => 'não', + 'facteur_smtp_auth_oui' => 'sim', + 'facteur_smtp_host' => 'Host:', + 'facteur_smtp_password' => 'Senha:', + 'facteur_smtp_port' => 'Porta:', + 'facteur_smtp_secure' => 'Conexão segura:', + 'facteur_smtp_secure_non' => 'náo', + 'facteur_smtp_secure_ssl' => 'SSL (obsoleto)', + 'facteur_smtp_secure_tls' => 'TLS (recomendado)', + 'facteur_smtp_sender' => 'Endereço pelo retorno dos erros (opcional)', + 'facteur_smtp_sender_descriptif' => 'Informa, no cabeçalho da mensagem, o endereço de e-mail de retorno dos erros (ou Return-Path)', + 'facteur_smtp_username' => 'Nome do usuário:', + + // L + 'label_facteur_forcer_from' => 'Forçar o endereço de envio quando o From não é no mesmo domínio.', + + // M + 'message_identite_email' => 'A configuração do plugin "Carteiro" define este endereço de e-mail para o envio das mensagens.', + + // N + 'note_test_configuration' => 'Um e-mail será enviado a este endereço.', + + // P + 'personnaliser' => 'Personalizar essas configurações', + + // T + 'tester' => 'Testar', + 'tester_la_configuration' => 'Testar a configuração', + + // U + 'utiliser_mail' => 'Usar a função mail do PHP', + 'utiliser_reglages_site' => 'Usar as configurações do site SPIP: :
                  @from@ ', + 'utiliser_smtp' => 'Usar SMTP', + + // V + 'valider' => 'Validar', + 'version_html' => 'Versão HTML.', + 'version_texte' => 'Versão texto.' +); diff --git a/www/plugins/facteur/lang/facteur_sk.php b/www/plugins/facteur/lang/facteur_sk.php index 3e35b133..e8bd1491 100644 --- a/www/plugins/facteur/lang/facteur_sk.php +++ b/www/plugins/facteur/lang/facteur_sk.php @@ -3,15 +3,17 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/facteur?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // C 'config_info_enregistree' => 'Nastavenia PoÅ¡tára sa uložili správne', - 'configuration_adresse_envoi' => 'Nastavenie adresy odosielateľa', + 'configuration_adresse_envoi' => 'Nastavenie adresy odosielateľa', # MODIF 'configuration_facteur' => 'PoÅ¡tár', - 'configuration_mailer' => 'Nastavenia PoÅ¡tára', + 'configuration_mailer' => 'Nastavenia PoÅ¡tára', # MODIF 'configuration_smtp' => 'Výber spôsobu odoslania e-mailu', 'configuration_smtp_descriptif' => 'Ak si nie ste istý, zvoľte si funkciu mail jazyka PHP.', 'corps_email_de_test' => 'Toto je testovací e-mail s diakritikou', @@ -30,8 +32,9 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_adresse_envoi_nom' => '(Obchodné) meno:', 'facteur_bcc' => 'Skrytá kópia (BCC):', 'facteur_cc' => 'Kópia (CC):', - 'facteur_copies' => 'Kópie:', + 'facteur_copies' => 'Kópie:', # MODIF 'facteur_copies_descriptif' => 'Kópia e-mailu sa poÅ¡le na zadané adresy. Na jednu adresu bude odoslaná bežná kópia a/lebo skrytá kópia.', + 'facteur_email_test' => 'Skúšobný e-mail poslaÅ¥ na adresu:', 'facteur_filtre_accents' => 'Diakritiku meniÅ¥ na entity html (užitočné najmä pre Hotmail).', 'facteur_filtre_css' => 'ZmeniÅ¥ Å¡týly medzi a  na "in-line" Å¡týly, užitočné pre webmaily, lebo in-line Å¡týly majú prednosÅ¥ pred externými.', 'facteur_filtre_images' => 'Do e-mailov pridávaÅ¥ obrázky, na ktoré sa v nich odkazuje', @@ -46,17 +49,17 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_smtp_port' => 'Port:', 'facteur_smtp_secure' => 'Zabezpečené pripojenie:', 'facteur_smtp_secure_non' => 'nie', - 'facteur_smtp_secure_ssl' => 'SSL', - 'facteur_smtp_secure_tls' => 'TLS', - 'facteur_smtp_sender' => 'Vypísanie chýb (nepovinné)', - 'facteur_smtp_sender_descriptif' => 'Zadané v hlavičke návratnej e-mailovej adresy pri chybe (alebo Return-Path) a pri jej odoslaní metódou SMTP je aj adresou odosielateľa.', + 'facteur_smtp_secure_ssl' => 'SSL (zastarané)', + 'facteur_smtp_secure_tls' => 'TLS (odporúča sa)', + 'facteur_smtp_sender' => 'Vypísanie chýb (nepovinné)', # MODIF + 'facteur_smtp_sender_descriptif' => 'Zadané v hlavičke návratnej e-mailovej adresy pri chybe (alebo Return-Path) a pri jej odoslaní metódou SMTP je aj adresou odosielateľa.', # MODIF 'facteur_smtp_username' => 'Používateľské meno:', // M 'message_identite_email' => 'Nastavenia zásuvného modulu "PoÅ¡tár" predvolili túto e-mailovú adresu na posielanie e-mailov.', // N - 'note_test_configuration' => 'E-mail bude odoslaný na uvedenú adresu (alebo webmasterovi).', + 'note_test_configuration' => 'E-mail bude odoslaný na túto adresu.', // P 'personnaliser' => 'PrispôsobiÅ¥ si tieto nastavenia', @@ -67,7 +70,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // U 'utiliser_mail' => 'PoužívaÅ¥ funkciu mail z PHP', - 'utiliser_reglages_site' => 'PoužiÅ¥ nastavenia stránky v SPIPe: zobrazovaný názov je názov stránky a e-mailová adresa je e-mail webmastera', + 'utiliser_reglages_site' => 'PoužiÅ¥ nastavenia stránky v SPIPe: zobrazovaný názov je názov stránky a e-mailová adresa je e-mail webmastera', # MODIF 'utiliser_smtp' => 'PoužívaÅ¥ SMTP', // V @@ -75,5 +78,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'version_html' => 'HTML verzia.', 'version_texte' => 'Textová verzia.' ); - -?> diff --git a/www/plugins/facteur/lang/paquet-facteur.xml b/www/plugins/facteur/lang/paquet-facteur.xml index 0902008c..b5bf31c9 100644 --- a/www/plugins/facteur/lang/paquet-facteur.xml +++ b/www/plugins/facteur/lang/paquet-facteur.xml @@ -14,6 +14,9 @@ + + + diff --git a/www/plugins/facteur/lang/paquet-facteur_de.php b/www/plugins/facteur/lang/paquet-facteur_de.php index 1ccd0773..ff1d7060 100755 --- a/www/plugins/facteur/lang/paquet-facteur_de.php +++ b/www/plugins/facteur/lang/paquet-facteur_de.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-facteur?lang_cible=de // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_nom' => 'Briefräger', 'facteur_slogan' => 'Er befördert ihre Emails' ); - -?> diff --git a/www/plugins/facteur/lang/paquet-facteur_en.php b/www/plugins/facteur/lang/paquet-facteur_en.php index b354c28b..055126a3 100644 --- a/www/plugins/facteur/lang/paquet-facteur_en.php +++ b/www/plugins/facteur/lang/paquet-facteur_en.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-facteur?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_nom' => 'Postman', 'facteur_slogan' => 'He delivers emails' ); - -?> diff --git a/www/plugins/facteur/lang/paquet-facteur_es.php b/www/plugins/facteur/lang/paquet-facteur_es.php index ffa1ba10..bb0d6ad8 100644 --- a/www/plugins/facteur/lang/paquet-facteur_es.php +++ b/www/plugins/facteur/lang/paquet-facteur_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-facteur?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_nom' => 'Cartero', 'facteur_slogan' => 'Distribuye sus correos electrónicos' ); - -?> diff --git a/www/plugins/facteur/lang/paquet-facteur_fr.php b/www/plugins/facteur/lang/paquet-facteur_fr.php index 72225acd..b903c882 100644 --- a/www/plugins/facteur/lang/paquet-facteur_fr.php +++ b/www/plugins/facteur/lang/paquet-facteur_fr.php @@ -1,7 +1,9 @@ 'Facteur', 'facteur_slogan' => 'Il distribue vos courriels' ); - -?> diff --git a/www/plugins/facteur/lang/paquet-facteur_fr_tu.php b/www/plugins/facteur/lang/paquet-facteur_fr_tu.php index 5e1b76a3..e9eef9f5 100644 --- a/www/plugins/facteur/lang/paquet-facteur_fr_tu.php +++ b/www/plugins/facteur/lang/paquet-facteur_fr_tu.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-facteur?lang_cible=fr_tu // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_nom' => 'Facteur', 'facteur_slogan' => 'Il distribue tes courriels' ); - -?> diff --git a/www/plugins/facteur/lang/paquet-facteur_nl.php b/www/plugins/facteur/lang/paquet-facteur_nl.php index 724cb174..2630334d 100644 --- a/www/plugins/facteur/lang/paquet-facteur_nl.php +++ b/www/plugins/facteur/lang/paquet-facteur_nl.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-facteur?lang_cible=nl // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_nom' => 'Postbode', 'facteur_slogan' => 'Hij verzendt uw mail' ); - -?> diff --git a/www/plugins/facteur/lang/paquet-facteur_pt_br.php b/www/plugins/facteur/lang/paquet-facteur_pt_br.php new file mode 100644 index 00000000..f06b414a --- /dev/null +++ b/www/plugins/facteur/lang/paquet-facteur_pt_br.php @@ -0,0 +1,16 @@ + 'O Carteiro cuida da distribuição de e-mails no formato HTML, texto ou misto; via SMTP ou não', + 'facteur_nom' => 'Carteiro', + 'facteur_slogan' => 'Distribui os seus e-mails' +); diff --git a/www/plugins/facteur/lang/paquet-facteur_ru.php b/www/plugins/facteur/lang/paquet-facteur_ru.php index 3c675e73..fd10f5d8 100644 --- a/www/plugins/facteur/lang/paquet-facteur_ru.php +++ b/www/plugins/facteur/lang/paquet-facteur_ru.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-facteur?lang_cible=ru // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_nom' => 'Почтальон (Facteur)', 'facteur_slogan' => 'Он отправляет письма' ); - -?> diff --git a/www/plugins/facteur/lang/paquet-facteur_sk.php b/www/plugins/facteur/lang/paquet-facteur_sk.php index de98cc7e..6bc4580d 100644 --- a/www/plugins/facteur/lang/paquet-facteur_sk.php +++ b/www/plugins/facteur/lang/paquet-facteur_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-facteur?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'facteur_nom' => 'PoÅ¡tár', 'facteur_slogan' => 'Posiela vaÅ¡u poÅ¡tu' ); - -?> diff --git a/www/plugins/facteur/paquet.xml b/www/plugins/facteur/paquet.xml index 72ff96a1..98516a66 100644 --- a/www/plugins/facteur/paquet.xml +++ b/www/plugins/facteur/paquet.xml @@ -1,22 +1,22 @@ - +> + Facteur - + Collectif SPIP - + - - + + - \ No newline at end of file + diff --git a/www/plugins/facteur/phpmailer-php5/LICENSE b/www/plugins/facteur/phpmailer-php5/LICENSE index 03851a33..8e0763d1 100755 --- a/www/plugins/facteur/phpmailer-php5/LICENSE +++ b/www/plugins/facteur/phpmailer-php5/LICENSE @@ -1,504 +1,504 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/www/plugins/facteur/phpmailer-php5/PHPMailerAutoload.php b/www/plugins/facteur/phpmailer-php5/PHPMailerAutoload.php new file mode 100644 index 00000000..eaa2e303 --- /dev/null +++ b/www/plugins/facteur/phpmailer-php5/PHPMailerAutoload.php @@ -0,0 +1,49 @@ + + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2012 - 2014 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 + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** + * PHPMailer SPL autoloader. + * @param string $classname The name of the class to load + */ +function PHPMailerAutoload($classname) +{ + //Can't use __DIR__ as it's only in PHP 5.3+ + $filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php'; + if (is_readable($filename)) { + require $filename; + } +} + +if (version_compare(PHP_VERSION, '5.1.2', '>=')) { + //SPL autoloading was introduced in PHP 5.1.2 + if (version_compare(PHP_VERSION, '5.3.0', '>=')) { + spl_autoload_register('PHPMailerAutoload', true, true); + } else { + spl_autoload_register('PHPMailerAutoload'); + } +} else { + /** + * Fall back to traditional autoload for old PHP versions + * @param string $classname The name of the class to load + */ + function __autoload($classname) + { + PHPMailerAutoload($classname); + } +} diff --git a/www/plugins/facteur/phpmailer-php5/README b/www/plugins/facteur/phpmailer-php5/README deleted file mode 100755 index 3670fb62..00000000 --- a/www/plugins/facteur/phpmailer-php5/README +++ /dev/null @@ -1,178 +0,0 @@ -/******************************************************************* -* The http://phpmailer.codeworxtech.com/ website now carries a few * -* advertisements through the Google Adsense network. Please visit * -* the advertiser sites and help us offset some of our costs. * -* Thanks .... * -********************************************************************/ - -PHPMailer -Full Featured Email Transfer Class for PHP -========================================== - -Version 2.1 (June 04 2008) - -With this release, we are announcing that the development of PHPMailer for PHP5 -will be our focus from this date on. We have implemented all the enhancements -and fixes from the latest release of PHPMailer for PHP4. - -Far more important, though, is that this release of PHPMailer (v2.1) is -fully tested with E_STRICT error checking enabled. - -** NOTE: WE HAVE A NEW LANGUAGE VARIABLE FOR DIGITALLY SIGNED S/MIME EMAILS. - IF YOU CAN HELP WITH LANGUAGES OTHER THAN ENGLISH AND SPANISH, IT WOULD BE - APPRECIATED. - -We have now added S/MIME functionality (ability to digitally sign emails). -BIG THANKS TO "sergiocambra" for posting this patch back in November 2007. -The "Signed Emails" functionality adds the Sign method to pass the private key -filename and the password to read it, and then email will be sent with -content-type multipart/signed and with the digital signature attached. - -A quick note on E_STRICT: - -- In about half the test environments the development version was subjected - to, an error was thrown for the date() functions (used at line 1565 and 1569). - This is NOT a PHPMailer error, it is the result of an incorrectly configured - PHP5 installation. The fix is to modify your 'php.ini' file and include the - date.timezone = America/New York - directive, (for your own server timezone) -- If you do get this error, and are unable to access your php.ini file, there is - a workaround. In your PHP script, add - date_default_timezone_set('America/Toronto'); - - * do NOT try to use - $myVar = date_default_timezone_get(); - as a test, it will throw an error. - -We have also included more example files to show the use of "sendmail", "mail()", -"smtp", and "gmail". - -We are also looking for more programmers to join the volunteer development team. -If you have an interest in this, please let us know. - -Enjoy! - - -Version 2.1.0beta1 & beta2 - -please note, this is BETA software -** DO NOT USE THIS IN PRODUCTION OR LIVE PROJECTS -INTENDED STRICTLY FOR TESTING - -** NOTE: - -As of November 2007, PHPMailer has a new project team headed by industry -veteran Andy Prevost (codeworxtech). The first release in more than two -years will focus on fixes, adding ease-of-use enhancements, provide -basic compatibility with PHP4 and PHP5 using PHP5 backwards compatibility -features. A new release is planned before year-end 2007 that will provide -full compatiblity with PHP4 and PHP5, as well as more bug fixes. - -We are looking for project developers to assist in restoring PHPMailer to -its leadership position. Our goals are to simplify use of PHPMailer, provide -good documentation and examples, and retain backward compatibility to level -1.7.3 standards. - -If you are interested in helping out, visit http://sourceforge.net/phpmailer -and indicate your interest. - -** - -http://phpmailer.sourceforge.net/ - -This software is licenced under the LGPL. Please read LICENSE for information on the -software availability and distribution. - -Class Features: -- Send emails with multiple TOs, CCs, BCCs and REPLY-TOs -- Redundant SMTP servers -- Multipart/alternative emails for mail clients that do not read HTML email -- Support for 8bit, base64, binary, and quoted-printable encoding -- Uses the same methods as the very popular AspEmail active server (COM) component -- SMTP authentication -- Native language support -- Word wrap, and more! - -Why you might need it: - -Many PHP developers utilize email in their code. The only PHP function -that supports this is the mail() function. However, it does not expose -any of the popular features that many email clients use nowadays like -HTML-based emails and attachments. There are two proprietary -development tools out there that have all the functionality built into -easy to use classes: AspEmail(tm) and AspMail. Both of these -programs are COM components only available on Windows. They are also a -little pricey for smaller projects. - -Since I do Linux development I’ve missed these tools for my PHP coding. -So I built a version myself that implements the same methods (object -calls) that the Windows-based components do. It is open source and the -LGPL license allows you to place the class in your proprietary PHP -projects. - - -Installation: - -Copy class.phpmailer.php into your php.ini include_path. If you are -using the SMTP mailer then place class.smtp.php in your path as well. -In the language directory you will find several files like -phpmailer.lang-en.php. If you look right before the .php extension -that there are two letters. These represent the language type of the -translation file. For instance "en" is the English file and "br" is -the Portuguese file. Chose the file that best fits with your language -and place it in the PHP include path. If your language is English -then you have nothing more to do. If it is a different language then -you must point PHPMailer to the correct translation. To do this, call -the PHPMailer SetLanguage method like so: - -// To load the Portuguese version -$mail->SetLanguage("br", "/optional/path/to/language/directory/"); - -That's it. You should now be ready to use PHPMailer! - - -A Simple Example: - -IsSMTP(); // set mailer to use SMTP -$mail->Host = "smtp1.example.com;smtp2.example.com"; // specify main and backup server -$mail->SMTPAuth = true; // turn on SMTP authentication -$mail->Username = "jswan"; // SMTP username -$mail->Password = "secret"; // SMTP password - -$mail->From = "from@example.com"; -$mail->FromName = "Mailer"; -$mail->AddAddress("josh@example.net", "Josh Adams"); -$mail->AddAddress("ellen@example.com"); // name is optional -$mail->AddReplyTo("info@example.com", "Information"); - -$mail->WordWrap = 50; // set word wrap to 50 characters -$mail->AddAttachment("/var/tmp/file.tar.gz"); // add attachments -$mail->AddAttachment("/tmp/image.jpg", "new.jpg"); // optional name -$mail->IsHTML(true); // set email format to HTML - -$mail->Subject = "Here is the subject"; -$mail->Body = "This is the HTML message body in bold!"; -$mail->AltBody = "This is the body in plain text for non-HTML mail clients"; - -if(!$mail->Send()) -{ - echo "Message could not be sent.

                  "; - echo "Mailer Error: " . $mail->ErrorInfo; - exit; -} - -echo "Message has been sent"; -?> - -CHANGELOG - -See ChangeLog.txt - -Download: http://sourceforge.net/project/showfiles.php?group_id=26031 - -Andy Prevost diff --git a/www/plugins/facteur/phpmailer-php5/README.md b/www/plugins/facteur/phpmailer-php5/README.md new file mode 100644 index 00000000..0ecfa5dc --- /dev/null +++ b/www/plugins/facteur/phpmailer-php5/README.md @@ -0,0 +1,184 @@ +![PHPMailer](https://raw.github.com/PHPMailer/PHPMailer/master/examples/images/phpmailer.png) + +# PHPMailer - A full-featured email creation and transfer class for PHP + +Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.svg)](https://travis-ci.org/PHPMailer/PHPMailer) +[![Scrutinizer Quality Score](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/badges/quality-score.png?s=3758e21d279becdf847a557a56a3ed16dfec9d5d)](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/) +[![Code Coverage](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/badges/coverage.png?s=3fe6ca5fe8cd2cdf96285756e42932f7ca256962)](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/) + +[![Latest Stable Version](https://poser.pugx.org/phpmailer/phpmailer/v/stable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![Total Downloads](https://poser.pugx.org/phpmailer/phpmailer/downloads)](https://packagist.org/packages/phpmailer/phpmailer) [![Latest Unstable Version](https://poser.pugx.org/phpmailer/phpmailer/v/unstable.svg)](https://packagist.org/packages/phpmailer/phpmailer) [![License](https://poser.pugx.org/phpmailer/phpmailer/license.svg)](https://packagist.org/packages/phpmailer/phpmailer) + +## Class Features + +- Probably the world's most popular code for sending email from PHP! +- Used by many open-source projects: WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla! and many more +- Integrated SMTP support - send without a local mail server +- Send emails with multiple TOs, CCs, BCCs and REPLY-TOs +- Multipart/alternative emails for mail clients that do not read HTML email +- Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings +- SMTP authentication with LOGIN, PLAIN, NTLM, CRAM-MD5 and Google's XOAUTH2 mechanisms over SSL and TLS transports +- Error messages in 47 languages! +- DKIM and S/MIME signing support +- Compatible with PHP 5.0 and later +- Much more! + +## Why you might need it + +Many PHP developers utilize email in their code. The only PHP function that supports this is the mail() function. However, it does not provide any assistance for making use of popular features such as HTML-based emails and attachments. + +Formatting email correctly is surprisingly difficult. There are myriad overlapping RFCs, requiring tight adherence to horribly complicated formatting and encoding rules - the vast majority of code that you'll find online that uses the mail() function directly is just plain wrong! +*Please* don't be tempted to do it yourself - if you don't use PHPMailer, there are many other excellent libraries that you should look at before rolling your own - try SwiftMailer, Zend_Mail, eZcomponents etc. + +The PHP mail() function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD and OS X platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP implementation allows email sending on Windows platforms without a local mail server. + +## License + +This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lgpl-2.1.html) license. Please read LICENSE for information on the +software availability and distribution. + +## Installation & loading + +PHPMailer is available via [Composer/Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), so just add this line to your `composer.json` file: + +```json +"phpmailer/phpmailer": "~5.2" +``` + +or + +```sh +composer require phpmailer/phpmailer +``` + +If you want to use the Gmail XOAUTH2 authentication class, you will also need to add a dependency on the `league/oauth2-client` package. + +Alternatively, copy the contents of the PHPMailer folder into somewhere that's in your PHP `include_path` setting. If you don't speak git or just want a tarball, click the 'zip' button at the top of the page in GitHub. + +If you're not using composer's autoloader, PHPMailer provides an SPL-compatible autoloader, and that is the preferred way of loading the library - just `require '/path/to/PHPMailerAutoload.php';` and everything should work. The autoloader does not throw errors if it can't find classes so it prepends itself to the SPL list, allowing your own (or your framework's) autoloader to catch errors. SPL autoloading was introduced in PHP 5.1.0, so if you are using a version older than that you will need to require/include each class manually. + +PHPMailer does *not* declare a namespace because namespaces were only introduced in PHP 5.3. + +If you want to use Google's XOAUTH2 authentication mechanism, you need to be running at least PHP 5.4, and load the dependencies listed in `composer.json`. + +### Minimal installation + +While installing the entire package manually or with composer is simple, convenient and reliable, you may want to include only vital files in your project. At the very least you will need [class.phpmailer.php](class.phpmailer.php). If you're using SMTP, you'll need [class.smtp.php](class.smtp.php), and if you're using POP-before SMTP, you'll need [class.pop3.php](class.pop3.php). For all of these, we recommend you use [the autoloader](PHPMailerAutoload.php) too as otherwise you will either have to `require` all classes manually or use some other autoloader. You can skip the [language](language/) folder if you're not showing errors to users and can make do with English-only errors. You may need the additional classes in the [extras](extras/) folder if you are using those features, including NTLM authentication and ics generation. If you're using Google XOAUTH2 you will need `class.phpmaileroauth.php` and `class.oauth.php` classes too, as well as the composer dependencies. + +## A Simple Example + +```php +SMTPDebug = 3; // Enable verbose debug output + +$mail->isSMTP(); // Set mailer to use SMTP +$mail->Host = 'smtp1.example.com;smtp2.example.com'; // Specify main and backup SMTP servers +$mail->SMTPAuth = true; // Enable SMTP authentication +$mail->Username = 'user@example.com'; // SMTP username +$mail->Password = 'secret'; // SMTP password +$mail->SMTPSecure = 'tls'; // Enable TLS encryption, `ssl` also accepted +$mail->Port = 587; // TCP port to connect to + +$mail->setFrom('from@example.com', 'Mailer'); +$mail->addAddress('joe@example.net', 'Joe User'); // Add a recipient +$mail->addAddress('ellen@example.com'); // Name is optional +$mail->addReplyTo('info@example.com', 'Information'); +$mail->addCC('cc@example.com'); +$mail->addBCC('bcc@example.com'); + +$mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments +$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name +$mail->isHTML(true); // Set email format to HTML + +$mail->Subject = 'Here is the subject'; +$mail->Body = 'This is the HTML message body in bold!'; +$mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; + +if(!$mail->send()) { + echo 'Message could not be sent.'; + echo 'Mailer Error: ' . $mail->ErrorInfo; +} else { + echo 'Message has been sent'; +} +``` + +You'll find plenty more to play with in the [examples](examples/) folder. + +That's it. You should now be ready to use PHPMailer! + +## Localization +PHPMailer defaults to English, but in the [language](language/) folder you'll find numerous (46 at the time of writing!) translations for PHPMailer error messages that you may encounter. Their filenames contain [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code for the translations, for example `fr` for French. To specify a language, you need to tell PHPMailer which one to use, like this: + +```php +// To load the French version +$mail->setLanguage('fr', '/optional/path/to/language/directory/'); +``` + +We welcome corrections and new languages - if you're looking for corrections to do, run the [phpmailerLangTest.php](test/phpmailerLangTest.php) script in the tests folder and it will show any missing translations. + +## Documentation + +Examples of how to use PHPMailer for common scenarios can be found in the [examples](examples/) folder. If you're looking for a good starting point, we recommend you start with [the gmail example](examples/gmail.phps). + +There are tips and a troubleshooting guide in the [GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki). If you're having trouble, this should be the first place you look as it's the most frequently updated. + +Complete generated API documentation is [available online](http://phpmailer.github.io/PHPMailer/). + +You'll find some basic user-level docs in the [docs](docs/) folder, and you can generate complete API-level documentation using the [generatedocs.sh](docs/generatedocs.sh) shell script in the docs folder, though you'll need to install [PHPDocumentor](http://www.phpdoc.org) first. You may find [the unit tests](test/phpmailerTest.php) a good source of how to do various operations such as encryption. + +If the documentation doesn't cover what you need, search the [many questions on StackOverflow](http://stackoverflow.com/questions/tagged/phpmailer), and before you ask a question about "SMTP Error: Could not connect to SMTP host.", [read the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting). + +## Tests + +There is a PHPUnit test script in the [test](test/) folder. + +Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.svg)](https://travis-ci.org/PHPMailer/PHPMailer) + +If this isn't passing, is there something you can do to help? + +## Contributing + +Please submit bug reports, suggestions and pull requests to the [GitHub issue tracker](https://github.com/PHPMailer/PHPMailer/issues). + +We're particularly interested in fixing edge-cases, expanding test coverage and updating translations. + +With the move to the PHPMailer GitHub organisation, you'll need to update any remote URLs referencing the old GitHub location with a command like this from within your clone: + +```sh +git remote set-url upstream https://github.com/PHPMailer/PHPMailer.git +``` + +Please *don't* use the SourceForge or Google Code projects any more. + +## Sponsorship + +Development time and resources for PHPMailer are provided by [Smartmessages.net](https://info.smartmessages.net/), a powerful email marketing system. + +Smartmessages email marketing + +Other contributions are gladly received, whether in beer 🍺, T-shirts 👕, Amazon wishlist raids, or cold, hard cash 💰. + +## Changelog + +See [changelog](changelog.md). + +## History +- PHPMailer was originally written in 2001 by Brent R. Matzelle as a [SourceForge project](http://sourceforge.net/projects/phpmailer/). +- Marcus Bointon (coolbru on SF) and Andy Prevost (codeworxtech) took over the project in 2004. +- Became an Apache incubator project on Google Code in 2010, managed by Jim Jagielski. +- Marcus created his fork on [GitHub](https://github.com/Synchro/PHPMailer). +- Jim and Marcus decide to join forces and use GitHub as the canonical and official repo for PHPMailer. +- PHPMailer moves to the [PHPMailer organisation](https://github.com/PHPMailer) on GitHub. + +### What's changed since moving from SourceForge? +- Official successor to the SourceForge and Google Code projects. +- Test suite. +- Continuous integration with Travis-CI. +- Composer support. +- Public development. +- Additional languages and language strings. +- CRAM-MD5 authentication support. +- Preserves full repo history of authors, commits and branches from the original SourceForge project. diff --git a/www/plugins/facteur/phpmailer-php5/VERSION b/www/plugins/facteur/phpmailer-php5/VERSION new file mode 100644 index 00000000..ba678f2d --- /dev/null +++ b/www/plugins/facteur/phpmailer-php5/VERSION @@ -0,0 +1 @@ +5.2.14 \ No newline at end of file diff --git a/www/plugins/facteur/phpmailer-php5/changelog.md b/www/plugins/facteur/phpmailer-php5/changelog.md new file mode 100644 index 00000000..486f3289 --- /dev/null +++ b/www/plugins/facteur/phpmailer-php5/changelog.md @@ -0,0 +1,620 @@ +# ChangeLog + +## Version 5.2.14 (Nov 1st 2015) +* Allow addresses with IDN (Internationalized Domain Name) in PHP 5.3+, thanks to @fbonzon +* Allow access to POP3 errors +* Make all POP3 private properties and methods protected +* **SECURITY** Fix vulnerability that allowed email addresses with line breaks (valid in RFC5322) to pass to SMTP, permitting message injection at the SMTP level. Mitigated in both the address validator and in the lower-level SMTP class. Thanks to Takeshi Terada. +* Updated Brazilian Portuguese translations (Thanks to @phelipealves) + +## Version 5.2.13 (Sep 14th 2015) +* Rename internal oauth class to avoid name clashes +* Improve Estonian translations + +## Version 5.2.12 (Sep 1st 2015) +* Fix incorrect composer package dependencies +* Skip existing embedded image `cid`s in `msgHTML` + +## Version 5.2.11 (Aug 31st 2015) +* Don't switch to quoted-printable for long lines if already using base64 +* Fixed Travis-CI config when run on PHP 7 +* Added Google XOAUTH2 authentication mechanism, thanks to @sherryl4george +* Add address parser for RFC822-format addresses +* Update MS Office MIME types +* Don't convert line breaks when using quoted-printable encoding +* Handle MS Exchange returning an invalid empty AUTH-type list in EHLO +* Don't set name or filename properties on MIME parts that don't have one + +## Version 5.2.10 (May 4th 2015) +* Add custom header getter +* Use `application/javascript` for .js attachments +* Improve RFC2821 compliance for timelimits, especially for end-of-data +* Add Azerbaijani translations (Thanks to @mirjalal) +* Minor code cleanup for robustness +* Add Indonesian translations (Thanks to @ceceprawiro) +* Avoid `error_log` Debugoutput naming clash +* Add ability to parse server capabilities in response to EHLO (useful for SendGrid etc) +* Amended default values for WordWrap to match RFC +* Remove html2text converter class (has incompatible license) +* Provide new mechanism for injecting html to text converters +* Improve pointers to docs and support in README +* Add example file upload script +* Refactor and major cleanup of EasyPeasyICS, now a lot more usable +* Make set() method simpler and more reliable +* Add Malay translation (Thanks to @nawawi) +* Add Bulgarian translation (Thanks to @mialy) +* Add Armenian translation (Thanks to Hrayr Grigoryan) +* Add Slovenian translation (Thanks to Klemen TuÅ¡ar) +* More efficient word wrapping +* Add support for S/MIME signing with additional CA certificate (thanks to @IgitBuh) +* Fix incorrect MIME structure when using S/MIME signing and isMail() (#372) +* Improved checks and error messages for missing extensions +* Store and report SMTP errors more consistently +* Add MIME multipart preamble for better Outlook compatibility +* Enable TLS encryption automatically if the server offers it +* Provide detailed errors when individual recipients fail +* Report more errors when connecting +* Add extras classes to composer classmap +* Expose stream_context_create options via new SMTPOptions property +* Automatic encoding switch to quoted-printable if message lines are too long +* Add Korean translation (Thanks to @ChalkPE) +* Provide a pointer to troubleshooting docs on SMTP connection failure + +## Version 5.2.9 (Sept 25th 2014) +* **Important: The autoloader is no longer autoloaded by the PHPMailer class** +* Update html2text from https://github.com/mtibben/html2text +* Improve Arabic translations (Thanks to @tarekdj) +* Consistent handling of connection variables in SMTP and POP3 +* PHPDoc cleanup +* Update composer to use PHPUnit 4.1 +* Pass consistent params to callbacks +* More consistent handling of error states and debug output +* Use property defaults, remove constructors +* Remove unreachable code +* Use older regex validation pattern for troublesome PCRE library versions +* Improve PCRE detection in older PHP versions +* Handle debug output consistently, and always in UTF-8 +* Allow user-defined debug output method via a callable +* msgHTML now converts data URIs to embedded images +* SMTP::getLastReply() will now always be populated +* Improved example code in README +* Ensure long filenames in Content-Disposition are encoded correctly +* Simplify SMTP debug output mechanism, clarify levels with constants +* Add SMTP connection check example +* Simplify examples, don't use mysql* functions + +## Version 5.2.8 (May 14th 2014) +* Increase timeout to match RFC2821 section 4.5.3.2 and thus not fail greetdelays, fixes #104 +* Add timestamps to default debug output +* Add connection events and new level 3 to debug output options +* Chinese language update (Thanks to @binaryoung) +* Allow custom Mailer types (Thanks to @michield) +* Cope with spaces around SMTP host specs +* Fix processing of multiple hosts in connect string +* Added Galician translation (Thanks to @donatorouco) +* Autoloader now prepends +* Docs updates +* Add Latvian translation (Thanks to @eddsstudio) +* Add Belarusian translation (Thanks to @amaksymiuk) +* Make autoloader work better on older PHP versions +* Avoid double-encoding if mbstring is overloading mail() +* Add Portuguese translation (Thanks to @Jonadabe) +* Make quoted-printable encoder respect line ending setting +* Improve Chinese translation (Thanks to @PeterDaveHello) +* Add Georgian translation (Thanks to @akalongman) +* Add Greek translation (Thanks to @lenasterg) +* Fix serverHostname on PHP < 5.3 +* Improve performance of SMTP class +* Implement automatic 7bit downgrade +* Add Vietnamese translation (Thanks to @vinades) +* Improve example images, switch to PNG +* Add Croatian translation (Thanks to @hrvoj3e) +* Remove setting the Return-Path and deprecate the Return-path property - it's just wrong! +* Fix language file loading if CWD has changed (@stephandesouza) +* Add HTML5 email validation pattern +* Improve Turkish translations (Thanks to @yasinaydin) +* Improve Romanian translations (Thanks to @aflorea) +* Check php.ini for path to sendmail/qmail before using default +* Improve Farsi translation (Thanks to @MHM5000) +* Don't use quoted-printable encoding for multipart types +* Add Serbian translation (Thanks to ajevremovic at gmail.com) +* Remove useless PHP5 check +* Use SVG for build status badges +* Store MessageDate on creation +* Better default behaviour for validateAddress + +## Version 5.2.7 (September 12th 2013) +* Add Ukrainian translation from @Krezalis +* Support for do_verp +* Fix bug in CRAM-MD5 AUTH +* Propagate Debugoutput option to SMTP class (@Reblutus) +* Determine MIME type of attachments automatically +* Add cross-platform, multibyte-safe pathinfo replacement (with tests) and use it +* Add a new 'html' Debugoutput type +* Clean up SMTP debug output, remove embedded HTML +* Some small changes in header formatting to improve IETF msglint test results +* Update test_script to use some recently changed features, rename to code_generator +* Generated code actually works! +* Update SyntaxHighlighter +* Major overhaul and cleanup of example code +* New PHPMailer graphic +* msgHTML now uses RFC2392-compliant content ids +* Add line break normalization function and use it in msgHTML +* Don't set unnecessary reply-to addresses +* Make fakesendmail.sh a bit cleaner and safer +* Set a content-transfer-encoding on multiparts (fixes msglint error) +* Fix cid generation in msgHTML (Thanks to @digitalthought) +* Fix handling of multiple SMTP servers (Thanks to @NanoCaiordo) +* SMTP->connect() now supports stream context options (Thanks to @stanislavdavid) +* Add support for iCal event alternatives (Thanks to @reblutus) +* Update to Polish language file (Thanks to Krzysztof Kowalewski) +* Update to Norwegian language file (Thanks to @datagutten) +* Update to Hungarian language file (Thanks to @dominicus-75) +* Add Persian/Farsi translation from @jaii +* Make SMTPDebug property type match type in SMTP class +* Add unit tests for DKIM +* Major refactor of SMTP class +* Reformat to PSR-2 coding standard +* Introduce autoloader +* Allow overriding of SMTP class +* Overhaul of PHPDocs +* Fix broken Q-encoding +* Czech language update (Thanks to @nemelu) +* Removal of excess blank lines in messages +* Added fake POP server and unit tests for POP-before-SMTP + +## Version 5.2.6 (April 11th 2013) +* Reflect move to PHPMailer GitHub organisation at https://github.com/PHPMailer/PHPMailer +* Fix unbumped version numbers +* Update packagist.org with new location +* Clean up Changelog + +## Version 5.2.5 (April 6th 2013) +* First official release after move from Google Code +* Fixes for qmail when sending via mail() +* Merge in changes from Google code 5.2.4 release +* Minor coding standards cleanup in SMTP class +* Improved unit tests, now tests S/MIME signing +* Travis-CI support on GitHub, runs tests with fake SMTP server + +## Version 5.2.4 (February 19, 2013) +* Fix tag and version bug. +* un-deprecate isSMTP(), isMail(), IsSendmail() and isQmail(). +* Numerous translation updates + +## Version 5.2.3 (February 8, 2013) +* Fix issue with older PCREs and ValidateAddress() (Bugz: 124) +* Add CRAM-MD5 authentication, thanks to Elijah madden, https://github.com/okonomiyaki3000 +* Replacement of obsolete Quoted-Printable encoder with a much better implementation +* Composer package definition +* New language added: Hebrew + +## Version 5.2.2 (December 3, 2012) +* Some fixes and syncs from https://github.com/Synchro/PHPMailer +* Add Slovak translation, thanks to Michal Tinka + +## Version 5.2.2-rc2 (November 6, 2012) +* Fix SMTP server rotation (Bugz: 118) +* Allow override of autogen'ed 'Date' header (for Drupal's + og_mailinglist module) +* No whitespace after '-f' option (Bugz: 116) +* Work around potential warning (Bugz: 114) + +## Version 5.2.2-rc1 (September 28, 2012) +* Header encoding works with long lines (Bugz: 93) +* Turkish language update (Bugz: 94) +* undefined $pattern in EncodeQ bug squashed (Bugz: 98) +* use of mail() in safe_mode now works (Bugz: 96) +* ValidateAddress() now 'public static' so people can override the + default and use their own validation scheme. +* ValidateAddress() no longer uses broken FILTER_VALIDATE_EMAIL +* Added in AUTH PLAIN SMTP authentication + +## Version 5.2.2-beta2 (August 17, 2012) +* Fixed Postfix VERP support (Bugz: 92) +* Allow action_function callbacks to pass/use + the From address (passed as final param) +* Prevent inf look for get_lines() (Bugz: 77) +* New public var ($UseSendmailOptions). Only pass sendmail() + options iff we really are using sendmail or something sendmail + compatible. (Bugz: 75) +* default setting for LE returned to "\n" due to popular demand. + +## Version 5.2.2-beta1 (July 13, 2012) +* Expose PreSend() and PostSend() as public methods to allow + for more control if serializing message sending. +* GetSentMIMEMessage() only constructs the message copy when + needed. Save memory. +* Only pass params to mail() if the underlying MTA is + "sendmail" (as defined as "having the string sendmail + in its pathname") [#69] +* Attachments now work with Amazon SES and others [Bugz#70] +* Debug output now sent to stdout (via echo) or error_log [Bugz#5] +* New var: Debugoutput (for above) [Bugz#5] +* SMTP reads now Timeout aware (new var: Timeout=15) [Bugz#71] +* SMTP reads now can have a Timelimit associated with them + (new var: Timelimit=30)[Bugz#71] +* Fix quoting issue associated with charsets +* default setting for LE is now RFC compliant: "\r\n" +* Return-Path can now be user defined (new var: ReturnPath) + (the default is "" which implies no change from previous + behavior, which was to use either From or Sender) [Bugz#46] +* X-Mailer header can now be disabled (by setting to a + whitespace string, eg " ") [Bugz#66] +* Bugz closed: #68, #60, #42, #43, #59, #55, #66, #48, #49, + #52, #31, #41, #5. #70, #69 + +## Version 5.2.1 (January 16, 2012) +* Closed several bugs #5 +* Performance improvements +* MsgHTML() now returns the message as required. +* New method: GetSentMIMEMessage() (returns full copy of sent message) + +## Version 5.2 (July 19, 2011) +* protected MIME body and header +* better DKIM DNS Resource Record support +* better aly handling +* htmlfilter class added to extras +* moved to Apache Extras + +## Version 5.1 (October 20, 2009) +* fixed filename issue with AddStringAttachment (thanks to Tony) +* fixed "SingleTo" property, now works with Senmail, Qmail, and SMTP in + addition to PHP mail() +* added DKIM digital signing functionality, new properties: + - DKIM_domain (sets the domain name) + - DKIM_private (holds DKIM private key) + - DKIM_passphrase (holds your DKIM passphrase) + - DKIM_selector (holds the DKIM "selector") + - DKIM_identity (holds the identifying email address) +* added callback function support + - callback function parameters include: + result, to, cc, bcc, subject and body + - see the test/test_callback.php file for usage. +* added "auto" identity functionality + - can automatically add: + - Return-path (if Sender not set) + - Reply-To (if ReplyTo not set) + - can be disabled: + - $mail->SetFrom('yourname@yourdomain.com','First Last',false); + - or by adding the $mail->Sender and/or $mail->ReplyTo properties + +Note: "auto" identity added to help with emails ending up in spam or junk boxes because of missing headers + +## Version 5.0.2 (May 24, 2009) +* Fix for missing attachments when inline graphics are present +* Fix for missing Cc in header when using SMTP (mail was sent, + but not displayed in header -- Cc receiver only saw email To: + line and no Cc line, but did get the email (To receiver + saw same) + +## Version 5.0.1 (April 05, 2009) +* Temporary fix for missing attachments + +## Version 5.0.0 (April 02, 2009) +With the release of this version, we are initiating a new version numbering +system to differentiate from the PHP4 version of PHPMailer. +Most notable in this release is fully object oriented code. + +### class.smtp.php: +* Refactored class.smtp.php to support new exception handling +* code size reduced from 29.2 Kb to 25.6 Kb +* Removed unnecessary functions from class.smtp.php: + - public function Expand($name) { + - public function Help($keyword="") { + - public function Noop() { + - public function Send($from) { + - public function SendOrMail($from) { + - public function Verify($name) { + +### class.phpmailer.php: +* Refactored class.phpmailer.php with new exception handling +* Changed processing functionality of Sendmail and Qmail so they cannot be + inadvertently used +* removed getFile() function, just became a simple wrapper for + file_get_contents() +* added check for PHP version (will gracefully exit if not at least PHP 5.0) +* enhanced code to check if an attachment source is the same as an embedded or + inline graphic source to eliminate duplicate attachments + +### New /test_script +We have written a test script you can use to test the script as part of your +installation. Once you press submit, the test script will send a multi-mime +email with either the message you type in or an HTML email with an inline +graphic. Two attachments are included in the email (one of the attachments +is also the inline graphic so you can see that only one copy of the graphic +is sent in the email). The test script will also display the functional +script that you can copy/paste to your editor to duplicate the functionality. + +### New examples +All new examples in both basic and advanced modes. Advanced examples show + Exception handling. + +### PHPDocumentator (phpdocs) documentation for PHPMailer version 5.0.0 +All new documentation + +## Version 2.3 (November 06, 2008) +* added Arabic language (many thanks to Bahjat Al Mostafa) +* removed English language from language files and made it a default within + class.phpmailer.php - if no language is found, it will default to use + the english language translation +* fixed public/private declarations +* corrected line 1728, $basedir to $directory +* added $sign_cert_file to avoid improper duplicate use of $sign_key_file +* corrected $this->Hello on line 612 to $this->Helo +* changed default of $LE to "\r\n" to comply with RFC 2822. Can be set by the user + if default is not acceptable +* removed trim() from return results in EncodeQP +* /test and three files it contained are removed from version 2.3 +* fixed phpunit.php for compliance with PHP5 +* changed $this->AltBody = $textMsg; to $this->AltBody = html_entity_decode($textMsg); +* We have removed the /phpdoc from the downloads. All documentation is now on + the http://phpmailer.codeworxtech.com website. + +## Version 2.2.1 () July 19 2008 +* fixed line 1092 in class.smtp.php (my apologies, error on my part) + +## Version 2.2 () July 15 2008 +* Fixed redirect issue (display of UTF-8 in thank you redirect) +* fixed error in getResponse function declaration (class.pop3.php) +* PHPMailer now PHP6 compliant +* fixed line 1092 in class.smtp.php (endless loop from missing = sign) + +## Version 2.1 (Wed, June 04 2008) +NOTE: WE HAVE A NEW LANGUAGE VARIABLE FOR DIGITALLY SIGNED S/MIME EMAILS. IF YOU CAN HELP WITH LANGUAGES OTHER THAN ENGLISH AND SPANISH, IT WOULD BE APPRECIATED. + +* added S/MIME functionality (ability to digitally sign emails) + BIG THANKS TO "sergiocambra" for posting this patch back in November 2007. + The "Signed Emails" functionality adds the Sign method to pass the private key + filename and the password to read it, and then email will be sent with + content-type multipart/signed and with the digital signature attached. +* fully compatible with E_STRICT error level + - Please note: + In about half the test environments this development version was subjected + to, an error was thrown for the date() functions used (line 1565 and 1569). + This is NOT a PHPMailer error, it is the result of an incorrectly configured + PHP5 installation. The fix is to modify your 'php.ini' file and include the + date.timezone = Etc/UTC (or your own zone) + directive, to your own server timezone + - If you do get this error, and are unable to access your php.ini file: + In your PHP script, add + `date_default_timezone_set('Etc/UTC');` + - do not try to use + `$myVar = date_default_timezone_get();` + as a test, it will throw an error. +* added ability to define path (mainly for embedded images) + function `MsgHTML($message,$basedir='')` ... where: + `$basedir` is the fully qualified path +* fixed `MsgHTML()` function: + - Embedded Images where images are specified by `://` will not be altered or embedded +* fixed the return value of SMTP exit code ( pclose ) +* addressed issue of multibyte characters in subject line and truncating +* added ability to have user specified Message ID + (default is still that PHPMailer create a unique Message ID) +* corrected unidentified message type to 'application/octet-stream' +* fixed chunk_split() multibyte issue (thanks to Colin Brown, et al). +* added check for added attachments +* enhanced conversion of HTML to text in MsgHTML (thanks to "brunny") + +## Version 2.1.0beta2 (Sun, Dec 02 2007) +* implemented updated EncodeQP (thanks to coolbru, aka Marcus Bointon) +* finished all testing, all known bugs corrected, enhancements tested + +Note: will NOT work with PHP4. + +Please note, this is BETA software **DO NOT USE THIS IN PRODUCTION OR LIVE PROJECTS; INTENDED STRICTLY FOR TESTING** + +## Version 2.1.0beta1 +Please note, this is BETA software +** DO NOT USE THIS IN PRODUCTION OR LIVE PROJECTS + INTENDED STRICTLY FOR TESTING + +## Version 2.0.0 rc2 (Fri, Nov 16 2007), interim release +* implements new property to control VERP in class.smtp.php + example (requires instantiating class.smtp.php): + $mail->do_verp = true; +* POP-before-SMTP functionality included, thanks to Richard Davey + (see class.pop3.php & pop3_before_smtp_test.php for examples) +* included example showing how to use PHPMailer with GMAIL +* fixed the missing Cc in SendMail() and Mail() + +## Version 2.0.0 rc1 (Thu, Nov 08 2007), interim release +* dramatically simplified using inline graphics ... it's fully automated and requires no user input +* added automatic document type detection for attachments and pictures +* added MsgHTML() function to replace Body tag for HTML emails +* fixed the SendMail security issues (input validation vulnerability) +* enhanced the AddAddresses functionality so that the "Name" portion is used in the email address +* removed the need to use the AltBody method (set from the HTML, or default text used) +* set the PHP Mail() function as the default (still support SendMail, SMTP Mail) +* removed the need to set the IsHTML property (set automatically) +* added Estonian language file by Indrek Päri +* added header injection patch +* added "set" method to permit users to create their own pseudo-properties like 'X-Headers', etc. +* fixed warning message in SMTP get_lines method +* added TLS/SSL SMTP support. +* PHPMailer has been tested with PHP4 (4.4.7) and PHP5 (5.2.7) +* Works with PHP installed as a module or as CGI-PHP +NOTE: will NOT work with PHP5 in E_STRICT error mode + +## Version 1.73 (Sun, Jun 10 2005) +* Fixed denial of service bug: http://www.cybsec.com/vuln/PHPMailer-DOS.pdf +* Now has a total of 20 translations +* Fixed alt attachments bug: http://tinyurl.com/98u9k + +## Version 1.72 (Wed, May 25 2004) +* Added Dutch, Swedish, Czech, Norwegian, and Turkish translations. +* Received: Removed this method because spam filter programs like + SpamAssassin reject this header. +* Fixed error count bug. +* SetLanguage default is now "language/". +* Fixed magic_quotes_runtime bug. + +## Version 1.71 (Tue, Jul 28 2003) +* Made several speed enhancements +* Added German and Italian translation files +* Fixed HELO/AUTH bugs on keep-alive connects +* Now provides an error message if language file does not load +* Fixed attachment EOL bug +* Updated some unclear documentation +* Added additional tests and improved others + +## Version 1.70 (Mon, Jun 20 2003) +* Added SMTP keep-alive support +* Added IsError method for error detection +* Added error message translation support (SetLanguage) +* Refactored many methods to increase library performance +* Hello now sends the newer EHLO message before HELO as per RFC 2821 +* Removed the boundary class and replaced it with GetBoundary +* Removed queue support methods +* New $Hostname variable +* New Message-ID header +* Received header reformat +* Helo variable default changed to $Hostname +* Removed extra spaces in Content-Type definition (#667182) +* Return-Path should be set to Sender when set +* Adds Q or B encoding to headers when necessary +* quoted-encoding should now encode NULs \000 +* Fixed encoding of body/AltBody (#553370) +* Adds "To: undisclosed-recipients:;" when all recipients are hidden (BCC) +* Multiple bug fixes + +## Version 1.65 (Fri, Aug 09 2002) +* Fixed non-visible attachment bug (#585097) for Outlook +* SMTP connections are now closed after each transaction +* Fixed SMTP::Expand return value +* Converted SMTP class documentation to phpDocumentor format + +## Version 1.62 (Wed, Jun 26 2002) +* Fixed multi-attach bug +* Set proper word wrapping +* Reduced memory use with attachments +* Added more debugging +* Changed documentation to phpDocumentor format + +## Version 1.60 (Sat, Mar 30 2002) +* Sendmail pipe and address patch (Christian Holtje) +* Added embedded image and read confirmation support (A. Ognio) +* Added unit tests +* Added SMTP timeout support (*nix only) +* Added possibly temporary PluginDir variable for SMTP class +* Added LE message line ending variable +* Refactored boundary and attachment code +* Eliminated SMTP class warnings +* Added SendToQueue method for future queuing support + +## Version 1.54 (Wed, Dec 19 2001) +* Add some queuing support code +* Fixed a pesky multi/alt bug +* Messages are no longer forced to have "To" addresses + +## Version 1.50 (Thu, Nov 08 2001) +* Fix extra lines when not using SMTP mailer +* Set WordWrap variable to int with a zero default + +## Version 1.47 (Tue, Oct 16 2001) +* Fixed Received header code format +* Fixed AltBody order error +* Fixed alternate port warning + +## Version 1.45 (Tue, Sep 25 2001) +* Added enhanced SMTP debug support +* Added support for multiple ports on SMTP +* Added Received header for tracing +* Fixed AddStringAttachment encoding +* Fixed possible header name quote bug +* Fixed wordwrap() trim bug +* Couple other small bug fixes + +## Version 1.41 (Wed, Aug 22 2001) +* Fixed AltBody bug w/o attachments +* Fixed rfc_date() for certain mail servers + +## Version 1.40 (Sun, Aug 12 2001) +* Added multipart/alternative support (AltBody) +* Documentation update +* Fixed bug in Mercury MTA + +## Version 1.29 (Fri, Aug 03 2001) +* Added AddStringAttachment() method +* Added SMTP authentication support + +## Version 1.28 (Mon, Jul 30 2001) +* Fixed a typo in SMTP class +* Fixed header issue with Imail (win32) SMTP server +* Made fopen() calls for attachments use "rb" to fix win32 error + +## Version 1.25 (Mon, Jul 02 2001) +* Added RFC 822 date fix (Patrice) +* Added improved error handling by adding a $ErrorInfo variable +* Removed MailerDebug variable (obsolete with new error handler) + +## Version 1.20 (Mon, Jun 25 2001) +* Added quoted-printable encoding (Patrice) +* Set Version as public and removed PrintVersion() +* Changed phpdoc to only display public variables and methods + +## Version 1.19 (Thu, Jun 21 2001) +* Fixed MS Mail header bug +* Added fix for Bcc problem with mail(). *Does not work on Win32* + (See PHP bug report: http://www.php.net/bugs.php?id=11616) +* mail() no longer passes a fifth parameter when not needed + +## Version 1.15 (Fri, Jun 15 2001) +Note: these changes contributed by Patrice Fournier +* Changed all remaining \n to \r\n +* Bcc: header no longer written to message except + when sent directly to sendmail +* Added a small message to non-MIME compliant mail reader +* Added Sender variable to change the Sender email + used in -f for sendmail/mail and in 'MAIL FROM' for smtp mode +* Changed boundary setting to a place it will be set only once +* Removed transfer encoding for whole message when using multipart +* Message body now uses Encoding in multipart messages +* Can set encoding and type to attachments 7bit, 8bit + and binary attachment are sent as is, base64 are encoded +* Can set Encoding to base64 to send 8 bits body + through 7 bits servers + +## Version 1.10 (Tue, Jun 12 2001) +* Fixed win32 mail header bug (printed out headers in message body) + +## Version 1.09 (Fri, Jun 08 2001) +* Changed date header to work with Netscape mail programs +* Altered phpdoc documentation + +## Version 1.08 (Tue, Jun 05 2001) +* Added enhanced error-checking +* Added phpdoc documentation to source + +## Version 1.06 (Fri, Jun 01 2001) +* Added optional name for file attachments + +## Version 1.05 (Tue, May 29 2001) +* Code cleanup +* Eliminated sendmail header warning message +* Fixed possible SMTP error + +## Version 1.03 (Thu, May 24 2001) +* Fixed problem where qmail sends out duplicate messages + +## Version 1.02 (Wed, May 23 2001) +* Added multiple recipient and attachment Clear* methods +* Added Sendmail public variable +* Fixed problem with loading SMTP library multiple times + +## Version 0.98 (Tue, May 22 2001) +* Fixed problem with redundant mail hosts sending out multiple messages +* Added additional error handler code +* Added AddCustomHeader() function +* Added support for Microsoft mail client headers (affects priority) +* Fixed small bug with Mailer variable +* Added PrintVersion() function + +## Version 0.92 (Tue, May 15 2001) +* Changed file names to class.phpmailer.php and class.smtp.php to match + current PHP class trend. +* Fixed problem where body not being printed when a message is attached +* Several small bug fixes + +## Version 0.90 (Tue, April 17 2001) +* Initial public release diff --git a/www/plugins/facteur/phpmailer-php5/class.phpmailer.php b/www/plugins/facteur/phpmailer-php5/class.phpmailer.php index 65baf42c..e4dd00bf 100755 --- a/www/plugins/facteur/phpmailer-php5/class.phpmailer.php +++ b/www/plugins/facteur/phpmailer-php5/class.phpmailer.php @@ -1,2320 +1,3883 @@ + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2012 - 2014 Marcus Bointon + * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost - * @version $Id: class.phpmailer.php 447 2009-05-25 01:36:38Z codeworxtech $ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. */ -if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n"); - -class PHPMailer { - - ///////////////////////////////////////////////// - // PROPERTIES, PUBLIC - ///////////////////////////////////////////////// - - /** - * Email priority (1 = High, 3 = Normal, 5 = low). - * @var int - */ - public $Priority = 3; - - /** - * Sets the CharSet of the message. - * @var string - */ - public $CharSet = 'iso-8859-1'; - - /** - * Sets the Content-type of the message. - * @var string - */ - public $ContentType = 'text/plain'; - - /** - * Sets the Encoding of the message. Options for this are - * "8bit", "7bit", "binary", "base64", and "quoted-printable". - * @var string - */ - public $Encoding = '8bit'; - - /** - * Holds the most recent mailer error message. - * @var string - */ - public $ErrorInfo = ''; - - /** - * Sets the From email address for the message. - * @var string - */ - public $From = 'root@localhost'; - - /** - * Sets the From name of the message. - * @var string - */ - public $FromName = 'Root User'; - - /** - * Sets the Sender email (Return-Path) of the message. If not empty, - * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. - * @var string - */ - public $Sender = ''; - - /** - * Sets the Subject of the message. - * @var string - */ - public $Subject = ''; - - /** - * Sets the Body of the message. This can be either an HTML or text body. - * If HTML then run IsHTML(true). - * @var string - */ - public $Body = ''; - - /** - * Sets the text-only body of the message. This automatically sets the - * email to multipart/alternative. This body can be read by mail - * clients that do not have HTML email capability such as mutt. Clients - * that can read HTML will view the normal Body. - * @var string - */ - public $AltBody = ''; - - /** - * Sets word wrapping on the body of the message to a given number of - * characters. - * @var int - */ - public $WordWrap = 0; - - /** - * Method to send mail: ("mail", "sendmail", or "smtp"). - * @var string - */ - public $Mailer = 'mail'; - - /** - * Sets the path of the sendmail program. - * @var string - */ - public $Sendmail = '/usr/sbin/sendmail'; - - /** - * Path to PHPMailer plugins. Useful if the SMTP class - * is in a different directory than the PHP include path. - * @var string - */ - public $PluginDir = ''; - - /** - * Sets the email address that a reading confirmation will be sent. - * @var string - */ - public $ConfirmReadingTo = ''; - - /** - * Sets the hostname to use in Message-Id and Received headers - * and as default HELO string. If empty, the value returned - * by SERVER_NAME is used or 'localhost.localdomain'. - * @var string - */ - public $Hostname = ''; - - /** - * Sets the message ID to be used in the Message-Id header. - * If empty, a unique id will be generated. - * @var string - */ - public $MessageID = ''; - - ///////////////////////////////////////////////// - // PROPERTIES FOR SMTP - ///////////////////////////////////////////////// - - /** - * Sets the SMTP hosts. All hosts must be separated by a - * semicolon. You can also specify a different port - * for each host by using this format: [hostname:port] - * (e.g. "smtp1.example.com:25;smtp2.example.com"). - * Hosts will be tried in order. - * @var string - */ - public $Host = 'localhost'; - - /** - * Sets the default SMTP server port. - * @var int - */ - public $Port = 25; - - /** - * Sets the SMTP HELO of the message (Default is $Hostname). - * @var string - */ - public $Helo = ''; - - /** - * Sets connection prefix. - * Options are "", "ssl" or "tls" - * @var string - */ - public $SMTPSecure = ''; - - /** - * Sets SMTP authentication. Utilizes the Username and Password variables. - * @var bool - */ - public $SMTPAuth = false; - - /** - * Sets SMTP username. - * @var string - */ - public $Username = ''; - - /** - * Sets SMTP password. - * @var string - */ - public $Password = ''; - - /** - * Sets the SMTP server timeout in seconds. - * This function will not work with the win32 version. - * @var int - */ - public $Timeout = 10; - - /** - * Sets SMTP class debugging on or off. - * @var bool - */ - public $SMTPDebug = false; - - /** - * Prevents the SMTP connection from being closed after each mail - * sending. If this is set to true then to close the connection - * requires an explicit call to SmtpClose(). - * @var bool - */ - public $SMTPKeepAlive = false; - - /** - * Provides the ability to have the TO field process individual - * emails, instead of sending to entire TO addresses - * @var bool - */ - public $SingleTo = false; - - /** - * If SingleTo is true, this provides the array to hold the email addresses - * @var bool - */ - public $SingleToArray = array(); - - /** - * Provides the ability to change the line ending - * @var string - */ - public $LE = "\n"; - - /** - * Used with DKIM DNS Resource Record - * @var string - */ - public $DKIM_selector = 'phpmailer'; - - /** - * Used with DKIM DNS Resource Record - * optional, in format of email address 'you@yourdomain.com' - * @var string - */ - public $DKIM_identity = ''; - - /** - * Used with DKIM DNS Resource Record - * optional, in format of email address 'you@yourdomain.com' - * @var string - */ - public $DKIM_domain = ''; - - /** - * Used with DKIM DNS Resource Record - * optional, in format of email address 'you@yourdomain.com' - * @var string - */ - public $DKIM_private = ''; - - /** - * Callback Action function name - * the function that handles the result of the send email action. Parameters: - * bool $result result of the send action - * string $to email address of the recipient - * string $cc cc email addresses - * string $bcc bcc email addresses - * string $subject the subject - * string $body the email body - * @var string - */ - public $action_function = ''; //'callbackAction'; - - /** - * Sets the PHPMailer Version number - * @var string - */ - public $Version = '5.1'; - - ///////////////////////////////////////////////// - // PROPERTIES, PRIVATE AND PROTECTED - ///////////////////////////////////////////////// - - private $smtp = NULL; - private $to = array(); - private $cc = array(); - private $bcc = array(); - private $ReplyTo = array(); - private $all_recipients = array(); - private $attachment = array(); - private $CustomHeader = array(); - private $message_type = ''; - private $boundary = array(); - protected $language = array(); - private $error_count = 0; - private $sign_cert_file = ""; - private $sign_key_file = ""; - private $sign_key_pass = ""; - private $exceptions = false; - - ///////////////////////////////////////////////// - // CONSTANTS - ///////////////////////////////////////////////// - - const STOP_MESSAGE = 0; // message only, continue processing - const STOP_CONTINUE = 1; // message?, likely ok to continue processing - const STOP_CRITICAL = 2; // message, plus full stop, critical error reached - - ///////////////////////////////////////////////// - // METHODS, VARIABLES - ///////////////////////////////////////////////// - - /** - * Constructor - * @param boolean $exceptions Should we throw external exceptions? - */ - public function __construct($exceptions = false) { - $this->exceptions = ($exceptions == true); - } - - /** - * Sets message type to HTML. - * @param bool $ishtml - * @return void - */ - public function IsHTML($ishtml = true) { - if ($ishtml) { - $this->ContentType = 'text/html'; - } else { - $this->ContentType = 'text/plain'; - } - } - - /** - * Sets Mailer to send message using SMTP. - * @return void - */ - public function IsSMTP() { - $this->Mailer = 'smtp'; - } - - /** - * Sets Mailer to send message using PHP mail() function. - * @return void - */ - public function IsMail() { - $this->Mailer = 'mail'; - } - - /** - * Sets Mailer to send message using the $Sendmail program. - * @return void - */ - public function IsSendmail() { - if (!stristr(ini_get('sendmail_path'), 'sendmail')) { - $this->Sendmail = '/var/qmail/bin/sendmail'; - } - $this->Mailer = 'sendmail'; - } - - /** - * Sets Mailer to send message using the qmail MTA. - * @return void - */ - public function IsQmail() { - if (stristr(ini_get('sendmail_path'), 'qmail')) { - $this->Sendmail = '/var/qmail/bin/sendmail'; - } - $this->Mailer = 'sendmail'; - } - - ///////////////////////////////////////////////// - // METHODS, RECIPIENTS - ///////////////////////////////////////////////// - - /** - * Adds a "To" address. - * @param string $address - * @param string $name - * @return boolean true on success, false if address already used - */ - public function AddAddress($address, $name = '') { - return $this->AddAnAddress('to', $address, $name); - } - - /** - * Adds a "Cc" address. - * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer. - * @param string $address - * @param string $name - * @return boolean true on success, false if address already used - */ - public function AddCC($address, $name = '') { - return $this->AddAnAddress('cc', $address, $name); - } - - /** - * Adds a "Bcc" address. - * Note: this function works with the SMTP mailer on win32, not with the "mail" mailer. - * @param string $address - * @param string $name - * @return boolean true on success, false if address already used - */ - public function AddBCC($address, $name = '') { - return $this->AddAnAddress('bcc', $address, $name); - } - - /** - * Adds a "Reply-to" address. - * @param string $address - * @param string $name - * @return boolean - */ - public function AddReplyTo($address, $name = '') { - return $this->AddAnAddress('ReplyTo', $address, $name); - } - - /** - * Adds an address to one of the recipient arrays - * Addresses that have been added already return false, but do not throw exceptions - * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo' - * @param string $address The email address to send to - * @param string $name - * @return boolean true on success, false if address already used or invalid in some way - * @access private - */ - private function AddAnAddress($kind, $address, $name = '') { - if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) { - echo 'Invalid recipient array: ' . kind; - return false; - } - $address = trim($address); - $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim - if (!self::ValidateAddress($address)) { - $this->SetError($this->Lang('invalid_address').': '. $address); - if ($this->exceptions) { - throw new phpmailerException($this->Lang('invalid_address').': '.$address); - } - echo $this->Lang('invalid_address').': '.$address; - return false; - } - if ($kind != 'ReplyTo') { - if (!isset($this->all_recipients[strtolower($address)])) { - array_push($this->$kind, array($address, $name)); - $this->all_recipients[strtolower($address)] = true; - return true; - } - } else { - if (!array_key_exists(strtolower($address), $this->ReplyTo)) { - $this->ReplyTo[strtolower($address)] = array($address, $name); - return true; - } - } - return false; -} - /** - * Set the From and FromName properties - * @param string $address - * @param string $name - * @return boolean + * PHPMailer - PHP email creation and transport class. + * @package PHPMailer + * @author Marcus Bointon (Synchro/coolbru) + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) */ - public function SetFrom($address, $name = '',$auto=1) { - $address = trim($address); - $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim - if (!self::ValidateAddress($address)) { - $this->SetError($this->Lang('invalid_address').': '. $address); - if ($this->exceptions) { - throw new phpmailerException($this->Lang('invalid_address').': '.$address); - } - echo $this->Lang('invalid_address').': '.$address; - return false; - } - $this->From = $address; - $this->FromName = $name; - if ($auto) { - if (empty($this->ReplyTo)) { - $this->AddAnAddress('ReplyTo', $address, $name); - } - if (empty($this->Sender)) { - $this->Sender = $address; - } - } - return true; - } - - /** - * Check that a string looks roughly like an email address should - * Static so it can be used without instantiation - * Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator - * Conforms approximately to RFC2822 - * @link http://www.hexillion.com/samples/#Regex Original pattern found here - * @param string $address The email address to check - * @return boolean - * @static - * @access public - */ - public static function ValidateAddress($address) { - if (function_exists('filter_var')) { //Introduced in PHP 5.2 - if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) { +class PHPMailer +{ + /** + * The PHPMailer Version number. + * @var string + */ + public $Version = '5.2.14'; + + /** + * Email priority. + * Options: null (default), 1 = High, 3 = Normal, 5 = low. + * When null, the header is not set at all. + * @var integer + */ + public $Priority = null; + + /** + * The character set of the message. + * @var string + */ + public $CharSet = 'iso-8859-1'; + + /** + * The MIME Content-type of the message. + * @var string + */ + public $ContentType = 'text/plain'; + + /** + * The message encoding. + * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable". + * @var string + */ + public $Encoding = '8bit'; + + /** + * Holds the most recent mailer error message. + * @var string + */ + public $ErrorInfo = ''; + + /** + * The From email address for the message. + * @var string + */ + public $From = 'root@localhost'; + + /** + * The From name of the message. + * @var string + */ + public $FromName = 'Root User'; + + /** + * The Sender email (Return-Path) of the message. + * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. + * @var string + */ + public $Sender = ''; + + /** + * The Return-Path of the message. + * If empty, it will be set to either From or Sender. + * @var string + * @deprecated Email senders should never set a return-path header; + * it's the receiver's job (RFC5321 section 4.4), so this no longer does anything. + * @link https://tools.ietf.org/html/rfc5321#section-4.4 RFC5321 reference + */ + public $ReturnPath = ''; + + /** + * The Subject of the message. + * @var string + */ + public $Subject = ''; + + /** + * An HTML or plain text message body. + * If HTML then call isHTML(true). + * @var string + */ + public $Body = ''; + + /** + * The plain-text message body. + * This body can be read by mail clients that do not have HTML email + * capability such as mutt & Eudora. + * Clients that can read HTML will view the normal Body. + * @var string + */ + public $AltBody = ''; + + /** + * An iCal message part body. + * Only supported in simple alt or alt_inline message types + * To generate iCal events, use the bundled extras/EasyPeasyICS.php class or iCalcreator + * @link http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/ + * @link http://kigkonsult.se/iCalcreator/ + * @var string + */ + public $Ical = ''; + + /** + * The complete compiled MIME message body. + * @access protected + * @var string + */ + protected $MIMEBody = ''; + + /** + * The complete compiled MIME message headers. + * @var string + * @access protected + */ + protected $MIMEHeader = ''; + + /** + * Extra headers that createHeader() doesn't fold in. + * @var string + * @access protected + */ + protected $mailHeader = ''; + + /** + * Word-wrap the message body to this number of chars. + * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance. + * @var integer + */ + public $WordWrap = 0; + + /** + * Which method to use to send mail. + * Options: "mail", "sendmail", or "smtp". + * @var string + */ + public $Mailer = 'mail'; + + /** + * The path to the sendmail program. + * @var string + */ + public $Sendmail = '/usr/sbin/sendmail'; + + /** + * Whether mail() uses a fully sendmail-compatible MTA. + * One which supports sendmail's "-oi -f" options. + * @var boolean + */ + public $UseSendmailOptions = true; + + /** + * Path to PHPMailer plugins. + * Useful if the SMTP class is not in the PHP include path. + * @var string + * @deprecated Should not be needed now there is an autoloader. + */ + public $PluginDir = ''; + + /** + * The email address that a reading confirmation should be sent to, also known as read receipt. + * @var string + */ + public $ConfirmReadingTo = ''; + + /** + * The hostname to use in the Message-ID header and as default HELO string. + * If empty, PHPMailer attempts to find one with, in order, + * $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value + * 'localhost.localdomain'. + * @var string + */ + public $Hostname = ''; + + /** + * An ID to be used in the Message-ID header. + * If empty, a unique id will be generated. + * @var string + */ + public $MessageID = ''; + + /** + * The message Date to be used in the Date header. + * If empty, the current date will be added. + * @var string + */ + public $MessageDate = ''; + + /** + * SMTP hosts. + * Either a single hostname or multiple semicolon-delimited hostnames. + * You can also specify a different port + * for each host by using this format: [hostname:port] + * (e.g. "smtp1.example.com:25;smtp2.example.com"). + * You can also specify encryption type, for example: + * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465"). + * Hosts will be tried in order. + * @var string + */ + public $Host = 'localhost'; + + /** + * The default SMTP server port. + * @var integer + * @TODO Why is this needed when the SMTP class takes care of it? + */ + public $Port = 25; + + /** + * The SMTP HELO of the message. + * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find + * one with the same method described above for $Hostname. + * @var string + * @see PHPMailer::$Hostname + */ + public $Helo = ''; + + /** + * What kind of encryption to use on the SMTP connection. + * Options: '', 'ssl' or 'tls' + * @var string + */ + public $SMTPSecure = ''; + + /** + * Whether to enable TLS encryption automatically if a server supports it, + * even if `SMTPSecure` is not set to 'tls'. + * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid. + * @var boolean + */ + public $SMTPAutoTLS = true; + + /** + * Whether to use SMTP authentication. + * Uses the Username and Password properties. + * @var boolean + * @see PHPMailer::$Username + * @see PHPMailer::$Password + */ + public $SMTPAuth = false; + + /** + * Options array passed to stream_context_create when connecting via SMTP. + * @var array + */ + public $SMTPOptions = array(); + + /** + * SMTP username. + * @var string + */ + public $Username = ''; + + /** + * SMTP password. + * @var string + */ + public $Password = ''; + + /** + * SMTP auth type. + * Options are LOGIN (default), PLAIN, NTLM, CRAM-MD5 + * @var string + */ + public $AuthType = ''; + + /** + * SMTP realm. + * Used for NTLM auth + * @var string + */ + public $Realm = ''; + + /** + * SMTP workstation. + * Used for NTLM auth + * @var string + */ + public $Workstation = ''; + + /** + * The SMTP server timeout in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * @var integer + */ + public $Timeout = 300; + + /** + * SMTP class debug output mode. + * Debug output level. + * Options: + * * `0` No output + * * `1` Commands + * * `2` Data and commands + * * `3` As 2 plus connection status + * * `4` Low-level data output + * @var integer + * @see SMTP::$do_debug + */ + public $SMTPDebug = 0; + + /** + * How to handle debug output. + * Options: + * * `echo` Output plain-text as-is, appropriate for CLI + * * `html` Output escaped, line breaks converted to `
                  `, appropriate for browser output + * * `error_log` Output to error log as configured in php.ini + * + * Alternatively, you can provide a callable expecting two params: a message string and the debug level: + * + * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; + * + * @var string|callable + * @see SMTP::$Debugoutput + */ + public $Debugoutput = 'echo'; + + /** + * Whether to keep SMTP connection open after each message. + * If this is set to true then to close the connection + * requires an explicit call to smtpClose(). + * @var boolean + */ + public $SMTPKeepAlive = false; + + /** + * Whether to split multiple to addresses into multiple messages + * or send them all in one message. + * @var boolean + */ + public $SingleTo = false; + + /** + * Storage for addresses when SingleTo is enabled. + * @var array + * @TODO This should really not be public + */ + public $SingleToArray = array(); + + /** + * Whether to generate VERP addresses on send. + * Only applicable when sending via SMTP. + * @link https://en.wikipedia.org/wiki/Variable_envelope_return_path + * @link http://www.postfix.org/VERP_README.html Postfix VERP info + * @var boolean + */ + public $do_verp = false; + + /** + * Whether to allow sending messages with an empty body. + * @var boolean + */ + public $AllowEmpty = false; + + /** + * The default line ending. + * @note The default remains "\n". We force CRLF where we know + * it must be used via self::CRLF. + * @var string + */ + public $LE = "\n"; + + /** + * DKIM selector. + * @var string + */ + public $DKIM_selector = ''; + + /** + * DKIM Identity. + * Usually the email address used as the source of the email + * @var string + */ + public $DKIM_identity = ''; + + /** + * DKIM passphrase. + * Used if your key is encrypted. + * @var string + */ + public $DKIM_passphrase = ''; + + /** + * DKIM signing domain name. + * @example 'example.com' + * @var string + */ + public $DKIM_domain = ''; + + /** + * DKIM private key file path. + * @var string + */ + public $DKIM_private = ''; + + /** + * Callback Action function name. + * + * The function that handles the result of the send email action. + * It is called out by send() for each email sent. + * + * Value can be any php callable: http://www.php.net/is_callable + * + * Parameters: + * boolean $result result of the send action + * string $to email address of the recipient + * string $cc cc email addresses + * string $bcc bcc email addresses + * string $subject the subject + * string $body the email body + * string $from email address of sender + * @var string + */ + public $action_function = ''; + + /** + * What to put in the X-Mailer header. + * Options: An empty string for PHPMailer default, whitespace for none, or a string to use + * @var string + */ + public $XMailer = ''; + + /** + * An instance of the SMTP sender class. + * @var SMTP + * @access protected + */ + protected $smtp = null; + + /** + * The array of 'to' names and addresses. + * @var array + * @access protected + */ + protected $to = array(); + + /** + * The array of 'cc' names and addresses. + * @var array + * @access protected + */ + protected $cc = array(); + + /** + * The array of 'bcc' names and addresses. + * @var array + * @access protected + */ + protected $bcc = array(); + + /** + * The array of reply-to names and addresses. + * @var array + * @access protected + */ + protected $ReplyTo = array(); + + /** + * An array of all kinds of addresses. + * Includes all of $to, $cc, $bcc + * @var array + * @access protected + * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc + */ + protected $all_recipients = array(); + + /** + * An array of names and addresses queued for validation. + * In send(), valid and non duplicate entries are moved to $all_recipients + * and one of $to, $cc, or $bcc. + * This array is used only for addresses with IDN. + * @var array + * @access protected + * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc + * @see PHPMailer::$all_recipients + */ + protected $RecipientsQueue = array(); + + /** + * An array of reply-to names and addresses queued for validation. + * In send(), valid and non duplicate entries are moved to $ReplyTo. + * This array is used only for addresses with IDN. + * @var array + * @access protected + * @see PHPMailer::$ReplyTo + */ + protected $ReplyToQueue = array(); + + /** + * The array of attachments. + * @var array + * @access protected + */ + protected $attachment = array(); + + /** + * The array of custom headers. + * @var array + * @access protected + */ + protected $CustomHeader = array(); + + /** + * The most recent Message-ID (including angular brackets). + * @var string + * @access protected + */ + protected $lastMessageID = ''; + + /** + * The message's MIME type. + * @var string + * @access protected + */ + protected $message_type = ''; + + /** + * The array of MIME boundary strings. + * @var array + * @access protected + */ + protected $boundary = array(); + + /** + * The array of available languages. + * @var array + * @access protected + */ + protected $language = array(); + + /** + * The number of errors encountered. + * @var integer + * @access protected + */ + protected $error_count = 0; + + /** + * The S/MIME certificate file path. + * @var string + * @access protected + */ + protected $sign_cert_file = ''; + + /** + * The S/MIME key file path. + * @var string + * @access protected + */ + protected $sign_key_file = ''; + + /** + * The optional S/MIME extra certificates ("CA Chain") file path. + * @var string + * @access protected + */ + protected $sign_extracerts_file = ''; + + /** + * The S/MIME password for the key. + * Used only if the key is encrypted. + * @var string + * @access protected + */ + protected $sign_key_pass = ''; + + /** + * Whether to throw exceptions for errors. + * @var boolean + * @access protected + */ + protected $exceptions = false; + + /** + * Unique ID used for message ID and boundaries. + * @var string + * @access protected + */ + protected $uniqueid = ''; + + /** + * Error severity: message only, continue processing. + */ + const STOP_MESSAGE = 0; + + /** + * Error severity: message, likely ok to continue processing. + */ + const STOP_CONTINUE = 1; + + /** + * Error severity: message, plus full stop, critical error reached. + */ + const STOP_CRITICAL = 2; + + /** + * SMTP RFC standard line ending. + */ + const CRLF = "\r\n"; + + /** + * The maximum line length allowed by RFC 2822 section 2.1.1 + * @var integer + */ + const MAX_LINE_LENGTH = 998; + + /** + * Constructor. + * @param boolean $exceptions Should we throw external exceptions? + */ + public function __construct($exceptions = false) + { + $this->exceptions = (boolean)$exceptions; + } + + /** + * Destructor. + */ + public function __destruct() + { + //Close any open SMTP connection nicely + if ($this->Mailer == 'smtp') { + $this->smtpClose(); + } + } + + /** + * Call mail() in a safe_mode-aware fashion. + * Also, unless sendmail_path points to sendmail (or something that + * claims to be sendmail), don't pass params (not a perfect fix, + * but it will do) + * @param string $to To + * @param string $subject Subject + * @param string $body Message Body + * @param string $header Additional Header(s) + * @param string $params Params + * @access private + * @return boolean + */ + private function mailPassthru($to, $subject, $body, $header, $params) + { + //Check overloading of mail function to avoid double-encoding + if (ini_get('mbstring.func_overload') & 1) { + $subject = $this->secureHeader($subject); + } else { + $subject = $this->encodeHeader($this->secureHeader($subject)); + } + if (ini_get('safe_mode') || !($this->UseSendmailOptions)) { + $result = @mail($to, $subject, $body, $header); + } else { + $result = @mail($to, $subject, $body, $header, $params); + } + return $result; + } + + /** + * Output debugging info via user-defined method. + * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug). + * @see PHPMailer::$Debugoutput + * @see PHPMailer::$SMTPDebug + * @param string $str + */ + protected function edebug($str) + { + if ($this->SMTPDebug <= 0) { + return; + } + //Avoid clash with built-in function names + if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) { + call_user_func($this->Debugoutput, $str, $this->SMTPDebug); + return; + } + switch ($this->Debugoutput) { + case 'error_log': + //Don't output, just log + error_log($str); + break; + case 'html': + //Cleans up output a bit for a better looking, HTML-safe output + echo htmlentities( + preg_replace('/[\r\n]+/', '', $str), + ENT_QUOTES, + 'UTF-8' + ) + . "
                  \n"; + break; + case 'echo': + default: + //Normalize line breaks + $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str); + echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( + "\n", + "\n \t ", + trim($str) + ) . "\n"; + } + } + + /** + * Sets message type to HTML or plain. + * @param boolean $isHtml True for HTML mode. + * @return void + */ + public function isHTML($isHtml = true) + { + if ($isHtml) { + $this->ContentType = 'text/html'; + } else { + $this->ContentType = 'text/plain'; + } + } + + /** + * Send messages using SMTP. + * @return void + */ + public function isSMTP() + { + $this->Mailer = 'smtp'; + } + + /** + * Send messages using PHP's mail() function. + * @return void + */ + public function isMail() + { + $this->Mailer = 'mail'; + } + + /** + * Send messages using $Sendmail. + * @return void + */ + public function isSendmail() + { + $ini_sendmail_path = ini_get('sendmail_path'); + + if (!stristr($ini_sendmail_path, 'sendmail')) { + $this->Sendmail = '/usr/sbin/sendmail'; + } else { + $this->Sendmail = $ini_sendmail_path; + } + $this->Mailer = 'sendmail'; + } + + /** + * Send messages using qmail. + * @return void + */ + public function isQmail() + { + $ini_sendmail_path = ini_get('sendmail_path'); + + if (!stristr($ini_sendmail_path, 'qmail')) { + $this->Sendmail = '/var/qmail/bin/qmail-inject'; + } else { + $this->Sendmail = $ini_sendmail_path; + } + $this->Mailer = 'qmail'; + } + + /** + * Add a "To" address. + * @param string $address The email address to send to + * @param string $name + * @return boolean true on success, false if address already used or invalid in some way + */ + public function addAddress($address, $name = '') + { + return $this->addOrEnqueueAnAddress('to', $address, $name); + } + + /** + * Add a "CC" address. + * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. + * @param string $address The email address to send to + * @param string $name + * @return boolean true on success, false if address already used or invalid in some way + */ + public function addCC($address, $name = '') + { + return $this->addOrEnqueueAnAddress('cc', $address, $name); + } + + /** + * Add a "BCC" address. + * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. + * @param string $address The email address to send to + * @param string $name + * @return boolean true on success, false if address already used or invalid in some way + */ + public function addBCC($address, $name = '') + { + return $this->addOrEnqueueAnAddress('bcc', $address, $name); + } + + /** + * Add a "Reply-To" address. + * @param string $address The email address to reply to + * @param string $name + * @return boolean true on success, false if address already used or invalid in some way + */ + public function addReplyTo($address, $name = '') + { + return $this->addOrEnqueueAnAddress('Reply-To', $address, $name); + } + + /** + * Add an address to one of the recipient arrays or to the ReplyTo array. Because PHPMailer + * can't validate addresses with an IDN without knowing the PHPMailer::$CharSet (that can still + * be modified after calling this function), addition of such addresses is delayed until send(). + * Addresses that have been added already return false, but do not throw exceptions. + * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' + * @param string $address The email address to send, resp. to reply to + * @param string $name + * @throws phpmailerException + * @return boolean true on success, false if address already used or invalid in some way + * @access protected + */ + protected function addOrEnqueueAnAddress($kind, $address, $name) + { + $address = trim($address); + $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim + if (($pos = strrpos($address, '@')) === false) { + // At-sign is misssing. + $error_message = $this->lang('invalid_address') . $address; + $this->setError($error_message); + $this->edebug($error_message); + if ($this->exceptions) { + throw new phpmailerException($error_message); + } + return false; + } + $params = array($kind, $address, $name); + // Enqueue addresses with IDN until we know the PHPMailer::$CharSet. + if ($this->has8bitChars(substr($address, ++$pos)) and $this->idnSupported()) { + if ($kind != 'Reply-To') { + if (!array_key_exists($address, $this->RecipientsQueue)) { + $this->RecipientsQueue[$address] = $params; + return true; + } + } else { + if (!array_key_exists($address, $this->ReplyToQueue)) { + $this->ReplyToQueue[$address] = $params; + return true; + } + } + return false; + } + // Immediately add standard addresses without IDN. + return call_user_func_array(array($this, 'addAnAddress'), $params); + } + + /** + * Add an address to one of the recipient arrays or to the ReplyTo array. + * Addresses that have been added already return false, but do not throw exceptions. + * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' + * @param string $address The email address to send, resp. to reply to + * @param string $name + * @throws phpmailerException + * @return boolean true on success, false if address already used or invalid in some way + * @access protected + */ + protected function addAnAddress($kind, $address, $name = '') + { + if (!in_array($kind, array('to', 'cc', 'bcc', 'Reply-To'))) { + $error_message = $this->lang('Invalid recipient kind: ') . $kind; + $this->setError($error_message); + $this->edebug($error_message); + if ($this->exceptions) { + throw new phpmailerException($error_message); + } + return false; + } + if (!$this->validateAddress($address)) { + $error_message = $this->lang('invalid_address') . $address; + $this->setError($error_message); + $this->edebug($error_message); + if ($this->exceptions) { + throw new phpmailerException($error_message); + } + return false; + } + if ($kind != 'Reply-To') { + if (!array_key_exists(strtolower($address), $this->all_recipients)) { + array_push($this->$kind, array($address, $name)); + $this->all_recipients[strtolower($address)] = true; + return true; + } + } else { + if (!array_key_exists(strtolower($address), $this->ReplyTo)) { + $this->ReplyTo[strtolower($address)] = array($address, $name); + return true; + } + } return false; - } else { - return true; - } - } else { - return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address); - } - } - - ///////////////////////////////////////////////// - // METHODS, MAIL SENDING - ///////////////////////////////////////////////// - - /** - * Creates message and assigns Mailer. If the message is - * not sent successfully then it returns false. Use the ErrorInfo - * variable to view description of the error. - * @return bool - */ - public function Send() { - try { - if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { - throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL); - } - - // Set whether the message is multipart/alternative - if(!empty($this->AltBody)) { - $this->ContentType = 'multipart/alternative'; - } - - $this->error_count = 0; // reset errors - $this->SetMessageType(); - $header = $this->CreateHeader(); - $body = $this->CreateBody(); - - if (empty($this->Body)) { - throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL); - } - - // digitally sign with DKIM if enabled - if ($this->DKIM_domain && $this->DKIM_private) { - $header_dkim = $this->DKIM_Add($header,$this->Subject,$body); - $header = str_replace("\r\n","\n",$header_dkim) . $header; - } - - // Choose the mailer and send through it - switch($this->Mailer) { - case 'sendmail': - return $this->SendmailSend($header, $body); - case 'smtp': - return $this->SmtpSend($header, $body); - default: - return $this->MailSend($header, $body); - } - - } catch (phpmailerException $e) { - $this->SetError($e->getMessage()); - if ($this->exceptions) { - throw $e; - } - echo $e->getMessage()."\n"; - return false; - } - } - - /** - * Sends mail using the $Sendmail program. - * @param string $header The message headers - * @param string $body The message body - * @access protected - * @return bool - */ - protected function SendmailSend($header, $body) { - if ($this->Sender != '') { - $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); - } else { - $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail)); - } - if ($this->SingleTo === true) { - foreach ($this->SingleToArray as $key => $val) { - if(!@$mail = popen($sendmail, 'w')) { - throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); - } - fputs($mail, "To: " . $val . "\n"); - fputs($mail, $header); - fputs($mail, $body); - $result = pclose($mail); - // implement call back function if it exists - $isSent = ($result == 0) ? 1 : 0; - $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body); - if($result != 0) { - throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); - } - } - } else { - if(!@$mail = popen($sendmail, 'w')) { - throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); - } - fputs($mail, $header); - fputs($mail, $body); - $result = pclose($mail); - // implement call back function if it exists - $isSent = ($result == 0) ? 1 : 0; - $this->doCallback($isSent,$this->to,$this->cc,$this->bcc,$this->Subject,$body); - if($result != 0) { - throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL); - } - } - return true; - } - - /** - * Sends mail using the PHP mail() function. - * @param string $header The message headers - * @param string $body The message body - * @access protected - * @return bool - */ - protected function MailSend($header, $body) { - $toArr = array(); - foreach($this->to as $t) { - $toArr[] = $this->AddrFormat($t); - } - $to = implode(', ', $toArr); - - $params = sprintf("-oi -f %s", $this->Sender); - if ($this->Sender != '' && strlen(ini_get('safe_mode'))< 1) { - $old_from = ini_get('sendmail_from'); - ini_set('sendmail_from', $this->Sender); - if ($this->SingleTo === true && count($toArr) > 1) { - foreach ($toArr as $key => $val) { - $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body); - } - } else { - $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent,$to,$this->cc,$this->bcc,$this->Subject,$body); - } - } else { - if ($this->SingleTo === true && count($toArr) > 1) { - foreach ($toArr as $key => $val) { - $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent,$val,$this->cc,$this->bcc,$this->Subject,$body); - } - } else { - $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header); - // implement call back function if it exists - $isSent = ($rt == 1) ? 1 : 0; - $this->doCallback($isSent,$to,$this->cc,$this->bcc,$this->Subject,$body); - } - } - if (isset($old_from)) { - ini_set('sendmail_from', $old_from); - } - if(!$rt) { - throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL); - } - return true; - } - - /** - * Sends mail via SMTP using PhpSMTP - * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. - * @param string $header The message headers - * @param string $body The message body - * @uses SMTP - * @access protected - * @return bool - */ - protected function SmtpSend($header, $body) { - require_once $this->PluginDir . 'class.smtp.php'; - $bad_rcpt = array(); - - if(!$this->SmtpConnect()) { - throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL); - } - $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; - if(!$this->smtp->Mail($smtp_from)) { - throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL); - } - - // Attempt to send attach all recipients - foreach($this->to as $to) { - if (!$this->smtp->Recipient($to[0])) { - $bad_rcpt[] = $to[0]; - // implement call back function if it exists - $isSent = 0; - $this->doCallback($isSent,$to[0],'','',$this->Subject,$body); - } else { - // implement call back function if it exists - $isSent = 1; - $this->doCallback($isSent,$to[0],'','',$this->Subject,$body); - } - } - foreach($this->cc as $cc) { - if (!$this->smtp->Recipient($cc[0])) { - $bad_rcpt[] = $cc[0]; - // implement call back function if it exists - $isSent = 0; - $this->doCallback($isSent,'',$cc[0],'',$this->Subject,$body); - } else { - // implement call back function if it exists - $isSent = 1; - $this->doCallback($isSent,'',$cc[0],'',$this->Subject,$body); - } - } - foreach($this->bcc as $bcc) { - if (!$this->smtp->Recipient($bcc[0])) { - $bad_rcpt[] = $bcc[0]; - // implement call back function if it exists - $isSent = 0; - $this->doCallback($isSent,'','',$bcc[0],$this->Subject,$body); - } else { - // implement call back function if it exists - $isSent = 1; - $this->doCallback($isSent,'','',$bcc[0],$this->Subject,$body); - } - } - - - if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses - $badaddresses = implode(', ', $bad_rcpt); - throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses); - } - if(!$this->smtp->Data($header . $body)) { - throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL); - } - if($this->SMTPKeepAlive == true) { - $this->smtp->Reset(); - } - return true; - } - - /** - * Initiates a connection to an SMTP server. - * Returns false if the operation failed. - * @uses SMTP - * @access public - * @return bool - */ - public function SmtpConnect() { - if(is_null($this->smtp)) { - $this->smtp = new SMTP(); - } - - $this->smtp->do_debug = $this->SMTPDebug; - $hosts = explode(';', $this->Host); - $index = 0; - $connection = $this->smtp->Connected(); - - // Retry while there is no connection - try { - while($index < count($hosts) && !$connection) { - $hostinfo = array(); - if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) { - $host = $hostinfo[1]; - $port = $hostinfo[2]; + } + + /** + * Parse and validate a string containing one or more RFC822-style comma-separated email addresses + * of the form "display name

                  " into an array of name/address pairs. + * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available. + * Note that quotes in the name part are removed. + * @param string $addrstr The address list string + * @param bool $useimap Whether to use the IMAP extension to parse the list + * @return array + * @link http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation + */ + public function parseAddresses($addrstr, $useimap = true) + { + $addresses = array(); + if ($useimap and function_exists('imap_rfc822_parse_adrlist')) { + //Use this built-in parser if it's available + $list = imap_rfc822_parse_adrlist($addrstr, ''); + foreach ($list as $address) { + if ($address->host != '.SYNTAX-ERROR.') { + if ($this->validateAddress($address->mailbox . '@' . $address->host)) { + $addresses[] = array( + 'name' => (property_exists($address, 'personal') ? $address->personal : ''), + 'address' => $address->mailbox . '@' . $address->host + ); + } + } + } } else { - $host = $hosts[$index]; - $port = $this->Port; - } - - $tls = ($this->SMTPSecure == 'tls'); - $ssl = ($this->SMTPSecure == 'ssl'); - - if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) { - - $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname()); - $this->smtp->Hello($hello); - - if ($tls) { - if (!$this->smtp->StartTLS()) { - throw new phpmailerException($this->Lang('tls')); - } - - //We must resend HELO after tls negotiation - $this->smtp->Hello($hello); - } - - $connection = true; - if ($this->SMTPAuth) { - if (!$this->smtp->Authenticate($this->Username, $this->Password)) { - throw new phpmailerException($this->Lang('authenticate')); - } - } - } - $index++; - if (!$connection) { - throw new phpmailerException($this->Lang('connect_host')); - } - } - } catch (phpmailerException $e) { - $this->smtp->Reset(); - throw $e; - } - return true; - } - - /** - * Closes the active SMTP session if one exists. - * @return void - */ - public function SmtpClose() { - if(!is_null($this->smtp)) { - if($this->smtp->Connected()) { - $this->smtp->Quit(); - $this->smtp->Close(); - } - } - } - - /** - * Sets the language for all class error messages. - * Returns false if it cannot load the language file. The default language is English. - * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br") - * @param string $lang_path Path to the language file directory - * @access public - */ - function SetLanguage($langcode = 'en', $lang_path = 'language/') { - //Define full set of translatable strings - $PHPMAILER_LANG = array( - 'provide_address' => 'You must provide at least one recipient email address.', - 'mailer_not_supported' => ' mailer is not supported.', - 'execute' => 'Could not execute: ', - 'instantiate' => 'Could not instantiate mail function.', - 'authenticate' => 'SMTP Error: Could not authenticate.', - 'from_failed' => 'The following From address failed: ', - 'recipients_failed' => 'SMTP Error: The following recipients failed: ', - 'data_not_accepted' => 'SMTP Error: Data not accepted.', - 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', - 'file_access' => 'Could not access file: ', - 'file_open' => 'File Error: Could not open file: ', - 'encoding' => 'Unknown encoding: ', - 'signing' => 'Signing Error: ', - 'smtp_error' => 'SMTP server error: ', - 'empty_message' => 'Message body empty', - 'invalid_address' => 'Invalid address', - 'variable_set' => 'Cannot set or reset variable: ' - ); - //Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"! - $l = true; - if ($langcode != 'en') { //There is no English translation file - $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php'; - } - $this->language = $PHPMAILER_LANG; - return ($l == true); //Returns false if language not found - } - - /** - * Return the current array of language strings - * @return array - */ - public function GetTranslations() { - return $this->language; - } - - ///////////////////////////////////////////////// - // METHODS, MESSAGE CREATION - ///////////////////////////////////////////////// - - /** - * Creates recipient headers. - * @access public - * @return string - */ - public function AddrAppend($type, $addr) { - $addr_str = $type . ': '; - $addresses = array(); - foreach ($addr as $a) { - $addresses[] = $this->AddrFormat($a); - } - $addr_str .= implode(', ', $addresses); - $addr_str .= $this->LE; - - return $addr_str; - } - - /** - * Formats an address correctly. - * @access public - * @return string - */ - public function AddrFormat($addr) { - if (empty($addr[1])) { - return $this->SecureHeader($addr[0]); - } else { - return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">"; - } - } - - /** - * Wraps message for use with mailers that do not - * automatically perform wrapping and for quoted-printable. - * Original written by philippe. - * @param string $message The message to wrap - * @param integer $length The line length to wrap to - * @param boolean $qp_mode Whether to run in Quoted-Printable mode - * @access public - * @return string - */ - public function WrapText($message, $length, $qp_mode = false) { - $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE; - // If utf-8 encoding is used, we will need to make sure we don't - // split multibyte characters when we wrap - $is_utf8 = (strtolower($this->CharSet) == "utf-8"); - - $message = $this->FixEOL($message); - if (substr($message, -1) == $this->LE) { - $message = substr($message, 0, -1); - } - - $line = explode($this->LE, $message); - $message = ''; - for ($i=0 ;$i < count($line); $i++) { - $line_part = explode(' ', $line[$i]); - $buf = ''; - for ($e = 0; $e $length)) { - $space_left = $length - strlen($buf) - 1; - if ($e != 0) { - if ($space_left > 20) { - $len = $space_left; - if ($is_utf8) { - $len = $this->UTF8CharBoundary($word, $len); - } elseif (substr($word, $len - 1, 1) == "=") { - $len--; - } elseif (substr($word, $len - 2, 1) == "=") { - $len -= 2; - } - $part = substr($word, 0, $len); - $word = substr($word, $len); - $buf .= ' ' . $part; - $message .= $buf . sprintf("=%s", $this->LE); + //Use this simpler parser + $list = explode(',', $addrstr); + foreach ($list as $address) { + $address = trim($address); + //Is there a separate name part? + if (strpos($address, '<') === false) { + //No separate name, just use the whole thing + if ($this->validateAddress($address)) { + $addresses[] = array( + 'name' => '', + 'address' => $address + ); + } + } else { + list($name, $email) = explode('<', $address); + $email = trim(str_replace('>', '', $email)); + if ($this->validateAddress($email)) { + $addresses[] = array( + 'name' => trim(str_replace(array('"', "'"), '', $name)), + 'address' => $email + ); + } + } + } + } + return $addresses; + } + + /** + * Set the From and FromName properties. + * @param string $address + * @param string $name + * @param boolean $auto Whether to also set the Sender address, defaults to true + * @throws phpmailerException + * @return boolean + */ + public function setFrom($address, $name = '', $auto = true) + { + $address = trim($address); + $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim + // Don't validate now addresses with IDN. Will be done in send(). + if (($pos = strrpos($address, '@')) === false or + (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and + !$this->validateAddress($address)) { + $error_message = $this->lang('invalid_address') . $address; + $this->setError($error_message); + $this->edebug($error_message); + if ($this->exceptions) { + throw new phpmailerException($error_message); + } + return false; + } + $this->From = $address; + $this->FromName = $name; + if ($auto) { + if (empty($this->Sender)) { + $this->Sender = $address; + } + } + return true; + } + + /** + * Return the Message-ID header of the last email. + * Technically this is the value from the last time the headers were created, + * but it's also the message ID of the last sent message except in + * pathological cases. + * @return string + */ + public function getLastMessageID() + { + return $this->lastMessageID; + } + + /** + * Check that a string looks like an email address. + * @param string $address The email address to check + * @param string $patternselect A selector for the validation pattern to use : + * * `auto` Pick best pattern automatically; + * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; + * * `pcre` Use old PCRE implementation; + * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; + * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. + * * `noregex` Don't use a regex: super fast, really dumb. + * @return boolean + * @static + * @access public + */ + public static function validateAddress($address, $patternselect = 'auto') + { + //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321 + if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) { + return false; + } + if (!$patternselect or $patternselect == 'auto') { + //Check this constant first so it works when extension_loaded() is disabled by safe mode + //Constant was added in PHP 5.2.4 + if (defined('PCRE_VERSION')) { + //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2 + if (version_compare(PCRE_VERSION, '8.0.3') >= 0) { + $patternselect = 'pcre8'; + } else { + $patternselect = 'pcre'; + } + } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) { + //Fall back to older PCRE + $patternselect = 'pcre'; } else { - $message .= $buf . $soft_break; + //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension + if (version_compare(PHP_VERSION, '5.2.0') >= 0) { + $patternselect = 'php'; + } else { + $patternselect = 'noregex'; + } } - $buf = ''; - } - while (strlen($word) > 0) { - $len = $length; - if ($is_utf8) { - $len = $this->UTF8CharBoundary($word, $len); - } elseif (substr($word, $len - 1, 1) == "=") { - $len--; - } elseif (substr($word, $len - 2, 1) == "=") { - $len -= 2; - } - $part = substr($word, 0, $len); - $word = substr($word, $len); - - if (strlen($word) > 0) { - $message .= $part . sprintf("=%s", $this->LE); + } + switch ($patternselect) { + case 'pcre8': + /** + * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains. + * @link http://squiloople.com/2009/12/20/email-address-validation/ + * @copyright 2009-2010 Michael Rushton + * Feel free to use and redistribute this code. But please keep this copyright notice. + */ + return (boolean)preg_match( + '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' . + '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' . + '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' . + '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' . + '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' . + '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' . + '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' . + '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' . + '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', + $address + ); + case 'pcre': + //An older regex that doesn't need a recent PCRE + return (boolean)preg_match( + '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' . + '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' . + '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' . + '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' . + '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' . + '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' . + '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' . + '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' . + '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' . + '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD', + $address + ); + case 'html5': + /** + * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements. + * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email) + */ + return (boolean)preg_match( + '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' . + '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD', + $address + ); + case 'noregex': + //No PCRE! Do something _very_ approximate! + //Check the address is 3 chars or longer and contains an @ that's not the first or last char + return (strlen($address) >= 3 + and strpos($address, '@') >= 1 + and strpos($address, '@') != strlen($address) - 1); + case 'php': + default: + return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL); + } + } + + /** + * Tells whether IDNs (Internationalized Domain Names) are supported or not. This requires the + * "intl" and "mbstring" PHP extensions. + * @return bool "true" if required functions for IDN support are present + */ + public function idnSupported() + { + // @TODO: Write our own "idn_to_ascii" function for PHP <= 5.2. + return function_exists('idn_to_ascii') and function_exists('mb_convert_encoding'); + } + + /** + * Converts IDN in given email address to its ASCII form, also known as punycode, if possible. + * Important: Address must be passed in same encoding as currently set in PHPMailer::$CharSet. + * This function silently returns unmodified address if: + * - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form) + * - Conversion to punycode is impossible (e.g. required PHP functions are not available) + * or fails for any reason (e.g. domain has characters not allowed in an IDN) + * @see PHPMailer::$CharSet + * @param string $address The email address to convert + * @return string The encoded address in ASCII form + */ + public function punyencodeAddress($address) + { + // Verify we have required functions, CharSet, and at-sign. + if ($this->idnSupported() and + !empty($this->CharSet) and + ($pos = strrpos($address, '@')) !== false) { + $domain = substr($address, ++$pos); + // Verify CharSet string is a valid one, and domain properly encoded in this CharSet. + if ($this->has8bitChars($domain) and @mb_check_encoding($domain, $this->CharSet)) { + $domain = mb_convert_encoding($domain, 'UTF-8', $this->CharSet); + if (($punycode = defined('INTL_IDNA_VARIANT_UTS46') ? + idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46) : + idn_to_ascii($domain)) !== false) { + return substr($address, 0, $pos) . $punycode; + } + } + } + return $address; + } + + /** + * Create a message and send it. + * Uses the sending method specified by $Mailer. + * @throws phpmailerException + * @return boolean false on error - See the ErrorInfo property for details of the error. + */ + public function send() + { + try { + if (!$this->preSend()) { + return false; + } + return $this->postSend(); + } catch (phpmailerException $exc) { + $this->mailHeader = ''; + $this->setError($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + return false; + } + } + + /** + * Prepare a message for sending. + * @throws phpmailerException + * @return boolean + */ + public function preSend() + { + try { + $this->error_count = 0; // Reset errors + $this->mailHeader = ''; + + // Dequeue recipient and Reply-To addresses with IDN + foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) { + $params[1] = $this->punyencodeAddress($params[1]); + call_user_func_array(array($this, 'addAnAddress'), $params); + } + if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { + throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL); + } + + // Validate From, Sender, and ConfirmReadingTo addresses + foreach (array('From', 'Sender', 'ConfirmReadingTo') as $address_kind) { + $this->$address_kind = trim($this->$address_kind); + if (empty($this->$address_kind)) { + continue; + } + $this->$address_kind = $this->punyencodeAddress($this->$address_kind); + if (!$this->validateAddress($this->$address_kind)) { + $error_message = $this->lang('invalid_address') . $this->$address_kind; + $this->setError($error_message); + $this->edebug($error_message); + if ($this->exceptions) { + throw new phpmailerException($error_message); + } + return false; + } + } + + // Set whether the message is multipart/alternative + if (!empty($this->AltBody)) { + $this->ContentType = 'multipart/alternative'; + } + + $this->setMessageType(); + // Refuse to send an empty message unless we are specifically allowing it + if (!$this->AllowEmpty and empty($this->Body)) { + throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL); + } + + // Create body before headers in case body makes changes to headers (e.g. altering transfer encoding) + $this->MIMEHeader = ''; + $this->MIMEBody = $this->createBody(); + // createBody may have added some headers, so retain them + $tempheaders = $this->MIMEHeader; + $this->MIMEHeader = $this->createHeader(); + $this->MIMEHeader .= $tempheaders; + + // To capture the complete message when using mail(), create + // an extra header list which createHeader() doesn't fold in + if ($this->Mailer == 'mail') { + if (count($this->to) > 0) { + $this->mailHeader .= $this->addrAppend('To', $this->to); + } else { + $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;'); + } + $this->mailHeader .= $this->headerLine( + 'Subject', + $this->encodeHeader($this->secureHeader(trim($this->Subject))) + ); + } + + // Sign with DKIM if enabled + if (!empty($this->DKIM_domain) + && !empty($this->DKIM_private) + && !empty($this->DKIM_selector) + && file_exists($this->DKIM_private)) { + $header_dkim = $this->DKIM_Add( + $this->MIMEHeader . $this->mailHeader, + $this->encodeHeader($this->secureHeader($this->Subject)), + $this->MIMEBody + ); + $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . self::CRLF . + str_replace("\r\n", "\n", $header_dkim) . self::CRLF; + } + return true; + } catch (phpmailerException $exc) { + $this->setError($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + return false; + } + } + + /** + * Actually send a message. + * Send the email via the selected mechanism + * @throws phpmailerException + * @return boolean + */ + public function postSend() + { + try { + // Choose the mailer and send through it + switch ($this->Mailer) { + case 'sendmail': + case 'qmail': + return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody); + case 'smtp': + return $this->smtpSend($this->MIMEHeader, $this->MIMEBody); + case 'mail': + return $this->mailSend($this->MIMEHeader, $this->MIMEBody); + default: + $sendMethod = $this->Mailer.'Send'; + if (method_exists($this, $sendMethod)) { + return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody); + } + + return $this->mailSend($this->MIMEHeader, $this->MIMEBody); + } + } catch (phpmailerException $exc) { + $this->setError($exc->getMessage()); + $this->edebug($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + } + return false; + } + + /** + * Send mail using the $Sendmail program. + * @param string $header The message headers + * @param string $body The message body + * @see PHPMailer::$Sendmail + * @throws phpmailerException + * @access protected + * @return boolean + */ + protected function sendmailSend($header, $body) + { + if ($this->Sender != '') { + if ($this->Mailer == 'qmail') { + $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + } else { + $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + } + } else { + if ($this->Mailer == 'qmail') { + $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail)); } else { - $buf = $part; + $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail)); + } + } + if ($this->SingleTo) { + foreach ($this->SingleToArray as $toAddr) { + if (!@$mail = popen($sendmail, 'w')) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + fputs($mail, 'To: ' . $toAddr . "\n"); + fputs($mail, $header); + fputs($mail, $body); + $result = pclose($mail); + $this->doCallback( + ($result == 0), + array($toAddr), + $this->cc, + $this->bcc, + $this->Subject, + $body, + $this->From + ); + if ($result != 0) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } } - } } else { - $buf_o = $buf; - $buf .= ($e == 0) ? $word : (' ' . $word); - - if (strlen($buf) > $length and $buf_o != '') { - $message .= $buf_o . $soft_break; - $buf = $word; - } - } - } - $message .= $buf . $this->LE; - } - - return $message; - } - - /** - * Finds last character boundary prior to maxLength in a utf-8 - * quoted (printable) encoded string. - * Original written by Colin Brown. - * @access public - * @param string $encodedText utf-8 QP text - * @param int $maxLength find last character boundary prior to this length - * @return int - */ - public function UTF8CharBoundary($encodedText, $maxLength) { - $foundSplitPos = false; - $lookBack = 3; - while (!$foundSplitPos) { - $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); - $encodedCharPos = strpos($lastChunk, "="); - if ($encodedCharPos !== false) { - // Found start of encoded character byte within $lookBack block. - // Check the encoded byte value (the 2 chars after the '=') - $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2); - $dec = hexdec($hex); - if ($dec < 128) { // Single byte character. - // If the encoded char was found at pos 0, it will fit - // otherwise reduce maxLength to start of the encoded char - $maxLength = ($encodedCharPos == 0) ? $maxLength : - $maxLength - ($lookBack - $encodedCharPos); - $foundSplitPos = true; - } elseif ($dec >= 192) { // First byte of a multi byte character - // Reduce maxLength to split at start of character - $maxLength = $maxLength - ($lookBack - $encodedCharPos); - $foundSplitPos = true; - } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back - $lookBack += 3; - } - } else { - // No encoded character found - $foundSplitPos = true; - } - } - return $maxLength; - } - - - /** - * Set the body wrapping. - * @access public - * @return void - */ - public function SetWordWrap() { - if($this->WordWrap < 1) { - return; - } - - switch($this->message_type) { - case 'alt': - case 'alt_attachments': - $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap); - break; - default: - $this->Body = $this->WrapText($this->Body, $this->WordWrap); - break; - } - } - - /** - * Assembles message header. - * @access public - * @return string The assembled header - */ - public function CreateHeader() { - $result = ''; - - // Set the boundaries - $uniq_id = md5(uniqid(time())); - $this->boundary[1] = 'b1_' . $uniq_id; - $this->boundary[2] = 'b2_' . $uniq_id; - - $result .= $this->HeaderLine('Date', self::RFCDate()); - if($this->Sender == '') { - $result .= $this->HeaderLine('Return-Path', trim($this->From)); - } else { - $result .= $this->HeaderLine('Return-Path', trim($this->Sender)); - } - - // To be created automatically by mail() - if($this->Mailer != 'mail') { - if ($this->SingleTo === true) { - foreach($this->to as $t) { - $this->SingleToArray[] = $this->AddrFormat($t); - } - } else { - if(count($this->to) > 0) { - $result .= $this->AddrAppend('To', $this->to); - } elseif (count($this->cc) == 0) { - $result .= $this->HeaderLine('To', 'undisclosed-recipients:;'); - } - } - } - - $from = array(); - $from[0][0] = trim($this->From); - $from[0][1] = $this->FromName; - $result .= $this->AddrAppend('From', $from); - - // sendmail and mail() extract Cc from the header before sending - if(count($this->cc) > 0) { - $result .= $this->AddrAppend('Cc', $this->cc); - } - - // sendmail and mail() extract Bcc from the header before sending - if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) { - $result .= $this->AddrAppend('Bcc', $this->bcc); - } - - if(count($this->ReplyTo) > 0) { - $result .= $this->AddrAppend('Reply-to', $this->ReplyTo); - } - - // mail() sets the subject itself - if($this->Mailer != 'mail') { - $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject))); - } - - if($this->MessageID != '') { - $result .= $this->HeaderLine('Message-ID',$this->MessageID); - } else { - $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE); - } - $result .= $this->HeaderLine('X-Priority', $this->Priority); - $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (phpmailer.sourceforge.net)'); + if (!@$mail = popen($sendmail, 'w')) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + fputs($mail, $header); + fputs($mail, $body); + $result = pclose($mail); + $this->doCallback( + ($result == 0), + $this->to, + $this->cc, + $this->bcc, + $this->Subject, + $body, + $this->From + ); + if ($result != 0) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + } + return true; + } + + /** + * Send mail using the PHP mail() function. + * @param string $header The message headers + * @param string $body The message body + * @link http://www.php.net/manual/en/book.mail.php + * @throws phpmailerException + * @access protected + * @return boolean + */ + protected function mailSend($header, $body) + { + $toArr = array(); + foreach ($this->to as $toaddr) { + $toArr[] = $this->addrFormat($toaddr); + } + $to = implode(', ', $toArr); - if($this->ConfirmReadingTo != '') { - $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>'); + if (empty($this->Sender)) { + $params = ' '; + } else { + $params = sprintf('-f%s', $this->Sender); + } + if ($this->Sender != '' and !ini_get('safe_mode')) { + $old_from = ini_get('sendmail_from'); + ini_set('sendmail_from', $this->Sender); + } + $result = false; + if ($this->SingleTo && count($toArr) > 1) { + foreach ($toArr as $toAddr) { + $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); + $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From); + } + } else { + $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params); + $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); + } + if (isset($old_from)) { + ini_set('sendmail_from', $old_from); + } + if (!$result) { + throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL); + } + return true; } - // Add custom headers - for($index = 0; $index < count($this->CustomHeader); $index++) { - $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1]))); + /** + * Get an instance to use for SMTP operations. + * Override this function to load your own SMTP implementation + * @return SMTP + */ + public function getSMTPInstance() + { + if (!is_object($this->smtp)) { + $this->smtp = new SMTP; + } + return $this->smtp; + } + + /** + * Send mail via SMTP. + * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. + * Uses the PHPMailerSMTP class by default. + * @see PHPMailer::getSMTPInstance() to use a different class. + * @param string $header The message headers + * @param string $body The message body + * @throws phpmailerException + * @uses SMTP + * @access protected + * @return boolean + */ + protected function smtpSend($header, $body) + { + $bad_rcpt = array(); + if (!$this->smtpConnect($this->SMTPOptions)) { + throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL); + } + if ('' == $this->Sender) { + $smtp_from = $this->From; + } else { + $smtp_from = $this->Sender; + } + if (!$this->smtp->mail($smtp_from)) { + $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError())); + throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL); + } + + // Attempt to send to all recipients + foreach (array($this->to, $this->cc, $this->bcc) as $togroup) { + foreach ($togroup as $to) { + if (!$this->smtp->recipient($to[0])) { + $error = $this->smtp->getError(); + $bad_rcpt[] = array('to' => $to[0], 'error' => $error['detail']); + $isSent = false; + } else { + $isSent = true; + } + $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From); + } + } + + // Only send the DATA command if we have viable recipients + if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) { + throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL); + } + if ($this->SMTPKeepAlive) { + $this->smtp->reset(); + } else { + $this->smtp->quit(); + $this->smtp->close(); + } + //Create error message for any bad addresses + if (count($bad_rcpt) > 0) { + $errstr = ''; + foreach ($bad_rcpt as $bad) { + $errstr .= $bad['to'] . ': ' . $bad['error']; + } + throw new phpmailerException( + $this->lang('recipients_failed') . $errstr, + self::STOP_CONTINUE + ); + } + return true; } - if (!$this->sign_key_file) { - $result .= $this->HeaderLine('MIME-Version', '1.0'); - $result .= $this->GetMailMIME(); + + /** + * Initiate a connection to an SMTP server. + * Returns false if the operation failed. + * @param array $options An array of options compatible with stream_context_create() + * @uses SMTP + * @access public + * @throws phpmailerException + * @return boolean + */ + public function smtpConnect($options = array()) + { + if (is_null($this->smtp)) { + $this->smtp = $this->getSMTPInstance(); + } + + // Already connected? + if ($this->smtp->connected()) { + return true; + } + + $this->smtp->setTimeout($this->Timeout); + $this->smtp->setDebugLevel($this->SMTPDebug); + $this->smtp->setDebugOutput($this->Debugoutput); + $this->smtp->setVerp($this->do_verp); + $hosts = explode(';', $this->Host); + $lastexception = null; + + foreach ($hosts as $hostentry) { + $hostinfo = array(); + if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) { + // Not a valid host entry + continue; + } + // $hostinfo[2]: optional ssl or tls prefix + // $hostinfo[3]: the hostname + // $hostinfo[4]: optional port number + // The host string prefix can temporarily override the current setting for SMTPSecure + // If it's not specified, the default value is used + $prefix = ''; + $secure = $this->SMTPSecure; + $tls = ($this->SMTPSecure == 'tls'); + if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) { + $prefix = 'ssl://'; + $tls = false; // Can't have SSL and TLS at the same time + $secure = 'ssl'; + } elseif ($hostinfo[2] == 'tls') { + $tls = true; + // tls doesn't use a prefix + $secure = 'tls'; + } + //Do we need the OpenSSL extension? + $sslext = defined('OPENSSL_ALGO_SHA1'); + if ('tls' === $secure or 'ssl' === $secure) { + //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled + if (!$sslext) { + throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL); + } + } + $host = $hostinfo[3]; + $port = $this->Port; + $tport = (integer)$hostinfo[4]; + if ($tport > 0 and $tport < 65536) { + $port = $tport; + } + if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) { + try { + if ($this->Helo) { + $hello = $this->Helo; + } else { + $hello = $this->serverHostname(); + } + $this->smtp->hello($hello); + //Automatically enable TLS encryption if: + // * it's not disabled + // * we have openssl extension + // * we are not already using SSL + // * the server offers STARTTLS + if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) { + $tls = true; + } + if ($tls) { + if (!$this->smtp->startTLS()) { + throw new phpmailerException($this->lang('connect_host')); + } + // We must resend HELO after tls negotiation + $this->smtp->hello($hello); + } + if ($this->SMTPAuth) { + if (!$this->smtp->authenticate( + $this->Username, + $this->Password, + $this->AuthType, + $this->Realm, + $this->Workstation + ) + ) { + throw new phpmailerException($this->lang('authenticate')); + } + } + return true; + } catch (phpmailerException $exc) { + $lastexception = $exc; + $this->edebug($exc->getMessage()); + // We must have connected, but then failed TLS or Auth, so close connection nicely + $this->smtp->quit(); + } + } + } + // If we get here, all connection attempts have failed, so close connection hard + $this->smtp->close(); + // As we've caught all exceptions, just report whatever the last one was + if ($this->exceptions and !is_null($lastexception)) { + throw $lastexception; + } + return false; + } + + /** + * Close the active SMTP session if one exists. + * @return void + */ + public function smtpClose() + { + if ($this->smtp !== null) { + if ($this->smtp->connected()) { + $this->smtp->quit(); + $this->smtp->close(); + } + } } - return $result; - } - - /** - * Returns the message MIME. - * @access public - * @return string - */ - public function GetMailMIME() { - $result = ''; - switch($this->message_type) { - case 'plain': - $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding); - $result .= sprintf("Content-Type: %s; charset=%s", $this->ContentType, $this->CharSet); - break; - case 'attachments': - case 'alt_attachments': - if($this->InlineImageExists()){ - $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE); + /** + * Set the language for error messages. + * Returns false if it cannot load the language file. + * The default language is English. + * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr") + * @param string $lang_path Path to the language file directory, with trailing separator (slash) + * @return boolean + * @access public + */ + public function setLanguage($langcode = 'en', $lang_path = '') + { + // Define full set of translatable strings in English + $PHPMAILER_LANG = array( + 'authenticate' => 'SMTP Error: Could not authenticate.', + 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', + 'data_not_accepted' => 'SMTP Error: data not accepted.', + 'empty_message' => 'Message body empty', + 'encoding' => 'Unknown encoding: ', + 'execute' => 'Could not execute: ', + 'file_access' => 'Could not access file: ', + 'file_open' => 'File Error: Could not open file: ', + 'from_failed' => 'The following From address failed: ', + 'instantiate' => 'Could not instantiate mail function.', + 'invalid_address' => 'Invalid address: ', + 'mailer_not_supported' => ' mailer is not supported.', + 'provide_address' => 'You must provide at least one recipient email address.', + 'recipients_failed' => 'SMTP Error: The following recipients failed: ', + 'signing' => 'Signing Error: ', + 'smtp_connect_failed' => 'SMTP connect() failed.', + 'smtp_error' => 'SMTP server error: ', + 'variable_set' => 'Cannot set or reset variable: ', + 'extension_missing' => 'Extension missing: ' + ); + if (empty($lang_path)) { + // Calculate an absolute path so it can work if CWD is not here + $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR; + } + $foundlang = true; + $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php'; + // There is no English translation file + if ($langcode != 'en') { + // Make sure language file path is readable + if (!is_readable($lang_file)) { + $foundlang = false; + } else { + // Overwrite language-specific strings. + // This way we'll never have missing translation keys. + $foundlang = include $lang_file; + } + } + $this->language = $PHPMAILER_LANG; + return (boolean)$foundlang; // Returns false if language not found + } + + /** + * Get the array of strings for the current language. + * @return array + */ + public function getTranslations() + { + return $this->language; + } + + /** + * Create recipient headers. + * @access public + * @param string $type + * @param array $addr An array of recipient, + * where each recipient is a 2-element indexed array with element 0 containing an address + * and element 1 containing a name, like: + * array(array('joe@example.com', 'Joe User'), array('zoe@example.com', 'Zoe User')) + * @return string + */ + public function addrAppend($type, $addr) + { + $addresses = array(); + foreach ($addr as $address) { + $addresses[] = $this->addrFormat($address); + } + return $type . ': ' . implode(', ', $addresses) . $this->LE; + } + + /** + * Format an address for use in a message header. + * @access public + * @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name + * like array('joe@example.com', 'Joe User') + * @return string + */ + public function addrFormat($addr) + { + if (empty($addr[1])) { // No name provided + return $this->secureHeader($addr[0]); } else { - $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;'); - $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); - } - break; - case 'alt': - $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;'); - $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"'); - break; - } - - if($this->Mailer != 'mail') { - $result .= $this->LE.$this->LE; - } - - return $result; - } - - /** - * Assembles the message body. Returns an empty string on failure. - * @access public - * @return string The assembled message body - */ - public function CreateBody() { - $body = ''; - - if ($this->sign_key_file) { - $body .= $this->GetMailMIME(); - } - - $this->SetWordWrap(); - - switch($this->message_type) { - case 'alt': - $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', ''); - $body .= $this->EncodeString($this->AltBody, $this->Encoding); - $body .= $this->LE.$this->LE; - $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', ''); - $body .= $this->EncodeString($this->Body, $this->Encoding); - $body .= $this->LE.$this->LE; - $body .= $this->EndBoundary($this->boundary[1]); - break; - case 'plain': - $body .= $this->EncodeString($this->Body, $this->Encoding); - break; - case 'attachments': - $body .= $this->GetBoundary($this->boundary[1], '', '', ''); - $body .= $this->EncodeString($this->Body, $this->Encoding); - $body .= $this->LE; - $body .= $this->AttachAll(); - break; - case 'alt_attachments': - $body .= sprintf("--%s%s", $this->boundary[1], $this->LE); - $body .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE); - $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body - $body .= $this->EncodeString($this->AltBody, $this->Encoding); - $body .= $this->LE.$this->LE; - $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body - $body .= $this->EncodeString($this->Body, $this->Encoding); - $body .= $this->LE.$this->LE; - $body .= $this->EndBoundary($this->boundary[2]); - $body .= $this->AttachAll(); - break; - } - - if ($this->IsError()) { - $body = ''; - } elseif ($this->sign_key_file) { - try { - $file = tempnam('', 'mail'); - file_put_contents($file, $body); //TODO check this worked - $signed = tempnam("", "signed"); - if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) { - @unlink($file); - @unlink($signed); - $body = file_get_contents($signed); + return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader( + $addr[0] + ) . '>'; + } + } + + /** + * Word-wrap message. + * For use with mailers that do not automatically perform wrapping + * and for quoted-printable encoded messages. + * Original written by philippe. + * @param string $message The message to wrap + * @param integer $length The line length to wrap to + * @param boolean $qp_mode Whether to run in Quoted-Printable mode + * @access public + * @return string + */ + public function wrapText($message, $length, $qp_mode = false) + { + if ($qp_mode) { + $soft_break = sprintf(' =%s', $this->LE); + } else { + $soft_break = $this->LE; + } + // If utf-8 encoding is used, we will need to make sure we don't + // split multibyte characters when we wrap + $is_utf8 = (strtolower($this->CharSet) == 'utf-8'); + $lelen = strlen($this->LE); + $crlflen = strlen(self::CRLF); + + $message = $this->fixEOL($message); + //Remove a trailing line break + if (substr($message, -$lelen) == $this->LE) { + $message = substr($message, 0, -$lelen); + } + + //Split message into lines + $lines = explode($this->LE, $message); + //Message will be rebuilt in here + $message = ''; + foreach ($lines as $line) { + $words = explode(' ', $line); + $buf = ''; + $firstword = true; + foreach ($words as $word) { + if ($qp_mode and (strlen($word) > $length)) { + $space_left = $length - strlen($buf) - $crlflen; + if (!$firstword) { + if ($space_left > 20) { + $len = $space_left; + if ($is_utf8) { + $len = $this->utf8CharBoundary($word, $len); + } elseif (substr($word, $len - 1, 1) == '=') { + $len--; + } elseif (substr($word, $len - 2, 1) == '=') { + $len -= 2; + } + $part = substr($word, 0, $len); + $word = substr($word, $len); + $buf .= ' ' . $part; + $message .= $buf . sprintf('=%s', self::CRLF); + } else { + $message .= $buf . $soft_break; + } + $buf = ''; + } + while (strlen($word) > 0) { + if ($length <= 0) { + break; + } + $len = $length; + if ($is_utf8) { + $len = $this->utf8CharBoundary($word, $len); + } elseif (substr($word, $len - 1, 1) == '=') { + $len--; + } elseif (substr($word, $len - 2, 1) == '=') { + $len -= 2; + } + $part = substr($word, 0, $len); + $word = substr($word, $len); + + if (strlen($word) > 0) { + $message .= $part . sprintf('=%s', self::CRLF); + } else { + $buf = $part; + } + } + } else { + $buf_o = $buf; + if (!$firstword) { + $buf .= ' '; + } + $buf .= $word; + + if (strlen($buf) > $length and $buf_o != '') { + $message .= $buf_o . $soft_break; + $buf = $word; + } + } + $firstword = false; + } + $message .= $buf . self::CRLF; + } + + return $message; + } + + /** + * Find the last character boundary prior to $maxLength in a utf-8 + * quoted-printable encoded string. + * Original written by Colin Brown. + * @access public + * @param string $encodedText utf-8 QP text + * @param integer $maxLength Find the last character boundary prior to this length + * @return integer + */ + public function utf8CharBoundary($encodedText, $maxLength) + { + $foundSplitPos = false; + $lookBack = 3; + while (!$foundSplitPos) { + $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); + $encodedCharPos = strpos($lastChunk, '='); + if (false !== $encodedCharPos) { + // Found start of encoded character byte within $lookBack block. + // Check the encoded byte value (the 2 chars after the '=') + $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2); + $dec = hexdec($hex); + if ($dec < 128) { + // Single byte character. + // If the encoded char was found at pos 0, it will fit + // otherwise reduce maxLength to start of the encoded char + if ($encodedCharPos > 0) { + $maxLength = $maxLength - ($lookBack - $encodedCharPos); + } + $foundSplitPos = true; + } elseif ($dec >= 192) { + // First byte of a multi byte character + // Reduce maxLength to split at start of character + $maxLength = $maxLength - ($lookBack - $encodedCharPos); + $foundSplitPos = true; + } elseif ($dec < 192) { + // Middle byte of a multi byte character, look further back + $lookBack += 3; + } + } else { + // No encoded character found + $foundSplitPos = true; + } + } + return $maxLength; + } + + /** + * Apply word wrapping to the message body. + * Wraps the message body to the number of chars set in the WordWrap property. + * You should only do this to plain-text bodies as wrapping HTML tags may break them. + * This is called automatically by createBody(), so you don't need to call it yourself. + * @access public + * @return void + */ + public function setWordWrap() + { + if ($this->WordWrap < 1) { + return; + } + + switch ($this->message_type) { + case 'alt': + case 'alt_inline': + case 'alt_attach': + case 'alt_inline_attach': + $this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap); + break; + default: + $this->Body = $this->wrapText($this->Body, $this->WordWrap); + break; + } + } + + /** + * Assemble message headers. + * @access public + * @return string The assembled headers + */ + public function createHeader() + { + $result = ''; + + if ($this->MessageDate == '') { + $this->MessageDate = self::rfcDate(); + } + $result .= $this->headerLine('Date', $this->MessageDate); + + // To be created automatically by mail() + if ($this->SingleTo) { + if ($this->Mailer != 'mail') { + foreach ($this->to as $toaddr) { + $this->SingleToArray[] = $this->addrFormat($toaddr); + } + } } else { - @unlink($file); - @unlink($signed); - throw new phpmailerException($this->Lang("signing").openssl_error_string()); + if (count($this->to) > 0) { + if ($this->Mailer != 'mail') { + $result .= $this->addrAppend('To', $this->to); + } + } elseif (count($this->cc) == 0) { + $result .= $this->headerLine('To', 'undisclosed-recipients:;'); + } } - } catch (phpmailerException $e) { + + $result .= $this->addrAppend('From', array(array(trim($this->From), $this->FromName))); + + // sendmail and mail() extract Cc from the header before sending + if (count($this->cc) > 0) { + $result .= $this->addrAppend('Cc', $this->cc); + } + + // sendmail and mail() extract Bcc from the header before sending + if (( + $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail' + ) + and count($this->bcc) > 0 + ) { + $result .= $this->addrAppend('Bcc', $this->bcc); + } + + if (count($this->ReplyTo) > 0) { + $result .= $this->addrAppend('Reply-To', $this->ReplyTo); + } + + // mail() sets the subject itself + if ($this->Mailer != 'mail') { + $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject))); + } + + if ($this->MessageID != '') { + $this->lastMessageID = $this->MessageID; + } else { + $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname()); + } + $result .= $this->headerLine('Message-ID', $this->lastMessageID); + if (!is_null($this->Priority)) { + $result .= $this->headerLine('X-Priority', $this->Priority); + } + if ($this->XMailer == '') { + $result .= $this->headerLine( + 'X-Mailer', + 'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer)' + ); + } else { + $myXmailer = trim($this->XMailer); + if ($myXmailer) { + $result .= $this->headerLine('X-Mailer', $myXmailer); + } + } + + if ($this->ConfirmReadingTo != '') { + $result .= $this->headerLine('Disposition-Notification-To', '<' . $this->ConfirmReadingTo . '>'); + } + + // Add custom headers + foreach ($this->CustomHeader as $header) { + $result .= $this->headerLine( + trim($header[0]), + $this->encodeHeader(trim($header[1])) + ); + } + if (!$this->sign_key_file) { + $result .= $this->headerLine('MIME-Version', '1.0'); + $result .= $this->getMailMIME(); + } + + return $result; + } + + /** + * Get the message MIME type headers. + * @access public + * @return string + */ + public function getMailMIME() + { + $result = ''; + $ismultipart = true; + switch ($this->message_type) { + case 'inline': + $result .= $this->headerLine('Content-Type', 'multipart/related;'); + $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + case 'attach': + case 'inline_attach': + case 'alt_attach': + case 'alt_inline_attach': + $result .= $this->headerLine('Content-Type', 'multipart/mixed;'); + $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + case 'alt': + case 'alt_inline': + $result .= $this->headerLine('Content-Type', 'multipart/alternative;'); + $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + default: + // Catches case 'plain': and case '': + $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet); + $ismultipart = false; + break; + } + // RFC1341 part 5 says 7bit is assumed if not specified + if ($this->Encoding != '7bit') { + // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE + if ($ismultipart) { + if ($this->Encoding == '8bit') { + $result .= $this->headerLine('Content-Transfer-Encoding', '8bit'); + } + // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible + } else { + $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding); + } + } + + if ($this->Mailer != 'mail') { + $result .= $this->LE; + } + + return $result; + } + + /** + * Returns the whole MIME message. + * Includes complete headers and body. + * Only valid post preSend(). + * @see PHPMailer::preSend() + * @access public + * @return string + */ + public function getSentMIMEMessage() + { + return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody; + } + + /** + * Assemble the message body. + * Returns an empty string on failure. + * @access public + * @throws phpmailerException + * @return string The assembled message body + */ + public function createBody() + { $body = ''; - if ($this->exceptions) { - throw $e; - } - } - } - - return $body; - } - - /** - * Returns the start of a message boundary. - * @access private - */ - private function GetBoundary($boundary, $charSet, $contentType, $encoding) { - $result = ''; - if($charSet == '') { - $charSet = $this->CharSet; - } - if($contentType == '') { - $contentType = $this->ContentType; - } - if($encoding == '') { - $encoding = $this->Encoding; - } - $result .= $this->TextLine('--' . $boundary); - $result .= sprintf("Content-Type: %s; charset=%s", $contentType, $charSet); - $result .= $this->LE; - $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding); - $result .= $this->LE; - - return $result; - } - - /** - * Returns the end of a message boundary. - * @access private - */ - private function EndBoundary($boundary) { - return $this->LE . '--' . $boundary . '--' . $this->LE; - } - - /** - * Sets the message type. - * @access private - * @return void - */ - private function SetMessageType() { - if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) { - $this->message_type = 'plain'; - } else { - if(count($this->attachment) > 0) { - $this->message_type = 'attachments'; - } - if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) { - $this->message_type = 'alt'; - } - if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) { - $this->message_type = 'alt_attachments'; - } - } - } - - /** - * Returns a formatted header line. - * @access public - * @return string - */ - public function HeaderLine($name, $value) { - return $name . ': ' . $value . $this->LE; - } - - /** - * Returns a formatted mail line. - * @access public - * @return string - */ - public function TextLine($value) { - return $value . $this->LE; - } - - ///////////////////////////////////////////////// - // CLASS METHODS, ATTACHMENTS - ///////////////////////////////////////////////// - - /** - * Adds an attachment from a path on the filesystem. - * Returns false if the file could not be found - * or accessed. - * @param string $path Path to the attachment. - * @param string $name Overrides the attachment name. - * @param string $encoding File encoding (see $Encoding). - * @param string $type File extension (MIME) type. - * @return bool - */ - public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { - try { - if ( !@is_file($path) ) { - throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE); - } - $filename = basename($path); - if ( $name == '' ) { - $name = $filename; - } - - $this->attachment[] = array( - 0 => $path, - 1 => $filename, - 2 => $name, - 3 => $encoding, - 4 => $type, - 5 => false, // isStringAttachment - 6 => 'attachment', - 7 => 0 - ); - - } catch (phpmailerException $e) { - $this->SetError($e->getMessage()); - if ($this->exceptions) { - throw $e; - } - echo $e->getMessage()."\n"; - if ( $e->getCode() == self::STOP_CRITICAL ) { - return false; - } - } - return true; - } - - /** - * Return the current array of attachments - * @return array - */ - public function GetAttachments() { - return $this->attachment; - } - - /** - * Attaches all fs, string, and binary attachments to the message. - * Returns an empty string on failure. - * @access private - * @return string - */ - private function AttachAll() { - // Return text of body - $mime = array(); - $cidUniq = array(); - $incl = array(); - - // Add all attachments - foreach ($this->attachment as $attachment) { - // Check for string attachment - $bString = $attachment[5]; - if ($bString) { - $string = $attachment[0]; - } else { - $path = $attachment[0]; - } - - if (in_array($attachment[0], $incl)) { continue; } - $filename = $attachment[1]; - $name = $attachment[2]; - $encoding = $attachment[3]; - $type = $attachment[4]; - $disposition = $attachment[6]; - $cid = $attachment[7]; - $incl[] = $attachment[0]; - if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; } - $cidUniq[$cid] = true; - - $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE); - $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE); - $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); - - if($disposition == 'inline') { - $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); - } - - $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); - - // Encode as string attachment - if($bString) { - $mime[] = $this->EncodeString($string, $encoding); - if($this->IsError()) { - return ''; - } - $mime[] = $this->LE.$this->LE; - } else { - $mime[] = $this->EncodeFile($path, $encoding); - if($this->IsError()) { - return ''; - } - $mime[] = $this->LE.$this->LE; - } - } - - $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE); - - return join('', $mime); - } - - /** - * Encodes attachment in requested format. - * Returns an empty string on failure. - * @param string $path The full path to the file - * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' - * @see EncodeFile() - * @access private - * @return string - */ - private function EncodeFile($path, $encoding = 'base64') { - try { - if (!is_readable($path)) { - throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE); - } - if (!function_exists('get_magic_quotes')) { - function get_magic_quotes() { - return false; - } - } - if (PHP_VERSION < 6 - AND $magic_quotes = get_magic_quotes_runtime()) { - set_magic_quotes_runtime(0); - } - $file_buffer = file_get_contents($path); - $file_buffer = $this->EncodeString($file_buffer, $encoding); - if (PHP_VERSION < 6 AND $magic_quotes) { set_magic_quotes_runtime($magic_quotes); } - return $file_buffer; - } catch (Exception $e) { - $this->SetError($e->getMessage()); - return ''; - } - } - - /** - * Encodes string to requested format. - * Returns an empty string on failure. - * @param string $str The text to encode - * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' - * @access public - * @return string - */ - public function EncodeString ($str, $encoding = 'base64') { - $encoded = ''; - switch(strtolower($encoding)) { - case 'base64': - $encoded = chunk_split(base64_encode($str), 76, $this->LE); - break; - case '7bit': - case '8bit': - $encoded = $this->FixEOL($str); - //Make sure it ends with a line break - if (substr($encoded, -(strlen($this->LE))) != $this->LE) - $encoded .= $this->LE; - break; - case 'binary': - $encoded = $str; - break; - case 'quoted-printable': - $encoded = $this->EncodeQP($str); - break; - default: - $this->SetError($this->Lang('encoding') . $encoding); - break; - } - return $encoded; - } - - /** - * Encode a header string to best (shortest) of Q, B, quoted or none. - * @access public - * @return string - */ - public function EncodeHeader($str, $position = 'text') { - $x = 0; - - switch (strtolower($position)) { - case 'phrase': - if (!preg_match('/[\200-\377]/', $str)) { - // Can't use addslashes as we don't know what value has magic_quotes_sybase - $encoded = addcslashes($str, "\0..\37\177\\\""); - if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { - return ($encoded); - } else { - return ("\"$encoded\""); - } - } - $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); - break; - case 'comment': - $x = preg_match_all('/[()"]/', $str, $matches); - // Fall-through - case 'text': - default: - $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); - break; - } - - if ($x == 0) { - return ($str); - } - - $maxlen = 75 - 7 - strlen($this->CharSet); - // Try to select the encoding which should produce the shortest output - if (strlen($str)/3 < $x) { - $encoding = 'B'; - if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) { - // Use a custom function which correctly encodes and wraps long - // multibyte strings without breaking lines within a character - $encoded = $this->Base64EncodeWrapMB($str); - } else { - $encoded = base64_encode($str); - $maxlen -= $maxlen % 4; - $encoded = trim(chunk_split($encoded, $maxlen, "\n")); - } - } else { - $encoding = 'Q'; - $encoded = $this->EncodeQ($str, $position); - $encoded = $this->WrapText($encoded, $maxlen, true); - $encoded = str_replace('='.$this->LE, "\n", trim($encoded)); - } - - $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded); - $encoded = trim(str_replace("\n", $this->LE, $encoded)); - - return $encoded; - } - - /** - * Checks if a string contains multibyte characters. - * @access public - * @param string $str multi-byte text to wrap encode - * @return bool - */ - public function HasMultiBytes($str) { - if (function_exists('mb_strlen')) { - return (strlen($str) > mb_strlen($str, $this->CharSet)); - } else { // Assume no multibytes (we can't handle without mbstring functions anyway) - return false; - } - } - - /** - * Correctly encodes and wraps long multibyte strings for mail headers - * without breaking lines within a character. - * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php - * @access public - * @param string $str multi-byte text to wrap encode - * @return string - */ - public function Base64EncodeWrapMB($str) { - $start = "=?".$this->CharSet."?B?"; - $end = "?="; - $encoded = ""; - - $mb_length = mb_strlen($str, $this->CharSet); - // Each line must have length <= 75, including $start and $end - $length = 75 - strlen($start) - strlen($end); - // Average multi-byte ratio - $ratio = $mb_length / strlen($str); - // Base64 has a 4:3 ratio - $offset = $avgLength = floor($length * $ratio * .75); - - for ($i = 0; $i < $mb_length; $i += $offset) { - $lookBack = 0; - - do { - $offset = $avgLength - $lookBack; - $chunk = mb_substr($str, $i, $offset, $this->CharSet); - $chunk = base64_encode($chunk); - $lookBack++; - } - while (strlen($chunk) > $length); - - $encoded .= $chunk . $this->LE; - } - - // Chomp the last linefeed - $encoded = substr($encoded, 0, -strlen($this->LE)); - return $encoded; - } - - /** - * Encode string to quoted-printable. - * Only uses standard PHP, slow, but will always work - * @access public - * @param string $string the text to encode - * @param integer $line_max Number of chars allowed on a line before wrapping - * @return string - */ - public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) { - $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'); - $lines = preg_split('/(?:\r\n|\r|\n)/', $input); - $eol = "\r\n"; - $escape = '='; - $output = ''; - while( list(, $line) = each($lines) ) { - $linlen = strlen($line); - $newline = ''; - for($i = 0; $i < $linlen; $i++) { - $c = substr( $line, $i, 1 ); - $dec = ord( $c ); - if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E - $c = '=2E'; - } - if ( $dec == 32 ) { - if ( $i == ( $linlen - 1 ) ) { // convert space at eol only - $c = '=20'; - } else if ( $space_conv ) { - $c = '=20'; - } - } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required - $h2 = floor($dec/16); - $h1 = floor($dec%16); - $c = $escape.$hex[$h2].$hex[$h1]; - } - if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted - $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay - $newline = ''; - // check if newline first character will be point or not - if ( $dec == 46 ) { - $c = '=2E'; - } - } - $newline .= $c; - } // end of for - $output .= $newline.$eol; - } // end of while - return $output; - } - - /** - * Encode string to RFC2045 (6.7) quoted-printable format - * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version - * Also results in same content as you started with after decoding - * @see EncodeQPphp() - * @access public - * @param string $string the text to encode - * @param integer $line_max Number of chars allowed on a line before wrapping - * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function - * @return string - * @author Marcus Bointon - */ - public function EncodeQP($string, $line_max = 76, $space_conv = false) { - if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3) - return quoted_printable_encode($string); - } - $filters = stream_get_filters(); - if (!in_array('convert.*', $filters)) { //Got convert stream filter? - return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation - } - $fp = fopen('php://temp/', 'r+'); - $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks - $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE); - $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params); - fputs($fp, $string); - rewind($fp); - $out = stream_get_contents($fp); - stream_filter_remove($s); - $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange - fclose($fp); - return $out; - } - - /** - * Encode string to q encoding. - * @link http://tools.ietf.org/html/rfc2047 - * @param string $str the text to encode - * @param string $position Where the text is going to be used, see the RFC for what that means - * @access public - * @return string - */ - public function EncodeQ ($str, $position = 'text') { - // There should not be any EOL in the string - $encoded = preg_replace('/[\r\n]*/', '', $str); - - switch (strtolower($position)) { - case 'phrase': - $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); - break; - case 'comment': - $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded); - case 'text': - default: - // Replace every high ascii, control =, ? and _ characters - //TODO using /e (equivalent to eval()) is probably not a good idea - $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e', - "'='.sprintf('%02X', ord('\\1'))", $encoded); - break; - } - - // Replace every spaces to _ (more readable than =20) - $encoded = str_replace(' ', '_', $encoded); - - return $encoded; - } - - /** - * Adds a string or binary attachment (non-filesystem) to the list. - * This method can be used to attach ascii or binary data, - * such as a BLOB record from a database. - * @param string $string String attachment data. - * @param string $filename Name of the attachment. - * @param string $encoding File encoding (see $Encoding). - * @param string $type File extension (MIME) type. - * @return void - */ - public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') { - // Append to $attachment array - $this->attachment[] = array( - 0 => $string, - 1 => $filename, - 2 => basename($filename), - 3 => $encoding, - 4 => $type, - 5 => true, // isStringAttachment - 6 => 'attachment', - 7 => 0 - ); - } - - /** - * Adds an embedded attachment. This can include images, sounds, and - * just about any other document. Make sure to set the $type to an - * image type. For JPEG images use "image/jpeg" and for GIF images - * use "image/gif". - * @param string $path Path to the attachment. - * @param string $cid Content ID of the attachment. Use this to identify - * the Id for accessing the image in an HTML form. - * @param string $name Overrides the attachment name. - * @param string $encoding File encoding (see $Encoding). - * @param string $type File extension (MIME) type. - * @return bool - */ - public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') { - - if ( !@is_file($path) ) { - $this->SetError($this->Lang('file_access') . $path); - return false; - } - - $filename = basename($path); - if ( $name == '' ) { - $name = $filename; - } - - // Append to $attachment array - $this->attachment[] = array( - 0 => $path, - 1 => $filename, - 2 => $name, - 3 => $encoding, - 4 => $type, - 5 => false, // isStringAttachment - 6 => 'inline', - 7 => $cid - ); - - return true; - } - - /** - * Returns true if an inline attachment is present. - * @access public - * @return bool - */ - public function InlineImageExists() { - foreach($this->attachment as $attachment) { - if ($attachment[6] == 'inline') { + //Create unique IDs and preset boundaries + $this->uniqueid = md5(uniqid(time())); + $this->boundary[1] = 'b1_' . $this->uniqueid; + $this->boundary[2] = 'b2_' . $this->uniqueid; + $this->boundary[3] = 'b3_' . $this->uniqueid; + + if ($this->sign_key_file) { + $body .= $this->getMailMIME() . $this->LE; + } + + $this->setWordWrap(); + + $bodyEncoding = $this->Encoding; + $bodyCharSet = $this->CharSet; + //Can we do a 7-bit downgrade? + if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) { + $bodyEncoding = '7bit'; + $bodyCharSet = 'us-ascii'; + } + //If lines are too long, and we're not already using an encoding that will shorten them, + //change to quoted-printable transfer encoding + if ('base64' != $this->Encoding and self::hasLineLongerThanMax($this->Body)) { + $this->Encoding = 'quoted-printable'; + $bodyEncoding = 'quoted-printable'; + } + + $altBodyEncoding = $this->Encoding; + $altBodyCharSet = $this->CharSet; + //Can we do a 7-bit downgrade? + if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) { + $altBodyEncoding = '7bit'; + $altBodyCharSet = 'us-ascii'; + } + //If lines are too long, change to quoted-printable transfer encoding + if (self::hasLineLongerThanMax($this->AltBody)) { + $altBodyEncoding = 'quoted-printable'; + } + //Use this as a preamble in all multipart message types + $mimepre = "This is a multi-part message in MIME format." . $this->LE . $this->LE; + switch ($this->message_type) { + case 'inline': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[1]); + break; + case 'attach': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + case 'inline_attach': + $body .= $mimepre; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/related;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[2]); + $body .= $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + case 'alt': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + if (!empty($this->Ical)) { + $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', ''); + $body .= $this->encodeString($this->Ical, $this->Encoding); + $body .= $this->LE . $this->LE; + } + $body .= $this->endBoundary($this->boundary[1]); + break; + case 'alt_inline': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/related;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[2]); + $body .= $this->LE; + $body .= $this->endBoundary($this->boundary[1]); + break; + case 'alt_attach': + $body .= $mimepre; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->endBoundary($this->boundary[2]); + $body .= $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + case 'alt_inline_attach': + $body .= $mimepre; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->textLine('--' . $this->boundary[2]); + $body .= $this->headerLine('Content-Type', 'multipart/related;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[3]); + $body .= $this->LE; + $body .= $this->endBoundary($this->boundary[2]); + $body .= $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + default: + // catch case 'plain' and case '' + $body .= $this->encodeString($this->Body, $bodyEncoding); + break; + } + + if ($this->isError()) { + $body = ''; + } elseif ($this->sign_key_file) { + try { + if (!defined('PKCS7_TEXT')) { + throw new phpmailerException($this->lang('extension_missing') . 'openssl'); + } + // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1 + $file = tempnam(sys_get_temp_dir(), 'mail'); + if (false === file_put_contents($file, $body)) { + throw new phpmailerException($this->lang('signing') . ' Could not write temp file'); + } + $signed = tempnam(sys_get_temp_dir(), 'signed'); + //Workaround for PHP bug https://bugs.php.net/bug.php?id=69197 + if (empty($this->sign_extracerts_file)) { + $sign = @openssl_pkcs7_sign( + $file, + $signed, + 'file://' . realpath($this->sign_cert_file), + array('file://' . realpath($this->sign_key_file), $this->sign_key_pass), + null + ); + } else { + $sign = @openssl_pkcs7_sign( + $file, + $signed, + 'file://' . realpath($this->sign_cert_file), + array('file://' . realpath($this->sign_key_file), $this->sign_key_pass), + null, + PKCS7_DETACHED, + $this->sign_extracerts_file + ); + } + if ($sign) { + @unlink($file); + $body = file_get_contents($signed); + @unlink($signed); + //The message returned by openssl contains both headers and body, so need to split them up + $parts = explode("\n\n", $body, 2); + $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE; + $body = $parts[1]; + } else { + @unlink($file); + @unlink($signed); + throw new phpmailerException($this->lang('signing') . openssl_error_string()); + } + } catch (phpmailerException $exc) { + $body = ''; + if ($this->exceptions) { + throw $exc; + } + } + } + return $body; + } + + /** + * Return the start of a message boundary. + * @access protected + * @param string $boundary + * @param string $charSet + * @param string $contentType + * @param string $encoding + * @return string + */ + protected function getBoundary($boundary, $charSet, $contentType, $encoding) + { + $result = ''; + if ($charSet == '') { + $charSet = $this->CharSet; + } + if ($contentType == '') { + $contentType = $this->ContentType; + } + if ($encoding == '') { + $encoding = $this->Encoding; + } + $result .= $this->textLine('--' . $boundary); + $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet); + $result .= $this->LE; + // RFC1341 part 5 says 7bit is assumed if not specified + if ($encoding != '7bit') { + $result .= $this->headerLine('Content-Transfer-Encoding', $encoding); + } + $result .= $this->LE; + + return $result; + } + + /** + * Return the end of a message boundary. + * @access protected + * @param string $boundary + * @return string + */ + protected function endBoundary($boundary) + { + return $this->LE . '--' . $boundary . '--' . $this->LE; + } + + /** + * Set the message type. + * PHPMailer only supports some preset message types, + * not arbitrary MIME structures. + * @access protected + * @return void + */ + protected function setMessageType() + { + $type = array(); + if ($this->alternativeExists()) { + $type[] = 'alt'; + } + if ($this->inlineImageExists()) { + $type[] = 'inline'; + } + if ($this->attachmentExists()) { + $type[] = 'attach'; + } + $this->message_type = implode('_', $type); + if ($this->message_type == '') { + $this->message_type = 'plain'; + } + } + + /** + * Format a header line. + * @access public + * @param string $name + * @param string $value + * @return string + */ + public function headerLine($name, $value) + { + return $name . ': ' . $value . $this->LE; + } + + /** + * Return a formatted mail line. + * @access public + * @param string $value + * @return string + */ + public function textLine($value) + { + return $value . $this->LE; + } + + /** + * Add an attachment from a path on the filesystem. + * Returns false if the file could not be found or read. + * @param string $path Path to the attachment. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @param string $disposition Disposition to use + * @throws phpmailerException + * @return boolean + */ + public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') + { + try { + if (!@is_file($path)) { + throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE); + } + + // If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($path); + } + + $filename = basename($path); + if ($name == '') { + $name = $filename; + } + + $this->attachment[] = array( + 0 => $path, + 1 => $filename, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => false, // isStringAttachment + 6 => $disposition, + 7 => 0 + ); + + } catch (phpmailerException $exc) { + $this->setError($exc->getMessage()); + $this->edebug($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + return false; + } + return true; + } + + /** + * Return the array of attachments. + * @return array + */ + public function getAttachments() + { + return $this->attachment; + } + + /** + * Attach all file, string, and binary attachments to the message. + * Returns an empty string on failure. + * @access protected + * @param string $disposition_type + * @param string $boundary + * @return string + */ + protected function attachAll($disposition_type, $boundary) + { + // Return text of body + $mime = array(); + $cidUniq = array(); + $incl = array(); + + // Add all attachments + foreach ($this->attachment as $attachment) { + // Check if it is a valid disposition_filter + if ($attachment[6] == $disposition_type) { + // Check for string attachment + $string = ''; + $path = ''; + $bString = $attachment[5]; + if ($bString) { + $string = $attachment[0]; + } else { + $path = $attachment[0]; + } + + $inclhash = md5(serialize($attachment)); + if (in_array($inclhash, $incl)) { + continue; + } + $incl[] = $inclhash; + $name = $attachment[2]; + $encoding = $attachment[3]; + $type = $attachment[4]; + $disposition = $attachment[6]; + $cid = $attachment[7]; + if ($disposition == 'inline' && array_key_exists($cid, $cidUniq)) { + continue; + } + $cidUniq[$cid] = true; + + $mime[] = sprintf('--%s%s', $boundary, $this->LE); + //Only include a filename property if we have one + if (!empty($name)) { + $mime[] = sprintf( + 'Content-Type: %s; name="%s"%s', + $type, + $this->encodeHeader($this->secureHeader($name)), + $this->LE + ); + } else { + $mime[] = sprintf( + 'Content-Type: %s%s', + $type, + $this->LE + ); + } + // RFC1341 part 5 says 7bit is assumed if not specified + if ($encoding != '7bit') { + $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE); + } + + if ($disposition == 'inline') { + $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE); + } + + // If a filename contains any of these chars, it should be quoted, + // but not otherwise: RFC2183 & RFC2045 5.1 + // Fixes a warning in IETF's msglint MIME checker + // Allow for bypassing the Content-Disposition header totally + if (!(empty($disposition))) { + $encoded_name = $this->encodeHeader($this->secureHeader($name)); + if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) { + $mime[] = sprintf( + 'Content-Disposition: %s; filename="%s"%s', + $disposition, + $encoded_name, + $this->LE . $this->LE + ); + } else { + if (!empty($encoded_name)) { + $mime[] = sprintf( + 'Content-Disposition: %s; filename=%s%s', + $disposition, + $encoded_name, + $this->LE . $this->LE + ); + } else { + $mime[] = sprintf( + 'Content-Disposition: %s%s', + $disposition, + $this->LE . $this->LE + ); + } + } + } else { + $mime[] = $this->LE; + } + + // Encode as string attachment + if ($bString) { + $mime[] = $this->encodeString($string, $encoding); + if ($this->isError()) { + return ''; + } + $mime[] = $this->LE . $this->LE; + } else { + $mime[] = $this->encodeFile($path, $encoding); + if ($this->isError()) { + return ''; + } + $mime[] = $this->LE . $this->LE; + } + } + } + + $mime[] = sprintf('--%s--%s', $boundary, $this->LE); + + return implode('', $mime); + } + + /** + * Encode a file attachment in requested format. + * Returns an empty string on failure. + * @param string $path The full path to the file + * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * @throws phpmailerException + * @access protected + * @return string + */ + protected function encodeFile($path, $encoding = 'base64') + { + try { + if (!is_readable($path)) { + throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE); + } + $magic_quotes = get_magic_quotes_runtime(); + if ($magic_quotes) { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + set_magic_quotes_runtime(false); + } else { + //Doesn't exist in PHP 5.4, but we don't need to check because + //get_magic_quotes_runtime always returns false in 5.4+ + //so it will never get here + ini_set('magic_quotes_runtime', false); + } + } + $file_buffer = file_get_contents($path); + $file_buffer = $this->encodeString($file_buffer, $encoding); + if ($magic_quotes) { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + set_magic_quotes_runtime($magic_quotes); + } else { + ini_set('magic_quotes_runtime', $magic_quotes); + } + } + return $file_buffer; + } catch (Exception $exc) { + $this->setError($exc->getMessage()); + return ''; + } + } + + /** + * Encode a string in requested format. + * Returns an empty string on failure. + * @param string $str The text to encode + * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * @access public + * @return string + */ + public function encodeString($str, $encoding = 'base64') + { + $encoded = ''; + switch (strtolower($encoding)) { + case 'base64': + $encoded = chunk_split(base64_encode($str), 76, $this->LE); + break; + case '7bit': + case '8bit': + $encoded = $this->fixEOL($str); + // Make sure it ends with a line break + if (substr($encoded, -(strlen($this->LE))) != $this->LE) { + $encoded .= $this->LE; + } + break; + case 'binary': + $encoded = $str; + break; + case 'quoted-printable': + $encoded = $this->encodeQP($str); + break; + default: + $this->setError($this->lang('encoding') . $encoding); + break; + } + return $encoded; + } + + /** + * Encode a header string optimally. + * Picks shortest of Q, B, quoted-printable or none. + * @access public + * @param string $str + * @param string $position + * @return string + */ + public function encodeHeader($str, $position = 'text') + { + $matchcount = 0; + switch (strtolower($position)) { + case 'phrase': + if (!preg_match('/[\200-\377]/', $str)) { + // Can't use addslashes as we don't know the value of magic_quotes_sybase + $encoded = addcslashes($str, "\0..\37\177\\\""); + if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { + return ($encoded); + } else { + return ("\"$encoded\""); + } + } + $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); + break; + /** @noinspection PhpMissingBreakStatementInspection */ + case 'comment': + $matchcount = preg_match_all('/[()"]/', $str, $matches); + // Intentional fall-through + case 'text': + default: + $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); + break; + } + + //There are no chars that need encoding + if ($matchcount == 0) { + return ($str); + } + + $maxlen = 75 - 7 - strlen($this->CharSet); + // Try to select the encoding which should produce the shortest output + if ($matchcount > strlen($str) / 3) { + // More than a third of the content will need encoding, so B encoding will be most efficient + $encoding = 'B'; + if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) { + // Use a custom function which correctly encodes and wraps long + // multibyte strings without breaking lines within a character + $encoded = $this->base64EncodeWrapMB($str, "\n"); + } else { + $encoded = base64_encode($str); + $maxlen -= $maxlen % 4; + $encoded = trim(chunk_split($encoded, $maxlen, "\n")); + } + } else { + $encoding = 'Q'; + $encoded = $this->encodeQ($str, $position); + $encoded = $this->wrapText($encoded, $maxlen, true); + $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded)); + } + + $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded); + $encoded = trim(str_replace("\n", $this->LE, $encoded)); + + return $encoded; + } + + /** + * Check if a string contains multi-byte characters. + * @access public + * @param string $str multi-byte text to wrap encode + * @return boolean + */ + public function hasMultiBytes($str) + { + if (function_exists('mb_strlen')) { + return (strlen($str) > mb_strlen($str, $this->CharSet)); + } else { // Assume no multibytes (we can't handle without mbstring functions anyway) + return false; + } + } + + /** + * Does a string contain any 8-bit chars (in any charset)? + * @param string $text + * @return boolean + */ + public function has8bitChars($text) + { + return (boolean)preg_match('/[\x80-\xFF]/', $text); + } + + /** + * Encode and wrap long multibyte strings for mail headers + * without breaking lines within a character. + * Adapted from a function by paravoid + * @link http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283 + * @access public + * @param string $str multi-byte text to wrap encode + * @param string $linebreak string to use as linefeed/end-of-line + * @return string + */ + public function base64EncodeWrapMB($str, $linebreak = null) + { + $start = '=?' . $this->CharSet . '?B?'; + $end = '?='; + $encoded = ''; + if ($linebreak === null) { + $linebreak = $this->LE; + } + + $mb_length = mb_strlen($str, $this->CharSet); + // Each line must have length <= 75, including $start and $end + $length = 75 - strlen($start) - strlen($end); + // Average multi-byte ratio + $ratio = $mb_length / strlen($str); + // Base64 has a 4:3 ratio + $avgLength = floor($length * $ratio * .75); + + for ($i = 0; $i < $mb_length; $i += $offset) { + $lookBack = 0; + do { + $offset = $avgLength - $lookBack; + $chunk = mb_substr($str, $i, $offset, $this->CharSet); + $chunk = base64_encode($chunk); + $lookBack++; + } while (strlen($chunk) > $length); + $encoded .= $chunk . $linebreak; + } + + // Chomp the last linefeed + $encoded = substr($encoded, 0, -strlen($linebreak)); + return $encoded; + } + + /** + * Encode a string in quoted-printable format. + * According to RFC2045 section 6.7. + * @access public + * @param string $string The text to encode + * @param integer $line_max Number of chars allowed on a line before wrapping + * @return string + * @link http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 Adapted from this comment + */ + public function encodeQP($string, $line_max = 76) + { + // Use native function if it's available (>= PHP5.3) + if (function_exists('quoted_printable_encode')) { + return quoted_printable_encode($string); + } + // Fall back to a pure PHP implementation + $string = str_replace( + array('%20', '%0D%0A.', '%0D%0A', '%'), + array(' ', "\r\n=2E", "\r\n", '='), + rawurlencode($string) + ); + return preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string); + } + + /** + * Backward compatibility wrapper for an old QP encoding function that was removed. + * @see PHPMailer::encodeQP() + * @access public + * @param string $string + * @param integer $line_max + * @param boolean $space_conv + * @return string + * @deprecated Use encodeQP instead. + */ + public function encodeQPphp( + $string, + $line_max = 76, + /** @noinspection PhpUnusedParameterInspection */ $space_conv = false + ) { + return $this->encodeQP($string, $line_max); + } + + /** + * Encode a string using Q encoding. + * @link http://tools.ietf.org/html/rfc2047 + * @param string $str the text to encode + * @param string $position Where the text is going to be used, see the RFC for what that means + * @access public + * @return string + */ + public function encodeQ($str, $position = 'text') + { + // There should not be any EOL in the string + $pattern = ''; + $encoded = str_replace(array("\r", "\n"), '', $str); + switch (strtolower($position)) { + case 'phrase': + // RFC 2047 section 5.3 + $pattern = '^A-Za-z0-9!*+\/ -'; + break; + /** @noinspection PhpMissingBreakStatementInspection */ + case 'comment': + // RFC 2047 section 5.2 + $pattern = '\(\)"'; + // intentional fall-through + // for this reason we build the $pattern without including delimiters and [] + case 'text': + default: + // RFC 2047 section 5.1 + // Replace every high ascii, control, =, ? and _ characters + $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern; + break; + } + $matches = array(); + if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) { + // If the string contains an '=', make sure it's the first thing we replace + // so as to avoid double-encoding + $eqkey = array_search('=', $matches[0]); + if (false !== $eqkey) { + unset($matches[0][$eqkey]); + array_unshift($matches[0], '='); + } + foreach (array_unique($matches[0]) as $char) { + $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded); + } + } + // Replace every spaces to _ (more readable than =20) + return str_replace(' ', '_', $encoded); + } + + /** + * Add a string or binary attachment (non-filesystem). + * This method can be used to attach ascii or binary data, + * such as a BLOB record from a database. + * @param string $string String attachment data. + * @param string $filename Name of the attachment. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @param string $disposition Disposition to use + * @return void + */ + public function addStringAttachment( + $string, + $filename, + $encoding = 'base64', + $type = '', + $disposition = 'attachment' + ) { + // If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($filename); + } + // Append to $attachment array + $this->attachment[] = array( + 0 => $string, + 1 => $filename, + 2 => basename($filename), + 3 => $encoding, + 4 => $type, + 5 => true, // isStringAttachment + 6 => $disposition, + 7 => 0 + ); + } + + /** + * Add an embedded (inline) attachment from a file. + * This can include images, sounds, and just about any other document type. + * These differ from 'regular' attachments in that they are intended to be + * displayed inline with the message, not just attached for download. + * This is used in HTML messages that embed the images + * the HTML refers to using the $cid value. + * @param string $path Path to the attachment. + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File MIME type. + * @param string $disposition Disposition to use + * @return boolean True on successfully adding an attachment + */ + public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') + { + if (!@is_file($path)) { + $this->setError($this->lang('file_access') . $path); + return false; + } + + // If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($path); + } + + $filename = basename($path); + if ($name == '') { + $name = $filename; + } + + // Append to $attachment array + $this->attachment[] = array( + 0 => $path, + 1 => $filename, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => false, // isStringAttachment + 6 => $disposition, + 7 => $cid + ); return true; - } - } - return false; - } - - ///////////////////////////////////////////////// - // CLASS METHODS, MESSAGE RESET - ///////////////////////////////////////////////// - - /** - * Clears all recipients assigned in the TO array. Returns void. - * @return void - */ - public function ClearAddresses() { - foreach($this->to as $to) { - unset($this->all_recipients[strtolower($to[0])]); - } - $this->to = array(); - } - - /** - * Clears all recipients assigned in the CC array. Returns void. - * @return void - */ - public function ClearCCs() { - foreach($this->cc as $cc) { - unset($this->all_recipients[strtolower($cc[0])]); - } - $this->cc = array(); - } - - /** - * Clears all recipients assigned in the BCC array. Returns void. - * @return void - */ - public function ClearBCCs() { - foreach($this->bcc as $bcc) { - unset($this->all_recipients[strtolower($bcc[0])]); - } - $this->bcc = array(); - } - - /** - * Clears all recipients assigned in the ReplyTo array. Returns void. - * @return void - */ - public function ClearReplyTos() { - $this->ReplyTo = array(); - } - - /** - * Clears all recipients assigned in the TO, CC and BCC - * array. Returns void. - * @return void - */ - public function ClearAllRecipients() { - $this->to = array(); - $this->cc = array(); - $this->bcc = array(); - $this->all_recipients = array(); - } - - /** - * Clears all previously set filesystem, string, and binary - * attachments. Returns void. - * @return void - */ - public function ClearAttachments() { - $this->attachment = array(); - } - - /** - * Clears all custom headers. Returns void. - * @return void - */ - public function ClearCustomHeaders() { - $this->CustomHeader = array(); - } - - ///////////////////////////////////////////////// - // CLASS METHODS, MISCELLANEOUS - ///////////////////////////////////////////////// - - /** - * Adds the error message to the error container. - * @access protected - * @return void - */ - protected function SetError($msg) { - $this->error_count++; - if ($this->Mailer == 'smtp' and !is_null($this->smtp)) { - $lasterror = $this->smtp->getError(); - if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) { - $msg .= '

                  ' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "

                  \n"; - } - } - $this->ErrorInfo = $msg; - } - - /** - * Returns the proper RFC 822 formatted date. - * @access public - * @return string - * @static - */ - public static function RFCDate() { - $tz = date('Z'); - $tzs = ($tz < 0) ? '-' : '+'; - $tz = abs($tz); - $tz = (int)($tz/3600)*100 + ($tz%3600)/60; - $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz); - - return $result; - } - - /** - * Returns the server hostname or 'localhost.localdomain' if unknown. - * @access private - * @return string - */ - private function ServerHostname() { - if (!empty($this->Hostname)) { - $result = $this->Hostname; - } elseif (isset($_SERVER['SERVER_NAME'])) { - $result = $_SERVER['SERVER_NAME']; - } else { - $result = 'localhost.localdomain'; - } - - return $result; - } - - /** - * Returns a message in the appropriate language. - * @access private - * @return string - */ - private function Lang($key) { - if(count($this->language) < 1) { - $this->SetLanguage('en'); // set the default language - } - - if(isset($this->language[$key])) { - return $this->language[$key]; - } else { - return 'Language string failed to load: ' . $key; - } - } - - /** - * Returns true if an error occurred. - * @access public - * @return bool - */ - public function IsError() { - return ($this->error_count > 0); - } - - /** - * Changes every end of line from CR or LF to CRLF. - * @access private - * @return string - */ - private function FixEOL($str) { - $str = str_replace("\r\n", "\n", $str); - $str = str_replace("\r", "\n", $str); - $str = str_replace("\n", $this->LE, $str); - return $str; - } - - /** - * Adds a custom header. - * @access public - * @return void - */ - public function AddCustomHeader($custom_header) { - $this->CustomHeader[] = explode(':', $custom_header, 2); - } - - /** - * Evaluates the message and returns modifications for inline images and backgrounds - * @access public - * @return $message - */ - public function MsgHTML($message, $basedir = '') { - preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images); - if(isset($images[2])) { - foreach($images[2] as $i => $url) { - // do not change urls for absolute images (thanks to corvuscorax) - if (!preg_match('#^[A-z]+://#',$url)) { - $filename = basename($url); - $directory = dirname($url); - ($directory == '.')?$directory='':''; - $cid = 'cid:' . md5($filename); - $ext = pathinfo($filename, PATHINFO_EXTENSION); - $mimeType = self::_mime_types($ext); - if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; } - if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; } - if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) { - $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message); - } - } - } - } - $this->IsHTML(true); - $this->Body = $message; - $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message))); - if (!empty($textMsg) && empty($this->AltBody)) { - $this->AltBody = html_entity_decode($textMsg,ENT_COMPAT | ENT_HTML401, strtoupper($this->CharSet)); - } - if (empty($this->AltBody)) { - $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n"; - } - } - - /** - * Gets the MIME type of the embedded or inline image - * @param string File extension - * @access public - * @return string MIME type of ext - * @static - */ - public static function _mime_types($ext = '') { - $mimes = array( - 'hqx' => 'application/mac-binhex40', - 'cpt' => 'application/mac-compactpro', - 'doc' => 'application/msword', - 'bin' => 'application/macbinary', - 'dms' => 'application/octet-stream', - 'lha' => 'application/octet-stream', - 'lzh' => 'application/octet-stream', - 'exe' => 'application/octet-stream', - 'class' => 'application/octet-stream', - 'psd' => 'application/octet-stream', - 'so' => 'application/octet-stream', - 'sea' => 'application/octet-stream', - 'dll' => 'application/octet-stream', - 'oda' => 'application/oda', - 'pdf' => 'application/pdf', - 'ai' => 'application/postscript', - 'eps' => 'application/postscript', - 'ps' => 'application/postscript', - 'smi' => 'application/smil', - 'smil' => 'application/smil', - 'mif' => 'application/vnd.mif', - 'xls' => 'application/vnd.ms-excel', - 'ppt' => 'application/vnd.ms-powerpoint', - 'wbxml' => 'application/vnd.wap.wbxml', - 'wmlc' => 'application/vnd.wap.wmlc', - 'dcr' => 'application/x-director', - 'dir' => 'application/x-director', - 'dxr' => 'application/x-director', - 'dvi' => 'application/x-dvi', - 'gtar' => 'application/x-gtar', - 'php' => 'application/x-httpd-php', - 'php4' => 'application/x-httpd-php', - 'php3' => 'application/x-httpd-php', - 'phtml' => 'application/x-httpd-php', - 'phps' => 'application/x-httpd-php-source', - 'js' => 'application/x-javascript', - 'swf' => 'application/x-shockwave-flash', - 'sit' => 'application/x-stuffit', - 'tar' => 'application/x-tar', - 'tgz' => 'application/x-tar', - 'xhtml' => 'application/xhtml+xml', - 'xht' => 'application/xhtml+xml', - 'zip' => 'application/zip', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mpga' => 'audio/mpeg', - 'mp2' => 'audio/mpeg', - 'mp3' => 'audio/mpeg', - 'aif' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'ram' => 'audio/x-pn-realaudio', - 'rm' => 'audio/x-pn-realaudio', - 'rpm' => 'audio/x-pn-realaudio-plugin', - 'ra' => 'audio/x-realaudio', - 'rv' => 'video/vnd.rn-realvideo', - 'wav' => 'audio/x-wav', - 'bmp' => 'image/bmp', - 'gif' => 'image/gif', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'jpe' => 'image/jpeg', - 'png' => 'image/png', - 'tiff' => 'image/tiff', - 'tif' => 'image/tiff', - 'css' => 'text/css', - 'html' => 'text/html', - 'htm' => 'text/html', - 'shtml' => 'text/html', - 'txt' => 'text/plain', - 'text' => 'text/plain', - 'log' => 'text/plain', - 'rtx' => 'text/richtext', - 'rtf' => 'text/rtf', - 'xml' => 'text/xml', - 'xsl' => 'text/xml', - 'mpeg' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mpe' => 'video/mpeg', - 'qt' => 'video/quicktime', - 'mov' => 'video/quicktime', - 'avi' => 'video/x-msvideo', - 'movie' => 'video/x-sgi-movie', - 'doc' => 'application/msword', - 'word' => 'application/msword', - 'xl' => 'application/excel', - 'eml' => 'message/rfc822' - ); - return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)]; - } - - /** - * Set (or reset) Class Objects (variables) - * - * Usage Example: - * $page->set('X-Priority', '3'); - * - * @access public - * @param string $name Parameter Name - * @param mixed $value Parameter Value - * NOTE: will not work with arrays, there are no arrays to set/reset - * @todo Should this not be using __set() magic function? - */ - public function set($name, $value = '') { - try { - if (isset($this->$name) ) { - $this->$name = $value; - } else { - throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL); - } - } catch (Exception $e) { - $this->SetError($e->getMessage()); - if ($e->getCode() == self::STOP_CRITICAL) { + } + + /** + * Add an embedded stringified attachment. + * This can include images, sounds, and just about any other document type. + * Be sure to set the $type to an image type for images: + * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'. + * @param string $string The attachment binary data. + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML. + * @param string $name + * @param string $encoding File encoding (see $Encoding). + * @param string $type MIME type. + * @param string $disposition Disposition to use + * @return boolean True on successfully adding an attachment + */ + public function addStringEmbeddedImage( + $string, + $cid, + $name = '', + $encoding = 'base64', + $type = '', + $disposition = 'inline' + ) { + // If a MIME type is not specified, try to work it out from the name + if ($type == '' and !empty($name)) { + $type = self::filenameToType($name); + } + + // Append to $attachment array + $this->attachment[] = array( + 0 => $string, + 1 => $name, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => true, // isStringAttachment + 6 => $disposition, + 7 => $cid + ); + return true; + } + + /** + * Check if an inline attachment is present. + * @access public + * @return boolean + */ + public function inlineImageExists() + { + foreach ($this->attachment as $attachment) { + if ($attachment[6] == 'inline') { + return true; + } + } return false; - } - } - return true; - } - - /** - * Strips newlines to prevent header injection. - * @access public - * @param string $str String - * @return string - */ - public function SecureHeader($str) { - $str = str_replace("\r", '', $str); - $str = str_replace("\n", '', $str); - return trim($str); - } - - /** - * Set the private key file and password to sign the message. - * - * @access public - * @param string $key_filename Parameter File Name - * @param string $key_pass Password for private key - */ - public function Sign($cert_filename, $key_filename, $key_pass) { - $this->sign_cert_file = $cert_filename; - $this->sign_key_file = $key_filename; - $this->sign_key_pass = $key_pass; - } - - /** - * Set the private key file and password to sign the message. - * - * @access public - * @param string $key_filename Parameter File Name - * @param string $key_pass Password for private key - */ - public function DKIM_QP($txt) { - $tmp=""; - $line=""; - for ($i=0;$iDKIM_private); - if ($this->DKIM_passphrase!='') { - $privKey = openssl_pkey_get_private($privKeyStr,$this->DKIM_passphrase); - } else { - $privKey = $privKeyStr; - } - if (openssl_sign($s, $signature, $privKey)) { - return base64_encode($signature); - } - } - - /** - * Generate DKIM Canonicalization Header - * - * @access public - * @param string $s Header - */ - public function DKIM_HeaderC($s) { - $s=preg_replace("/\r\n\s+/"," ",$s); - $lines=explode("\r\n",$s); - foreach ($lines as $key=>$line) { - list($heading,$value)=explode(":",$line,2); - $heading=strtolower($heading); - $value=preg_replace("/\s+/"," ",$value) ; // Compress useless spaces - $lines[$key]=$heading.":".trim($value) ; // Don't forget to remove WSP around the value - } - $s=implode("\r\n",$lines); - return $s; - } - - /** - * Generate DKIM Canonicalization Body - * - * @access public - * @param string $body Message Body - */ - public function DKIM_BodyC($body) { - if ($body == '') return "\r\n"; - // stabilize line endings - $body=str_replace("\r\n","\n",$body); - $body=str_replace("\n","\r\n",$body); - // END stabilize line endings - while (substr($body,strlen($body)-4,4) == "\r\n\r\n") { - $body=substr($body,0,strlen($body)-2); - } - return $body; - } - - /** - * Create the DKIM header, body, as new header - * - * @access public - * @param string $headers_line Header lines - * @param string $subject Subject - * @param string $body Body - */ - public function DKIM_Add($headers_line,$subject,$body) { - $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms - $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body - $DKIMquery = 'dns/txt'; // Query method - $DKIMtime = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) - $subject_header = "Subject: $subject"; - $headers = explode("\r\n",$headers_line); - foreach($headers as $header) { - if (strpos($header,'From:') === 0) { - $from_header=$header; - } elseif (strpos($header,'To:') === 0) { - $to_header=$header; - } - } - $from = str_replace('|','=7C',$this->DKIM_QP($from_header)); - $to = str_replace('|','=7C',$this->DKIM_QP($to_header)); - $subject = str_replace('|','=7C',$this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable - $body = $this->DKIM_BodyC($body); - $DKIMlen = strlen($body) ; // Length of body - $DKIMb64 = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body - $ident = ($this->DKIM_identity == '')? '' : " i=" . $this->DKIM_identity . ";"; - $dkimhdrs = "DKIM-Signature: v=1; a=" . $DKIMsignatureType . "; q=" . $DKIMquery . "; l=" . $DKIMlen . "; s=" . $this->DKIM_selector . ";\r\n". - "\tt=" . $DKIMtime . "; c=" . $DKIMcanonicalization . ";\r\n". - "\th=From:To:Subject;\r\n". - "\td=" . $this->DKIM_domain . ";" . $ident . "\r\n". - "\tz=$from\r\n". - "\t|$to\r\n". - "\t|$subject;\r\n". - "\tbh=" . $DKIMb64 . ";\r\n". - "\tb="; - $toSign = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs); - $signed = $this->DKIM_Sign($toSign); - return "X-PHPMAILER-DKIM: phpmailer.worxware.com\r\n".$dkimhdrs.$signed."\r\n"; - } - - protected function doCallback($isSent,$to,$cc,$bcc,$subject,$body) { - if (!empty($this->action_function) && function_exists($this->action_function)) { - $params = array($isSent,$to,$cc,$bcc,$subject,$body); - call_user_func_array($this->action_function,$params); - } - } + } + + /** + * Check if an attachment (non-inline) is present. + * @return boolean + */ + public function attachmentExists() + { + foreach ($this->attachment as $attachment) { + if ($attachment[6] == 'attachment') { + return true; + } + } + return false; + } + + /** + * Check if this message has an alternative body set. + * @return boolean + */ + public function alternativeExists() + { + return !empty($this->AltBody); + } + + /** + * Clear queued addresses of given kind. + * @access protected + * @param string $kind 'to', 'cc', or 'bcc' + * @return void + */ + public function clearQueuedAddresses($kind) + { + $RecipientsQueue = $this->RecipientsQueue; + foreach ($RecipientsQueue as $address => $params) { + if ($params[0] == $kind) { + unset($this->RecipientsQueue[$address]); + } + } + } + + /** + * Clear all To recipients. + * @return void + */ + public function clearAddresses() + { + foreach ($this->to as $to) { + unset($this->all_recipients[strtolower($to[0])]); + } + $this->to = array(); + $this->clearQueuedAddresses('to'); + } + + /** + * Clear all CC recipients. + * @return void + */ + public function clearCCs() + { + foreach ($this->cc as $cc) { + unset($this->all_recipients[strtolower($cc[0])]); + } + $this->cc = array(); + $this->clearQueuedAddresses('cc'); + } + + /** + * Clear all BCC recipients. + * @return void + */ + public function clearBCCs() + { + foreach ($this->bcc as $bcc) { + unset($this->all_recipients[strtolower($bcc[0])]); + } + $this->bcc = array(); + $this->clearQueuedAddresses('bcc'); + } + + /** + * Clear all ReplyTo recipients. + * @return void + */ + public function clearReplyTos() + { + $this->ReplyTo = array(); + $this->ReplyToQueue = array(); + } + + /** + * Clear all recipient types. + * @return void + */ + public function clearAllRecipients() + { + $this->to = array(); + $this->cc = array(); + $this->bcc = array(); + $this->all_recipients = array(); + $this->RecipientsQueue = array(); + } + + /** + * Clear all filesystem, string, and binary attachments. + * @return void + */ + public function clearAttachments() + { + $this->attachment = array(); + } + + /** + * Clear all custom headers. + * @return void + */ + public function clearCustomHeaders() + { + $this->CustomHeader = array(); + } + + /** + * Add an error message to the error container. + * @access protected + * @param string $msg + * @return void + */ + protected function setError($msg) + { + $this->error_count++; + if ($this->Mailer == 'smtp' and !is_null($this->smtp)) { + $lasterror = $this->smtp->getError(); + if (!empty($lasterror['error'])) { + $msg .= $this->lang('smtp_error') . $lasterror['error']; + if (!empty($lasterror['detail'])) { + $msg .= ' Detail: '. $lasterror['detail']; + } + if (!empty($lasterror['smtp_code'])) { + $msg .= ' SMTP code: ' . $lasterror['smtp_code']; + } + if (!empty($lasterror['smtp_code_ex'])) { + $msg .= ' Additional SMTP info: ' . $lasterror['smtp_code_ex']; + } + } + } + $this->ErrorInfo = $msg; + } + + /** + * Return an RFC 822 formatted date. + * @access public + * @return string + * @static + */ + public static function rfcDate() + { + // Set the time zone to whatever the default is to avoid 500 errors + // Will default to UTC if it's not set properly in php.ini + date_default_timezone_set(@date_default_timezone_get()); + return date('D, j M Y H:i:s O'); + } + + /** + * Get the server hostname. + * Returns 'localhost.localdomain' if unknown. + * @access protected + * @return string + */ + protected function serverHostname() + { + $result = 'localhost.localdomain'; + if (!empty($this->Hostname)) { + $result = $this->Hostname; + } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) { + $result = $_SERVER['SERVER_NAME']; + } elseif (function_exists('gethostname') && gethostname() !== false) { + $result = gethostname(); + } elseif (php_uname('n') !== false) { + $result = php_uname('n'); + } + return $result; + } + + /** + * Get an error message in the current language. + * @access protected + * @param string $key + * @return string + */ + protected function lang($key) + { + if (count($this->language) < 1) { + $this->setLanguage('en'); // set the default language + } + + if (array_key_exists($key, $this->language)) { + if ($key == 'smtp_connect_failed') { + //Include a link to troubleshooting docs on SMTP connection failure + //this is by far the biggest cause of support questions + //but it's usually not PHPMailer's fault. + return $this->language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting'; + } + return $this->language[$key]; + } else { + //Return the key as a fallback + return $key; + } + } + + /** + * Check if an error occurred. + * @access public + * @return boolean True if an error did occur. + */ + public function isError() + { + return ($this->error_count > 0); + } + + /** + * Ensure consistent line endings in a string. + * Changes every end of line from CRLF, CR or LF to $this->LE. + * @access public + * @param string $str String to fixEOL + * @return string + */ + public function fixEOL($str) + { + // Normalise to \n + $nstr = str_replace(array("\r\n", "\r"), "\n", $str); + // Now convert LE as needed + if ($this->LE !== "\n") { + $nstr = str_replace("\n", $this->LE, $nstr); + } + return $nstr; + } + + /** + * Add a custom header. + * $name value can be overloaded to contain + * both header name and value (name:value) + * @access public + * @param string $name Custom header name + * @param string $value Header value + * @return void + */ + public function addCustomHeader($name, $value = null) + { + if ($value === null) { + // Value passed in as name:value + $this->CustomHeader[] = explode(':', $name, 2); + } else { + $this->CustomHeader[] = array($name, $value); + } + } + + /** + * Returns all custom headers. + * @return array + */ + public function getCustomHeaders() + { + return $this->CustomHeader; + } + + /** + * Create a message from an HTML string. + * Automatically makes modifications for inline images and backgrounds + * and creates a plain-text version by converting the HTML. + * Overwrites any existing values in $this->Body and $this->AltBody + * @access public + * @param string $message HTML message string + * @param string $basedir baseline directory for path + * @param boolean|callable $advanced Whether to use the internal HTML to text converter + * or your own custom converter @see PHPMailer::html2text() + * @return string $message + */ + public function msgHTML($message, $basedir = '', $advanced = false) + { + preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images); + if (array_key_exists(2, $images)) { + foreach ($images[2] as $imgindex => $url) { + // Convert data URIs into embedded images + if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) { + $data = substr($url, strpos($url, ',')); + if ($match[2]) { + $data = base64_decode($data); + } else { + $data = rawurldecode($data); + } + $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 + if ($this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, 'base64', $match[1])) { + $message = str_replace( + $images[0][$imgindex], + $images[1][$imgindex] . '="cid:' . $cid . '"', + $message + ); + } + } elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[A-z]+://#', $url)) { + // Do not change urls for absolute images (thanks to corvuscorax) + // Do not change urls that are already inline images + $filename = basename($url); + $directory = dirname($url); + if ($directory == '.') { + $directory = ''; + } + $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 + if (strlen($basedir) > 1 && substr($basedir, -1) != '/') { + $basedir .= '/'; + } + if (strlen($directory) > 1 && substr($directory, -1) != '/') { + $directory .= '/'; + } + if ($this->addEmbeddedImage( + $basedir . $directory . $filename, + $cid, + $filename, + 'base64', + self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION)) + ) + ) { + $message = preg_replace( + '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui', + $images[1][$imgindex] . '="cid:' . $cid . '"', + $message + ); + } + } + } + } + $this->isHTML(true); + // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better + $this->Body = $this->normalizeBreaks($message); + $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced)); + if (empty($this->AltBody)) { + $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . + self::CRLF . self::CRLF; + } + return $this->Body; + } + + /** + * Convert an HTML string into plain text. + * This is used by msgHTML(). + * Note - older versions of this function used a bundled advanced converter + * which was been removed for license reasons in #232 + * Example usage: + * + * // Use default conversion + * $plain = $mail->html2text($html); + * // Use your own custom converter + * $plain = $mail->html2text($html, function($html) { + * $converter = new MyHtml2text($html); + * return $converter->get_text(); + * }); + * + * @param string $html The HTML text to convert + * @param boolean|callable $advanced Any boolean value to use the internal converter, + * or provide your own callable for custom conversion. + * @return string + */ + public function html2text($html, $advanced = false) + { + if (is_callable($advanced)) { + return call_user_func($advanced, $html); + } + return html_entity_decode( + trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), + ENT_QUOTES, + $this->CharSet + ); + } + + /** + * Get the MIME type for a file extension. + * @param string $ext File extension + * @access public + * @return string MIME type of file. + * @static + */ + public static function _mime_types($ext = '') + { + $mimes = array( + 'xl' => 'application/excel', + 'js' => 'application/javascript', + 'hqx' => 'application/mac-binhex40', + 'cpt' => 'application/mac-compactpro', + 'bin' => 'application/macbinary', + 'doc' => 'application/msword', + 'word' => 'application/msword', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'class' => 'application/octet-stream', + 'dll' => 'application/octet-stream', + 'dms' => 'application/octet-stream', + 'exe' => 'application/octet-stream', + 'lha' => 'application/octet-stream', + 'lzh' => 'application/octet-stream', + 'psd' => 'application/octet-stream', + 'sea' => 'application/octet-stream', + 'so' => 'application/octet-stream', + 'oda' => 'application/oda', + 'pdf' => 'application/pdf', + 'ai' => 'application/postscript', + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'mif' => 'application/vnd.mif', + 'xls' => 'application/vnd.ms-excel', + 'ppt' => 'application/vnd.ms-powerpoint', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'gtar' => 'application/x-gtar', + 'php3' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'php' => 'application/x-httpd-php', + 'phtml' => 'application/x-httpd-php', + 'phps' => 'application/x-httpd-php-source', + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/x-stuffit', + 'tar' => 'application/x-tar', + 'tgz' => 'application/x-tar', + 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', + 'zip' => 'application/zip', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mp2' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mpga' => 'audio/mpeg', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'ram' => 'audio/x-pn-realaudio', + 'rm' => 'audio/x-pn-realaudio', + 'rpm' => 'audio/x-pn-realaudio-plugin', + 'ra' => 'audio/x-realaudio', + 'wav' => 'audio/x-wav', + 'bmp' => 'image/bmp', + 'gif' => 'image/gif', + 'jpeg' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'png' => 'image/png', + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'eml' => 'message/rfc822', + 'css' => 'text/css', + 'html' => 'text/html', + 'htm' => 'text/html', + 'shtml' => 'text/html', + 'log' => 'text/plain', + 'text' => 'text/plain', + 'txt' => 'text/plain', + 'rtx' => 'text/richtext', + 'rtf' => 'text/rtf', + 'vcf' => 'text/vcard', + 'vcard' => 'text/vcard', + 'xml' => 'text/xml', + 'xsl' => 'text/xml', + 'mpeg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mov' => 'video/quicktime', + 'qt' => 'video/quicktime', + 'rv' => 'video/vnd.rn-realvideo', + 'avi' => 'video/x-msvideo', + 'movie' => 'video/x-sgi-movie' + ); + if (array_key_exists(strtolower($ext), $mimes)) { + return $mimes[strtolower($ext)]; + } + return 'application/octet-stream'; + } + + /** + * Map a file name to a MIME type. + * Defaults to 'application/octet-stream', i.e.. arbitrary binary data. + * @param string $filename A file name or full path, does not need to exist as a file + * @return string + * @static + */ + public static function filenameToType($filename) + { + // In case the path is a URL, strip any query string before getting extension + $qpos = strpos($filename, '?'); + if (false !== $qpos) { + $filename = substr($filename, 0, $qpos); + } + $pathinfo = self::mb_pathinfo($filename); + return self::_mime_types($pathinfo['extension']); + } + + /** + * Multi-byte-safe pathinfo replacement. + * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe. + * Works similarly to the one in PHP >= 5.2.0 + * @link http://www.php.net/manual/en/function.pathinfo.php#107461 + * @param string $path A filename or path, does not need to exist as a file + * @param integer|string $options Either a PATHINFO_* constant, + * or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2 + * @return string|array + * @static + */ + public static function mb_pathinfo($path, $options = null) + { + $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''); + $pathinfo = array(); + if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) { + if (array_key_exists(1, $pathinfo)) { + $ret['dirname'] = $pathinfo[1]; + } + if (array_key_exists(2, $pathinfo)) { + $ret['basename'] = $pathinfo[2]; + } + if (array_key_exists(5, $pathinfo)) { + $ret['extension'] = $pathinfo[5]; + } + if (array_key_exists(3, $pathinfo)) { + $ret['filename'] = $pathinfo[3]; + } + } + switch ($options) { + case PATHINFO_DIRNAME: + case 'dirname': + return $ret['dirname']; + case PATHINFO_BASENAME: + case 'basename': + return $ret['basename']; + case PATHINFO_EXTENSION: + case 'extension': + return $ret['extension']; + case PATHINFO_FILENAME: + case 'filename': + return $ret['filename']; + default: + return $ret; + } + } + + /** + * Set or reset instance properties. + * You should avoid this function - it's more verbose, less efficient, more error-prone and + * harder to debug than setting properties directly. + * Usage Example: + * `$mail->set('SMTPSecure', 'tls');` + * is the same as: + * `$mail->SMTPSecure = 'tls';` + * @access public + * @param string $name The property name to set + * @param mixed $value The value to set the property to + * @return boolean + * @TODO Should this not be using the __set() magic function? + */ + public function set($name, $value = '') + { + if (property_exists($this, $name)) { + $this->$name = $value; + return true; + } else { + $this->setError($this->lang('variable_set') . $name); + return false; + } + } + + /** + * Strip newlines to prevent header injection. + * @access public + * @param string $str + * @return string + */ + public function secureHeader($str) + { + return trim(str_replace(array("\r", "\n"), '', $str)); + } + + /** + * Normalize line breaks in a string. + * Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format. + * Defaults to CRLF (for message bodies) and preserves consecutive breaks. + * @param string $text + * @param string $breaktype What kind of line break to use, defaults to CRLF + * @return string + * @access public + * @static + */ + public static function normalizeBreaks($text, $breaktype = "\r\n") + { + return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text); + } + + /** + * Set the public and private key files and password for S/MIME signing. + * @access public + * @param string $cert_filename + * @param string $key_filename + * @param string $key_pass Password for private key + * @param string $extracerts_filename Optional path to chain certificate + */ + public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '') + { + $this->sign_cert_file = $cert_filename; + $this->sign_key_file = $key_filename; + $this->sign_key_pass = $key_pass; + $this->sign_extracerts_file = $extracerts_filename; + } + + /** + * Quoted-Printable-encode a DKIM header. + * @access public + * @param string $txt + * @return string + */ + public function DKIM_QP($txt) + { + $line = ''; + for ($i = 0; $i < strlen($txt); $i++) { + $ord = ord($txt[$i]); + if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) { + $line .= $txt[$i]; + } else { + $line .= '=' . sprintf('%02X', $ord); + } + } + return $line; + } + + /** + * Generate a DKIM signature. + * @access public + * @param string $signHeader + * @throws phpmailerException + * @return string + */ + public function DKIM_Sign($signHeader) + { + if (!defined('PKCS7_TEXT')) { + if ($this->exceptions) { + throw new phpmailerException($this->lang('extension_missing') . 'openssl'); + } + return ''; + } + $privKeyStr = file_get_contents($this->DKIM_private); + if ($this->DKIM_passphrase != '') { + $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); + } else { + $privKey = $privKeyStr; + } + if (openssl_sign($signHeader, $signature, $privKey)) { + return base64_encode($signature); + } + return ''; + } + + /** + * Generate a DKIM canonicalization header. + * @access public + * @param string $signHeader Header + * @return string + */ + public function DKIM_HeaderC($signHeader) + { + $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader); + $lines = explode("\r\n", $signHeader); + foreach ($lines as $key => $line) { + list($heading, $value) = explode(':', $line, 2); + $heading = strtolower($heading); + $value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces + $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value + } + $signHeader = implode("\r\n", $lines); + return $signHeader; + } + + /** + * Generate a DKIM canonicalization body. + * @access public + * @param string $body Message Body + * @return string + */ + public function DKIM_BodyC($body) + { + if ($body == '') { + return "\r\n"; + } + // stabilize line endings + $body = str_replace("\r\n", "\n", $body); + $body = str_replace("\n", "\r\n", $body); + // END stabilize line endings + while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") { + $body = substr($body, 0, strlen($body) - 2); + } + return $body; + } + + /** + * Create the DKIM header and body in a new message header. + * @access public + * @param string $headers_line Header lines + * @param string $subject Subject + * @param string $body Body + * @return string + */ + public function DKIM_Add($headers_line, $subject, $body) + { + $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms + $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body + $DKIMquery = 'dns/txt'; // Query method + $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) + $subject_header = "Subject: $subject"; + $headers = explode($this->LE, $headers_line); + $from_header = ''; + $to_header = ''; + $current = ''; + foreach ($headers as $header) { + if (strpos($header, 'From:') === 0) { + $from_header = $header; + $current = 'from_header'; + } elseif (strpos($header, 'To:') === 0) { + $to_header = $header; + $current = 'to_header'; + } else { + if (!empty($$current) && strpos($header, ' =?') === 0) { + $$current .= $header; + } else { + $current = ''; + } + } + } + $from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); + $to = str_replace('|', '=7C', $this->DKIM_QP($to_header)); + $subject = str_replace( + '|', + '=7C', + $this->DKIM_QP($subject_header) + ); // Copied header fields (dkim-quoted-printable) + $body = $this->DKIM_BodyC($body); + $DKIMlen = strlen($body); // Length of body + $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body + if ('' == $this->DKIM_identity) { + $ident = ''; + } else { + $ident = ' i=' . $this->DKIM_identity . ';'; + } + $dkimhdrs = 'DKIM-Signature: v=1; a=' . + $DKIMsignatureType . '; q=' . + $DKIMquery . '; l=' . + $DKIMlen . '; s=' . + $this->DKIM_selector . + ";\r\n" . + "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" . + "\th=From:To:Subject;\r\n" . + "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" . + "\tz=$from\r\n" . + "\t|$to\r\n" . + "\t|$subject;\r\n" . + "\tbh=" . $DKIMb64 . ";\r\n" . + "\tb="; + $toSign = $this->DKIM_HeaderC( + $from_header . "\r\n" . + $to_header . "\r\n" . + $subject_header . "\r\n" . + $dkimhdrs + ); + $signed = $this->DKIM_Sign($toSign); + return $dkimhdrs . $signed . "\r\n"; + } + + /** + * Detect if a string contains a line longer than the maximum line length allowed. + * @param string $str + * @return boolean + * @static + */ + public static function hasLineLongerThanMax($str) + { + //+2 to include CRLF line break for a 1000 total + return (boolean)preg_match('/^(.{'.(self::MAX_LINE_LENGTH + 2).',})/m', $str); + } + + /** + * Allows for public read access to 'to' property. + * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * @access public + * @return array + */ + public function getToAddresses() + { + return $this->to; + } + + /** + * Allows for public read access to 'cc' property. + * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * @access public + * @return array + */ + public function getCcAddresses() + { + return $this->cc; + } + + /** + * Allows for public read access to 'bcc' property. + * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * @access public + * @return array + */ + public function getBccAddresses() + { + return $this->bcc; + } + + /** + * Allows for public read access to 'ReplyTo' property. + * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * @access public + * @return array + */ + public function getReplyToAddresses() + { + return $this->ReplyTo; + } + + /** + * Allows for public read access to 'all_recipients' property. + * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * @access public + * @return array + */ + public function getAllRecipientAddresses() + { + return $this->all_recipients; + } + + /** + * Perform a callback. + * @param boolean $isSent + * @param array $to + * @param array $cc + * @param array $bcc + * @param string $subject + * @param string $body + * @param string $from + */ + protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from) + { + if (!empty($this->action_function) && is_callable($this->action_function)) { + $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from); + call_user_func_array($this->action_function, $params); + } + } } -class phpmailerException extends Exception { - public function errorMessage() { - $errorMsg = '' . $this->getMessage() . "
                  \n"; - return $errorMsg; - } +/** + * PHPMailer exception handler + * @package PHPMailer + */ +class phpmailerException extends Exception +{ + /** + * Prettify error message output + * @return string + */ + public function errorMessage() + { + $errorMsg = '' . $this->getMessage() . "
                  \n"; + return $errorMsg; + } } -?> diff --git a/www/plugins/facteur/phpmailer-php5/class.phpmaileroauth.php b/www/plugins/facteur/phpmailer-php5/class.phpmaileroauth.php new file mode 100644 index 00000000..f9cd7b42 --- /dev/null +++ b/www/plugins/facteur/phpmailer-php5/class.phpmaileroauth.php @@ -0,0 +1,196 @@ + + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2012 - 2014 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 + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** + * PHPMailerOAuth - PHPMailer subclass adding OAuth support. + * @package PHPMailer + * @author @sherryl4george + * @author Marcus Bointon (@Synchro) + */ +class PHPMailerOAuth extends PHPMailer +{ + /** + * The OAuth user's email address + * @var string + */ + public $oauthUserEmail = ''; + + /** + * The OAuth refresh token + * @var string + */ + public $oauthRefreshToken = ''; + + /** + * The OAuth client ID + * @var string + */ + public $oauthClientId = ''; + + /** + * The OAuth client secret + * @var string + */ + public $oauthClientSecret = ''; + + /** + * An instance of the PHPMailerOAuthGoogle class. + * @var PHPMailerOAuthGoogle + * @access protected + */ + protected $oauth = null; + + /** + * Get a PHPMailerOAuthGoogle instance to use. + * @return PHPMailerOAuthGoogle + */ + public function getOAUTHInstance() + { + if (!is_object($this->oauth)) { + $this->oauth = new PHPMailerOAuthGoogle( + $this->oauthUserEmail, + $this->oauthClientSecret, + $this->oauthClientId, + $this->oauthRefreshToken + ); + } + return $this->oauth; + } + + /** + * Initiate a connection to an SMTP server. + * Overrides the original smtpConnect method to add support for OAuth. + * @param array $options An array of options compatible with stream_context_create() + * @uses SMTP + * @access public + * @return bool + */ + public function smtpConnect($options = array()) + { + if (is_null($this->smtp)) { + $this->smtp = $this->getSMTPInstance(); + } + + if (is_null($this->oauth)) { + $this->oauth = $this->getOAUTHInstance(); + } + + // Already connected? + if ($this->smtp->connected()) { + return true; + } + + $this->smtp->setTimeout($this->Timeout); + $this->smtp->setDebugLevel($this->SMTPDebug); + $this->smtp->setDebugOutput($this->Debugoutput); + $this->smtp->setVerp($this->do_verp); + $hosts = explode(';', $this->Host); + $lastexception = null; + + foreach ($hosts as $hostentry) { + $hostinfo = array(); + if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) { + // Not a valid host entry + continue; + } + // $hostinfo[2]: optional ssl or tls prefix + // $hostinfo[3]: the hostname + // $hostinfo[4]: optional port number + // The host string prefix can temporarily override the current setting for SMTPSecure + // If it's not specified, the default value is used + $prefix = ''; + $secure = $this->SMTPSecure; + $tls = ($this->SMTPSecure == 'tls'); + if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) { + $prefix = 'ssl://'; + $tls = false; // Can't have SSL and TLS at the same time + $secure = 'ssl'; + } elseif ($hostinfo[2] == 'tls') { + $tls = true; + // tls doesn't use a prefix + $secure = 'tls'; + } + //Do we need the OpenSSL extension? + $sslext = defined('OPENSSL_ALGO_SHA1'); + if ('tls' === $secure or 'ssl' === $secure) { + //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled + if (!$sslext) { + throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL); + } + } + $host = $hostinfo[3]; + $port = $this->Port; + $tport = (integer)$hostinfo[4]; + if ($tport > 0 and $tport < 65536) { + $port = $tport; + } + if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) { + try { + if ($this->Helo) { + $hello = $this->Helo; + } else { + $hello = $this->serverHostname(); + } + $this->smtp->hello($hello); + //Automatically enable TLS encryption if: + // * it's not disabled + // * we have openssl extension + // * we are not already using SSL + // * the server offers STARTTLS + if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) { + $tls = true; + } + if ($tls) { + if (!$this->smtp->startTLS()) { + throw new phpmailerException($this->lang('connect_host')); + } + // We must resend HELO after tls negotiation + $this->smtp->hello($hello); + } + if ($this->SMTPAuth) { + if (!$this->smtp->authenticate( + $this->Username, + $this->Password, + $this->AuthType, + $this->Realm, + $this->Workstation, + $this->oauth + ) + ) { + throw new phpmailerException($this->lang('authenticate')); + } + } + return true; + } catch (phpmailerException $exc) { + $lastexception = $exc; + $this->edebug($exc->getMessage()); + // We must have connected, but then failed TLS or Auth, so close connection nicely + $this->smtp->quit(); + } + } + } + // If we get here, all connection attempts have failed, so close connection hard + $this->smtp->close(); + // As we've caught all exceptions, just report whatever the last one was + if ($this->exceptions and !is_null($lastexception)) { + throw $lastexception; + } + return false; + } +} diff --git a/www/plugins/facteur/phpmailer-php5/class.phpmaileroauthgoogle.php b/www/plugins/facteur/phpmailer-php5/class.phpmaileroauthgoogle.php new file mode 100644 index 00000000..ab6292b8 --- /dev/null +++ b/www/plugins/facteur/phpmailer-php5/class.phpmaileroauthgoogle.php @@ -0,0 +1,76 @@ + + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2012 - 2014 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 + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** + * PHPMailerOAuthGoogle - Wrapper for League OAuth2 Google provider. + * @package PHPMailer + * @author @sherryl4george + * @author Marcus Bointon (@Synchro) + * @link https://github.com/thephpleague/oauth2-client + */ +class PHPMailerOAuthGoogle +{ + private $oauthUserEmail = ''; + private $oauthRefreshToken = ''; + private $oauthClientId = ''; + private $oauthClientSecret = ''; + + /** + * @param string $UserEmail + * @param string $ClientSecret + * @param string $ClientId + * @param string $RefreshToken + */ + public function __construct( + $UserEmail, + $ClientSecret, + $ClientId, + $RefreshToken + ) { + $this->oauthClientId = $ClientId; + $this->oauthClientSecret = $ClientSecret; + $this->oauthRefreshToken = $RefreshToken; + $this->oauthUserEmail = $UserEmail; + } + + private function getProvider() { + return new League\OAuth2\Client\Provider\Google([ + 'clientId' => $this->oauthClientId, + 'clientSecret' => $this->oauthClientSecret + ]); + } + + private function getGrant() + { + return new \League\OAuth2\Client\Grant\RefreshToken(); + } + + private function getToken() + { + $provider = $this->getProvider(); + $grant = $this->getGrant(); + return $provider->getAccessToken($grant, ['refresh_token' => $this->oauthRefreshToken]); + } + + public function getOauth64() + { + $token = $this->getToken(); + return base64_encode("user=" . $this->oauthUserEmail . "\001auth=Bearer " . $token . "\001\001"); + } +} diff --git a/www/plugins/facteur/phpmailer-php5/class.pop3.php b/www/plugins/facteur/phpmailer-php5/class.pop3.php index f9fd3b2e..403b573e 100755 --- a/www/plugins/facteur/phpmailer-php5/class.pop3.php +++ b/www/plugins/facteur/phpmailer-php5/class.pop3.php @@ -1,407 +1,407 @@ + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2012 - 2014 Marcus Bointon + * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost - * @license http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL) - * @version $Id: class.pop3.php 444 2009-05-05 11:22:26Z coolbru $ + * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. */ /** - * POP Before SMTP Authentication Class - * Version 5.0.0 - * - * Author: Richard Davey (rich@corephp.co.uk) - * Modifications: Andy Prevost - * License: LGPL, see PHPMailer License - * - * Specifically for PHPMailer to allow POP before SMTP authentication. - * Does not yet work with APOP - if you have an APOP account, contact Richard Davey - * and we can test changes to this script. - * - * This class is based on the structure of the SMTP class originally authored by Chris Ryan - * - * This class is rfc 1939 compliant and implements all the commands - * required for POP3 connection, authentication and disconnection. - * + * PHPMailer POP-Before-SMTP Authentication Class. + * Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication. + * Does not support APOP. * @package PHPMailer - * @author Richard Davey + * @author Richard Davey (original author) + * @author Marcus Bointon (Synchro/coolbru) + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) */ - -class POP3 { - /** - * Default POP3 port - * @var int - */ - public $POP3_PORT = 110; - - /** - * Default Timeout - * @var int - */ - public $POP3_TIMEOUT = 30; - - /** - * POP3 Carriage Return + Line Feed - * @var string - */ - public $CRLF = "\r\n"; - - /** - * Displaying Debug warnings? (0 = now, 1+ = yes) - * @var int - */ - public $do_debug = 2; - - /** - * POP3 Mail Server - * @var string - */ - public $host; - - /** - * POP3 Port - * @var int - */ - public $port; - - /** - * POP3 Timeout Value - * @var int - */ - public $tval; - - /** - * POP3 Username - * @var string - */ - public $username; - - /** - * POP3 Password - * @var string - */ - public $password; - - ///////////////////////////////////////////////// - // PROPERTIES, PRIVATE AND PROTECTED - ///////////////////////////////////////////////// - - private $pop_conn; - private $connected; - private $error; // Error log array - - /** - * Constructor, sets the initial values - * @access public - * @return POP3 - */ - public function __construct() { - $this->pop_conn = 0; - $this->connected = false; - $this->error = null; - } - - /** - * Combination of public events - connect, login, disconnect - * @access public - * @param string $host - * @param integer $port - * @param integer $tval - * @param string $username - * @param string $password - */ - public function Authorise ($host, $port = false, $tval = false, $username, $password, $debug_level = 0) { - $this->host = $host; - - // If no port value is passed, retrieve it - if ($port == false) { - $this->port = $this->POP3_PORT; - } else { - $this->port = $port; - } - - // If no port value is passed, retrieve it - if ($tval == false) { - $this->tval = $this->POP3_TIMEOUT; - } else { - $this->tval = $tval; - } - - $this->do_debug = $debug_level; - $this->username = $username; - $this->password = $password; - - // Refresh the error log - $this->error = null; - - // Connect - $result = $this->Connect($this->host, $this->port, $this->tval); - - if ($result) { - $login_result = $this->Login($this->username, $this->password); - - if ($login_result) { - $this->Disconnect(); - - return true; - } - +class POP3 +{ + /** + * The POP3 PHPMailer Version number. + * @var string + * @access public + */ + public $Version = '5.2.14'; + + /** + * Default POP3 port number. + * @var integer + * @access public + */ + public $POP3_PORT = 110; + + /** + * Default timeout in seconds. + * @var integer + * @access public + */ + public $POP3_TIMEOUT = 30; + + /** + * POP3 Carriage Return + Line Feed. + * @var string + * @access public + * @deprecated Use the constant instead + */ + public $CRLF = "\r\n"; + + /** + * Debug display level. + * Options: 0 = no, 1+ = yes + * @var integer + * @access public + */ + public $do_debug = 0; + + /** + * POP3 mail server hostname. + * @var string + * @access public + */ + public $host; + + /** + * POP3 port number. + * @var integer + * @access public + */ + public $port; + + /** + * POP3 Timeout Value in seconds. + * @var integer + * @access public + */ + public $tval; + + /** + * POP3 username + * @var string + * @access public + */ + public $username; + + /** + * POP3 password. + * @var string + * @access public + */ + public $password; + + /** + * Resource handle for the POP3 connection socket. + * @var resource + * @access protected + */ + protected $pop_conn; + + /** + * Are we connected? + * @var boolean + * @access protected + */ + protected $connected = false; + + /** + * Error container. + * @var array + * @access protected + */ + protected $errors = array(); + + /** + * Line break constant + */ + const CRLF = "\r\n"; + + /** + * Simple static wrapper for all-in-one POP before SMTP + * @param $host + * @param integer|boolean $port The port number to connect to + * @param integer|boolean $timeout The timeout value + * @param string $username + * @param string $password + * @param integer $debug_level + * @return boolean + */ + public static function popBeforeSmtp( + $host, + $port = false, + $timeout = false, + $username = '', + $password = '', + $debug_level = 0 + ) { + $pop = new POP3; + return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level); } - // We need to disconnect regardless if the login succeeded - $this->Disconnect(); - - return false; - } - - /** - * Connect to the POP3 server - * @access public - * @param string $host - * @param integer $port - * @param integer $tval - * @return boolean - */ - public function Connect ($host, $port = false, $tval = 30) { - // Are we already connected? - if ($this->connected) { - return true; + /** + * Authenticate with a POP3 server. + * A connect, login, disconnect sequence + * appropriate for POP-before SMTP authorisation. + * @access public + * @param string $host The hostname to connect to + * @param integer|boolean $port The port number to connect to + * @param integer|boolean $timeout The timeout value + * @param string $username + * @param string $password + * @param integer $debug_level + * @return boolean + */ + public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0) + { + $this->host = $host; + // If no port value provided, use default + if (false === $port) { + $this->port = $this->POP3_PORT; + } else { + $this->port = (integer)$port; + } + // If no timeout value provided, use default + if (false === $timeout) { + $this->tval = $this->POP3_TIMEOUT; + } else { + $this->tval = (integer)$timeout; + } + $this->do_debug = $debug_level; + $this->username = $username; + $this->password = $password; + // Reset the error log + $this->errors = array(); + // connect + $result = $this->connect($this->host, $this->port, $this->tval); + if ($result) { + $login_result = $this->login($this->username, $this->password); + if ($login_result) { + $this->disconnect(); + return true; + } + } + // We need to disconnect regardless of whether the login succeeded + $this->disconnect(); + return false; } - /* - On Windows this will raise a PHP Warning error if the hostname doesn't exist. - Rather than supress it with @fsockopen, let's capture it cleanly instead - */ - - set_error_handler(array(&$this, 'catchWarning')); - - // Connect to the POP3 server - $this->pop_conn = fsockopen($host, // POP3 Host - $port, // Port # - $errno, // Error Number - $errstr, // Error Message - $tval); // Timeout (seconds) - - // Restore the error handler - restore_error_handler(); - - // Does the Error Log now contain anything? - if ($this->error && $this->do_debug >= 1) { - $this->displayErrors(); + /** + * Connect to a POP3 server. + * @access public + * @param string $host + * @param integer|boolean $port + * @param integer $tval + * @return boolean + */ + public function connect($host, $port = false, $tval = 30) + { + // Are we already connected? + if ($this->connected) { + return true; + } + + //On Windows this will raise a PHP Warning error if the hostname doesn't exist. + //Rather than suppress it with @fsockopen, capture it cleanly instead + set_error_handler(array($this, 'catchWarning')); + + if (false === $port) { + $port = $this->POP3_PORT; + } + + // connect to the POP3 server + $this->pop_conn = fsockopen( + $host, // POP3 Host + $port, // Port # + $errno, // Error Number + $errstr, // Error Message + $tval + ); // Timeout (seconds) + // Restore the error handler + restore_error_handler(); + + // Did we connect? + if (false === $this->pop_conn) { + // It would appear not... + $this->setError(array( + 'error' => "Failed to connect to server $host on port $port", + 'errno' => $errno, + 'errstr' => $errstr + )); + return false; + } + + // Increase the stream time-out + stream_set_timeout($this->pop_conn, $tval, 0); + + // Get the POP3 server response + $pop3_response = $this->getResponse(); + // Check for the +OK + if ($this->checkResponse($pop3_response)) { + // The connection is established and the POP3 server is talking + $this->connected = true; + return true; + } + return false; } - // Did we connect? - if ($this->pop_conn == false) { - // It would appear not... - $this->error = array( - 'error' => "Failed to connect to server $host on port $port", - 'errno' => $errno, - 'errstr' => $errstr - ); - - if ($this->do_debug >= 1) { - $this->displayErrors(); - } - - return false; + /** + * Log in to the POP3 server. + * Does not support APOP (RFC 2828, 4949). + * @access public + * @param string $username + * @param string $password + * @return boolean + */ + public function login($username = '', $password = '') + { + if (!$this->connected) { + $this->setError('Not connected to POP3 server'); + } + if (empty($username)) { + $username = $this->username; + } + if (empty($password)) { + $password = $this->password; + } + + // Send the Username + $this->sendString("USER $username" . self::CRLF); + $pop3_response = $this->getResponse(); + if ($this->checkResponse($pop3_response)) { + // Send the Password + $this->sendString("PASS $password" . self::CRLF); + $pop3_response = $this->getResponse(); + if ($this->checkResponse($pop3_response)) { + return true; + } + } + return false; } - // Increase the stream time-out - - // Check for PHP 4.3.0 or later - if (version_compare(phpversion(), '5.0.0', 'ge')) { - stream_set_timeout($this->pop_conn, $tval, 0); - } else { - // Does not work on Windows - if (substr(PHP_OS, 0, 3) !== 'WIN') { - socket_set_timeout($this->pop_conn, $tval, 0); - } + /** + * Disconnect from the POP3 server. + * @access public + */ + public function disconnect() + { + $this->sendString('QUIT'); + //The QUIT command may cause the daemon to exit, which will kill our connection + //So ignore errors here + try { + @fclose($this->pop_conn); + } catch (Exception $e) { + //Do nothing + }; } - // Get the POP3 server response - $pop3_response = $this->getResponse(); - - // Check for the +OK - if ($this->checkResponse($pop3_response)) { - // The connection is established and the POP3 server is talking - $this->connected = true; - return true; + /** + * Get a response from the POP3 server. + * $size is the maximum number of bytes to retrieve + * @param integer $size + * @return string + * @access protected + */ + protected function getResponse($size = 128) + { + $response = fgets($this->pop_conn, $size); + if ($this->do_debug >= 1) { + echo "Server -> Client: $response"; + } + return $response; } - } - - /** - * Login to the POP3 server (does not support APOP yet) - * @access public - * @param string $username - * @param string $password - * @return boolean - */ - public function Login ($username = '', $password = '') { - if ($this->connected == false) { - $this->error = 'Not connected to POP3 server'; - - if ($this->do_debug >= 1) { - $this->displayErrors(); - } + /** + * Send raw data to the POP3 server. + * @param string $string + * @return integer + * @access protected + */ + protected function sendString($string) + { + if ($this->pop_conn) { + if ($this->do_debug >= 2) { //Show client messages when debug >= 2 + echo "Client -> Server: $string"; + } + return fwrite($this->pop_conn, $string, strlen($string)); + } + return 0; } - if (empty($username)) { - $username = $this->username; + /** + * Checks the POP3 server response. + * Looks for for +OK or -ERR. + * @param string $string + * @return boolean + * @access protected + */ + protected function checkResponse($string) + { + if (substr($string, 0, 3) !== '+OK') { + $this->setError(array( + 'error' => "Server reported an error: $string", + 'errno' => 0, + 'errstr' => '' + )); + return false; + } else { + return true; + } } - if (empty($password)) { - $password = $this->password; + /** + * Add an error to the internal error store. + * Also display debug output if it's enabled. + * @param $error + * @access protected + */ + protected function setError($error) + { + $this->errors[] = $error; + if ($this->do_debug >= 1) { + echo '
                  ';
                  +            foreach ($this->errors as $error) {
                  +                print_r($error);
                  +            }
                  +            echo '
                  '; + } } - $pop_username = "USER $username" . $this->CRLF; - $pop_password = "PASS $password" . $this->CRLF; - - // Send the Username - $this->sendString($pop_username); - $pop3_response = $this->getResponse(); - - if ($this->checkResponse($pop3_response)) { - // Send the Password - $this->sendString($pop_password); - $pop3_response = $this->getResponse(); - - if ($this->checkResponse($pop3_response)) { - return true; - } else { - return false; - } - } else { - return false; - } - } - - /** - * Disconnect from the POP3 server - * @access public - */ - public function Disconnect () { - $this->sendString('QUIT'); - - fclose($this->pop_conn); - } - - ///////////////////////////////////////////////// - // Private Methods - ///////////////////////////////////////////////// - - /** - * Get the socket response back. - * $size is the maximum number of bytes to retrieve - * @access private - * @param integer $size - * @return string - */ - private function getResponse ($size = 128) { - $pop3_response = fgets($this->pop_conn, $size); - - return $pop3_response; - } - - /** - * Send a string down the open socket connection to the POP3 server - * @access private - * @param string $string - * @return integer - */ - private function sendString ($string) { - $bytes_sent = fwrite($this->pop_conn, $string, strlen($string)); - - return $bytes_sent; - } - - /** - * Checks the POP3 server response for +OK or -ERR - * @access private - * @param string $string - * @return boolean - */ - private function checkResponse ($string) { - if (substr($string, 0, 3) !== '+OK') { - $this->error = array( - 'error' => "Server reported an error: $string", - 'errno' => 0, - 'errstr' => '' - ); - - if ($this->do_debug >= 1) { - $this->displayErrors(); - } - - return false; - } else { - return true; + /** + * Get an array of error messages, if any. + * @return array + */ + public function getErrors() + { + return $this->errors; } - } - - /** - * If debug is enabled, display the error message array - * @access private - */ - private function displayErrors () { - echo '
                  ';
                  -
                  -    foreach ($this->error as $single_error) {
                  -      print_r($single_error);
                  +    /**
                  +     * POP3 connection error handler.
                  +     * @param integer $errno
                  +     * @param string $errstr
                  +     * @param string $errfile
                  +     * @param integer $errline
                  +     * @access protected
                  +     */
                  +    protected function catchWarning($errno, $errstr, $errfile, $errline)
                  +    {
                  +        $this->setError(array(
                  +            'error' => "Connecting to the POP3 server raised a PHP warning: ",
                  +            'errno' => $errno,
                  +            'errstr' => $errstr,
                  +            'errfile' => $errfile,
                  +            'errline' => $errline
                  +        ));
                       }
                  -
                  -    echo '
                  '; - } - - /** - * Takes over from PHP for the socket warning handler - * @access private - * @param integer $errno - * @param string $errstr - * @param string $errfile - * @param integer $errline - */ - private function catchWarning ($errno, $errstr, $errfile, $errline) { - $this->error[] = array( - 'error' => "Connecting to the POP3 server raised a PHP warning: ", - 'errno' => $errno, - 'errstr' => $errstr - ); - } - - // End of class } -?> \ No newline at end of file diff --git a/www/plugins/facteur/phpmailer-php5/class.smtp.php b/www/plugins/facteur/phpmailer-php5/class.smtp.php index c2ca1cb3..2e32e2fc 100755 --- a/www/plugins/facteur/phpmailer-php5/class.smtp.php +++ b/www/plugins/facteur/phpmailer-php5/class.smtp.php @@ -1,814 +1,1181 @@ -smtp_conn = 0; - $this->error = null; - $this->helo_rply = null; - - $this->do_debug = 0; - } - - ///////////////////////////////////////////////// - // CONNECTION FUNCTIONS - ///////////////////////////////////////////////// - - /** - * Connect to the server specified on the port specified. - * If the port is not specified use the default SMTP_PORT. - * If tval is specified then a connection will try and be - * established with the server for that number of seconds. - * If tval is not specified the default is 30 seconds to - * try on the connection. - * - * SMTP CODE SUCCESS: 220 - * SMTP CODE FAILURE: 421 - * @access public - * @return bool - */ - public function Connect($host, $port = 0, $tval = 30) { - // set the error val to null so there is no confusion - $this->error = null; - - // make sure we are __not__ connected - if($this->connected()) { - // already connected, generate error - $this->error = array("error" => "Already connected to a server"); - return false; - } - - if(empty($port)) { - $port = $this->SMTP_PORT; - } - - // connect to the smtp server - $this->smtp_conn = @fsockopen($host, // the host of the server - $port, // the port to use - $errno, // error number if any - $errstr, // error message if any - $tval); // give up after ? secs - // verify we connected properly - if(empty($this->smtp_conn)) { - $this->error = array("error" => "Failed to connect to server", - "errno" => $errno, - "errstr" => $errstr); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '
                  '; - } - return false; - } - - // SMTP server can take longer to respond, give longer timeout for first read - // Windows does not have support for this timeout function - if(substr(PHP_OS, 0, 3) != "WIN") - socket_set_timeout($this->smtp_conn, $tval, 0); - - // get any announcement - $announce = $this->get_lines(); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '
                  '; - } - - return true; - } - - /** - * Initiate a TLS communication with the server. - * - * SMTP CODE 220 Ready to start TLS - * SMTP CODE 501 Syntax error (no parameters allowed) - * SMTP CODE 454 TLS not available due to temporary reason - * @access public - * @return bool success - */ - public function StartTLS() { - $this->error = null; # to avoid confusion - - if(!$this->connected()) { - $this->error = array("error" => "Called StartTLS() without being connected"); - return false; - } - - fputs($this->smtp_conn,"STARTTLS" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
                  '; - } - - if($code != 220) { - $this->error = - array("error" => "STARTTLS not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - - // Begin encrypted connection - if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { - return false; - } - - return true; - } - - /** - * Performs SMTP authentication. Must be run after running the - * Hello() method. Returns true if successfully authenticated. - * @access public - * @return bool - */ - public function Authenticate($username, $password) { - // Start authentication - fputs($this->smtp_conn,"AUTH LOGIN" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($code != 334) { - $this->error = - array("error" => "AUTH not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - - // Send encoded username - fputs($this->smtp_conn, base64_encode($username) . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($code != 334) { - $this->error = - array("error" => "Username not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - - // Send encoded password - fputs($this->smtp_conn, base64_encode($password) . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($code != 235) { - $this->error = - array("error" => "Password not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - - return true; - } - - /** - * Returns true if connected to a server otherwise false - * @access public - * @return bool - */ - public function Connected() { - if(!empty($this->smtp_conn)) { - $sock_status = socket_get_status($this->smtp_conn); - if($sock_status["eof"]) { - // the socket is valid but we are not connected - if($this->do_debug >= 1) { - echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected"; - } - $this->Close(); - return false; - } - return true; // everything looks good - } - return false; - } - - /** - * Closes the socket and cleans up the state of the class. - * It is not considered good to use this function without - * first trying to use QUIT. - * @access public - * @return void - */ - public function Close() { - $this->error = null; // so there is no confusion - $this->helo_rply = null; - if(!empty($this->smtp_conn)) { - // close the connection and cleanup - fclose($this->smtp_conn); - $this->smtp_conn = 0; - } - } - - ///////////////////////////////////////////////// - // SMTP COMMANDS - ///////////////////////////////////////////////// - - /** - * Issues a data command and sends the msg_data to the server - * finializing 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 with the message headers - * and the message body being seperated by and additional . - * - * Implements rfc 821: DATA - * - * SMTP CODE INTERMEDIATE: 354 - * [data] - * . - * SMTP CODE SUCCESS: 250 - * SMTP CODE FAILURE: 552,554,451,452 - * SMTP CODE FAILURE: 451,554 - * SMTP CODE ERROR : 500,501,503,421 - * @access public - * @return bool - */ - public function Data($msg_data) { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Data() without being connected"); - return false; - } - - fputs($this->smtp_conn,"DATA" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
                  '; - } - - if($code != 354) { - $this->error = - array("error" => "DATA command not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - - /* the server is ready to accept data! - * according to rfc 821 we should not send more than 1000 - * including the CRLF - * characters on a single line so we will break the data up - * into lines by \r and/or \n then if needed we will break - * each of those into smaller lines to fit within the limit. - * in addition we will be looking for lines that start with - * a period '.' and append and additional period '.' to that - * line. NOTE: this does not count towards limit. - */ - - // normalize the line breaks so we know the explode works - $msg_data = str_replace("\r\n","\n",$msg_data); - $msg_data = str_replace("\r","\n",$msg_data); - $lines = explode("\n",$msg_data); - - /* we need to find a good way to determine is headers are - * in the msg_data or if it is a straight msg body - * currently I am assuming rfc 822 definitions of msg headers - * and if the first field of the first line (':' sperated) - * does not contain a space then it _should_ be a header - * and we can process all lines before a blank "" line as - * headers. - */ - - $field = substr($lines[0],0,strpos($lines[0],":")); - $in_headers = false; - if(!empty($field) && !strstr($field," ")) { - $in_headers = true; - } - - $max_line_length = 998; // used below; set here for ease in change - - while(list(,$line) = @each($lines)) { - $lines_out = null; - if($line == "" && $in_headers) { - $in_headers = false; - } - // ok we need to break this line up into several smaller lines - while(strlen($line) > $max_line_length) { - $pos = strrpos(substr($line,0,$max_line_length)," "); - - // Patch to fix DOS attack - if(!$pos) { - $pos = $max_line_length - 1; - $lines_out[] = substr($line,0,$pos); - $line = substr($line,$pos); - } else { - $lines_out[] = substr($line,0,$pos); - $line = substr($line,$pos + 1); - } - - /* if processing headers add a LWSP-char to the front of new line - * rfc 822 on long msg headers - */ - if($in_headers) { - $line = "\t" . $line; - } - } - $lines_out[] = $line; - - // send the lines to the server - while(list(,$line_out) = @each($lines_out)) { - if(strlen($line_out) > 0) - { - if(substr($line_out, 0, 1) == ".") { - $line_out = "." . $line_out; - } - } - fputs($this->smtp_conn,$line_out . $this->CRLF); - } - } - - // message data has been sent - fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
                  '; - } - - if($code != 250) { - $this->error = - array("error" => "DATA not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - return true; - } - - /** - * Sends the HELO command to the smtp server. - * This makes sure that we and the server are in - * the same known state. - * - * Implements from rfc 821: HELO - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE ERROR : 500, 501, 504, 421 - * @access public - * @return bool - */ - public function Hello($host = '') { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Hello() without being connected"); - return false; - } - - // if hostname for HELO was not specified send default - if(empty($host)) { - // determine appropriate default to send to server - $host = "localhost"; - } - - // Send extended hello first (RFC 2821) - if(!$this->SendHello("EHLO", $host)) { - if(!$this->SendHello("HELO", $host)) { - return false; - } - } - - return true; - } - - /** - * Sends a HELO/EHLO command. - * @access private - * @return bool - */ - private function SendHello($hello, $host) { - fputs($this->smtp_conn, $hello . " " . $host . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '
                  '; - } - - if($code != 250) { - $this->error = - array("error" => $hello . " not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - - $this->helo_rply = $rply; - - return true; - } - - /** - * Starts a mail transaction from the email address specified in - * $from. Returns true if successful or false otherwise. If True - * the mail transaction is started and then one or more Recipient - * commands may be called followed by a Data command. - * - * Implements rfc 821: MAIL FROM: - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE SUCCESS: 552,451,452 - * SMTP CODE SUCCESS: 500,501,421 - * @access public - * @return bool - */ - public function Mail($from) { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Mail() without being connected"); - return false; - } - - $useVerp = ($this->do_verp ? "XVERP" : ""); - fputs($this->smtp_conn,"MAIL FROM:<" . $from . ">" . $useVerp . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
                  '; - } - - if($code != 250) { - $this->error = - array("error" => "MAIL not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - return true; - } - - /** - * Sends the quit command to the server and then closes the socket - * if there is no error or the $close_on_error argument is true. - * - * Implements from rfc 821: QUIT - * - * SMTP CODE SUCCESS: 221 - * SMTP CODE ERROR : 500 - * @access public - * @return bool - */ - public function Quit($close_on_error = true) { - $this->error = null; // so there is no confusion - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Quit() without being connected"); - return false; - } - - // send the quit command to the server - fputs($this->smtp_conn,"quit" . $this->CRLF); - - // get any good-bye messages - $byemsg = $this->get_lines(); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '
                  '; - } - - $rval = true; - $e = null; - - $code = substr($byemsg,0,3); - if($code != 221) { - // use e as a tmp var cause Close will overwrite $this->error - $e = array("error" => "SMTP server rejected quit command", - "smtp_code" => $code, - "smtp_rply" => substr($byemsg,4)); - $rval = false; - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '
                  '; - } - } - - if(empty($e) || $close_on_error) { - $this->Close(); - } - - return $rval; - } - - /** - * Sends the command RCPT to the SMTP server with the TO: argument of $to. - * Returns true if the recipient was accepted false if it was rejected. - * - * Implements from rfc 821: RCPT TO: - * - * SMTP CODE SUCCESS: 250,251 - * SMTP CODE FAILURE: 550,551,552,553,450,451,452 - * SMTP CODE ERROR : 500,501,503,421 - * @access public - * @return bool - */ - public function Recipient($to) { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Recipient() without being connected"); - return false; - } - - fputs($this->smtp_conn,"RCPT TO:<" . $to . ">" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
                  '; - } - - if($code != 250 && $code != 251) { - $this->error = - array("error" => "RCPT not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - return true; - } - - /** - * Sends the RSET command to abort and transaction that is - * currently in progress. Returns true if successful false - * otherwise. - * - * Implements rfc 821: RSET - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE ERROR : 500,501,504,421 - * @access public - * @return bool - */ - public function Reset() { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called Reset() without being connected"); - return false; - } - - fputs($this->smtp_conn,"RSET" . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
                  '; - } - - if($code != 250) { - $this->error = - array("error" => "RSET failed", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - - return true; - } - - /** - * Starts a mail transaction from the email address specified in - * $from. Returns true if successful or false otherwise. If True - * the mail transaction is started and then one or more Recipient - * commands may be called followed by a Data command. This command - * will send the message to the users terminal if they are logged - * in and send them an email. - * - * Implements rfc 821: SAML FROM: - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE SUCCESS: 552,451,452 - * SMTP CODE SUCCESS: 500,501,502,421 - * @access public - * @return bool - */ - public function SendAndMail($from) { - $this->error = null; // so no confusion is caused - - if(!$this->connected()) { - $this->error = array( - "error" => "Called SendAndMail() without being connected"); - return false; - } - - fputs($this->smtp_conn,"SAML FROM:" . $from . $this->CRLF); - - $rply = $this->get_lines(); - $code = substr($rply,0,3); - - if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
                  '; - } - - if($code != 250) { - $this->error = - array("error" => "SAML not accepted from server", - "smtp_code" => $code, - "smtp_msg" => substr($rply,4)); - if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
                  '; - } - return false; - } - return true; - } - - /** - * This is an optional command for SMTP that this class does not - * support. This method is here to make the RFC821 Definition - * complete for this class and __may__ be implimented in the future - * - * Implements from rfc 821: TURN - * - * SMTP CODE SUCCESS: 250 - * SMTP CODE FAILURE: 502 - * SMTP CODE ERROR : 500, 503 - * @access public - * @return bool - */ - public function Turn() { - $this->error = array("error" => "This method, TURN, of the SMTP ". - "is not implemented"); - if($this->do_debug >= 1) { - echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '
                  '; - } - return false; - } - - /** - * Get the current error - * @access public - * @return array - */ - public function getError() { - return $this->error; - } - - ///////////////////////////////////////////////// - // INTERNAL FUNCTIONS - ///////////////////////////////////////////////// - - /** - * Read in as many lines as possible - * either before eof or socket timeout occurs on the operation. - * With SMTP we can tell if we have more lines to read if the - * 4th character is '-' symbol. If it is a space then we don't - * need to read anything else. - * @access private - * @return string - */ - private function get_lines() { - $data = ""; - while($str = @fgets($this->smtp_conn,515)) { - if($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '
                  '; - echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '
                  '; - } - $data .= $str; - if($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '
                  '; - } - // if 4th character is a space, we are done reading, break the loop - if(substr($str,3,1) == " ") { break; } - } - return $data; - } - -} - -?> \ No newline at end of file + + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2014 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 + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** + * PHPMailer RFC821 SMTP email transport class. + * Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server. + * @package PHPMailer + * @author Chris Ryan + * @author Marcus Bointon + */ +class SMTP +{ + /** + * The PHPMailer SMTP version number. + * @var string + */ + const VERSION = '5.2.14'; + + /** + * SMTP line break constant. + * @var string + */ + const CRLF = "\r\n"; + + /** + * The SMTP port to use if one is not specified. + * @var integer + */ + const DEFAULT_SMTP_PORT = 25; + + /** + * The maximum line length allowed by RFC 2822 section 2.1.1 + * @var integer + */ + const MAX_LINE_LENGTH = 998; + + /** + * Debug level for no output + */ + const DEBUG_OFF = 0; + + /** + * Debug level to show client -> server messages + */ + const DEBUG_CLIENT = 1; + + /** + * Debug level to show client -> server and server -> client messages + */ + const DEBUG_SERVER = 2; + + /** + * Debug level to show connection status, client -> server and server -> client messages + */ + const DEBUG_CONNECTION = 3; + + /** + * Debug level to show all messages + */ + const DEBUG_LOWLEVEL = 4; + + /** + * The PHPMailer SMTP Version number. + * @var string + * @deprecated Use the `VERSION` constant instead + * @see SMTP::VERSION + */ + public $Version = '5.2.14'; + + /** + * SMTP server port number. + * @var integer + * @deprecated This is only ever used as a default value, so use the `DEFAULT_SMTP_PORT` constant instead + * @see SMTP::DEFAULT_SMTP_PORT + */ + public $SMTP_PORT = 25; + + /** + * SMTP reply line ending. + * @var string + * @deprecated Use the `CRLF` constant instead + * @see SMTP::CRLF + */ + public $CRLF = "\r\n"; + + /** + * Debug output level. + * Options: + * * self::DEBUG_OFF (`0`) No debug output, default + * * self::DEBUG_CLIENT (`1`) Client commands + * * self::DEBUG_SERVER (`2`) Client commands and server responses + * * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status + * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages + * @var integer + */ + public $do_debug = self::DEBUG_OFF; + + /** + * How to handle debug output. + * Options: + * * `echo` Output plain-text as-is, appropriate for CLI + * * `html` Output escaped, line breaks converted to `
                  `, appropriate for browser output + * * `error_log` Output to error log as configured in php.ini + * + * Alternatively, you can provide a callable expecting two params: a message string and the debug level: + * + * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; + * + * @var string|callable + */ + public $Debugoutput = 'echo'; + + /** + * Whether to use VERP. + * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path + * @link http://www.postfix.org/VERP_README.html Info on VERP + * @var boolean + */ + public $do_verp = false; + + /** + * The timeout value for connection, in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure. + * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2 + * @var integer + */ + public $Timeout = 300; + + /** + * How long to wait for commands to complete, in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * @var integer + */ + public $Timelimit = 300; + + /** + * The socket for the server connection. + * @var resource + */ + protected $smtp_conn; + + /** + * Error information, if any, for the last SMTP command. + * @var array + */ + protected $error = array( + 'error' => '', + 'detail' => '', + 'smtp_code' => '', + 'smtp_code_ex' => '' + ); + + /** + * The reply the server sent to us for HELO. + * If null, no HELO string has yet been received. + * @var string|null + */ + protected $helo_rply = null; + + /** + * The set of SMTP extensions sent in reply to EHLO command. + * Indexes of the array are extension names. + * Value at index 'HELO' or 'EHLO' (according to command that was sent) + * represents the server name. In case of HELO it is the only element of the array. + * Other values can be boolean TRUE or an array containing extension options. + * If null, no HELO/EHLO string has yet been received. + * @var array|null + */ + protected $server_caps = null; + + /** + * The most recent reply received from the server. + * @var string + */ + protected $last_reply = ''; + + /** + * Output debugging info via a user-selected method. + * @see SMTP::$Debugoutput + * @see SMTP::$do_debug + * @param string $str Debug string to output + * @param integer $level The debug level of this message; see DEBUG_* constants + * @return void + */ + protected function edebug($str, $level = 0) + { + if ($level > $this->do_debug) { + return; + } + //Avoid clash with built-in function names + if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) { + call_user_func($this->Debugoutput, $str, $this->do_debug); + return; + } + switch ($this->Debugoutput) { + case 'error_log': + //Don't output, just log + error_log($str); + break; + case 'html': + //Cleans up output a bit for a better looking, HTML-safe output + echo htmlentities( + preg_replace('/[\r\n]+/', '', $str), + ENT_QUOTES, + 'UTF-8' + ) + . "
                  \n"; + break; + case 'echo': + default: + //Normalize line breaks + $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str); + echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( + "\n", + "\n \t ", + trim($str) + )."\n"; + } + } + + /** + * Connect to an SMTP server. + * @param string $host SMTP server IP or host name + * @param integer $port The port number to connect to + * @param integer $timeout How long to wait for the connection to open + * @param array $options An array of options for stream_context_create() + * @access public + * @return boolean + */ + public function connect($host, $port = null, $timeout = 30, $options = array()) + { + static $streamok; + //This is enabled by default since 5.0.0 but some providers disable it + //Check this once and cache the result + if (is_null($streamok)) { + $streamok = function_exists('stream_socket_client'); + } + // Clear errors to avoid confusion + $this->setError(''); + // Make sure we are __not__ connected + if ($this->connected()) { + // Already connected, generate error + $this->setError('Already connected to a server'); + return false; + } + if (empty($port)) { + $port = self::DEFAULT_SMTP_PORT; + } + // Connect to the SMTP server + $this->edebug( + "Connection: opening to $host:$port, timeout=$timeout, options=".var_export($options, true), + self::DEBUG_CONNECTION + ); + $errno = 0; + $errstr = ''; + if ($streamok) { + $socket_context = stream_context_create($options); + //Suppress errors; connection failures are handled at a higher level + $this->smtp_conn = @stream_socket_client( + $host . ":" . $port, + $errno, + $errstr, + $timeout, + STREAM_CLIENT_CONNECT, + $socket_context + ); + } else { + //Fall back to fsockopen which should work in more places, but is missing some features + $this->edebug( + "Connection: stream_socket_client not available, falling back to fsockopen", + self::DEBUG_CONNECTION + ); + $this->smtp_conn = fsockopen( + $host, + $port, + $errno, + $errstr, + $timeout + ); + } + // Verify we connected properly + if (!is_resource($this->smtp_conn)) { + $this->setError( + 'Failed to connect to server', + $errno, + $errstr + ); + $this->edebug( + 'SMTP ERROR: ' . $this->error['error'] + . ": $errstr ($errno)", + self::DEBUG_CLIENT + ); + 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 + if (substr(PHP_OS, 0, 3) != 'WIN') { + $max = ini_get('max_execution_time'); + // Don't bother if unlimited + if ($max != 0 && $timeout > $max) { + @set_time_limit($timeout); + } + stream_set_timeout($this->smtp_conn, $timeout, 0); + } + // Get any announcement + $announce = $this->get_lines(); + $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER); + return true; + } + + /** + * Initiate a TLS (encrypted) session. + * @access public + * @return boolean + */ + public function startTLS() + { + if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) { + return false; + } + // Begin encrypted connection + if (!stream_socket_enable_crypto( + $this->smtp_conn, + true, + STREAM_CRYPTO_METHOD_TLS_CLIENT + )) { + return false; + } + return true; + } + + /** + * Perform SMTP authentication. + * Must be run after hello(). + * @see hello() + * @param string $username The user name + * @param string $password The password + * @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5, XOAUTH2) + * @param string $realm The auth realm for NTLM + * @param string $workstation The auth workstation for NTLM + * @param null|OAuth $OAuth An optional OAuth instance (@see PHPMailerOAuth) + * @return bool True if successfully authenticated.* @access public + */ + public function authenticate( + $username, + $password, + $authtype = null, + $realm = '', + $workstation = '', + $OAuth = null + ) { + if (!$this->server_caps) { + $this->setError('Authentication is not allowed before HELO/EHLO'); + return false; + } + + if (array_key_exists('EHLO', $this->server_caps)) { + // SMTP extensions are available. Let's 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 + return false; + } + + self::edebug('Auth method requested: ' . ($authtype ? $authtype : 'UNKNOWN'), self::DEBUG_LOWLEVEL); + self::edebug( + 'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']), + self::DEBUG_LOWLEVEL + ); + + if (empty($authtype)) { + foreach (array('LOGIN', 'CRAM-MD5', 'NTLM', 'PLAIN', 'XOAUTH2') as $method) { + if (in_array($method, $this->server_caps['AUTH'])) { + $authtype = $method; + break; + } + } + if (empty($authtype)) { + $this->setError('No supported authentication methods found'); + return false; + } + self::edebug('Auth method selected: '.$authtype, self::DEBUG_LOWLEVEL); + } + + if (!in_array($authtype, $this->server_caps['AUTH'])) { + $this->setError("The requested authentication method \"$authtype\" is not supported by the server"); + return false; + } + } elseif (empty($authtype)) { + $authtype = 'LOGIN'; + } + switch ($authtype) { + case 'PLAIN': + // 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 + ) + ) { + return false; + } + break; + case 'LOGIN': + // Start authentication + if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) { + return false; + } + if (!$this->sendCommand("Username", base64_encode($username), 334)) { + return false; + } + if (!$this->sendCommand("Password", base64_encode($password), 235)) { + return false; + } + break; + case 'XOAUTH2': + //If the OAuth Instance is not set. Can be a case when PHPMailer is used + //instead of PHPMailerOAuth + if (is_null($OAuth)) { + return false; + } + $oauth = $OAuth->getOauth64(); + + // Start authentication + if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) { + return false; + } + break; + case 'NTLM': + /* + * ntlm_sasl_client.php + * Bundled with Permission + * + * How to telnet in windows: + * http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx + * PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication + */ + require_once 'extras/ntlm_sasl_client.php'; + $temp = new stdClass; + $ntlm_client = new ntlm_sasl_client_class; + //Check that functions are available + if (!$ntlm_client->Initialize($temp)) { + $this->setError($temp->error); + $this->edebug( + 'You need to enable some modules in your php.ini file: ' + . $this->error['error'], + self::DEBUG_CLIENT + ); + return false; + } + //msg1 + $msg1 = $ntlm_client->TypeMsg1($realm, $workstation); //msg1 + + if (!$this->sendCommand( + 'AUTH NTLM', + 'AUTH NTLM ' . base64_encode($msg1), + 334 + ) + ) { + return false; + } + //Though 0 based, there is a white space after the 3 digit number + //msg2 + $challenge = substr($this->last_reply, 3); + $challenge = base64_decode($challenge); + $ntlm_res = $ntlm_client->NTLMResponse( + substr($challenge, 24, 8), + $password + ); + //msg3 + $msg3 = $ntlm_client->TypeMsg3( + $ntlm_res, + $username, + $realm, + $workstation + ); + // send encoded username + return $this->sendCommand('Username', base64_encode($msg3), 235); + case 'CRAM-MD5': + // Start authentication + if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) { + return false; + } + // Get the challenge + $challenge = base64_decode(substr($this->last_reply, 4)); + + // Build the response + $response = $username . ' ' . $this->hmac($challenge, $password); + + // send encoded credentials + return $this->sendCommand('Username', base64_encode($response), 235); + default: + $this->setError("Authentication method \"$authtype\" is not supported"); + return false; + } + return true; + } + + /** + * Calculate an MD5 HMAC hash. + * Works like hash_hmac('md5', $data, $key) + * in case that function is not available + * @param string $data The data to hash + * @param string $key The key to hash with + * @access protected + * @return string + */ + protected function hmac($data, $key) + { + if (function_exists('hash_hmac')) { + return hash_hmac('md5', $data, $key); + } + + // 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 + + $bytelen = 64; // byte length for md5 + if (strlen($key) > $bytelen) { + $key = pack('H*', md5($key)); + } + $key = str_pad($key, $bytelen, chr(0x00)); + $ipad = str_pad('', $bytelen, chr(0x36)); + $opad = str_pad('', $bytelen, chr(0x5c)); + $k_ipad = $key ^ $ipad; + $k_opad = $key ^ $opad; + + return md5($k_opad . pack('H*', md5($k_ipad . $data))); + } + + /** + * Check connection state. + * @access public + * @return boolean True if connected. + */ + public function connected() + { + 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 + $this->edebug( + 'SMTP NOTICE: EOF caught while checking if connected', + self::DEBUG_CLIENT + ); + $this->close(); + return false; + } + return true; // everything looks good + } + return false; + } + + /** + * Close the socket and clean up the state of the class. + * Don't use this function without first trying to use QUIT. + * @see quit() + * @access public + * @return void + */ + public function close() + { + $this->setError(''); + $this->server_caps = null; + $this->helo_rply = null; + if (is_resource($this->smtp_conn)) { + // close the connection and cleanup + fclose($this->smtp_conn); + $this->smtp_conn = null; //Makes for cleaner serialization + $this->edebug('Connection: closed', self::DEBUG_CONNECTION); + } + } + + /** + * 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 + * that is to be send with the headers. Each header needs to be + * on a single line followed by a with the message headers + * and the message body being separated by and additional . + * Implements rfc 821: DATA + * @param string $msg_data Message data to send + * @access public + * @return boolean + */ + public function data($msg_data) + { + //This will use the standard timelimit + if (!$this->sendCommand('DATA', 'DATA', 354)) { + return false; + } + + /* The server is ready to accept data! + * According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF) + * so we will break the data up into lines by \r and/or \n then if needed we will break each of those into + * smaller lines to fit within the limit. + * We will also look for lines that start with a '.' and prepend an additional '.'. + * NOTE: this does not count towards line-length limit. + */ + + // Normalize line breaks before exploding + $lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data)); + + /* To distinguish between a complete RFC822 message and a plain message body, we check if the first field + * of the first line (':' separated) does not contain a space then it _should_ be a header and we will + * process all lines before a blank line as headers. + */ + + $field = substr($lines[0], 0, strpos($lines[0], ':')); + $in_headers = false; + if (!empty($field) && strpos($field, ' ') === false) { + $in_headers = true; + } + + foreach ($lines as $line) { + $lines_out = array(); + if ($in_headers and $line == '') { + $in_headers = false; + } + //Break this line up into several smaller lines if it's too long + //Micro-optimisation: isset($str[$len]) is faster than (strlen($str) > $len), + while (isset($line[self::MAX_LINE_LENGTH])) { + //Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on + //so as to avoid breaking in the middle of a word + $pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' '); + //Deliberately matches both false and 0 + if (!$pos) { + //No nice break found, add a hard break + $pos = self::MAX_LINE_LENGTH - 1; + $lines_out[] = substr($line, 0, $pos); + $line = substr($line, $pos); + } else { + //Break at the found point + $lines_out[] = substr($line, 0, $pos); + //Move along by the amount we dealt with + $line = substr($line, $pos + 1); + } + //If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1 + if ($in_headers) { + $line = "\t" . $line; + } + } + $lines_out[] = $line; + + //Send the lines to the server + foreach ($lines_out as $line_out) { + //RFC2821 section 4.5.2 + if (!empty($line_out) and $line_out[0] == '.') { + $line_out = '.' . $line_out; + } + $this->client_send($line_out . self::CRLF); + } + } + + //Message data has been sent, complete the command + //Increase timelimit for end of DATA command + $savetimelimit = $this->Timelimit; + $this->Timelimit = $this->Timelimit * 2; + $result = $this->sendCommand('DATA END', '.', 250); + //Restore timelimit + $this->Timelimit = $savetimelimit; + return $result; + } + + /** + * Send an SMTP HELO or EHLO command. + * Used to identify the sending server to the receiving server. + * This makes sure that client and server are in a known state. + * Implements RFC 821: HELO + * and RFC 2821 EHLO. + * @param string $host The host name or IP to connect to + * @access public + * @return boolean + */ + public function hello($host = '') + { + //Try extended hello first (RFC 2821) + return (boolean)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host)); + } + + /** + * Send an SMTP HELO or EHLO command. + * Low-level implementation used by hello() + * @see hello() + * @param string $hello The HELO string + * @param string $host The hostname to say we are + * @access protected + * @return boolean + */ + protected function sendHello($hello, $host) + { + $noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250); + $this->helo_rply = $this->last_reply; + if ($noerror) { + $this->parseHelloFields($hello); + } else { + $this->server_caps = null; + } + return $noerror; + } + + /** + * Parse a reply to HELO/EHLO command to discover server extensions. + * In case of HELO, the only parameter that can be discovered is a server name. + * @access protected + * @param string $type - 'HELO' or 'EHLO' + */ + protected function parseHelloFields($type) + { + $this->server_caps = array(); + $lines = explode("\n", $this->last_reply); + + foreach ($lines as $n => $s) { + //First 4 chars contain response code followed by - or space + $s = trim(substr($s, 4)); + if (empty($s)) { + continue; + } + $fields = explode(' ', $s); + if (!empty($fields)) { + if (!$n) { + $name = $type; + $fields = $fields[0]; + } else { + $name = array_shift($fields); + switch ($name) { + case 'SIZE': + $fields = ($fields ? $fields[0] : 0); + break; + case 'AUTH': + if (!is_array($fields)) { + $fields = array(); + } + break; + default: + $fields = true; + } + } + $this->server_caps[$name] = $fields; + } + } + } + + /** + * Send an SMTP MAIL command. + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more recipient + * commands may be called followed by a data command. + * Implements rfc 821: MAIL FROM: + * @param string $from Source address of this message + * @access public + * @return boolean + */ + public function mail($from) + { + $useVerp = ($this->do_verp ? ' XVERP' : ''); + return $this->sendCommand( + 'MAIL FROM', + 'MAIL FROM:<' . $from . '>' . $useVerp, + 250 + ); + } + + /** + * Send an SMTP QUIT command. + * Closes the socket if there is no error or the $close_on_error argument is true. + * Implements from rfc 821: QUIT + * @param boolean $close_on_error Should the connection close if an error occurs? + * @access public + * @return boolean + */ + public function quit($close_on_error = true) + { + $noerror = $this->sendCommand('QUIT', 'QUIT', 221); + $err = $this->error; //Save any error + if ($noerror or $close_on_error) { + $this->close(); + $this->error = $err; //Restore any error from the quit command + } + return $noerror; + } + + /** + * Send an SMTP RCPT command. + * Sets the TO argument to $toaddr. + * Returns true if the recipient was accepted false if it was rejected. + * Implements from rfc 821: RCPT TO: + * @param string $address The address the message is being sent to + * @access public + * @return boolean + */ + public function recipient($address) + { + return $this->sendCommand( + 'RCPT TO', + 'RCPT TO:<' . $address . '>', + array(250, 251) + ); + } + + /** + * Send an SMTP RSET command. + * Abort any transaction that is currently in progress. + * Implements rfc 821: RSET + * @access public + * @return boolean True on success. + */ + public function reset() + { + return $this->sendCommand('RSET', 'RSET', 250); + } + + /** + * Send a command to an SMTP server and check its return code. + * @param string $command The command name - not sent to the server + * @param string $commandstring The actual command to send + * @param integer|array $expect One or more expected integer success codes + * @access protected + * @return boolean True on success. + */ + protected function sendCommand($command, $commandstring, $expect) + { + if (!$this->connected()) { + $this->setError("Called $command without being connected"); + return false; + } + //Reject line breaks in all commands + if (strpos($commandstring, "\n") !== false or strpos($commandstring, "\r") !== false) { + $this->setError("Command '$command' contained line breaks"); + return false; + } + $this->client_send($commandstring . self::CRLF); + + $this->last_reply = $this->get_lines(); + // Fetch SMTP code and possible error code explanation + $matches = array(); + if (preg_match("/^([0-9]{3})[ -](?:([0-9]\\.[0-9]\\.[0-9]) )?/", $this->last_reply, $matches)) { + $code = $matches[1]; + $code_ex = (count($matches) > 2 ? $matches[2] : null); + // Cut off error code from each response line + $detail = preg_replace( + "/{$code}[ -]".($code_ex ? str_replace('.', '\\.', $code_ex).' ' : '')."/m", + '', + $this->last_reply + ); + } else { + // Fall back to simple parsing if regex fails + $code = substr($this->last_reply, 0, 3); + $code_ex = null; + $detail = substr($this->last_reply, 4); + } + + $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER); + + if (!in_array($code, (array)$expect)) { + $this->setError( + "$command command failed", + $detail, + $code, + $code_ex + ); + $this->edebug( + 'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply, + self::DEBUG_CLIENT + ); + return false; + } + + $this->setError(''); + return true; + } + + /** + * Send an SMTP SAML command. + * Starts a mail transaction from the email address specified in $from. + * Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more recipient + * commands may be called followed by a data command. This command + * will send the message to the users terminal if they are logged + * in and send them an email. + * Implements rfc 821: SAML FROM: + * @param string $from The address the message is from + * @access public + * @return boolean + */ + public function sendAndMail($from) + { + return $this->sendCommand('SAML', "SAML FROM:$from", 250); + } + + /** + * Send an SMTP VRFY command. + * @param string $name The name to verify + * @access public + * @return boolean + */ + public function verify($name) + { + return $this->sendCommand('VRFY', "VRFY $name", array(250, 251)); + } + + /** + * Send an SMTP NOOP command. + * Used to keep keep-alives alive, doesn't actually do anything + * @access public + * @return boolean + */ + public function noop() + { + return $this->sendCommand('NOOP', 'NOOP', 250); + } + + /** + * Send an SMTP TURN command. + * This is an optional command for SMTP that this class does not support. + * This method is here to make the RFC821 Definition complete for this class + * and _may_ be implemented in future + * Implements from rfc 821: TURN + * @access public + * @return boolean + */ + public function turn() + { + $this->setError('The SMTP TURN command is not implemented'); + $this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT); + return false; + } + + /** + * Send raw data to the server. + * @param string $data The data to send + * @access public + * @return integer|boolean The number of bytes sent to the server or false on error + */ + public function client_send($data) + { + $this->edebug("CLIENT -> SERVER: $data", self::DEBUG_CLIENT); + return fwrite($this->smtp_conn, $data); + } + + /** + * Get the latest error. + * @access public + * @return array + */ + public function getError() + { + return $this->error; + } + + /** + * Get SMTP extensions available on the server + * @access public + * @return array|null + */ + public function getServerExtList() + { + return $this->server_caps; + } + + /** + * A multipurpose method + * The method works in three ways, dependent on argument value and current state + * 1. HELO/EHLO was not sent - returns null and set up $this->error + * 2. HELO was sent + * $name = 'HELO': returns server name + * $name = 'EHLO': returns boolean false + * $name = any string: returns null and set up $this->error + * 3. EHLO was sent + * $name = 'HELO'|'EHLO': returns server name + * $name = any string: if extension $name exists, returns boolean True + * or its options. Otherwise returns boolean False + * In other words, one can use this method to detect 3 conditions: + * - null returned: handshake was not or we don't know about ext (refer to $this->error) + * - false returned: the requested feature exactly not exists + * - positive value returned: the requested feature exists + * @param string $name Name of SMTP extension or 'HELO'|'EHLO' + * @return mixed + */ + public function getServerExt($name) + { + if (!$this->server_caps) { + $this->setError('No HELO/EHLO was sent'); + return null; + } + + // the tight logic knot ;) + if (!array_key_exists($name, $this->server_caps)) { + if ($name == 'HELO') { + return $this->server_caps['EHLO']; + } + if ($name == 'EHLO' || array_key_exists('EHLO', $this->server_caps)) { + return false; + } + $this->setError('HELO handshake was used. Client knows nothing about server extensions'); + return null; + } + + return $this->server_caps[$name]; + } + + /** + * Get the last reply from the server. + * @access public + * @return string + */ + public function getLastReply() + { + return $this->last_reply; + } + + /** + * Read the SMTP server's response. + * Either before eof or socket timeout occurs on the operation. + * With SMTP we can tell if we have more lines to read if the + * 4th character is '-' symbol. If it is a space then we don't + * need to read anything else. + * @access protected + * @return string + */ + protected function get_lines() + { + // If the connection is bad, give up straight away + if (!is_resource($this->smtp_conn)) { + return ''; + } + $data = ''; + $endtime = 0; + stream_set_timeout($this->smtp_conn, $this->Timeout); + if ($this->Timelimit > 0) { + $endtime = time() + $this->Timelimit; + } + while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) { + $str = @fgets($this->smtp_conn, 515); + $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL); + $this->edebug("SMTP -> get_lines(): \$str is \"$str\"", self::DEBUG_LOWLEVEL); + $data .= $str; + // If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen + if ((isset($str[3]) and $str[3] == ' ')) { + break; + } + // Timed-out? Log and break + $info = stream_get_meta_data($this->smtp_conn); + if ($info['timed_out']) { + $this->edebug( + 'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)', + self::DEBUG_LOWLEVEL + ); + break; + } + // Now check if reads took too long + if ($endtime and time() > $endtime) { + $this->edebug( + 'SMTP -> get_lines(): timelimit reached ('. + $this->Timelimit . ' sec)', + self::DEBUG_LOWLEVEL + ); + break; + } + } + return $data; + } + + /** + * Enable or disable VERP address generation. + * @param boolean $enabled + */ + public function setVerp($enabled = false) + { + $this->do_verp = $enabled; + } + + /** + * Get VERP address generation mode. + * @return boolean + */ + public function getVerp() + { + return $this->do_verp; + } + + /** + * Set error messages and codes. + * @param string $message The error message + * @param string $detail Further detail on the error + * @param string $smtp_code An associated SMTP error code + * @param string $smtp_code_ex Extended SMTP code + */ + protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ex = '') + { + $this->error = array( + 'error' => $message, + 'detail' => $detail, + 'smtp_code' => $smtp_code, + 'smtp_code_ex' => $smtp_code_ex + ); + } + + /** + * Set debug output method. + * @param string|callable $method The name of the mechanism to use for debugging output, or a callable to handle it. + */ + public function setDebugOutput($method = 'echo') + { + $this->Debugoutput = $method; + } + + /** + * Get debug output method. + * @return string + */ + public function getDebugOutput() + { + return $this->Debugoutput; + } + + /** + * Set debug output level. + * @param integer $level + */ + public function setDebugLevel($level = 0) + { + $this->do_debug = $level; + } + + /** + * Get debug output level. + * @return integer + */ + public function getDebugLevel() + { + return $this->do_debug; + } + + /** + * Set SMTP timeout. + * @param integer $timeout + */ + public function setTimeout($timeout = 0) + { + $this->Timeout = $timeout; + } + + /** + * Get SMTP timeout. + * @return integer + */ + public function getTimeout() + { + return $this->Timeout; + } +} diff --git a/www/plugins/facteur/phpmailer-php5/composer.json b/www/plugins/facteur/phpmailer-php5/composer.json new file mode 100644 index 00000000..9521a12f --- /dev/null +++ b/www/plugins/facteur/phpmailer-php5/composer.json @@ -0,0 +1,45 @@ +{ + "name": "phpmailer/phpmailer", + "type": "library", + "description": "PHPMailer is a full-featured email creation and transfer class for PHP", + "authors": [ + { + "name": "Marcus Bointon", + "email": "phpmailer@synchromedia.co.uk" + }, + { + "name": "Jim Jagielski", + "email": "jimjag@gmail.com" + }, + { + "name": "Andy Prevost", + "email": "codeworxtech@users.sourceforge.net" + }, + { + "name": "Brent R. Matzelle" + } + ], + "require": { + "php": ">=5.0.0" + }, + "require-dev": { + "phpdocumentor/phpdocumentor": "*", + "phpunit/phpunit": "4.7.*" + }, + "suggest": { + "league/oauth2-client": "Needed for XOAUTH2 authentication", + "league/oauth2-google": "Needed for Gmail XOAUTH2" + }, + "autoload": { + "classmap": [ + "class.phpmailer.php", + "class.phpmaileroauth.php", + "class.phpmaileroauthgoogle.php", + "class.smtp.php", + "class.pop3.php", + "extras/EasyPeasyICS.php", + "extras/ntlm_sasl_client.php" + ] + }, + "license": "LGPL-2.1" +} diff --git a/www/plugins/facteur/phpmailer-php5/extras/EasyPeasyICS.php b/www/plugins/facteur/phpmailer-php5/extras/EasyPeasyICS.php new file mode 100644 index 00000000..d8bfcfae --- /dev/null +++ b/www/plugins/facteur/phpmailer-php5/extras/EasyPeasyICS.php @@ -0,0 +1,148 @@ + + * @author Manuel Reinhard + * + * Built with inspiration from + * http://stackoverflow.com/questions/1463480/how-can-i-use-php-to-dynamically-publish-an-ical-file-to-be-read-by-google-calend/1464355#1464355 + * History: + * 2010/12/17 - Manuel Reinhard - when it all started + * 2014 PHPMailer project becomes maintainer + */ + +/** + * Class EasyPeasyICS. + * Simple ICS data generator + * @package phpmailer + * @subpackage easypeasyics + */ +class EasyPeasyICS +{ + /** + * The name of the calendar + * @var string + */ + protected $calendarName; + /** + * The array of events to add to this calendar + * @var array + */ + protected $events = array(); + + /** + * Constructor + * @param string $calendarName + */ + public function __construct($calendarName = "") + { + $this->calendarName = $calendarName; + } + + /** + * Add an event to this calendar. + * @param string $start The start date and time as a unix timestamp + * @param string $end The end date and time as a unix timestamp + * @param string $summary A summary or title for the event + * @param string $description A description of the event + * @param string $url A URL for the event + * @param string $uid A unique identifier for the event - generated automatically if not provided + * @return array An array of event details, including any generated UID + */ + public function addEvent($start, $end, $summary = '', $description = '', $url = '', $uid = '') + { + if (empty($uid)) { + $uid = md5(uniqid(mt_rand(), true)) . '@EasyPeasyICS'; + } + $event = array( + 'start' => gmdate('Ymd', $start) . 'T' . gmdate('His', $start) . 'Z', + 'end' => gmdate('Ymd', $end) . 'T' . gmdate('His', $end) . 'Z', + 'summary' => $summary, + 'description' => $description, + 'url' => $url, + 'uid' => $uid + ); + $this->events[] = $event; + return $event; + } + + /** + * @return array Get the array of events. + */ + public function getEvents() + { + return $this->events; + } + + /** + * Clear all events. + */ + public function clearEvents() + { + $this->events = array(); + } + + /** + * Get the name of the calendar. + * @return string + */ + public function getName() + { + return $this->calendarName; + } + + /** + * Set the name of the calendar. + * @param $name + */ + public function setName($name) + { + $this->calendarName = $name; + } + + /** + * Render and optionally output a vcal string. + * @param bool $output Whether to output the calendar data directly (the default). + * @return string The complete rendered vlal + */ + public function render($output = true) + { + //Add header + $ics = 'BEGIN:VCALENDAR +METHOD:PUBLISH +VERSION:2.0 +X-WR-CALNAME:' . $this->calendarName . ' +PRODID:-//hacksw/handcal//NONSGML v1.0//EN'; + + //Add events + foreach ($this->events as $event) { + $ics .= ' +BEGIN:VEVENT +UID:' . $event['uid'] . ' +DTSTAMP:' . gmdate('Ymd') . 'T' . gmdate('His') . 'Z +DTSTART:' . $event['start'] . ' +DTEND:' . $event['end'] . ' +SUMMARY:' . str_replace("\n", "\\n", $event['summary']) . ' +DESCRIPTION:' . str_replace("\n", "\\n", $event['description']) . ' +URL;VALUE=URI:' . $event['url'] . ' +END:VEVENT'; + } + + //Add footer + $ics .= ' +END:VCALENDAR'; + + if ($output) { + //Output + $filename = $this->calendarName; + //Filename needs quoting if it contains spaces + if (strpos($filename, ' ') !== false) { + $filename = '"'.$filename.'"'; + } + header('Content-type: text/calendar; charset=utf-8'); + header('Content-Disposition: inline; filename=' . $filename . '.ics'); + echo $ics; + } + return $ics; + } +} diff --git a/www/plugins/facteur/phpmailer-php5/extras/README.md b/www/plugins/facteur/phpmailer-php5/extras/README.md new file mode 100644 index 00000000..dac79e05 --- /dev/null +++ b/www/plugins/facteur/phpmailer-php5/extras/README.md @@ -0,0 +1,17 @@ +#PHPMailer Extras + +These classes provide optional additional functions to PHPMailer. + +These are not loaded by the PHPMailer autoloader, so in some cases you may need to `require` them yourself before using them. + +##EasyPeasyICS + +This class was originally written by Manuel Reinhard and provides a simple means of generating ICS/vCal files that are used in sending calendar events. PHPMailer does not use it directly, but you can use it to generate content appropriate for placing in the `Ical` property of PHPMailer. The PHPMailer project is now its official home as Manuel has given permission for that and is no longer maintaining it himself. + +##htmlfilter + +This class by Konstantin Riabitsev and Jim Jagielski implements HTML filtering to remove potentially malicious tags, such as `'; + $flux .="\n".''; } - + return $flux; } @@ -46,7 +51,7 @@ function gis_insert_head($flux){ * @param $flux * @return mixed */ -function gis_header_prive($flux){ +function gis_header_prive($flux) { $flux .= gis_insert_head_css(''); $flux .= gis_insert_head(''); return $flux; @@ -58,13 +63,12 @@ function gis_header_prive($flux){ * @param $flux * @return mixed */ -function gis_afficher_contenu_objet($flux){ +function gis_afficher_contenu_objet($flux) { if ($objet = $flux['args']['type'] and include_spip('inc/config') and in_array(table_objet_sql($objet), lire_config('gis/gis_objets', array())) and ($id = intval($flux['args']['id_objet'])) - - ){ + ) { $texte = recuperer_fond( 'prive/contenu/gis_objet', array( @@ -75,7 +79,7 @@ function gis_afficher_contenu_objet($flux){ ); $flux['data'] .= $texte; } - + return $flux; } @@ -86,86 +90,82 @@ function gis_afficher_contenu_objet($flux){ * @param $flux * @return mixed */ -function gis_post_edition($flux){ - if (is_array($flux) && isset($flux['args']['operation']) && ($flux['args']['operation'] == 'ajouter_document') - AND ($document = sql_fetsel("*","spip_documents","id_document=".intval($flux['args']['id_objet']))) - AND (in_array(table_objet_sql('document'), lire_config('gis/gis_objets', array()))) +function gis_post_edition($flux) { + if (is_array($flux) && isset($flux['args']['operation']) && ($flux['args']['operation'] == 'ajouter_document') + and ($document = sql_fetsel('*', 'spip_documents', 'id_document=' . intval($flux['args']['id_objet']))) + and (in_array(table_objet_sql('document'), lire_config('gis/gis_objets', array()))) ) { - if (in_array($document['extension'],array('jpg','kml','kmz'))) { + if (in_array($document['extension'], array('jpg', 'kml', 'kmz'))) { $config = @unserialize($GLOBALS['meta']['gis']); - if (!is_array($config)) + if (!is_array($config)) { $config = array(); + } include_spip('inc/documents'); $fichier = get_spip_doc($document['fichier']); $id_document = $document['id_document']; } if ($document['extension'] == 'jpg') { // on recupere les coords definies dans les exif du document s'il y en a - if (function_exists('exif_read_data') AND $exifs = @exif_read_data($fichier,'GPS')) { - if (!function_exists('dms_to_dec')) + if (function_exists('exif_read_data') and $exifs = @exif_read_data($fichier, 'GPS')) { + if (!function_exists('dms_to_dec')) { include_spip('gis_fonctions'); - spip_log("GIS EXIFS : Récuperation des coordonnees du fichier $fichier","gis"); - - $LatDeg = explode("/",$exifs["GPSLatitude"][0]); - if (is_numeric($LatDeg[1]) > 0) - $intLatDeg = $LatDeg[0]/$LatDeg[1]; + } + spip_log("GIS EXIFS : Récuperation des coordonnees du fichier $fichier", 'gis'); + + $LatDeg = explode('/', $exifs['GPSLatitude'][0]); + $intLatDeg = $LatDeg[0] / ($LatDeg[1] ? $LatDeg[1] : 1); - $LatMin = explode("/",$exifs["GPSLatitude"][1]); - if (is_numeric($LatMin[1]) > 0) - $intLatMin = $LatMin[0]/$LatMin[1]; + $LatMin = explode('/', $exifs['GPSLatitude'][1]); + $intLatMin = $LatMin[0] / ($LatMin[1] ? $LatMin[1] : 1); - $LatSec = explode("/",$exifs["GPSLatitude"][2]); - if (is_numeric($LatSec[1]) > 0) - $intLatSec = $LatSec[0]/$LatSec[1]; + $LatSec = explode('/', $exifs['GPSLatitude'][2]); + $intLatSec = $LatSec[0] / ($LatSec[1] ? $LatSec[1] : 1); - $LongDeg = explode("/",$exifs["GPSLongitude"][0]); - if (is_numeric($LongDeg[1]) > 0) - $intLongDeg = $LongDeg[0]/$LongDeg[1]; + $LongDeg = explode('/', $exifs['GPSLongitude'][0]); + $intLongDeg = $LongDeg[0] / ($LongDeg[1] ? $LongDeg[1] : 1); - $LongMin = explode("/",$exifs["GPSLongitude"][1]); - if (is_numeric($LongMin[1]) > 0) - $intLongMin = $LongMin[0]/$LongMin[1]; + $LongMin = explode('/', $exifs['GPSLongitude'][1]); + $intLongMin = $LongMin[0] / ($LongMin[1] ? $LongMin[1] : 1); - $LongSec = explode("/",$exifs["GPSLongitude"][2]); - if (is_numeric($LongSec[1]) > 0) - $intLongSec = $LongSec[0]/$LongSec[1]; + $LongSec = explode('/', $exifs['GPSLongitude'][2]); + $intLongSec = $LongSec[0] / ($LongSec[1] ? $LongSec[1] : 1); // round to 5 = approximately 1 meter accuracy - if (is_numeric($intLatDeg) && is_numeric($intLatMin) && is_numeric($intLatSec)) - $latitude = round(dms_to_dec($exifs["GPSLatitudeRef"], - $intLatDeg,$intLatMin,$intLatSec),5); + if (is_numeric($intLatDeg) && is_numeric($intLatMin) && is_numeric($intLatSec)) { + $latitude = round(dms_to_dec($exifs['GPSLatitudeRef'], $intLatDeg, $intLatMin, $intLatSec), 5); + } - if (is_numeric($intLongDeg) && is_numeric($intLongMin) && is_numeric($intLongSec)) - $longitude = round(dms_to_dec($exifs["GPSLongitudeRef"], - $intLongDeg,$intLongMin,$intLongSec), 5); + if (is_numeric($intLongDeg) && is_numeric($intLongMin) && is_numeric($intLongSec)) { + $longitude = round(dms_to_dec($exifs['GPSLongitudeRef'], $intLongDeg, $intLongMin, $intLongSec), 5); + } if ($config['geocoder'] == 'on') { include_spip('inc/distant'); $url_geocoder = 'http://nominatim.openstreetmap.org/reverse/?format=xml&addressdetails=1&accept-language='.urlencode($GLOBALS['meta']['langue_site']).'&lat='.urlencode($latitude).'&lon='.urlencode($longitude); $json = recuperer_page($url_geocoder); - $geocoder = json_decode($json,true); + $geocoder = json_decode($json, true); if (is_array($geocoder)) { $pays = $geocoder['address']['country']; $code_pays = $geocoder['address']['country_code']; $region = $geocoder['address']['state']; if ($geocoder['address']['city']) { $ville = $geocoder['address']['city']; - } else if ($geocoder['address']['town']) { + } elseif ($geocoder['address']['town']) { $ville = $geocoder['address']['town']; - } else if ($geocoder['address']['village']) { + } elseif ($geocoder['address']['village']) { $ville = $geocoder['address']['village']; } $code_postal = $geocoder['address']['postcode']; $adresse = $geocoder['address']['road']; } } - } else if (file_exists($fichier)) { - include_spip("inc/iptc"); + } elseif (file_exists($fichier)) { + include_spip('inc/iptc'); $er = new class_IPTC($fichier); $iptc = $er->fct_lireIPTC(); $codesiptc = $er->h_codesIptc; $string_recherche = ''; - + if ($iptc['city']) { $string_recherche .= $iptc['city'].', '; } @@ -179,7 +179,7 @@ function gis_post_edition($flux){ include_spip('inc/distant'); $url_geocoder = 'http://nominatim.openstreetmap.org/search/?format=json&addressdetails=1&limit=1&accept-language='.urlencode($GLOBALS['meta']['langue_site']).'&q='.urlencode($string_recherche); $json = recuperer_page($url_geocoder); - $geocoder = json_decode($json,true); + $geocoder = json_decode($json, true); if (is_array($geocoder[0])) { $latitude = $geocoder[0]['lat']; $longitude = $geocoder[0]['lon']; @@ -189,9 +189,9 @@ function gis_post_edition($flux){ $region = $geocoder[0]['address']['state']; if ($geocoder[0]['address']['city']) { $ville = $geocoder[0]['address']['city']; - } else if ($geocoder[0]['address']['town']) { + } elseif ($geocoder[0]['address']['town']) { $ville = $geocoder[0]['address']['town']; - } else if ($geocoder[0]['address']['village']) { + } elseif ($geocoder[0]['address']['village']) { $ville = $geocoder[0]['address']['village']; } } @@ -212,28 +212,28 @@ function gis_post_edition($flux){ 'pays' => $pays, 'code_pays' => $code_pays ); - + if (defined('_DIR_PLUGIN_GISGEOM')) { $geojson = '{"type":"Point","coordinates":['.$longitude.','.$latitude.']}'; - set_request('geojson',$geojson); + set_request('geojson', $geojson); } - + include_spip('action/editer_gis'); - - if ($id_gis = sql_getfetsel("G.id_gis","spip_gis AS G LEFT JOIN spip_gis_liens AS T ON T.id_gis=G.id_gis ","T.id_objet=" . intval($id_document) . " AND T.objet='document'")) { + + if ($id_gis = sql_getfetsel('G.id_gis', 'spip_gis AS G LEFT JOIN spip_gis_liens AS T ON T.id_gis=G.id_gis', 'T.id_objet=' . intval($id_document) . " AND T.objet='document'")) { // Des coordonnées sont déjà définies pour ce document => on les update - revisions_gis($id_gis,$c); - spip_log("GIS EXIFS : Update des coordonnées depuis EXIFS pour le document $id_document => id_gis = $id_gis","gis"); + revisions_gis($id_gis, $c); + spip_log("GIS EXIFS : Update des coordonnées depuis EXIFS pour le document $id_document => id_gis = $id_gis", 'gis'); } else { // Aucune coordonnée n'est définie pour ce document => on les crées $id_gis = insert_gis(); - revisions_gis($id_gis,$c); + revisions_gis($id_gis, $c); lier_gis($id_gis, 'document', $id_document); - spip_log("GIS EXIFS : Création des coordonnées depuis EXIFS pour le document $id_document => id_gis = $id_gis","gis"); + spip_log("GIS EXIFS : Création des coordonnées depuis EXIFS pour le document $id_document => id_gis = $id_gis", 'gis'); } } - } elseif (in_array($document['extension'],array('kml','kmz','gpx'))) { - $recuperer_info = charger_fonction('kml_infos','inc'); + } elseif (in_array($document['extension'], array('kml','kmz','gpx'))) { + $recuperer_info = charger_fonction('kml_infos', 'inc'); $infos = $recuperer_info($document['id_document']); if ($infos) { if (is_numeric($latitude = $infos['latitude']) && is_numeric($longitude = $infos['longitude'])) { @@ -244,19 +244,19 @@ function gis_post_edition($flux){ 'lon' => $longitude, 'zoom' => $config['zoom'] ? $config['zoom'] :'4' ); - + include_spip('action/editer_gis'); - - if ($id_gis = sql_getfetsel("G.id_gis","spip_gis AS G LEFT JOIN spip_gis_liens AS T ON T.id_gis=G.id_gis ","T.id_objet=" . intval($id_document) . " AND T.objet='document'")) { + + if ($id_gis = sql_getfetsel('G.id_gis', 'spip_gis AS G LEFT JOIN spip_gis_liens AS T ON T.id_gis=G.id_gis', 'T.id_objet=' . intval($id_document) . " AND T.objet='document'")) { // Des coordonnées sont déjà définies pour ce document => on les update - revisions_gis($id_gis,$c); - spip_log("GIS EXIFS : Update des coordonnées depuis EXIFS pour le document $id_document => id_gis = $id_gis","gis"); + revisions_gis($id_gis, $c); + spip_log("GIS EXIFS : Update des coordonnées depuis EXIFS pour le document $id_document => id_gis = $id_gis", 'gis'); } else { // Aucune coordonnée n'est définie pour ce document => on les crées $id_gis = insert_gis(); - revisions_gis($id_gis,$c); + revisions_gis($id_gis, $c); lier_gis($id_gis, 'document', $id_document); - spip_log("GIS EXIFS : Création des coordonnées depuis EXIFS pour le document $id_document => id_gis = $id_gis","gis"); + spip_log("GIS EXIFS : Création des coordonnées depuis EXIFS pour le document $id_document => id_gis = $id_gis", 'gis'); } } unset($infos['longitude']); @@ -268,15 +268,15 @@ function gis_post_edition($flux){ } } } - if (is_array($flux) && isset($flux['args']['operation']) && ($flux['args']['operation'] == 'supprimer_document') - AND ($id_document = intval($flux['args']['id_objet']) - AND ($id_gis = sql_getfetsel("G.id_gis","spip_gis AS G LEFT JOIN spip_gis_liens AS T ON T.id_gis=G.id_gis ","T.id_objet=" . intval($id_document) . " AND T.objet='document'"))) + if (is_array($flux) && isset($flux['args']['operation']) && ($flux['args']['operation'] == 'supprimer_document') + and ($id_document = intval($flux['args']['id_objet']) + and ($id_gis = sql_getfetsel('G.id_gis', 'spip_gis AS G LEFT JOIN spip_gis_liens AS T ON T.id_gis=G.id_gis', 'T.id_objet=' . intval($id_document) . " AND T.objet='document'"))) ) { include_spip('action/editer_gis'); supprimer_gis($id_gis); - spip_log("GIS EXIFS : Suppression des coordonnées pour le document $id_document => id_gis = $id_gis","gis"); + spip_log("GIS EXIFS : Suppression des coordonnées pour le document $id_document => id_gis = $id_gis", 'gis'); } - + return $flux; } @@ -287,18 +287,18 @@ function gis_post_edition($flux){ * @param array $flux * @return array */ -function gis_optimiser_base_disparus($flux){ +function gis_optimiser_base_disparus($flux) { include_spip('action/editer_liens'); // optimiser les liens morts : // entre gis vers des objets effaces // depuis des gis effaces - $flux['data'] += objet_optimiser_liens(array('gis'=>'*'),'*'); + $flux['data'] += objet_optimiser_liens(array('gis' => '*'), '*'); return $flux; } -function gis_saisies_autonomes($flux){ +function gis_saisies_autonomes($flux) { $flux[] = 'carte'; return $flux; } @@ -306,13 +306,13 @@ function gis_saisies_autonomes($flux){ /** * Insertion dans le pipeline xmlrpc_methodes (xmlrpc) * Ajout de méthodes xml-rpc spécifiques à GIS - * + * * @param array $flux : un array des methodes déjà présentes, fonctionnant sous la forme : * -* clé = nom de la méthode; * -* valeur = le nom de la fonction à appeler; - * @return array $flux : l'array complété avec nos nouvelles méthodes + * @return array $flux : l'array complété avec nos nouvelles méthodes */ -function gis_xmlrpc_methodes($flux){ +function gis_xmlrpc_methodes($flux) { $flux['spip.liste_gis'] = 'spip_liste_gis'; $flux['spip.lire_gis'] = 'spip_lire_gis'; return $flux; @@ -320,31 +320,30 @@ function gis_xmlrpc_methodes($flux){ /** * Insertion dans le pipeline xmlrpc_server_class (xmlrpc) - * Ajout de fonctions spécifiques utilisés par le serveur xml-rpc + * Ajout de fonctions spécifiques utilisés par le serveur xml-rpc */ -function gis_xmlrpc_server_class($flux){ +function gis_xmlrpc_server_class($flux) { include_spip('inc/gis_xmlrpc'); return $flux; } /** * Insertion dans le traitement du formulaire de configuration - * + * * Purger le répertoire js si on a une carte google dans les layers pour recalculer le js statique * Peut être à améliorer - * + * * @param array $flux * Le contexte du pipeline * @return array $flux */ -function gis_formulaire_traiter($flux){ - if($flux['args']['form'] == 'configurer_gis'){ - if (count(array_intersect(array('google_roadmap', 'google_satellite', 'google_terrain'), _request('layers'))) > 0){ +function gis_formulaire_traiter($flux) { + if ($flux['args']['form'] == 'configurer_gis') { + if (count(array_intersect(array('google_roadmap', 'google_satellite', 'google_terrain'), _request('layers'))) > 0) { include_spip('inc/invalideur'); - purger_repertoire(_DIR_VAR.'cache-js'); + purger_repertoire(_DIR_VAR . 'cache-js'); suivre_invalideur(1); } } return $flux; } -?> diff --git a/www/plugins/gis/icones_barre/gis.png b/www/plugins/gis/icones_barre/gis.png index b0e5a4cd8271e43ceb57d98fc6573022ee391753..399d41ca6b67a482f65f2b430b8db110e7dde62c 100644 GIT binary patch delta 203 zcmV;+05t!L0{a1wB!9w5L_t(|0b@V|LJW!wVhmUTCxf+Slhi`>6AYHvq$MO48J|!4 zU-UQhJ%a`|1?-$LQQyk{m;6uqBb5p(Gb}Kk+j^+N(`JeY+do@-C{~4rP6aJ_F z&-(BFfWZ{20tR=#kIDa&fY9_Zw-XixOhLZi;{V6~kN@xgpOKp%NgR%ZK&~Kx?Yz8r z6fnpso#*nzr+`^-F-H|11wh|K3d~@@r+|TnA&P+mj{=||69W^B4FFJl>Qt3-X^Q{= N002ovPDHLkV1i=WV_g6M diff --git a/www/plugins/gis/images/gis-16.png b/www/plugins/gis/images/gis-16.png index b0e5a4cd8271e43ceb57d98fc6573022ee391753..399d41ca6b67a482f65f2b430b8db110e7dde62c 100644 GIT binary patch delta 203 zcmV;+05t!L0{a1wB!9w5L_t(|0b@V|LJW!wVhmUTCxf+Slhi`>6AYHvq$MO48J|!4 zU-UQhJ%a`|1?-$LQQyk{m;6uqBb5p(Gb}Kk+j^+N(`JeY+do@-C{~4rP6aJ_F z&-(BFfWZ{20tR=#kIDa&fY9_Zw-XixOhLZi;{V6~kN@xgpOKp%NgR%ZK&~Kx?Yz8r z6fnpso#*nzr+`^-F-H|11wh|K3d~@@r+|TnA&P+mj{=||69W^B4FFJl>Qt3-X^Q{= N002ovPDHLkV1i=WV_g6M diff --git a/www/plugins/gis/images/gis-24.png b/www/plugins/gis/images/gis-24.png index 6cb9f54090783c3be5461b4ebf5819b2b0f2f23f..25d1e7ef2a3fe740f6c89a68e9a2d27f570cbd3d 100755 GIT binary patch delta 334 zcmV-U0kQtd1>ORX8Gi%-002sU^>Y9K0VPR9K~#7FmD2-ICs6=^@$YQgwr$(CZQH}U z8fUx4${1t};$_j`?$OGsUO2pWB}{9i#B#xvKAQ=xP;*<-!lo=zpK#< z7>uOd*dB?-;e+@f-Z#9_3}6tFmZEzw>YZq7g^&D}Mq~e~;eWMg>0~kwk@fpp!AsH7 zqe=|vhm7Of!k&t@=6JCP8B-=WJrZplOXCwGkfD9K{Jv;wTO@`|LDGYLNw-BuyW;qS zgh7~GuDT&Q+7iVdB+Q%YaYeMXCk+Q)F&YW8C%Wy;+>x>_@<86PQvR_BS%-PcW6tqy zPcGk4VZ$6>>_-@ZVneW+AH+^n_^>IHx2UjpUI>;9M6prWjB#N)Dmw(EZ*psMAUL&X(s%#> z0zpYcK~zYIwUtdz6Hyd~pVO97i>3(;*eYhE(nQ;U5kC?(uz!OkZrm7`Ze5hM|Gt1ylHUs;B7R^3xC&eW&H**xiK@Q!B&cdj0a4%%@N|59+@7DG-vVA_GMOr{ z2n5^hJ*+^Ru79V2`*U-1lS@lW?`CIbrvVlg7Lvvor_q~d_kgd>^`F2mV~m^0WbV4I zi|e|ms`z}qzH~aB0Mb1JRP_V!aCv!o!*Lun#&B4pqoX6hjpIy!s{RJDrBbQbn4qC} zJboUSte>df0QGv4&*#58j>BR3{r-?;S!2N1aRKYuY=8D!^DQ#QkV>VJz-)h{CQcx7cJ1yq0{aCv5C<^izp z72XKxO2Bo?vTWcvFyQ6)dJkIF=JxjX=R_iL3ApBE?i!$~2f$`D8a>kYsFw)<)=Q<* z4`4z>IzGpq0l8dmD-wwe1H&f{P}O~4EgTM?0XAYM4yf0wot>Re!0ApV&!2wB%_28} j16AGlFMv8kv_r^Wd_{TA4_k;>00000NkvXXu0mjf43I=` diff --git a/www/plugins/gis/images/gis.png b/www/plugins/gis/images/gis.png index 8f867fc7f57fbeee3ecc663d7a21e617884ca133..79d32bcb82f9395f74e5ad54f50067db8f22d39d 100755 GIT binary patch literal 5559 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 FV1g!%lEeT2 literal 6005 zcmV-*7mDbKP)Lj%qJk_62}y|D z5QoJLVF_Tcjcvv@US`G~&-V7^ZvD==cLrndcx)!bG``Zs^WJ^$zyJCE@0|0U^WTRN z1Od(-Z#>Mi5S#_(EHGz*ISb6&f7oyKrePSraX=iOo$dJ^@a;Z+Rf}l6nPG2svj=;S z8ZhuT{Q++1wCojTOPl>pV1hq2;U4weokIqGa3H`JZ#s6YmLp*NGuw|0GXy4;1~O!MOFOz(uUgRe!qzYF>SsU`sINt4+nCs8tR1B=l4{MHZi;%6lUoh~qT zE}mFoIaREmJc##>kK(6A2lx6}WUMSc9!z3GP&vbu8d)O@X9!^2fYFzL*aXzY_QvS~ z6EjT9^7E4jrlt^-OSsZ^aCuO~=4uSzG;_Ew-i+V#^SCr9pP6dWXOi$p44&FYw2d0U$cuDK?u%V?3fc{LU85=%=EF;^ziqX z!hu==-zFqa#Jd@Ps4Hz@P{4mBp<~*H{bO-LQ92h}nei#$E(CNC;iH;m+ zd6!kf?X@z#6AU& zvG>-yFmU6o$mN<}_kMG83%YxHu{V=N^7D5hIXZO0F|suKMx%;L3Bsl0z^&I@#B#^O zp20z7$?<)oSS*Gmix*>iZ3FJx_H*3cG)p}>M?3VhCv~OBCr@_PaxG}S?anuVGE;Q1 zZd-EEDvV!o{hY>olrFU5{0mSb+a_7SR%k;oHY?!uVzJl*`j5*;=^_o4Wj(se_ zxZ}_bPI6~SHZ@@hSuvNxVR2|1v&WAhQoind=@<_u0Y+LL&M9;N1Q=`f&o$9V0Y$)> z%h8}~W#$45=26F-j4{&s_3Cp3h66g3DOO_k&xw%@0y9^}NDQjRQ+U$0aIsT*)1HC= zW6f8s^|b`-w)q9Ii0&WW}91AgRPT{DTidQ>ta4u zIg{Aq6!8-~gJ)BnSmjl*woyVl0?41E@-^qe82^|6{AQ<5-uk3(;fD{+?nd;X(zhP~ z5+@$(*zBD_ZG3{`lK_3jpcD{cTIdb-Gd(|T3(k(=Cvf4 zZ9tPo?ElQCv8c5b*~{PeMt}G;h5jg7f~h?ZQDLUKn>tH4nCEB zLldRT)e zNG4(0wt{2Zv1pQf#m}0|24a}pSRC2V*HY7jlkw^`rd~(4d1UoPxyER0BAr!(Jg&NB z$2pD(j{#b~6JxDaDdY)|jTFlX1*s8M-iBrB`vPFtq$hLuy;wX6o2)P_gX>yBtz6N$ zB~wibtm`&7j?eGL@xtEW({rUprGRQVk9wt{d(<(ZVTLy_Z5n0K7*{Ok4S6G_y2Z)W zb;YEHIWk#AcSjSB94%qXwh{ES#IR~0Lom&V5jNZ$CoZB!7Tu+xRDb1C0dd~Tti(d2 zIaaOg!RNJx=o(=r?@QZhC>bCeVs+@&9n`HD5~-xl!6D;o<)Vs8gN$^2hYRG;6fPtS zUVoO%TKNLs-Lel~-?R${k1!*o zV#uXq7@nxZ;)JX923^z-LDliN`lOP_)oj$Osx|0b(Y5ezpH;W#)N}*QCu`)Ith_Y0 zZGs}76DEqYyA4;})*@4c<#t>rOyI+N3WIdd|8%mFZkM<+u~?Wc8RRKM>;&Q&8 z>*=XXF$6qQ0iCU|niUu$X6X$CVF_doSK4dfL)q{NMyFTO+Lo*~^wUW8YXEg<3e4=aE6e2#FUO84Weq_Zq4^TnV83oU+FX z`v*Q_k}yfw##by2HKS-iE)r<$|!!!Rup%24rj4GGbv%R2k%HfVPCbytZ;6hm{MPS>O1` z7aM5FB*>J80-s34xDZT;WQfEdI}um5%2BKa$Rw>On}xn0tP$`zNzG1%DIgIPUjns< zP0x>E#e!xmA81o1oAG$4zB#@s%@Z+ZWaUa6drpJmbM;&XI*AFf1SiM?nVG6vX{;&pwK_mEIluS(!4kf;AH3*t?9j7s-iiQ z#G0jTSl*u{&^~IE56=!xa$Ex!FJ_huEX_8(Uk zrG!H}1o+t+q4o)y>2{2iGb|^J=0T_f(%B}I3Psfdnmx!S$x)193&FM79cmrth0KlZWf5{Hl8)^}(M3C4gbS6+mj@VGRY$4J3P)ipI+ZG2Ck zM*IDvB}^5=3C0*BI)Avo7M&FZEvC|ZADAU;^za5P)Et! zULLM$0$I@23U4Bho}HuU+&6*d@d`4Ve){v&4L6J&4~}(rd%MPob9U@7j(p@J=jXrr z)q86P_y0pq1YO-j;=oa~J@GQ@8?s|z7X?xU`;S(zd1sk!P{QiP?dsJD+PeKf9?N^1 zlt~g&WQFz}E+L!n!>nM2X;wRa1SMZ_@yPZ(E?SV{>WdCB$;<=}jn@(5=PqEZirJQC zJ&84vR&?y>Y0-330-LvvAVubMXDv+(aelrl8`liAYq-eQ2I`KFLt|B(w{1TzdVD+5 zRTnWQKz6Et#^B&b%lG~FLTBgBr_$G4Gt)=4Ywk>II9A%d`?G%B`2D79u7X7$*BHr_ zs1F}P>hY)GF$kBJ=;u$p|W1;8831ve&?LF1i>{h(}WQj!PgFnTdte9 zaG(Wof{}=)w0;pm+)P6UI#LR-xSttqA$pGJordZdkqQkahlO1!OqOe)*hMqd^>wS- z$skji+TWH!Q!<9-9dWE3d=)Mwb#P=1&W_!oZ7*(vx9@1O2bvNh(Sp$D^+23XfO*T#wu`f2~M(z^~!f(F@aBQTohH_)IWZh3vRx+lXY24%Mi(4T9vo?(DW}7f$tz+_i_K0A!XO)E1ESHKJ`jo$6V5#B7h9&uN+2!OippG@xgsMhk*7O z`V4Rk?$jhol2ArRZ|ChdDKKTnneIPyRJn|%Uq_}s`dZsSq&O#%7beiRlT~Vf<}{=< zDpSH=a&7{7`s|atC$M2@PM6lv3f99*2Z|_h;v1H>>UiOpTs0b3s5)5MlcK9sHPc8~ zmDYm9p>iX@1CQ;;RVzENlrc-vu>Mg;H=ozc)gZ{$)D(kx=$g}IOiApc^hg`^jyE!fVq=O~!7~W}CzpsafQ0H2 z2N@&swn%lRyK;qUnDmP=NEj4j*DOomTfeMprcp8Hg+=Djctc~2f+4L3FWe`U)VFp~ zN4IL47c@{TlwfQ2*r$ReiaYnCT4TBfX*%2#v( zi<%|fNu-!=yeO-L&+!R(ftD9rc9+o8WMDx@3@Osuj}*7hSzo@Q1(z>t(LlXxq=c~& zjqPbdj@o2-ZxS2M%Tk|&RsV~x7SP-jLr*S}Bth8ds+U-l@;+8qP8nC>JUrS~qaDd; zN3tZqh_6bO4&%icG4~(o^z`2s5W($&T%4e!q6)Jbp(?^OyM6_X4d=3yXZDb)P_mE| zYE+|=J(LY**s#ji479VVwxfbin|@{}w6rPC_nz5T#*QNnZo9Y{xu)c6RlU?zOak(+ zRLg$D3oGZD?qHx#UW&GnRQ`=8r|^N*E$CyK*7k?APQ7qLw!*ST_0N|5C_M8DM!y;hSp_{ zZnQ}=$_nFCq`g$naNI!Rp&4%bR`~ZqX0a3lsVNP#sAQ2j$wr)nlSD@|O3w_!;)@zj z2@ln%-5Lu)`urbNDi6;HysHKI5EwZh<+-1e?_E)2r0VDQqvfV`$o6(}da%b1HpQ$B87(}97W z7SyU`R49t1D3tV`Y0lE4ENz28S`x){npZ@_ojs^?VseEIWnES{fJ}Gtk|VWMMXe z64UjPHj^cQhtXnyqkP?&i{mJ3s-L}F!iD|u@TnzVibhwB3>9>s)Rxvn!wJ*{gl*yu zU5r(CY-rcOeDG))uN-x7$+9*y#ll~Yc#SY#NMlY4%{mKAo9x&-TE_WZHk#t5)NHRs`6zt%%{gi<{q_!j(UswfIjU1`Tg5b+WXk5GJQiwc zR+6q}5N(Ktf-Eq#BnUfgApp915rL48dHVS;Dj_$SUz=XclcF$2lZ+2rxR7~VO* z@(&_V$|7_l8&3Kd-kg7T9RXoSpu7_q<3xb?C)^b|O 0) && $args['objet']){ + if ((intval($args['id_objet']) > 0) && $args['objet']) { $where[] = 'lien.id_objet='.intval($args['id_objet']).' AND lien.objet='.sql_quote($args['objet']); } - - if(in_array('distance',$order) OR in_array('!distance',$order)){ + + if (in_array('distance', $order) or in_array('!distance', $order)) { $distance = true; $lat = $args['lat']; $lon = $args['lon']; - if(!is_numeric($lon) OR !is_numeric($lat)){ + if (!is_numeric($lon) or !is_numeric($lat)) { $erreur = _T('gis:erreur_xmlrpc_lat_lon'); return new IXR_Error(-32601, attribut_html($erreur)); - }else{ + } else { $what[] = "(6371 * acos( cos( radians(\"$lat\") ) * cos( radians( gis.lat ) ) * cos( radians( gis.lon ) - radians(\"$lon\") ) + sin( radians(\"$lat\") ) * sin( radians( gis.lat ) ) ) ) AS distance"; } } - + /** * Une recherche - */ - if(is_string($args['recherche']) AND strlen($args['recherche']) > 3){ + */ + if (is_string($args['recherche']) and strlen($args['recherche']) > 3) { $prepare_recherche = charger_fonction('prepare_recherche', 'inc'); list($rech_select, $rech_where) = $prepare_recherche($args['recherche'], $objet.'s', $where); $what[] = $rech_select; $from .= ' INNER JOIN spip_resultats AS resultats ON ( resultats.id = gis.id_gis ) '; $where[] = 'resultats.'.$rech_where; } - + $points_struct = array(); - if($points = sql_select($what,$from,$where,'',$order,$args['limite'])){ - while($point = sql_fetch($points)){ + if ($points = sql_select($what, $from, $where, '', $order, $args['limite'])) { + while ($point = sql_fetch($points)) { $struct=array(); $args['id_gis'] = $point['id_gis']; /** * On utilise la fonction geodiv_lire_media pour éviter de dupliquer trop de code */ $struct = spip_lire_gis($args); - if($distance) + if ($distance) { $struct['distance'] = $point['distance']; + } $points_struct[] = $struct; } } @@ -76,7 +80,7 @@ function spip_liste_gis($args) { /** * Récupère le contenu d'un point géolocalisé - * + * * Arguments possibles : * -* login * -* pass @@ -84,49 +88,51 @@ function spip_liste_gis($args) { * -* lat : si disponible avec lon, on ajoute la distance dans les infos * -* lon : si disponible avec lat, on ajoute la distance dans les infos */ -function spip_lire_gis($args){ +function spip_lire_gis($args) { global $spip_xmlrpc_serveur; - - if(!$spip_xmlrpc_serveur) + + if (!$spip_xmlrpc_serveur) { return false; - - if(!intval($args['id_gis']) > 0){ - $erreur = _T('xmlrpc:erreur_identifiant',array('objet'=>'gis')); + } + + if (!intval($args['id_gis']) > 0) { + $erreur = _T('xmlrpc:erreur_identifiant', array('objet'=>'gis')); return new IXR_Error(-32601, attribut_html($erreur)); } - - $args_gis = array('objet'=>'gis','id_objet'=>$args['id_gis']); + + $args_gis = array('objet' => 'gis','id_objet' => $args['id_gis']); $res = $spip_xmlrpc_serveur->read($args_gis); - if(!$res) + if (!$res) { return $spip_xmlrpc_serveur->error; - - if(isset($args['lat']) && is_numeric($args['lat']) && isset($args['lon']) && is_numeric($args['lon'])){ + } + + if (isset($args['lat']) && is_numeric($args['lat']) && isset($args['lon']) && is_numeric($args['lon'])) { $lat = $args['lat']; $lon = $args['lon']; $what[] = 'gis.id_gis'; $what[] = "(6371 * acos( cos( radians(\"$lat\") ) * cos( radians( gis.lat ) ) * cos( radians( gis.lon ) - radians(\"$lon\") ) + sin( radians(\"$lat\") ) * sin( radians( gis.lat ) ) ) ) AS distance"; - $distance = sql_fetsel($what,"spip_gis AS gis","gis.id_gis=".intval($args['id_gis'])); + $distance = sql_fetsel($what, 'spip_gis AS gis', 'gis.id_gis='.intval($args['id_gis'])); $res['result'][0]['distance'] = $distance['distance']; } - - if(autoriser('modifier','gis',$args['id_gis'],$GLOBALS['visiteur_session'])) + + if (autoriser('modifier', 'gis', $args['id_gis'], $GLOBALS['visiteur_session'])) { $res['result'][0]['modifiable'] = 1; - else + } else { $res['result'][0]['modifiable'] = 0; - $logo = quete_logo('id_gis','on', $res['result'][0]['id_gis'], '', false); - if(is_array($logo)) + } + $logo = quete_logo('id_gis', 'on', $res['result'][0]['id_gis'], '', false); + if (is_array($logo)) { $res['result'][0]['logo'] = url_absolue($logo[0]); + } - if(defined('_DIR_PLUGIN_GISGEOM')){ - if(isset($res['result'][0]['geo'])){ + if (defined('_DIR_PLUGIN_GISGEOM')) { + if (isset($res['result'][0]['geo'])) { include_spip('gisgeom_fonctions'); $res['result'][0]['geo'] = wkt_to_json($wkt); } } $gis_struct = $res['result'][0]; - $gis_struct = array_map('texte_backend',$gis_struct); + $gis_struct = array_map('texte_backend', $gis_struct); return $gis_struct; } - -?> \ No newline at end of file diff --git a/www/plugins/gis/inc/iptc.php b/www/plugins/gis/inc/iptc.php index 9eff943a..56baaa35 100644 --- a/www/plugins/gis/inc/iptc.php +++ b/www/plugins/gis/inc/iptc.php @@ -5,48 +5,48 @@ if (!defined('_ECRIRE_INC_VERSION')) return; //############################################################################################# //############################################################################################## -/* INFOS SUR LE FICHIER +/* INFOS SUR LE FICHIER -Nom : iptc.class.php -Rôle : contient la classe permettant de gérer les IPTC d'un fichier image -Développeur(s) : Arica Alex, Thies C. Arntzen +Nom : iptc.class.php +Rôle : contient la classe permettant de gérer les IPTC d'un fichier image +Développeur(s) : Arica Alex, Thies C. Arntzen -FIN INFOS SUR LE FICHIER +FIN INFOS SUR LE FICHIER -INFOS SUR LA CLASSE 'class_iptc' +INFOS SUR LA CLASSE 'class_iptc' -REFERENCES : Développée le 04 Octobre 02 par Arica Alex avec l'aide de Thies C. Arntzen +REFERENCES : Développée le 04 Octobre 02 par Arica Alex avec l'aide de Thies C. Arntzen -ROLE : permet de manipuler les iptc d'une image +ROLE : permet de manipuler les iptc d'une image -VARIABLES : -- $h_codesIptc -- $h_cheminFichier -- $h_iptcData +VARIABLES : +- $h_codesIptc +- $h_cheminFichier +- $h_iptcData -METHODES : -- fct_lireIPTC -- fct_ecrireIPTC -- fct_iptcMaketag +METHODES : +- fct_lireIPTC +- fct_ecrireIPTC +- fct_iptcMaketag -FIN INFOS SUR LA CLASSE +FIN INFOS SUR LA CLASSE -*/ +*/ -class class_IPTC -{ +class class_IPTC +{ -/* VARIABLES statics */ +/* VARIABLES statics */ -var $h_codesIptc; /* $h_codesIptc : (tableau associatif) contient les codes des champs IPTC associés à un libellé */ -var $h_cheminImg; /* $h_cheminImg : (chaine) contient le chemin complet du fichier d'image */ -var $h_iptcData; /* $h_iptcData : (chaine) contient les données encodées de l'iptc de l'image */ +var $h_codesIptc; /* $h_codesIptc : (tableau associatif) contient les codes des champs IPTC associés à un libellé */ +var $h_cheminImg; /* $h_cheminImg : (chaine) contient le chemin complet du fichier d'image */ +var $h_iptcData; /* $h_iptcData : (chaine) contient les données encodées de l'iptc de l'image */ -/* FIN VARIABLES statics +/* FIN VARIABLES statics @@ -56,7 +56,7 @@ var $h_iptcData; /* $h_iptcData : (chaine) contient les données encodées de l' -------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------------- @@ -65,68 +65,68 @@ var $h_iptcData; /* $h_iptcData : (chaine) contient les données encodées de l' -INFOS SUR LA FONCTION +INFOS SUR LA FONCTION -ROLE : constructeur -FONCTION : class_IPTC($cheminImg) -DESCRIPTION DES PARAMETRES : -- $cheminImg = (chaine) le chemin complet du fichier d'image à traiter +ROLE : constructeur +FONCTION : class_IPTC($cheminImg) +DESCRIPTION DES PARAMETRES : +- $cheminImg = (chaine) le chemin complet du fichier d'image à traiter -FIN INFOS SUR LA FONCTION */ +FIN INFOS SUR LA FONCTION */ -function class_IPTC($cheminImg) -{ +function class_IPTC($cheminImg) +{ -// Inititalisations +// Inititalisations -// Les valeurs IPTC pouvant être manipulées -$this -> h_codesIptc = array("005" => "objectName", -"007" => "editStatus", -"010" => "priority", -"015" => "category", -"020" => "supplementalCategory", -"022" => "fixtureIdentifier", -"025" => "keywords", -"030" => "releaseDate", -"035" => "releaseTime", -"040" => "specialInstructions", -"045" => "referenceService", -"047" => "referenceDate", -"050" => "referenceNumber", -"055" => "createdDate", -"060" => "createdTime", -"065" => "originatingProgram", -"070" => "programVersion", -"075" => "objectCycle", -"080" => "byline", -"085" => "bylineTitle", -"090" => "city", -"095" => "provinceState", -"100" => "countryCode", -"101" => "country", -"103" => "originalTransmissionReference", -"105" => "headline", -"110" => "credit", -"115" => "source", -"116" => "copyright", -"120" => "caption", -"121" => "localCaption", -"122" => "captionWriter"); +// Les valeurs IPTC pouvant être manipulées +$this -> h_codesIptc = array("005" => "objectName", +"007" => "editStatus", +"010" => "priority", +"015" => "category", +"020" => "supplementalCategory", +"022" => "fixtureIdentifier", +"025" => "keywords", +"030" => "releaseDate", +"035" => "releaseTime", +"040" => "specialInstructions", +"045" => "referenceService", +"047" => "referenceDate", +"050" => "referenceNumber", +"055" => "createdDate", +"060" => "createdTime", +"065" => "originatingProgram", +"070" => "programVersion", +"075" => "objectCycle", +"080" => "byline", +"085" => "bylineTitle", +"090" => "city", +"095" => "provinceState", +"100" => "countryCode", +"101" => "country", +"103" => "originalTransmissionReference", +"105" => "headline", +"110" => "credit", +"115" => "source", +"116" => "copyright", +"120" => "caption", +"121" => "localCaption", +"122" => "captionWriter"); -// On enregistre le chemin de l'image à traiter -$this -> h_cheminImg = $cheminImg; +// On enregistre le chemin de l'image à traiter +$this -> h_cheminImg = $cheminImg; -// On extrait les données encodées de l'iptc +// On extrait les données encodées de l'iptc // getimagesize($this -> h_cheminImg, &$info); //avant,marche pas sinon -getimagesize($this -> h_cheminImg, $info); //marche sans le & -$this -> h_iptcData = $info["APP13"]; +getimagesize($this -> h_cheminImg, $info); //marche sans le & +$this -> h_iptcData = $info["APP13"]; -} +} -/* FIN FONCTION class_IPTC(); +/* FIN FONCTION class_IPTC(); @@ -136,7 +136,7 @@ $this -> h_iptcData = $info["APP13"]; -------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------------- @@ -145,38 +145,38 @@ $this -> h_iptcData = $info["APP13"]; -INFOS SUR LA FONCTION +INFOS SUR LA FONCTION -ROLE : lit les IPTC d'une image et les renvoie dans un tableau associatif -FONCTION : fct_lireIPTC() -TYPE RETOURNE : chaine sous forme de tableau associatif +ROLE : lit les IPTC d'une image et les renvoie dans un tableau associatif +FONCTION : fct_lireIPTC() +TYPE RETOURNE : chaine sous forme de tableau associatif -FIN INFOS SUR LA FONCTION */ +FIN INFOS SUR LA FONCTION */ -function fct_lireIPTC() -{ - $tblIPTC = iptcparse($this -> h_iptcData); - - while( (is_array($tblIPTC)) && (list($codeIPTC, $valeurIPTC) = each($tblIPTC)) ) - { - $codeIPTC = str_replace("2#", "", $codeIPTC); - - if( ($codeIPTC != "000") && ($codeIPTC != "140") && $this->h_codesIptc["$codeIPTC"]) - { - while(list($index, ) = each($valeurIPTC)) - { +function fct_lireIPTC() +{ + $tblIPTC = iptcparse($this -> h_iptcData); + + while( (is_array($tblIPTC)) && (list($codeIPTC, $valeurIPTC) = each($tblIPTC)) ) + { + $codeIPTC = str_replace("2#", "", $codeIPTC); + + if( ($codeIPTC != "000") && ($codeIPTC != "140") && $this->h_codesIptc["$codeIPTC"]) + { + while(list($index, ) = each($valeurIPTC)) + { if ($this->h_codesIptc["$codeIPTC"]) $codeIPTC = $this->h_codesIptc["$codeIPTC"]; - $lesIptc[$codeIPTC] .= $valeurIPTC[$index].$retourLigne; - $retourLigne = "\n"; - } - } - } - - if(is_array($lesIptc)) return $lesIptc; - else return false; -} + $lesIptc[$codeIPTC] .= $valeurIPTC[$index].$retourLigne; + $retourLigne = "\n"; + } + } + } + + if(is_array($lesIptc)) return $lesIptc; + else return false; +} -/* FIN FONCTION fct_lireIPTC(); +/* FIN FONCTION fct_lireIPTC(); @@ -185,7 +185,7 @@ function fct_lireIPTC() -------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------------- @@ -194,79 +194,79 @@ function fct_lireIPTC() -INFOS SUR LA FONCTION +INFOS SUR LA FONCTION -ROLE : écrit des IPTC dans le fichier image -FONCTION : fct_ecrireIPTC() -DESCRIPTION DES PARAMETRES : -- $tblIPTC_util = (tableau associatif) contient les codes des champs IPTC à modifier associés leur valeur -- $cheminImgAModifier = (chaine) stocke le chemin de l'image dont l'IPTC est à modifier ; s'il est null -le chemin sera celui contenu dans '$this -> h_cheminImg' -TYPE RETOURNE : booléen +ROLE : écrit des IPTC dans le fichier image +FONCTION : fct_ecrireIPTC() +DESCRIPTION DES PARAMETRES : +- $tblIPTC_util = (tableau associatif) contient les codes des champs IPTC à modifier associés leur valeur +- $cheminImgAModifier = (chaine) stocke le chemin de l'image dont l'IPTC est à modifier ; s'il est null +le chemin sera celui contenu dans '$this -> h_cheminImg' +TYPE RETOURNE : booléen -FIN INFOS SUR LA FONCTION */ +FIN INFOS SUR LA FONCTION */ -function fct_ecrireIPTC($tblIPTC_util, $cheminImgAModifier = "") -{ +function fct_ecrireIPTC($tblIPTC_util, $cheminImgAModifier = "") +{ -// La tableau devant contenir des IPTC est vide ou n'est pas un tableau associatif -if( (empty($tblIPTC_util)) || (!is_array($tblIPTC_util)) ) return false; +// La tableau devant contenir des IPTC est vide ou n'est pas un tableau associatif +if( (empty($tblIPTC_util)) || (!is_array($tblIPTC_util)) ) return false; -// Si le chemin de l'image à modifier est vide alors on lui spécifie le chemin par défaut -if(empty($cheminImgAModifier)) $cheminImgAModifier = $this -> h_cheminImg; +// Si le chemin de l'image à modifier est vide alors on lui spécifie le chemin par défaut +if(empty($cheminImgAModifier)) $cheminImgAModifier = $this -> h_cheminImg; -// On récupère l'IPTC du fichier image courant -$tblIPTC_old = iptcparse($this -> h_iptcData); +// On récupère l'IPTC du fichier image courant +$tblIPTC_old = iptcparse($this -> h_iptcData); -// On prélève le tableau contenant les codes et les valeurs des IPTC de la photo -while(list($codeIPTC, $codeLibIPTC) = each($this -> h_codesIptc)) -{ +// On prélève le tableau contenant les codes et les valeurs des IPTC de la photo +while(list($codeIPTC, $codeLibIPTC) = each($this -> h_codesIptc)) +{ -// On teste si les données originelles correspondant au code en cours sont présents -if (is_array($tblIPTC_old["2#".$codeIPTC])) $valIPTC_new = $tblIPTC_old["2#".$codeIPTC]; -else $valIPTC_new = array(); +// On teste si les données originelles correspondant au code en cours sont présents +if (is_array($tblIPTC_old["2#".$codeIPTC])) $valIPTC_new = $tblIPTC_old["2#".$codeIPTC]; +else $valIPTC_new = array(); -// On remplace les valeurs des IPTC demandées -if (is_array($tblIPTC_util[$codeIPTC])) -{ -if (count($tblIPTC_util[$codeIPTC])) $valIPTC_new = $tblIPTC_util[$codeIPTC]; +// On remplace les valeurs des IPTC demandées +if (is_array($tblIPTC_util[$codeIPTC])) +{ +if (count($tblIPTC_util[$codeIPTC])) $valIPTC_new = $tblIPTC_util[$codeIPTC]; -}else{ +}else{ -$val = trim(strval($tblIPTC_util[$codeIPTC])); -if (strlen($val)) $valIPTC_new[0] = $val; -} +$val = trim(strval($tblIPTC_util[$codeIPTC])); +if (strlen($val)) $valIPTC_new[0] = $val; +} -// On crée un nouveau iptcData à partir de '$tblIPTC_new' qui contient le code et la valeur de l'IPTC -foreach($valIPTC_new as $val) -{ -$iptcData_new .= $this -> fct_iptcMaketag(2, $codeIPTC, $val); -} +// On crée un nouveau iptcData à partir de '$tblIPTC_new' qui contient le code et la valeur de l'IPTC +foreach($valIPTC_new as $val) +{ +$iptcData_new .= $this -> fct_iptcMaketag(2, $codeIPTC, $val); +} -} +} -/* A partir du nouveau iptcData contenu dans '$iptcData_new' on crée grâce à la fonction 'iptcembed()' -le contenu binaire du fichier image avec le nouveau IPTC inclu */ -$contenuImage = iptcembed($iptcData_new, $this -> h_cheminImg); +/* A partir du nouveau iptcData contenu dans '$iptcData_new' on crée grâce à la fonction 'iptcembed()' +le contenu binaire du fichier image avec le nouveau IPTC inclu */ +$contenuImage = iptcembed($iptcData_new, $this -> h_cheminImg); -// Ecriture dans le fichier image -$idFichier = fopen($cheminImgAModifier, "wb"); -fwrite($idFichier, $contenuImage); -fclose($idFichier); +// Ecriture dans le fichier image +$idFichier = fopen($cheminImgAModifier, "wb"); +fwrite($idFichier, $contenuImage); +fclose($idFichier); -return true; +return true; -} +} -/* FIN FONCTION fct_ecrireIPTC(); +/* FIN FONCTION fct_ecrireIPTC(); @@ -275,7 +275,7 @@ return true; -------------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------------- @@ -284,44 +284,44 @@ return true; -INFOS SUR LA FONCTION +INFOS SUR LA FONCTION -ROLE : permet de transformer une valeur de d'IPTC (code + valeur) en iptcData -AUTEUR : Thies C. Arntzen -FONCTION : fct_iptcMaketag($rec, $dat, $val) -DESCRIPTION DES PARAMETRES : -- $rec = (entier) toujours à mettre à 2 -- $dat = (chaine) le code de l'IPTC (de type '110' et non '2#110') -- $val = (chaine) la valeur de l'IPTC -TYPE RETOURNE : booléen +ROLE : permet de transformer une valeur de d'IPTC (code + valeur) en iptcData +AUTEUR : Thies C. Arntzen +FONCTION : fct_iptcMaketag($rec, $dat, $val) +DESCRIPTION DES PARAMETRES : +- $rec = (entier) toujours à mettre à 2 +- $dat = (chaine) le code de l'IPTC (de type '110' et non '2#110') +- $val = (chaine) la valeur de l'IPTC +TYPE RETOURNE : booléen -FIN INFOS SUR LA FONCTION */ +FIN INFOS SUR LA FONCTION */ -function fct_iptcMaketag($rec, $dat, $val) -{ -$len = strlen($val); -if ($len < 0x8000) -return chr(0x1c).chr($rec).chr($dat). -chr($len >> 8). -chr($len & 0xff). -$val; -else -return chr(0x1c).chr($rec).chr($dat). -chr(0x80).chr(0x04). -chr(($len >> 24) & 0xff). -chr(($len >> 16) & 0xff). -chr(($len >> 8 ) & 0xff). -chr(($len ) & 0xff). -$val; -} +function fct_iptcMaketag($rec, $dat, $val) +{ +$len = strlen($val); +if ($len < 0x8000) +return chr(0x1c).chr($rec).chr($dat). +chr($len >> 8). +chr($len & 0xff). +$val; +else +return chr(0x1c).chr($rec).chr($dat). +chr(0x80).chr(0x04). +chr(($len >> 24) & 0xff). +chr(($len >> 16) & 0xff). +chr(($len >> 8 ) & 0xff). +chr(($len ) & 0xff). +$val; +} -// FIN FONCTION fct_iptcMaketag(); +// FIN FONCTION fct_iptcMaketag(); -} +} /* Fin class_IPTC */ diff --git a/www/plugins/gis/inc/kml_infos.php b/www/plugins/gis/inc/kml_infos.php index 484c03ee..3fd76639 100644 --- a/www/plugins/gis/inc/kml_infos.php +++ b/www/plugins/gis/inc/kml_infos.php @@ -6,30 +6,33 @@ * -* récupérer un titre * -* récupérer un descriptif */ -if (!defined("_ECRIRE_INC_VERSION")) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} -function inc_kml_infos($id_document){ - if(!intval($id_document)) +function inc_kml_infos($id_document) { + if (!intval($id_document)) { return false; + } include_spip('inc/documents'); - $document = sql_fetsel("*", "spip_documents","id_document=".intval($id_document)); + $document = sql_fetsel('*', 'spip_documents', 'id_document=' . intval($id_document)); $chemin = $document['fichier']; $chemin = get_spip_doc($chemin); $extension = $document['extension']; - - if(in_array($extension,array('kml','kmz'))){ + + if (in_array($extension, array('kml','kmz'))) { $supprimer_chemin = false; /** * Si on est dans un kmz (kml + autres fichiers compressés en zip), * On dézip pour trouver le kml */ - if($extension == 'kmz'){ + if ($extension == 'kmz') { include_spip('inc/pclzip'); $zip = new PclZip($chemin); $list = $zip->listContent(); - foreach($list as $fichier => $info_fichier){ - if(substr(basename($info_fichier['filename']),-3) == 'kml'){ - $zip->extractByIndex($info_fichier['index'],_DIR_TMP); + foreach ($list as $fichier => $info_fichier) { + if (substr(basename($info_fichier['filename']), -3) == 'kml') { + $zip->extractByIndex($info_fichier['index'], _DIR_TMP); $chemin = _DIR_TMP.$info_fichier['filename']; $supprimer_chemin = true; break; @@ -37,50 +40,58 @@ function inc_kml_infos($id_document){ } } include_spip('inc/xml'); - $ret = lire_fichier($chemin,$donnees); + $donnees = ''; + lire_fichier($chemin, $donnees); $arbre = spip_xml_parse($donnees); - spip_xml_match_nodes(",^Document,",$arbre, $documents); - foreach($documents as $document => $info){ + $documents = $infos = array(); + spip_xml_match_nodes(',^Document,', $arbre, $documents); + foreach ($documents as $document => $info) { $infos['titre'] = $info[0]['name'][0]; $infos['descriptif'] = $info[0]['description'][0]; $infos['longitude'] = $info[0]['LookAt'][0]['longitude'][0] ? $info[0]['LookAt'][0]['longitude'][0] : false; $infos['latitude'] = $info[0]['LookAt'][0]['latitude'][0] ? $info[0]['LookAt'][0]['latitude'][0] : false; } - + /** - * Si on n'a pas de longitude ou de latitude, + * Si on n'a pas de longitude ou de latitude, * on essaie de faire une moyenne des placemarks */ - if(!$infos['longitude'] OR !$infos['latitude']){ - spip_xml_match_nodes(",^Placemark,",$arbre, $placemarks); + if (!$infos['longitude'] or !$infos['latitude']) { + $placemarks = array(); + spip_xml_match_nodes(',^Placemark,', $arbre, $placemarks); $latitude = 0; $longitude = 0; $compte = 0; - foreach($placemarks as $places){ - foreach($places as $placemark => $lieu){ - if($compte > 500) - break; - if($lieu['LookAt'][0]['longitude'][0] && $latitude + $lieu['LookAt'][0]['latitude'][0]){ - if($compte > 500) - break; + foreach ($placemarks as $places) { + foreach ($places as $lieu) { + if ($compte > 500) { + break; + } + if ($lieu['LookAt'][0]['longitude'][0] && $latitude + $lieu['LookAt'][0]['latitude'][0]) { + if ($compte > 500) { + break; + } $latitude = $latitude + $lieu['LookAt'][0]['latitude'][0]; $longitude = $longitude + $lieu['LookAt'][0]['longitude'][0]; $compte++; - }else if($lieu['Point'][0]['coordinates'][0]){ - if($compte > 500) + } elseif ($lieu['Point'][0]['coordinates'][0]) { + if ($compte > 500) { break; - $coordinates = explode(',',$lieu['Point'][0]['coordinates'][0]); + } + $coordinates = explode(',', $lieu['Point'][0]['coordinates'][0]); $latitude = $latitude + trim($coordinates[1]); $longitude = $longitude + trim($coordinates[0]); $compte++; - }else if($lieu['Polygon'][0]['outerBoundaryIs'][0]['LinearRing'][0]['coordinates'][0]){ - if($compte > 500) + } elseif ($lieu['Polygon'][0]['outerBoundaryIs'][0]['LinearRing'][0]['coordinates'][0]) { + if ($compte > 500) { break; - $coordinates = explode(' ',trim($lieu['Polygon'][0]['outerBoundaryIs'][0]['LinearRing'][0]['coordinates'][0])); - foreach($coordinates as $coordinate){ - if($compte > 500) + } + $coordinates = explode(' ', trim($lieu['Polygon'][0]['outerBoundaryIs'][0]['LinearRing'][0]['coordinates'][0])); + foreach ($coordinates as $coordinate) { + if ($compte > 500) { break; - $coordinate = explode(',',$coordinate); + } + $coordinate = explode(',', $coordinate); $latitude = $latitude + trim($coordinate[1]); $longitude = $longitude + trim($coordinate[0]); $compte++; @@ -88,100 +99,112 @@ function inc_kml_infos($id_document){ } } } - if(($latitude != 0) && ($longitude != 0)){ + if (($latitude != 0) and ($longitude != 0)) { $infos['latitude'] = $latitude / $compte; - $infos['longitude'] = $longitude / $compte; + $infos['longitude'] = $longitude / $compte; } } - + /** * Si pas de titre ou si le titre est égal au nom de fichier ou contient kml ou kmz : * -* on regarde s'il n'y a qu'un seul Folder et on récupère son nom; * -* on regarde s'il n'y a qu'un seul Placemark et on récupère son nom; */ - if(!$infos['titre'] OR ($infos['titre'] == basename($chemin)) OR (preg_match(',\.km.,',$infos['titre']) > 0)){ - spip_xml_match_nodes(",^Folder,",$arbre, $folders); - if(count($folders['Folder']) == 1){ - foreach($folders['Folder'] as $folder => $dossier){ - if($dossier['name'][0]) + if (!$infos['titre'] or ($infos['titre'] == basename($chemin)) or (preg_match(',\.km.,', $infos['titre']) > 0)) { + $folders = array(); + spip_xml_match_nodes(',^Folder,', $arbre, $folders); + if (count($folders['Folder']) == 1) { + foreach ($folders['Folder'] as $dossier) { + if ($dossier['name'][0]) { $infos['titre'] = $dossier['name'][0]; - if(!$infos['descriptif'] && $dossier['description'][0]) + } + if (!$infos['descriptif'] && $dossier['description'][0]) { $infos['descriptif'] = $dossier['description'][0]; + } } - }else{ - if(!is_array($placemarks)){ - spip_xml_match_nodes(",^Placemark,",$arbre, $placemarks); + } else { + if (!is_array($placemarks)) { + spip_xml_match_nodes(',^Placemark,', $arbre, $placemarks); } - if(count($placemarks) == 1){ - foreach($placemarks as $places){ - if(count($places) == 1){ - foreach($places as $placemark => $lieu){ - if($lieu['name'][0]) + if (count($placemarks) == 1) { + foreach ($placemarks as $places) { + if (count($places) == 1) { + foreach ($places as $lieu) { + if ($lieu['name'][0]) { $infos['titre'] = $lieu['name'][0]; - if(!$infos['descriptif'] && $lieu['description'][0]) + } + if (!$infos['descriptif'] && $lieu['description'][0]) { $infos['descriptif'] = $lieu['description'][0]; + } } } } } } } - }else if(in_array($extension,array('gpx'))){ + } elseif (in_array($extension, array('gpx'))) { $supprimer_chemin = false; include_spip('inc/xml'); - $ret = lire_fichier($chemin,$donnees); + $donnees = ''; + lire_fichier($chemin, $donnees); $arbre = spip_xml_parse($donnees); - spip_xml_match_nodes(",^metadata,",$arbre, $metadatas); - foreach($metadatas as $metadata => $info){ + $metadatas = array(); + spip_xml_match_nodes(',^metadata,', $arbre, $metadatas); + foreach ($metadatas as $info) { $infos['titre'] = $info[0]['name'][0]; //$infos['date'] = $info[0]['time'][0]; $infos['descriptif'] = $info[0]['description'][0]; - foreach($info[0] as $meta => $data){ - if(preg_match(',^bounds ,',$meta)){ + foreach ($info[0] as $meta => $data) { + if (preg_match(',^bounds ,', $meta)) { $meta = '<'.$meta.'>'; - $maxlat = extraire_attribut($meta,'maxlat'); - $minlat = extraire_attribut($meta,'minlat'); - $maxlon = extraire_attribut($meta,'maxlon'); - $minlon = extraire_attribut($meta,'minlon'); - if($maxlat && $minlat) + $maxlat = extraire_attribut($meta, 'maxlat'); + $minlat = extraire_attribut($meta, 'minlat'); + $maxlon = extraire_attribut($meta, 'maxlon'); + $minlon = extraire_attribut($meta, 'minlon'); + if ($maxlat && $minlat) { $infos['latitude'] = (($maxlat+$minlat)/2); - if($maxlon && $minlon) + } + if ($maxlon && $minlon) { $infos['longitude'] = (($maxlon+$minlon)/2); + } } } } /** - * Si on n'a pas de longitude ou de latitude, + * Si on n'a pas de longitude ou de latitude, * on essaie de faire une moyenne des placemarks */ - if(!$infos['longitude'] OR !$infos['latitude']){ - spip_xml_match_nodes(",^trkpt,",$arbre, $trackpoints); + if (!$infos['longitude'] or !$infos['latitude']) { + $trackpoints = array(); + spip_xml_match_nodes(',^trkpt,', $arbre, $trackpoints); $latitude = 0; $longitude = 0; $compte = 0; - foreach($trackpoints as $places => $place){ - foreach($place as $placemark => $lieu){ - if($compte > 10) - break; + foreach ($trackpoints as $places => $place) { + foreach ($place as $lieu) { + if ($compte > 10) { + break; + } } } - if(($latitude != 0) && ($longitude != 0)){ + if (($latitude != 0) && ($longitude != 0)) { $infos['latitude'] = $latitude / $compte; - $infos['longitude'] = $longitude / $compte; + $infos['longitude'] = $longitude / $compte; } } - }else + } else { return false; - - if(isset($infos['titre'])) - $infos['titre'] = preg_replace('//is', '$1',$infos['titre']); - if(isset($infos['descriptif'])) + } + + if (isset($infos['titre'])) { + $infos['titre'] = preg_replace('//is', '$1', $infos['titre']); + } + if (isset($infos['descriptif'])) { $infos['descriptif'] = preg_replace('//is', '$1', $infos['descriptif']); - - if($supprimer_chemin){ + } + if ($supprimer_chemin) { supprimer_fichier($chemin); } - + return $infos; } -?> \ No newline at end of file diff --git a/www/plugins/gis/javascript/.eslintrc b/www/plugins/gis/javascript/.eslintrc new file mode 100644 index 00000000..4ebb8822 --- /dev/null +++ b/www/plugins/gis/javascript/.eslintrc @@ -0,0 +1,32 @@ +{ + "rules": { + "camelcase": 0, + "quotes": [2, "single", "avoid-escape"], + "no-mixed-spaces-and-tabs": [2, "smart-tabs"], + "space-before-function-paren": 2, + "space-in-parens": 2, + "object-curly-spacing": [2, "never"], + "array-bracket-spacing": 2, + "computed-property-spacing": 2, + "space-before-blocks": 2, + "keyword-spacing": 2, + "no-lonely-if": 2, + "comma-style": 2, + "no-underscore-dangle": 0, + "no-constant-condition": 0, + "no-multi-spaces": 0, + "strict": 0, + "key-spacing": 0, + "no-shadow": 0, + "no-unused-vars": 2 + }, + "globals": { + "L": true, + "module": false, + "define": false, + "require": true + }, + "env": { + "browser": true + } +} diff --git a/www/plugins/gis/javascript/gis.js.html b/www/plugins/gis/javascript/gis.js.html index 8537b6a5..cacd2080 100644 --- a/www/plugins/gis/javascript/gis.js.html +++ b/www/plugins/gis/javascript/gis.js.html @@ -2,19 +2,19 @@ [(#INCLURE{lib/leaflet/dist/[(#CONFIG{auto_compress_js}|=={oui}|?{'leaflet','leaflet-src'})].js})] -[L.Icon.Default.imagePath = "(#CHEMIN{lib/leaflet/dist/images}|url_absolue)";] +[L.Icon.Default.imagePath = '(#CHEMIN{lib/leaflet/dist/images}|url_absolue)';] (function() { L.gisConfig = { - "gis_layers":#EVAL{json_encode($GLOBALS['gis_layers'])}, - "default_layer":"[(#REM|gis_layer_defaut)]", - "affiche_layers":[(#CONFIG{gis/layers,#ARRAY}|json_encode)] + 'gis_layers': #EVAL{json_encode($GLOBALS['gis_layers'])}, + 'default_layer': '[(#REM|gis_layer_defaut)]', + 'affiche_layers': [(#CONFIG{gis/layers,#ARRAY}|json_encode)] }; L.geocoderConfig = { - "forwardUrl":"[(#VAL{gis_geocoder_rechercher}|generer_url_action{mode=search}|html_entity_decode)]", - "reverseUrl":"[(#VAL{gis_geocoder_rechercher}|generer_url_action{mode=reverse}|html_entity_decode)]" + 'forwardUrl': '[(#VAL{gis_geocoder_rechercher}|generer_url_action{mode=search}|html_entity_decode)]', + 'reverseUrl': '[(#VAL{gis_geocoder_rechercher}|generer_url_action{mode=reverse}|html_entity_decode)]' }; })(); @@ -27,6 +27,8 @@ L.geocoderConfig = { [(#INCLURE{lib/leaflet/plugins/GPX.js})] +[(#INCLURE{lib/leaflet/plugins/TOPOJSON.js})] + [(#INCLURE{lib/leaflet/plugins/leaflet-providers.js})] [(#INCLURE{lib/leaflet/plugins/Control.FullScreen.js})] @@ -53,5 +55,5 @@ L.geocoderConfig = { [(#INCLURE{javascript/leaflet.gis.js})] [(#CONFIG{auto_compress_js}|=={oui}|oui) -#FILTRE{compacte} -] +// gis.js +#FILTRE{trim|compacte}] \ No newline at end of file diff --git a/www/plugins/gis/javascript/gis_geocoder.js b/www/plugins/gis/javascript/gis_geocoder.js index 1494d32c..3eec60df 100644 --- a/www/plugins/gis/javascript/gis_geocoder.js +++ b/www/plugins/gis/javascript/gis_geocoder.js @@ -36,7 +36,7 @@ L.Geocoder = L.Class.extend({ q: text, limit: this.options.limit, addressdetails: this.options.addressdetails, - "accept-language":this.options.acceptLanguage + 'accept-language': this.options.acceptLanguage } ); }, @@ -60,66 +60,126 @@ L.Geocoder = L.Class.extend({ dataType: 'jsonp', jsonp: 'json_callback', success: this._callback, + error: function (e) { + /** + * Photon me renvoie une erreur à chaque fois + */ + if (e.statusText == 'OK' && e.status == '200') { + this._callback(e.responseText,e.status,e); + } + }, url: url }); }, - _callback: function (response,textStatus,jqXHR) { - var return_location = {}; - if(this.options.search) + _callback: function (response, textStatus, jqXHR) { + var return_location = {}, + geocoder_server = false; + if (this.options.search) { return_location.search = this.options.search; + } + if (typeof response === 'string') { + geocoder_server = 'photon'; + response = JSON.parse(response); + } if (((response instanceof Array) && (!response.length)) || ((response instanceof Object) && (response.error))) { return_location.error = 'not found'; } else { return_location.street = return_location.postcode = return_location.postcode = return_location.locality = return_location.region = return_location.country = ''; + if (geocoder_server == 'photon') { + if (!response.features.length || response.features.length == 0) { + return_location.error = 'not found'; + } + else { + place = response.features[0]; + var street_components = []; - if (response.length > 0) - place = response[0]; - else { - place = response; + if (place.properties.country) { + return_location.country = place.properties.country; + } + if (place.properties.country_code) { + return_location.country_code = place.properties.country_code; + } + if (place.properties.state) { + return_location.region = place.properties.state; + } + if (place.properties.city) { + return_location.locality = place.properties.city; + } else if (place.properties.town) { + return_location.locality = place.properties.town; + } else if (place.properties.village) { + return_location.locality = place.properties.village; + } else if (place.properties.osm_key == 'place' && (place.properties.osm_value == 'city' || place.properties.osm_value == 'village')) { + return_location.locality = place.properties.name; + } else if (place.properties.county) { + street_components.push(place.properties.county); + } + if (place.properties.postcode) { + return_location.postcode = place.properties.postcode; + } + if (place.properties.street) { + street_components.push(place.properties.street); + } + else if (place.properties.road) { + street_components.push(place.properties.road); + } else if (place.properties.pedestrian) { + street_components.push(place.properties.pedestrian); + } + if (place.properties.housenumber) { + street_components.unshift(place.properties.housenumber); + } + if (return_location.street === '' && street_components.length > 0) { + return_location.street = street_components.join(' '); + } + place.lat = place.geometry.coordinates[1]; + place.lon = place.geometry.coordinates[0]; + return_location.point = new L.LatLng(place.lat, place.lon); + } } + else { + if (response.length > 0) + place = response[0]; + else { + place = response; + } - var street_components = []; - - if (place.address.country) { - return_location.country = place.address.country; - } - if (place.address.country_code) { - return_location.country_code = place.address.country_code; - } - if (place.address.state) { - return_location.region = place.address.state; - } - /* un jour peut-être... - if (place.address.county) { - return_location.departement = place.address.county; - } - */ - if (place.address.city) { - return_location.locality = place.address.city; - } else if (place.address.town) { - return_location.locality = place.address.town; - } else if (place.address.village) { - return_location.locality = place.address.village; - } else if (place.address.county) { - street_components.push(place.address.county); - } - if (place.address.postcode) { - return_location.postcode = place.address.postcode; - } - if (place.address.road) { - street_components.push(place.address.road); - } else if (place.address.pedestrian) { - street_components.push(place.address.pedestrian); - } - if (place.address.house_number) { - street_components.unshift(place.address.house_number); - } - if (return_location.street === '' && street_components.length > 0) { - return_location.street = street_components.join(' '); + var street_components = []; + + if (place.address.country) { + return_location.country = place.address.country; + } + if (place.address.country_code) { + return_location.country_code = place.address.country_code; + } + if (place.address.state) { + return_location.region = place.address.state; + } + if (place.address.city) { + return_location.locality = place.address.city; + } else if (place.address.town) { + return_location.locality = place.address.town; + } else if (place.address.village) { + return_location.locality = place.address.village; + } else if (place.address.county) { + street_components.push(place.address.county); + } + if (place.address.postcode) { + return_location.postcode = place.address.postcode; + } + if (place.address.road) { + street_components.push(place.address.road); + } else if (place.address.pedestrian) { + street_components.push(place.address.pedestrian); + } + if (place.address.house_number) { + street_components.unshift(place.address.house_number); + } + if (return_location.street === '' && street_components.length > 0) { + return_location.street = street_components.join(' '); + } + return_location.point = new L.LatLng(place.lat, place.lon); } - return_location.point = new L.LatLng(place.lat, place.lon); } this._user_callback(return_location); } diff --git a/www/plugins/gis/javascript/gis_utils.js b/www/plugins/gis/javascript/gis_utils.js index 0faa8fd3..c636b46f 100644 --- a/www/plugins/gis/javascript/gis_utils.js +++ b/www/plugins/gis/javascript/gis_utils.js @@ -1,11 +1,11 @@ -function gis_focus_marker(id, map) { +function gis_focus_marker (id, map) { var carte = eval('map'+ map); var i, count = 0; - for(i in carte._layers) { + for (i in carte._layers) { if ((carte._layers[i].feature) && (carte._layers[i].feature.id == id)) { carte.panTo(carte._layers[i].getLatLng()); carte._layers[i].openPopup(); } - count++; + count++; } } \ No newline at end of file diff --git a/www/plugins/gis/javascript/leaflet.gis.js b/www/plugins/gis/javascript/leaflet.gis.js index f55cd4a7..87a89929 100644 --- a/www/plugins/gis/javascript/leaflet.gis.js +++ b/www/plugins/gis/javascript/leaflet.gis.js @@ -1,4 +1,4 @@ -(function() { +(function () { // Plugin Leaflet L.Map.Gis L.Map.Gis = L.Map.extend({ @@ -31,38 +31,40 @@ L.Map.Gis = L.Map.extend({ openId: false, affiche_points: true, json_points: { - url: "", - objets: "", + url: '', + objets: '', limit: 500, env: [], - titre: "", - description: "", - icone: "" + titre: '', + description: '', + icone: '' }, localize_visitor: false, localize_visitor_zoom: 0, centrer_fichier: true, kml: false, gpx: false, - geojson: false + geojson: false, + topojson: false, + langue: false }, initialize: function (id,options) { L.Util.setOptions(this, options); - this.on('load',function(e){ + this.on('load', function () { // Affecter sur l'objet du DOM - jQuery("#"+this._container.id).get(0).map = this; + jQuery('#'+this._container.id).get(0).map = this; // Appeler l'éventuelle fonction de callback - if (this.options.callback && typeof(this.options.callback) === "function") + if (this.options.callback && typeof(this.options.callback) === 'function') this.options.callback(this); // trigger load sur l'objet du DOM - jQuery("#"+this._container.id).trigger('load',this); + jQuery('#'+this._container.id).trigger('load',this); }); L.Map.prototype.initialize.call(this, id, options); - if (this.options.utiliser_bb){ + if (this.options.utiliser_bb) { this.fitBounds( L.latLngBounds( [this.options.sw_lat, this.options.sw_lon], @@ -79,9 +81,9 @@ L.Map.Gis = L.Map.extend({ this.addOverlays(); - if (this.options.localize_visitor){ + if (this.options.localize_visitor) { var maxZoom = this.options.localize_visitor_zoom; - this.on('locationerror',function(e){ + this.on('locationerror',function (e) { maxZoom = this.options.zoom; alert(e.message); }); @@ -89,22 +91,27 @@ L.Map.Gis = L.Map.extend({ } // Si pas de points affichés trigger ready ici - if (!this.options.affiche_points || !this.options.json_points.length) - jQuery("#"+this._container.id).trigger('ready',this); + if (!this.options.affiche_points || !Object.keys(this.options.json_points).length) { + jQuery('#'+this._container.id).trigger('ready', this); + } }, - populateTileLayers: function (tilelayers) { + populateTileLayers: function () { // Fond de carte par défaut - var default_layer = this.createTileLayer(this.options.default_layer); - this.addLayer(default_layer); + if (this.options.default_layer != 'none') { + var default_layer = this.createTileLayer(this.options.default_layer); + this.addLayer(default_layer); + } // Fonds de carte supplémentaires - if (this.options.layersControl && !this.options.noControl && this.options.affiche_layers.length>1){ + if (this.options.layersControl && !this.options.noControl && this.options.affiche_layers.length>1) { var layers_control = L.control.layers('','',this.options.layersControlOptions); - layers_control.addBaseLayer(default_layer,this.options.gis_layers[this.options.default_layer].nom); - for(var l in this.options.affiche_layers){ - if (this.options.affiche_layers[l]!==this.options.default_layer){ + if (this.options.default_layer != 'none') { + layers_control.addBaseLayer(default_layer,this.options.gis_layers[this.options.default_layer].nom); + } + for (var l in this.options.affiche_layers) { + if (this.options.affiche_layers[l]!==this.options.default_layer) { var layer = this.createTileLayer(this.options.affiche_layers[l]); - if (typeof layer!=="undefined") + if (typeof layer!=='undefined') layers_control.addBaseLayer(layer,this.options.gis_layers[this.options.affiche_layers[l]].nom); } } @@ -120,7 +127,7 @@ L.Map.Gis = L.Map.extend({ this.attributionControl.setPrefix(''); if (this.options.scaleControl) L.control.scale().addTo(this); - if (this.options.overviewControl){ + if (this.options.overviewControl && this.options.default_layer != 'none') { // todo ajouter une option pour permettre de choisir la couche à afficher dans la minimap var minimap_layer = this.createTileLayer(this.options.default_layer); L.control.minimap(minimap_layer,{width: 100,height: 100, toggleDisplay: true}).addTo(this); @@ -129,15 +136,15 @@ L.Map.Gis = L.Map.extend({ createTileLayer: function (name) { var layer; - if (typeof this.options.gis_layers[name]!=="undefined") - eval("layer=new "+ this.options.gis_layers[name].layer +";"); + if (typeof this.options.gis_layers[name]!=='undefined') + eval('layer=new '+ this.options.gis_layers[name].layer +';'); return layer; }, // API setGeoJsonFeatureIcon : Pour Ajouter l'icone d'un point (feature = item d'un GeoJson) setGeoJsonFeatureIcon: function (feature, layer) { // Déclarer l'icone du points, si défini - if (feature.properties && feature.properties.icon){ + if (feature.properties && feature.properties.icon) { icon_options = { 'iconUrl': feature.properties.icon, 'iconSize': [feature.properties.icon_size[0], feature.properties.icon_size[1]], @@ -156,12 +163,26 @@ L.Map.Gis = L.Map.extend({ // API setGeoJsonFeaturePopup : Pour Ajouter le texte de popup d'un point (feature = item d'un GeoJson) setGeoJsonFeaturePopup: function (feature, layer) { // Déclarer le contenu de la popup s'il y en a - if (feature.properties && (feature.properties.title || feature.properties.description)){ - var popupContent = ''; - var popupOptions = ''; - if (feature.properties.title) + if (feature.properties + && !feature.properties.noclick + && (feature.properties.title || feature.properties.description || + (this.options.langue && (feature.properties['title_'+this.options.langue] || feature.properties['description_'+this.options.langue])))) { + var popupContent = '', + popupOptions = '', + description_ok = false; + if (this.options.langue) { + langue = this.options.langue; + if (feature.properties['title_'+langue]) { + popupContent = '' + feature.properties['title_'+langue] + ''; + } else if (feature.properties.title) + popupContent = '' + feature.properties.title + ''; + if (feature.properties['description_'+langue]) { + popupContent = popupContent + feature.properties['description_'+langue]; + description_ok = true; + } + } else if(feature.properties.title) popupContent = '' + feature.properties.title + ''; - if (feature.properties.description) + if (!description_ok && feature.properties.description) popupContent = popupContent + feature.properties.description; if (feature.properties.popup_options) popupOptions = feature.properties.popup_options; @@ -170,22 +191,29 @@ L.Map.Gis = L.Map.extend({ }, // API parseGeoJson - parseGeoJson: function(data) { + parseGeoJson: function (data) { var map = this; // Analyse des points et déclaration (sans regroupement des points en cluster) - if (!map.options.cluster){ - if (data.features.length > 0){ + if (!map.options.cluster) { + if (data.features && data.features.length > 0) { var geojson = L.geoJson('', { - style: this.options.pathStyles, + style: this.options.pathStyles ? this.options.pathStyles : function (feature) { + if (feature.properties && feature.properties.styles) + return feature.properties.styles; + else + return ''; + }, onEachFeature: function (feature, layer) { // Déclarer l'icone du point - map.setGeoJsonFeatureIcon(feature, layer); + if (feature.geometry.type == 'Point') { + map.setGeoJsonFeatureIcon(feature, layer); + } // Déclarer le contenu de la popup s'il y en a map.setGeoJsonFeaturePopup(feature, layer); } }).addData(data).addTo(map); - - if (map.options.autocenterandzoom){ + + if (map.options.autocenterandzoom) { if (data.features.length == 1 && data.features[0].geometry.type == 'Point') map.setView(geojson.getBounds().getCenter(), map.options.zoom); else @@ -194,15 +222,15 @@ L.Map.Gis = L.Map.extend({ if (map.options.openId) gis_focus_marker(map.options.openId,map.options.mapId); - if (typeof map.geojsons=="undefined") map.geojsons = []; + if (typeof map.geojsons=='undefined') map.geojsons = []; map.geojsons.push(geojson); } } else { - map.markers = L.markerClusterGroup(map.options.clusterOptions); - + map.markerCluster = L.markerClusterGroup(map.options.clusterOptions).addTo(map); + var markers = []; /* Pour chaque points présents, on crée un marqueur */ - jQuery.each(data.features, function(i, feature){ - if (feature.geometry.coordinates[0]){ + jQuery.each(data.features, function (i, feature) { + if (feature.geometry.coordinates[0]) { var marker = L.marker([feature.geometry.coordinates[1], feature.geometry.coordinates[0]]); // Déclarer l'icone du point @@ -211,30 +239,35 @@ L.Map.Gis = L.Map.extend({ map.setGeoJsonFeaturePopup(feature, marker); marker.id = feature.id; - map.markers.addLayer(marker); + markers.push(marker); } }); - map.addLayer(map.markers); + map.markerCluster.addLayers(markers); - if (map.options.autocenterandzoom){ + if (map.options.autocenterandzoom) { if (data.features.length > 1) - map.fitBounds(map.markers.getBounds()); + map.fitBounds(map.markerCluster.getBounds()); else - map.setView(map.markers.getBounds().getCenter(), map.options.zoom); + map.setView(map.markerCluster.getBounds().getCenter(), map.options.zoom); } } }, // API Compat GIS3 - addJSON: function(data) { + addJSON: function (data) { return this.parseGeoJson(data); }, // API Compat GIS3 - removeAllMarkers: function(){ - if (typeof this.geojsons=="undefined") this.geojsons = []; - for(var i in this.geojsons){ + removeAllMarkers: function () { + // virer les éléments du cluster s'il est utilisé + if (this.options.cluster) { + this.markerCluster.clearLayers(); + } + // virer les points de la carte + if (typeof this.geojsons=='undefined') this.geojsons = []; + for (var i in this.geojsons) { this.geojsons[i].clearLayers(); this.removeLayer(this.geojsons[i]); } @@ -244,32 +277,32 @@ L.Map.Gis = L.Map.extend({ loadData: function () { var map = this; if (map.options.affiche_points - && typeof(map.options.json_points) !== "undefined" - && map.options.json_points.url.length){ + && typeof(map.options.json_points) !== 'undefined' + && map.options.json_points.url.length) { // Récupération des points à mettre sur la carte, via json externe var args = {}; jQuery.extend(true, args, map.options.json_points.env); - if (typeof map.options.json_points.objets !== "undefined"){ + if (typeof map.options.json_points.objets !== 'undefined') { args.objets = map.options.json_points.objets; - if (args.objets == "point_libre"){ + if (args.objets == 'point_libre') { args.lat = map.options.center[0]; args.lon = map.options.center[1]; - if (typeof map.options.json_points.titre !== "undefined") + if (typeof map.options.json_points.titre !== 'undefined') args.titre = map.options.json_points.titre; - if (typeof map.options.json_points.description !== "undefined") + if (typeof map.options.json_points.description !== 'undefined') args.description = map.options.json_points.description; - if (typeof map.options.json_points.icone !== "undefined") + if (typeof map.options.json_points.icone !== 'undefined') args.icone = map.options.json_points.icone; } } - if (typeof map.options.json_points.limit !== "undefined") + if (typeof map.options.json_points.limit !== 'undefined') args.limit = map.options.json_points.limit; jQuery.getJSON(map.options.json_points.url,args, - function(data) { - if (data){ + function (data) { + if (data) { // Charger le json (data) et déclarer les points map.parseGeoJson(data); - jQuery("#"+map._container.id).trigger('ready',map); + jQuery('#'+map._container.id).trigger('ready',map); } } ); @@ -278,32 +311,41 @@ L.Map.Gis = L.Map.extend({ addOverlays: function () { var map = this; - if (map.options.kml && map.options.kml.length){ + if (map.options.kml && map.options.kml.length) { map.kml = {}; - for(var i in map.options.kml){ + for (var i in map.options.kml) { map.kml[i] = new L.KML(map.options.kml[i], {async: true}); if (map.options.centrer_fichier) - map.kml[i].on("loaded", function(e) { map.fitBounds(e.target.getBounds()); }); + map.kml[i].on('loaded', function (e) { map.fitBounds(e.target.getBounds()); }); map.addLayer(map.kml[i]); } } - if (map.options.gpx && map.options.gpx.length){ + if (map.options.gpx && map.options.gpx.length) { map.gpx = {}; - for(var i in map.options.gpx){ + for (var i in map.options.gpx) { map.gpx[i] = new L.GPX(map.options.gpx[i], {async: true}); if (map.options.centrer_fichier) - map.gpx[i].on("loaded", function(e) { map.fitBounds(e.target.getBounds()); }); + map.gpx[i].on('loaded', function (e) { map.fitBounds(e.target.getBounds()); }); map.addLayer(map.gpx[i]); } } - if (map.options.geojson && map.options.geojson.length){ - for(var i in map.options.geojson){ - jQuery.getJSON(map.options.geojson[i], function(data){ + if (map.options.geojson && map.options.geojson.length) { + for (var i in map.options.geojson) { + jQuery.getJSON(map.options.geojson[i], function (data) { if (data) map.parseGeoJson(data); }); } } + if (map.options.topojson && map.options.topojson.length) { + for (var i in map.options.topojson) { + map.topojson[i] = new L.TOPOJSON(map.options.topojson[i], {async: true}); + if (map.options.centrer_fichier) { + map.topojson[i].on('loaded', function (e) { map.fitBounds(e.target.getBounds()); }); + } + map.addLayer(map.topojson[i]); + } + } } }); diff --git a/www/plugins/gis/json/gis.html b/www/plugins/gis/json/gis.html index 01a19676..d658695c 100644 --- a/www/plugins/gis/json/gis.html +++ b/www/plugins/gis/json/gis.html @@ -5,5 +5,6 @@ "properties": { "title":[(#TITRE*|extraire_multi|supprimer_numero|json_encode)], "description":[(#DESCRIPTIF|json_encode)][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} diff --git a/www/plugins/gis/json/gis_articles.html b/www/plugins/gis/json/gis_articles.html index a50f3898..be318400 100644 --- a/www/plugins/gis/json/gis_articles.html +++ b/www/plugins/gis/json/gis_articles.html @@ -5,5 +5,6 @@ "properties": { "title":[(#URL_ARTICLE|lien_ou_expose{[(#TITRE_GIS*|sinon{#TITRE*}|extraire_multi|supprimer_numero)]}|json_encode)], "description":[(#DESCRIPTIF_GIS|sinon{#DESCRIPTIF}|json_encode)][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} \ No newline at end of file diff --git a/www/plugins/gis/json/gis_articles_branche.html b/www/plugins/gis/json/gis_articles_branche.html index f988b034..dd91e96a 100644 --- a/www/plugins/gis/json/gis_articles_branche.html +++ b/www/plugins/gis/json/gis_articles_branche.html @@ -5,5 +5,6 @@ "properties": { "title":[(#URL_ARTICLE|lien_ou_expose{[(#TITRE_GIS*|sinon{#TITRE*}|extraire_multi|supprimer_numero)]}|json_encode)], "description":[(#DESCRIPTIF_GIS|sinon{#DESCRIPTIF}|json_encode)][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} \ No newline at end of file diff --git a/www/plugins/gis/json/gis_auteurs.html b/www/plugins/gis/json/gis_auteurs.html index 5a23c091..1731fc33 100644 --- a/www/plugins/gis/json/gis_auteurs.html +++ b/www/plugins/gis/json/gis_auteurs.html @@ -5,5 +5,6 @@ "properties": { "title":[(#URL_AUTEUR|lien_ou_expose{[(#TITRE_GIS*|sinon{#NOM*}|extraire_multi|supprimer_numero)]}|json_encode)], "description":[(#DESCRIPTIF_GIS|sinon{#BIO}|json_encode)][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} \ No newline at end of file diff --git a/www/plugins/gis/json/gis_documents.html b/www/plugins/gis/json/gis_documents.html index b2215c9e..3f718d37 100644 --- a/www/plugins/gis/json/gis_documents.html +++ b/www/plugins/gis/json/gis_documents.html @@ -5,5 +5,6 @@ "properties": { "title":[(#URL_DOCUMENT|lien_ou_expose{[(#TITRE_GIS*|sinon{#TITRE*}|extraire_multi|supprimer_numero)]}|json_encode)], "description":[(#DESCRIPTIF_GIS|sinon{#DESCRIPTIF}|json_encode)][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} \ No newline at end of file diff --git a/www/plugins/gis/json/gis_evenements.html b/www/plugins/gis/json/gis_evenements.html index f0589499..968eeba0 100644 --- a/www/plugins/gis/json/gis_evenements.html +++ b/www/plugins/gis/json/gis_evenements.html @@ -5,5 +5,6 @@ "properties": { "title":[(#URL_EVENEMENT|extraire_multi|lien_ou_expose{[(#TITRE_GIS*|sinon{#TITRE*}|supprimer_numero)]}|json_encode)], "description":[(#DESCRIPTIF_GIS|sinon{#DESCRIPTIF}|json_encode)][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} diff --git a/www/plugins/gis/json/gis_mots.html b/www/plugins/gis/json/gis_mots.html index e1c9861a..7d10cc83 100644 --- a/www/plugins/gis/json/gis_mots.html +++ b/www/plugins/gis/json/gis_mots.html @@ -5,5 +5,6 @@ "properties": { "title":[(#URL_MOT|lien_ou_expose{[(#TITRE_GIS*|sinon{#TITRE*}|extraire_multi|supprimer_numero)]}|json_encode)], "description":[(#DESCRIPTIF_GIS|sinon{#DESCRIPTIF}|json_encode)][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} \ No newline at end of file diff --git a/www/plugins/gis/json/gis_organisations.html b/www/plugins/gis/json/gis_organisations.html index d0dbbd9e..63ccf744 100644 --- a/www/plugins/gis/json/gis_organisations.html +++ b/www/plugins/gis/json/gis_organisations.html @@ -5,5 +5,6 @@ "properties": { "title":[(#TITRE_GIS*|sinon{#NOM*}|extraire_multi|supprimer_numero|json_encode)], "description":[(#DESCRIPTIF_GIS|sinon{#DESCRIPTIF}|json_encode)][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} diff --git a/www/plugins/gis/json/gis_rubriques.html b/www/plugins/gis/json/gis_rubriques.html index dc14b2d4..39516a0d 100644 --- a/www/plugins/gis/json/gis_rubriques.html +++ b/www/plugins/gis/json/gis_rubriques.html @@ -5,5 +5,6 @@ "properties": { "title":[(#URL_RUBRIQUE|extraire_multi|lien_ou_expose{[(#TITRE_GIS*|sinon{#TITRE*}|supprimer_numero)]}|json_encode)], "description":[(#DESCRIPTIF_GIS|sinon{#DESCRIPTIF}|json_encode)][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} \ No newline at end of file diff --git a/www/plugins/gis/json/gis_sites.html b/www/plugins/gis/json/gis_sites.html index a43b62fd..b16fcf49 100644 --- a/www/plugins/gis/json/gis_sites.html +++ b/www/plugins/gis/json/gis_sites.html @@ -5,5 +5,6 @@ "properties": { "title":[(#ID_SYNDIC|generer_url_entite{site}|lien_ou_expose{[(#TITRE_GIS*|sinon{#NOM_SITE*}|extraire_multi|supprimer_numero)]}|json_encode)], "description":[(#DESCRIPTIF_GIS|sinon{#DESCRIPTIF}|json_encode)][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} \ No newline at end of file diff --git a/www/plugins/gis/json/gis_tous_avec_liens_espace_prive.html b/www/plugins/gis/json/gis_tous_avec_liens_espace_prive.html index bceae48c..7577ff30 100644 --- a/www/plugins/gis/json/gis_tous_avec_liens_espace_prive.html +++ b/www/plugins/gis/json/gis_tous_avec_liens_espace_prive.html @@ -5,5 +5,6 @@ "properties": { "title":[(#VAL{[(#TITRE*|extraire_multi|supprimer_numero|sinon{----})]}|json_encode)], "description":[(#DESCRIPTIF|json_encode)][(#SET{logo_doc,''})][ - (#LOGO_GIS|gis_icon_properties)] + (#LOGO_GIS|gis_icon_properties)][, + "styles": (#GEOMETRY_STYLES|appliquer_filtre{geometry_styles_to_json})] }} diff --git a/www/plugins/gis/lang/gis.xml b/www/plugins/gis/lang/gis.xml index 42f47237..f1a2f999 100644 --- a/www/plugins/gis/lang/gis.xml +++ b/www/plugins/gis/lang/gis.xml @@ -1,29 +1,29 @@ - + - + - + - + - + - + - + diff --git a/www/plugins/gis/lang/gis_de.php b/www/plugins/gis/lang/gis_de.php index 73e67fc2..7cd9bd35 100644 --- a/www/plugins/gis/lang/gis_de.php +++ b/www/plugins/gis/lang/gis_de.php @@ -22,42 +22,27 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'cfg_descr_gis' => 'Geoinformationssystem
                  zur Dokumentation.', 'cfg_inf_adresse' => 'Adressfelder anzeigen (Land, Satdt, Region, Adresse ...)', 'cfg_inf_bing' => 'Der Layer Bing Aerial benötigt einen Schlüssel zu erzeugen auf der Bing Website.', - 'cfg_inf_cloudmade' => 'Diese API benötigt einen Schlüssel. Zu erzeugen auf der CloudMade Website.', 'cfg_inf_geocoder' => 'Geocoding aktivieren (Suche nach einer Adresse, Anzeige von Adressen zu den Koordinaten).', 'cfg_inf_geolocaliser_user_html5' => 'Wenn es der Browser des Nutzers erlaubt, wird sein ungefährer Standort als Voreinstellung für die Position von Punkten genommen.', - 'cfg_inf_google' => 'Diese API benötigt einen Schlüssel. Zu erzeugen auf der le GoogleMaps Seite .', - 'cfg_inf_yandex' => 'Diese API benötigt einen Schlüssel. Zu erzeugen auf der Yandex Website.', + 'cfg_inf_google' => 'Diese API benötigt einen Schlüssel. Zu erzeugen auf der le GoogleMaps Seite .', # MODIF 'cfg_lbl_activer_objets' => 'Geotargeting für folgende Inhalte aktivieren:', 'cfg_lbl_adresse' => 'Adressfelder anzeigen', 'cfg_lbl_api' => 'Karten-API ', - 'cfg_lbl_api_cloudmade' => 'CloudMade', - 'cfg_lbl_api_google' => 'Google Maps v2', - 'cfg_lbl_api_googlev3' => 'Google Maps v3', 'cfg_lbl_api_key_bing' => 'Bing Schlüssel', - 'cfg_lbl_api_key_cloudmade' => 'CloudMade Schlüssel', 'cfg_lbl_api_key_google' => 'GoogleMaps Schlüssel', - 'cfg_lbl_api_key_yandex' => 'Yandex Schlüssel', - 'cfg_lbl_api_mapquest' => 'MapQuest', 'cfg_lbl_api_microsoft' => 'Microsoft Bing', - 'cfg_lbl_api_openlayers' => 'OpenLayers', - 'cfg_lbl_api_ovi' => 'Ovi Nokia', - 'cfg_lbl_api_yandex' => 'Yandex', 'cfg_lbl_geocoder' => 'Geocoder', 'cfg_lbl_geolocaliser_user_html5' => 'Karte beim Anlegen auf den Standort des Nutzers zentrieren.', 'cfg_lbl_layer_defaut' => 'Standardlayer', 'cfg_lbl_layers' => 'Vorgeschlagene Layer', 'cfg_lbl_maptype' => 'Kartentyp', - 'cfg_lbl_maptype_carte' => 'Karte', - 'cfg_lbl_maptype_hybride' => 'Hybrid', - 'cfg_lbl_maptype_relief' => 'Relief', - 'cfg_lbl_maptype_satellite' => 'Satellit', 'cfg_titre_gis' => 'GIS Einstellungen', // E 'editer_gis_editer' => 'Punkt bearbeiten', 'editer_gis_nouveau' => 'Neuen Punkt anlegen', 'editer_gis_titre' => 'GIS Punkte', - 'erreur_geocoder' => 'Ihre Suche ergab kein Ergebnis:', + 'erreur_geocoder' => 'Ihre Suche ergab kein Ergebnis:', # MODIF 'erreur_recherche_pas_resultats' => 'Kein Punkt passt zu Ihrer Suche.', 'erreur_xmlrpc_lat_lon' => 'Länge und Breite müssen als Argumente übergeben werden.', 'explication_api_forcee' => 'Die API wird durch ein Plugin oder Skelett erzwungen.', @@ -169,5 +154,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'zoom' => 'Zoom' ); - -?> diff --git a/www/plugins/gis/lang/gis_en.php b/www/plugins/gis/lang/gis_en.php index 448ca413..7bed0d92 100644 --- a/www/plugins/gis/lang/gis_en.php +++ b/www/plugins/gis/lang/gis_en.php @@ -14,6 +14,8 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'aucun_objet' => 'No object', // B + 'bouton_annuler_title' => 'Cancel all modifications.', + 'bouton_enregistrer_title' => 'Save your modifications.', 'bouton_lier' => 'Link this point', 'bouton_supprimer_gis' => 'Delete this point permanently', 'bouton_supprimer_lien' => 'Remove this link', @@ -22,35 +24,22 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'cfg_descr_gis' => 'Geographic Information System.
                  Link to the documentation.', 'cfg_inf_adresse' => 'Displays additional address fields (country, city, state, address ...)', 'cfg_inf_bing' => 'The Bing Aerial layer needs a key you can create on the Bing website.', - 'cfg_inf_cloudmade' => 'This API needs a key you can create on the CloudMade website.', 'cfg_inf_geocoder' => 'Enable geocoder functions (search from an address, recovery of the address from the coordinates).', 'cfg_inf_geolocaliser_user_html5' => 'If the user’s browser allows it, its approximate geographic location is retrieved to give the default position when creating a new point.', - 'cfg_inf_google' => 'This API needs a key you can create on the GoogleMaps website.', - 'cfg_inf_yandex' => 'This API needs a key you can create on the yandex website.', + 'cfg_inf_google' => 'This API needs a key that you can create on the Google Maps website.', + 'cfg_inf_styles' => 'Show additional style fields (color, opacity, thickness...)', 'cfg_lbl_activer_objets' => 'Enable geotagging of content:', 'cfg_lbl_adresse' => 'Show address fields', 'cfg_lbl_api' => 'Geolocation API', - 'cfg_lbl_api_cloudmade' => 'CloudMade', - 'cfg_lbl_api_google' => 'Google Maps v2', - 'cfg_lbl_api_googlev3' => 'Google Maps v3', 'cfg_lbl_api_key_bing' => 'Bing key', - 'cfg_lbl_api_key_cloudmade' => 'CloudMade API key', 'cfg_lbl_api_key_google' => 'GoogleMaps API key', - 'cfg_lbl_api_key_yandex' => 'Yandex API key', - 'cfg_lbl_api_mapquest' => 'MapQuest', 'cfg_lbl_api_microsoft' => 'Microsoft Bing', - 'cfg_lbl_api_openlayers' => 'OpenLayers', - 'cfg_lbl_api_ovi' => 'Ovi Nokia', - 'cfg_lbl_api_yandex' => 'Yandex', 'cfg_lbl_geocoder' => 'Geocoder', 'cfg_lbl_geolocaliser_user_html5' => 'Center the map on the location of the user at the creation step', 'cfg_lbl_layer_defaut' => 'Default layer', 'cfg_lbl_layers' => 'Proposed layers', 'cfg_lbl_maptype' => 'Base map', - 'cfg_lbl_maptype_carte' => 'Map', - 'cfg_lbl_maptype_hybride' => 'Hybrid', - 'cfg_lbl_maptype_relief' => 'Relief', - 'cfg_lbl_maptype_satellite' => 'Satellite', + 'cfg_lbl_styles' => 'Show the style fields', 'cfg_titre_gis' => 'GIS configuration', // E @@ -61,9 +50,14 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'erreur_recherche_pas_resultats' => 'No point corresponds to the searched text.', 'erreur_xmlrpc_lat_lon' => 'Latitude and longitude should be set as arguments', 'explication_api_forcee' => 'The is imposed by another plugin or skeleton.', + 'explication_color' => 'Line color in CSS format (default: #0033FF)', + 'explication_fillcolor' => 'Fill color in CSS format (default: inherited from the line color)', + 'explication_fillopacity' => 'Filler opacity between 0 and 1 (default: 0.2)', 'explication_import' => 'Import a file in GPX or KML format.', 'explication_layer_forcee' => 'The layer is imposed by another plugin or skeleton.', 'explication_maptype_force' => 'The base map is imposed by another plugin or skeleton.', + 'explication_opacity' => 'Line opacity between 0 and 1 (default: 0.5)', + 'explication_weight' => 'Line thickness (default: 5)', // F 'formulaire_creer_gis' => 'Create a new location-based point:', @@ -95,7 +89,10 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_adress' => 'Address', 'label_code_pays' => 'Country code', 'label_code_postal' => 'Postal code', + 'label_color' => 'Color', 'label_departement' => 'Department', + 'label_fillcolor' => 'Fill color', + 'label_fillopacity' => 'Filler opacity', 'label_import' => 'Import', 'label_inserer_modele_articles' => 'linked to articles', 'label_inserer_modele_articles_sites' => 'linked to articles + websites', @@ -128,16 +125,21 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_inserer_modele_rubriques' => 'linked to sections', 'label_inserer_modele_sites' => 'linked to websites', 'label_inserer_modele_titre_carte' => 'Map title', + 'label_opacity' => 'Opacity', 'label_pays' => 'Country', 'label_rechercher_address' => 'Search for an address', 'label_rechercher_point' => 'Search for a point', 'label_region' => 'Region', 'label_ville' => 'Town', + 'label_weight' => 'Thickness', 'lat' => 'Latitude', 'libelle_logo_gis' => 'POINT\\’S LOGO', 'lien_ajouter_gis' => 'Add this point', 'lon' => 'Longitude', + // P + 'placeholder_geocoder' => 'An address, a town, a country, a touristic site...', + // T 'telecharger_gis' => 'Download in @format@ format', 'texte_ajouter_gis' => 'Add a location-based point', @@ -153,9 +155,18 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'titre_nouveau_point' => 'New point', 'titre_objet' => 'Title', 'toolbar_actions_title' => 'Cancel the drawing', + 'toolbar_buttons_circle' => 'Draw a circle', 'toolbar_buttons_marker' => 'Plot a point', 'toolbar_buttons_polygon' => 'Draw a polygon', 'toolbar_buttons_polyline' => 'Draw a line', + 'toolbar_buttons_rectangle' => 'Draw a rectangle', + 'toolbar_edit_buttons_edit' => 'Modify the object', + 'toolbar_edit_buttons_editdisabled' => 'No modifiable objects', + 'toolbar_edit_buttons_remove' => 'Delete an object', + 'toolbar_edit_buttons_removedisabled' => 'No objects to be deleted', + 'toolbar_edit_handlers_edit_tooltip_subtext' => 'Clickc cancel to suppress your modifications', + 'toolbar_edit_handlers_edit_tooltip_text' => 'Move the markers to modify the object.', + 'toolbar_edit_handlers_remove_tooltip_text' => 'Click on an object to delete it', 'toolbar_handlers_marker_tooltip_start' => 'Click to set marker', 'toolbar_handlers_polygon_tooltip_cont' => 'Click to continue drawing the polygon', 'toolbar_handlers_polygon_tooltip_end' => 'Click the first point to close the polygon', @@ -163,11 +174,11 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'toolbar_handlers_polyline_tooltip_cont' => 'Click to continue to draw the line', 'toolbar_handlers_polyline_tooltip_end' => 'Click the last point to end line', 'toolbar_handlers_polyline_tooltip_start' => 'Click to start drawing the line', + 'toolbar_handlers_rectangle_tooltip_start' => 'Click and drag to draw a rectangle', + 'toolbar_handlers_simpleshape_tooltip_end' => 'Release the mouse to complete the design', 'toolbar_undo_text' => 'Delete last point', 'toolbar_undo_title' => 'Delete last point drawn', // Z 'zoom' => 'Zoom' ); - -?> diff --git a/www/plugins/gis/lang/gis_es.php b/www/plugins/gis/lang/gis_es.php index cbdfaa18..a6b3741a 100644 --- a/www/plugins/gis/lang/gis_es.php +++ b/www/plugins/gis/lang/gis_es.php @@ -22,42 +22,27 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'cfg_descr_gis' => 'Sistema de Información Geográfica.
                  Ir a la documentación.', 'cfg_inf_adresse' => 'Mostrar campos adicionales de dirección (país, ciudad, región, dirección...)', 'cfg_inf_bing' => 'La capa Bing Aerial necesita crear una clave el sitio de Bing.', - 'cfg_inf_cloudmade' => 'Esta API necesita crear una clave en el sitio de CloudMade.', 'cfg_inf_geocoder' => 'Activar las funciones del geocoder (búsqueda desde una dirección, recuperación de una dirección partiendo de coordenadas).', 'cfg_inf_geolocaliser_user_html5' => 'Si el navegador del usuario lo permite, su ubicación geográfica aproximada se recupera para dar la posición por defecto durante la creación de un punto.', - 'cfg_inf_google' => 'Esta API necesita crear una clave en el sitio de GoogleMaps.', - 'cfg_inf_yandex' => 'Esta API necesita crear una clave en el sitio de Yandex.', + 'cfg_inf_google' => 'Esta API necesita crear una clave en el sitio de GoogleMaps.', # MODIF 'cfg_lbl_activer_objets' => 'Activar la geolocalización en los contenidos:', 'cfg_lbl_adresse' => 'Mostrar los campos de dirección', 'cfg_lbl_api' => 'API de cartografía', - 'cfg_lbl_api_cloudmade' => 'CloudMade', - 'cfg_lbl_api_google' => 'Google Maps v2', - 'cfg_lbl_api_googlev3' => 'Google Maps v3', 'cfg_lbl_api_key_bing' => 'Clave Bing', - 'cfg_lbl_api_key_cloudmade' => 'Clave CloudMade', 'cfg_lbl_api_key_google' => 'Clave GoogleMaps', - 'cfg_lbl_api_key_yandex' => 'Clave Yandex', - 'cfg_lbl_api_mapquest' => 'MapQuest', 'cfg_lbl_api_microsoft' => 'Microsoft Bing', - 'cfg_lbl_api_openlayers' => 'OpenLayers', - 'cfg_lbl_api_ovi' => 'Ovi Nokia', - 'cfg_lbl_api_yandex' => 'Yandex', 'cfg_lbl_geocoder' => 'Geocoder', 'cfg_lbl_geolocaliser_user_html5' => 'Centrar el mapa en base a la ubicación del usuario durante la creación', 'cfg_lbl_layer_defaut' => 'Capa por defecto', 'cfg_lbl_layers' => 'Capas propuestas', 'cfg_lbl_maptype' => 'Fondo cartográfico', - 'cfg_lbl_maptype_carte' => 'Mapa', - 'cfg_lbl_maptype_hybride' => 'Híbrido', - 'cfg_lbl_maptype_relief' => 'Relieve', - 'cfg_lbl_maptype_satellite' => 'Satélite', 'cfg_titre_gis' => 'configuración de GIS', // E 'editer_gis_editer' => 'Modificar este punto', 'editer_gis_nouveau' => 'Crear un nuevo punto', 'editer_gis_titre' => 'Puntos geolocalizados', - 'erreur_geocoder' => 'Ningún resultado para su búsqueda:', + 'erreur_geocoder' => 'Ningún resultado para su búsqueda:', # MODIF 'erreur_recherche_pas_resultats' => 'Ningún punto corresponde a la búsqueda.', 'erreur_xmlrpc_lat_lon' => 'La latitud y la longitud deben indicarse como parámetros', 'explication_api_forcee' => 'La API esta impuesta por otro plugin o esqueleto.', @@ -169,5 +154,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'zoom' => 'Zoom' ); - -?> diff --git a/www/plugins/gis/lang/gis_fr.php b/www/plugins/gis/lang/gis_fr.php index dbc04ec2..01999744 100644 --- a/www/plugins/gis/lang/gis_fr.php +++ b/www/plugins/gis/lang/gis_fr.php @@ -12,6 +12,8 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'aucun_objet' => 'Aucun objet', // B + 'bouton_annuler_title' => 'Annuler l’édition, effacera toutes les modifications.', + 'bouton_enregistrer_title' => 'Enregistrez vos modifications.', 'bouton_lier' => 'Lier ce point', 'bouton_supprimer_gis' => 'Supprimer définitivement ce point', 'bouton_supprimer_lien' => 'Supprimer ce lien', @@ -20,48 +22,40 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'cfg_descr_gis' => 'Système d’Information Géographique.
                  Accéder la documentation.', 'cfg_inf_adresse' => 'Affiche des champs supplémentaires d’adresse (pays, ville, région, adresse...)', 'cfg_inf_bing' => 'La couche Bing Aerial nécessite une clé à créer sur le site de Bing.', - 'cfg_inf_cloudmade' => 'Cette API nécessite une clé à créer sur le site de CloudMade.', 'cfg_inf_geocoder' => 'Activer les fonctions du geocoder (recherche à partir d’une adresse, récupération de l’adresse à partir des coordonnées).', 'cfg_inf_geolocaliser_user_html5' => 'Si le navigateur de l’utilisateur le permet, son emplacement géographique approximatif est récupéré pour donner la position par défaut lors de la création d’un point.', - 'cfg_inf_google' => 'Cette API nécessite une clé à créer sur le site de GoogleMaps.', - 'cfg_inf_yandex' => 'Cette API nécessite une clé à créer sur le site de Yandex.', + 'cfg_inf_google' => 'Les couches Google nécessitent une clé à créer sur le site de GoogleMaps.', + 'cfg_inf_styles' => 'Affiche des champs supplémentaires de style (couleur, opacité, épaisseur...)', 'cfg_lbl_activer_objets' => 'Activer la géolocalisation sur les contenus :', 'cfg_lbl_adresse' => 'Afficher les champs d’adresse', 'cfg_lbl_api' => 'API de cartographie', - 'cfg_lbl_api_cloudmade' => 'CloudMade', - 'cfg_lbl_api_google' => 'Google Maps v2', - 'cfg_lbl_api_googlev3' => 'Google Maps v3', 'cfg_lbl_api_key_bing' => 'Clé Bing', - 'cfg_lbl_api_key_cloudmade' => 'Clé CloudMade', 'cfg_lbl_api_key_google' => 'Clé GoogleMaps', - 'cfg_lbl_api_key_yandex' => 'Clé Yandex', - 'cfg_lbl_api_mapquest' => 'MapQuest', 'cfg_lbl_api_microsoft' => 'Microsoft Bing', - 'cfg_lbl_api_openlayers' => 'OpenLayers', - 'cfg_lbl_api_ovi' => 'Ovi Nokia', - 'cfg_lbl_api_yandex' => 'Yandex', 'cfg_lbl_geocoder' => 'Geocoder', 'cfg_lbl_geolocaliser_user_html5' => 'Centrer la carte sur l’emplacement de l’utilisateur à la création', 'cfg_lbl_layer_defaut' => 'Couche par défaut', 'cfg_lbl_layers' => 'Couches proposées', 'cfg_lbl_maptype' => 'Fond cartographique', - 'cfg_lbl_maptype_carte' => 'Carte', - 'cfg_lbl_maptype_hybride' => 'Hybride', - 'cfg_lbl_maptype_relief' => 'Relief', - 'cfg_lbl_maptype_satellite' => 'Satellite', + 'cfg_lbl_styles' => 'Afficher les champs de styles', 'cfg_titre_gis' => 'Configuration de GIS', // E 'editer_gis_editer' => 'Modifier ce point', 'editer_gis_nouveau' => 'Créer un nouveau point', 'editer_gis_titre' => 'Les points géolocalisés', - 'erreur_geocoder' => 'Aucun résultat pour votre recherche :', + 'erreur_geocoder' => 'Aucun résultat pour votre recherche', 'erreur_recherche_pas_resultats' => 'Aucun point ne correspond à la recherche.', 'erreur_xmlrpc_lat_lon' => 'La latitude et la longitude doivent être passées en argument', 'explication_api_forcee' => 'L’API est imposée par un autre plugin ou squelette.', + 'explication_color' => 'Couleur de trait au format CSS (valeur par défaut : #0033FF)', + 'explication_fillcolor' => 'Couleur de remplissage au format CSS (valeur par défaut : héritée de la couleur de trait)', + 'explication_fillopacity' => 'Opacité du remplissage de 0 à 1 (valeur par défaut : 0.2)', 'explication_import' => 'Importer un fichier au format GPX ou KML.', 'explication_layer_forcee' => 'La couche est imposée par un autre plugin ou un squelette.', 'explication_maptype_force' => 'Le fond cartographique est imposé par un autre plugin ou squelette.', + 'explication_opacity' => 'Opacité du trait de 0 à 1 (valeur par défaut : 0.5)', + 'explication_weight' => 'Épaisseur du trait (valeur par défaut : 5)', // F 'formulaire_creer_gis' => 'Créer un point géolocalisé :', @@ -93,7 +87,10 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_adress' => 'Adresse', 'label_code_pays' => 'Code pays', 'label_code_postal' => 'Code postal', + 'label_color' => 'Couleur', 'label_departement' => 'Département', + 'label_fillcolor' => 'Couleur de remplissage', + 'label_fillopacity' => 'Opacité de remplissage', 'label_import' => 'Importer', 'label_inserer_modele_articles' => 'liés aux articles', 'label_inserer_modele_articles_sites' => 'liés aux articles + sites', @@ -126,16 +123,21 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_inserer_modele_rubriques' => 'liés aux rubriques', 'label_inserer_modele_sites' => 'liés aux sites', 'label_inserer_modele_titre_carte' => 'Titre de la carte', + 'label_opacity' => 'Opacité', 'label_pays' => 'Pays', 'label_rechercher_address' => 'Rechercher une adresse', 'label_rechercher_point' => 'Rechercher un point', 'label_region' => 'Région', 'label_ville' => 'Ville', + 'label_weight' => 'Épaisseur', 'lat' => 'Latitude', 'libelle_logo_gis' => 'LOGO DU POINT', 'lien_ajouter_gis' => 'Ajouter ce point', 'lon' => 'Longitude', + // P + 'placeholder_geocoder' => 'Une adresse, une ville, un pays, un lieu touristique...', + // T 'telecharger_gis' => 'Télécharger au format @format@', 'texte_ajouter_gis' => 'Ajouter un point géolocalisé', @@ -151,9 +153,18 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'titre_nouveau_point' => 'Nouveau point', 'titre_objet' => 'Titre', 'toolbar_actions_title' => 'Annuler le tracé', + 'toolbar_buttons_circle' => 'Tracer un cercle', 'toolbar_buttons_marker' => 'Tracer un point', 'toolbar_buttons_polygon' => 'Tracer un polygone', 'toolbar_buttons_polyline' => 'Tracer une ligne', + 'toolbar_buttons_rectangle' => 'Tracer un rectangle', + 'toolbar_edit_buttons_edit' => 'Modifier l’objet', + 'toolbar_edit_buttons_editdisabled' => 'Aucun objet modifiable', + 'toolbar_edit_buttons_remove' => 'Supprimer un objet', + 'toolbar_edit_buttons_removedisabled' => 'Aucun objet à supprimer', + 'toolbar_edit_handlers_edit_tooltip_subtext' => 'Cliquez sur annuler pour supprimer les modifications', + 'toolbar_edit_handlers_edit_tooltip_text' => 'Déplacez les poignées ou le marker pour modifier l’objet.', + 'toolbar_edit_handlers_remove_tooltip_text' => 'Cliquez sur un objet pour le supprimer', 'toolbar_handlers_marker_tooltip_start' => 'Cliquez pour placer le marqueur', 'toolbar_handlers_polygon_tooltip_cont' => 'Cliquez pour continuer à tracer le polygone', 'toolbar_handlers_polygon_tooltip_end' => 'Cliquez sur le premier point pour fermer le polygone', @@ -161,11 +172,11 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'toolbar_handlers_polyline_tooltip_cont' => 'Cliquez pour continuer à tracer la ligne', 'toolbar_handlers_polyline_tooltip_end' => 'Cliquez sur le dernier point pour terminer la ligne', 'toolbar_handlers_polyline_tooltip_start' => 'Cliquez pour commencer à tracer la ligne', + 'toolbar_handlers_rectangle_tooltip_start' => 'Cliquez et déplacez pour tracer un rectangle', + 'toolbar_handlers_simpleshape_tooltip_end' => 'Relâchez la souris pour terminer le dessin', 'toolbar_undo_text' => 'Effacer le dernier point', 'toolbar_undo_title' => 'Effacer le dernier point tracé', // Z 'zoom' => 'Zoom' ); - -?> diff --git a/www/plugins/gis/lang/gis_nl.php b/www/plugins/gis/lang/gis_nl.php index 8ac51ec4..47a8a474 100644 --- a/www/plugins/gis/lang/gis_nl.php +++ b/www/plugins/gis/lang/gis_nl.php @@ -14,6 +14,8 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'aucun_objet' => 'Geen object', // B + 'bouton_annuler_title' => 'Stop en verwijder alle aanpassing.', + 'bouton_enregistrer_title' => 'Sla je aanpassingen op.', 'bouton_lier' => 'Koppel dit punt', 'bouton_supprimer_gis' => 'Verwijder dit punt permanent', 'bouton_supprimer_lien' => 'Verwijder deze link', @@ -22,48 +24,40 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'cfg_descr_gis' => 'Geografisch Informatie Systeem.
                  Naar de documentatie.', 'cfg_inf_adresse' => 'Toon extra addresvelden (land, stad, staat, adres ...)', 'cfg_inf_bing' => 'De Bing Aerial layer heeft een sleutel nodig die je kunt aanmaken op de Bing website.', - 'cfg_inf_cloudmade' => 'Deze API heeft een sleutel nodig die je kunt aanmaken op de CloudMade website.', 'cfg_inf_geocoder' => 'Maak geocoder functies mogelijk (adres zoeken, adres vinden aan de hand van coördinaten).', 'cfg_inf_geolocaliser_user_html5' => 'Als de browser het toestaat, wordt de geografische locatie gebruikt als default positie bij het aanmaken van een nieuw punt.', - 'cfg_inf_google' => 'Deze API heeft een sleutel nodig die je kunt aanmaken op de GoogleMaps website.', - 'cfg_inf_yandex' => 'Deze API heeft een sleutel nodig die je kunt aanmaken op de Yandex website.', + 'cfg_inf_google' => 'Deze API heeft een sleutel nodig die je kunt aanmaken op de Google Maps website.', + 'cfg_inf_styles' => 'Toon de aanvullend stijlvelden (kleur, opaciteit, dikte...)', 'cfg_lbl_activer_objets' => 'Maak geotagging mogelijk van inhoud:', 'cfg_lbl_adresse' => 'Toon adresvelden', 'cfg_lbl_api' => 'Geolocatie API', - 'cfg_lbl_api_cloudmade' => 'CloudMade', - 'cfg_lbl_api_google' => 'Google Maps v2', - 'cfg_lbl_api_googlev3' => 'Google Maps v3', 'cfg_lbl_api_key_bing' => 'Bing key', - 'cfg_lbl_api_key_cloudmade' => 'CloudMade API key', 'cfg_lbl_api_key_google' => 'GoogleMaps API key', - 'cfg_lbl_api_key_yandex' => 'Yandex API key', - 'cfg_lbl_api_mapquest' => 'MapQuest', 'cfg_lbl_api_microsoft' => 'Microsoft Bing', - 'cfg_lbl_api_openlayers' => 'OpenLayers', - 'cfg_lbl_api_ovi' => 'Ovi Nokia', - 'cfg_lbl_api_yandex' => 'Yandex', 'cfg_lbl_geocoder' => 'Geocoder', 'cfg_lbl_geolocaliser_user_html5' => 'Centreer de map op de locatie van de gebruiker tijdens het aanmaken', 'cfg_lbl_layer_defaut' => 'Standaard layer', 'cfg_lbl_layers' => 'Voorgestelde layers', 'cfg_lbl_maptype' => 'Basiskaart', - 'cfg_lbl_maptype_carte' => 'Kaart', - 'cfg_lbl_maptype_hybride' => 'Hybrid', - 'cfg_lbl_maptype_relief' => 'Relief', - 'cfg_lbl_maptype_satellite' => 'Satelliet', + 'cfg_lbl_styles' => 'Toon de stijlvelden', 'cfg_titre_gis' => 'Configuratie van GIS', // E 'editer_gis_editer' => 'Pas dit punt aan', 'editer_gis_nouveau' => 'Maak een nieuw punt', 'editer_gis_titre' => 'Locatiepunten', - 'erreur_geocoder' => 'Geen resultaat voor zoekopdracht:', + 'erreur_geocoder' => 'Geen resultaat voor de zoekopdracht', 'erreur_recherche_pas_resultats' => 'Geen enkel punt correspondeert met de gezochte tekst.', 'erreur_xmlrpc_lat_lon' => 'Latitude en longitude moeten worden ingevuld', 'explication_api_forcee' => 'Dit is vereist door een andere plugin or een ander model.', + 'explication_color' => 'Kleur van de streep in CSS-formaat (standaardwaarde: #0033FF)', + 'explication_fillcolor' => 'Opvulkleur in CSS-formaat (standaardwaarde: die van de streep)', + 'explication_fillopacity' => 'Opaciteit van de opvulling tussen 0 en 1 (standaardwaarde: 0.2)', 'explication_import' => 'Importeer een bestand in GPX of KML formaat.', 'explication_layer_forcee' => 'De layer is vereist door een andere plugin of een ander model.', 'explication_maptype_force' => 'De basiskaart is vereist door een andere plugin of een ander model.', + 'explication_opacity' => 'Opaciteit van de streep tussen 0 en 1 (standaardwaarde: 0.5)', + 'explication_weight' => 'Streepdikte (standaardwaarde: 5)', // F 'formulaire_creer_gis' => 'Maak een nieuw locatiepunt:', @@ -95,7 +89,10 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_adress' => 'Adres', 'label_code_pays' => 'Landcode', 'label_code_postal' => 'Postcode', + 'label_color' => 'Kleur', 'label_departement' => 'Departement', + 'label_fillcolor' => 'Opvulkleur', + 'label_fillopacity' => 'Opaciteit van de opvulling', 'label_import' => 'Importeer', 'label_inserer_modele_articles' => 'gekoppeld aan artikelen', 'label_inserer_modele_articles_sites' => 'gekoppeld aan artikelen + websites', @@ -128,16 +125,21 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'label_inserer_modele_rubriques' => 'gekoppeld aan rubrieken', 'label_inserer_modele_sites' => 'gekoppeld aan websites', 'label_inserer_modele_titre_carte' => 'Kaarttitel', + 'label_opacity' => 'Opaciteit', 'label_pays' => 'Land', 'label_rechercher_address' => 'Zoek een adres', 'label_rechercher_point' => 'Zoek een punt', 'label_region' => 'Regio', 'label_ville' => 'Stad', + 'label_weight' => 'Dikte', 'lat' => 'Breedtegraad', 'libelle_logo_gis' => 'LOGO VAN HET PUNT', 'lien_ajouter_gis' => 'Voeg dit punt toe', 'lon' => 'Lengtegraad', + // P + 'placeholder_geocoder' => 'Een adres, een plaats, een land, een toeristische plek...', + // T 'telecharger_gis' => 'Download in @format@ formaat', 'texte_ajouter_gis' => 'Voeg een locatiepunt toe', @@ -153,9 +155,18 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'titre_nouveau_point' => 'Nieuw punt', 'titre_objet' => 'Titel', 'toolbar_actions_title' => 'Annuleer de tekening', + 'toolbar_buttons_circle' => 'Teken een circel', 'toolbar_buttons_marker' => 'Plot een punt', 'toolbar_buttons_polygon' => 'Teken een polygoon', 'toolbar_buttons_polyline' => 'Teken een lijn', + 'toolbar_buttons_rectangle' => 'Teken een rechthoek', + 'toolbar_edit_buttons_edit' => 'Pas het object aan', + 'toolbar_edit_buttons_editdisabled' => 'Geen aanpasbaar object', + 'toolbar_edit_buttons_remove' => 'Een object verwijderen', + 'toolbar_edit_buttons_removedisabled' => 'Geen te verwijderen object', + 'toolbar_edit_handlers_edit_tooltip_subtext' => 'Klik op annuleren om de aanpassingen ongedaan te maken', + 'toolbar_edit_handlers_edit_tooltip_text' => 'Verplaats de markeringen om het object aan te passen.', + 'toolbar_edit_handlers_remove_tooltip_text' => 'Klik op een object om het te verwijderen', 'toolbar_handlers_marker_tooltip_start' => 'Klik om de marker in te stellen', 'toolbar_handlers_polygon_tooltip_cont' => 'Klik om de polygoon verder te tekenen', 'toolbar_handlers_polygon_tooltip_end' => 'Klik op het eerste punt om de polygoon te sluiten', @@ -163,11 +174,11 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'toolbar_handlers_polyline_tooltip_cont' => 'Klik om de lijn verder te tekenen', 'toolbar_handlers_polyline_tooltip_end' => 'Klik het laatste punt voor het einde van de lijn', 'toolbar_handlers_polyline_tooltip_start' => 'Klik om een lijn te gaan tekenen', + 'toolbar_handlers_rectangle_tooltip_start' => 'Klik en verplaats om een rechthoek te tekenen', + 'toolbar_handlers_simpleshape_tooltip_end' => 'Laat de muisknop los om het ontwerp te beëindigen', 'toolbar_undo_text' => 'Wis het laatste punt', 'toolbar_undo_title' => 'Wis het laatst uitgestippelde punt', // Z 'zoom' => 'Zoom' ); - -?> diff --git a/www/plugins/gis/lang/gis_ru.php b/www/plugins/gis/lang/gis_ru.php index 0e4a80b2..79b9a19a 100644 --- a/www/plugins/gis/lang/gis_ru.php +++ b/www/plugins/gis/lang/gis_ru.php @@ -22,35 +22,20 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'cfg_descr_gis' => 'Географическая Информационная Система (GIS).
                  Документация.', # MODIF 'cfg_inf_adresse' => 'Показываются дополнительные поля для ввода адреса (страна, город, область, адрес...)', 'cfg_inf_bing' => 'Для использования карты Bing Aerial необходимо создать ключ на сайте Bing.', - 'cfg_inf_cloudmade' => 'Для использования карты необходимо создать ключ на сайте CloudMade.', 'cfg_inf_geocoder' => 'Включить функцию геопоиска (поиск точки на карте по адресу).', 'cfg_inf_geolocaliser_user_html5' => 'Новая карта центрируется по расположению пользователя ( если позволяет его браузер).', - 'cfg_inf_google' => 'Для работы с картой необходим API ключ, который можно создать на сайте GoogleMaps.', - 'cfg_inf_yandex' => 'Для работы с картой необходим API ключ. Получить на сайте Yandex.', + 'cfg_inf_google' => 'Для работы с картой необходим API ключ, который можно создать на сайте GoogleMaps.', # MODIF 'cfg_lbl_activer_objets' => 'Связывать карту с объектами:', 'cfg_lbl_adresse' => 'Показать поля для адреса', 'cfg_lbl_api' => 'Используемое API', - 'cfg_lbl_api_cloudmade' => 'CloudMade', - 'cfg_lbl_api_google' => 'Google Maps v2', - 'cfg_lbl_api_googlev3' => 'Google Maps v3', 'cfg_lbl_api_key_bing' => 'API ключ Bing', - 'cfg_lbl_api_key_cloudmade' => 'API ключ CloudMade ', 'cfg_lbl_api_key_google' => 'API ключ GoogleMaps', - 'cfg_lbl_api_key_yandex' => 'Yandex API ключ', - 'cfg_lbl_api_mapquest' => 'MapQuest', 'cfg_lbl_api_microsoft' => 'Microsoft Bing', - 'cfg_lbl_api_openlayers' => 'OpenLayers', - 'cfg_lbl_api_ovi' => 'Ovi Nokia', - 'cfg_lbl_api_yandex' => 'Yandex', 'cfg_lbl_geocoder' => 'Geocoder', 'cfg_lbl_geolocaliser_user_html5' => 'Центрировать карту по месту расположения пользователя, создавшего карту', 'cfg_lbl_layer_defaut' => 'Слой по умолчанию', 'cfg_lbl_layers' => 'Предложенные слои', 'cfg_lbl_maptype' => 'Тип карты', - 'cfg_lbl_maptype_carte' => 'Карта', - 'cfg_lbl_maptype_hybride' => 'Гибрид', - 'cfg_lbl_maptype_relief' => 'Рельеф', - 'cfg_lbl_maptype_satellite' => 'Спутник', 'cfg_titre_gis' => 'GIS', # MODIF // E @@ -153,5 +138,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'zoom' => 'Zoom' ); - -?> diff --git a/www/plugins/gis/lang/gis_sk.php b/www/plugins/gis/lang/gis_sk.php index b6756a90..a43eb8b6 100644 --- a/www/plugins/gis/lang/gis_sk.php +++ b/www/plugins/gis/lang/gis_sk.php @@ -22,42 +22,27 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'cfg_descr_gis' => 'Geografický informačný systém.
                  Prejsť na dokumentáciu.', 'cfg_inf_adresse' => 'Zobrazí ďalšie polia adresy (krajinu, mesto, štát, adresu a pod.)', 'cfg_inf_bing' => 'Vrstva Bing Aerial si vyžaduje, aby ste na stránke vyhľadávača Bing vytvorili kľúč.', - 'cfg_inf_cloudmade' => 'Táto aplikácia potrebuje kľúč na vytvorenie stránky v Cloude.', 'cfg_inf_geocoder' => 'Aktivovať funkciu geokódera (vyhľadávanie z jednej adresy, zistenie adresy zo súradníc).', 'cfg_inf_geolocaliser_user_html5' => 'Ak to povoľuje prehliadač používateľa, na určenie predvolenej polohy pri vytváraní nového bodu sa ukladá približná geografická poloha používateľa.', - 'cfg_inf_google' => 'Táto aplikácia potrebuje kľúč, ktorý si treba vytvoriť na stránke GoogleMaps.', - 'cfg_inf_yandex' => 'Táto aplikácia potrebuje kľúč na vytvorenie stránky v Yandexe.', + 'cfg_inf_google' => 'Táto aplikácia potrebuje kľúč, ktorý si treba vytvoriť na stránke GoogleMaps.', # MODIF 'cfg_lbl_activer_objets' => 'Aktivovať geolokalizáciu obsahu:', 'cfg_lbl_adresse' => 'Zobraziť polia adresy', 'cfg_lbl_api' => 'Geolokačná API', - 'cfg_lbl_api_cloudmade' => 'CloudMade', - 'cfg_lbl_api_google' => 'Google Maps v2', - 'cfg_lbl_api_googlev3' => 'Google Maps v3', 'cfg_lbl_api_key_bing' => 'Kľúč pre Bing', - 'cfg_lbl_api_key_cloudmade' => 'Kľúč CloudMade', 'cfg_lbl_api_key_google' => 'Kľúč GoogleMaps', - 'cfg_lbl_api_key_yandex' => 'Kľúč Yandex', - 'cfg_lbl_api_mapquest' => 'MapQuest', 'cfg_lbl_api_microsoft' => 'Microsoft Bing', - 'cfg_lbl_api_openlayers' => 'OpenLayers', - 'cfg_lbl_api_ovi' => 'Ovi Nokia', - 'cfg_lbl_api_yandex' => 'Yandex', 'cfg_lbl_geocoder' => 'Geocoder', 'cfg_lbl_geolocaliser_user_html5' => 'Pri vytváraní vycentrujte mapu na polohe používateľa', 'cfg_lbl_layer_defaut' => 'Predvolená vrstva', 'cfg_lbl_layers' => 'Navrhované vrstvy', 'cfg_lbl_maptype' => 'Základná mapa', - 'cfg_lbl_maptype_carte' => 'Mapa', - 'cfg_lbl_maptype_hybride' => 'Zmiešaná', - 'cfg_lbl_maptype_relief' => 'Reliéf', - 'cfg_lbl_maptype_satellite' => 'Satelitná', 'cfg_titre_gis' => 'GIS', # MODIF // E 'editer_gis_editer' => 'Upraviť tento bod', 'editer_gis_nouveau' => 'Vytvoriť nový bod', 'editer_gis_titre' => 'Geolokalizované body', - 'erreur_geocoder' => 'Žiaden výsledok k vášmu vyhľadávaniu:', + 'erreur_geocoder' => 'Žiaden výsledok k vášmu vyhľadávaniu:', # MODIF 'erreur_recherche_pas_resultats' => 'Vyhľadávania sa netýka žiaden bod.', 'erreur_xmlrpc_lat_lon' => 'Zemepisná šírka a dĺžka musia byť odovzdané ako parameter', 'explication_api_forcee' => 'Túto aplikáciu používa iný zásuvný modul alebo iná šablóna.', @@ -169,5 +154,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( // Z 'zoom' => 'Lupa' ); - -?> diff --git a/www/plugins/gis/lang/paquet-gis_en.php b/www/plugins/gis/lang/paquet-gis_en.php index 7ec83af3..a88581b5 100644 --- a/www/plugins/gis/lang/paquet-gis_en.php +++ b/www/plugins/gis/lang/paquet-gis_en.php @@ -13,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'gis_description' => 'This plugin allows you to create location-based points that can be attached to SPIP objects to display them on maps in the pages of your site. They can use the tiles from different maps vendors through the Leaflet library.', 'gis_slogan' => 'Geographic Information System' ); - -?> diff --git a/www/plugins/gis/lang/paquet-gis_es.php b/www/plugins/gis/lang/paquet-gis_es.php index c50b6fd7..2bf3e49d 100644 --- a/www/plugins/gis/lang/paquet-gis_es.php +++ b/www/plugins/gis/lang/paquet-gis_es.php @@ -13,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'gis_description' => 'Este plugin permite crear puntos geolocalizados que pueden adjuntarse a los objetos de SPIP a fin de mostrarlos en los mapas de las páginas de su sitio web. Éstos útlimos pueden utilizar las tejas de diferentes proveedores gracias a la librería Leaflet. ', 'gis_slogan' => 'Sistema de información geográfica' ); - -?> diff --git a/www/plugins/gis/lang/paquet-gis_fr.php b/www/plugins/gis/lang/paquet-gis_fr.php index a24c1fee..0102ada2 100644 --- a/www/plugins/gis/lang/paquet-gis_fr.php +++ b/www/plugins/gis/lang/paquet-gis_fr.php @@ -11,5 +11,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'gis_description' => 'Ce plugin permet de créer des points géolocalisés qui peuvent être attachés aux objets de SPIP afin de les afficher sur des cartes dans les pages de votre site. Ces dernières peuvent utiliser les tuiles de différents fournisseurs grâce à la librairie Leaflet.', 'gis_slogan' => 'Système d’information géographique' ); - -?> diff --git a/www/plugins/gis/lang/paquet-gis_nl.php b/www/plugins/gis/lang/paquet-gis_nl.php index b4a05931..e9bf9018 100644 --- a/www/plugins/gis/lang/paquet-gis_nl.php +++ b/www/plugins/gis/lang/paquet-gis_nl.php @@ -13,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'gis_description' => 'Deze plugin laat je locatiepunten maken die aan SPIP-objecten kunnen worden gekoppeld om een kaart te tonen. Verschillende soorten kaarten zijn mogelijk dankzij de Leaflet bibliotheek.', 'gis_slogan' => 'Geografisch Informatie Systeem' ); - -?> diff --git a/www/plugins/gis/lang/paquet-gis_ru.php b/www/plugins/gis/lang/paquet-gis_ru.php index ec329f08..0e5298c3 100644 --- a/www/plugins/gis/lang/paquet-gis_ru.php +++ b/www/plugins/gis/lang/paquet-gis_ru.php @@ -13,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'gis_description' => 'Плагин GIS позволяет создавать элементы на карте и привязвать их к существующим объектам SPIP. Вы можете использовать созданные карты на страницах своего сайта. Могут использовать разные карты, доступ к которым обеспечивается при помощи библиотеки Leaflet.', 'gis_slogan' => 'Географическая Информационная Система (GIS)' ); - -?> diff --git a/www/plugins/gis/lang/paquet-gis_sk.php b/www/plugins/gis/lang/paquet-gis_sk.php index bd404e5f..b31feb1e 100644 --- a/www/plugins/gis/lang/paquet-gis_sk.php +++ b/www/plugins/gis/lang/paquet-gis_sk.php @@ -13,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'gis_description' => 'Tento zásuvný modul umožňuje vytvárať zemepisné body, ktoré môžete pripojiť k objektom SPIPu, aby sa dali zobraziť na mapách na stránkach vášho webu. Vďaka knižnici Leaflet môžete používať rozhranie od rôznych výrobcov.', 'gis_slogan' => 'Geografický informačný systém' ); - -?> diff --git a/www/plugins/gis/lib/leaflet/README.md b/www/plugins/gis/lib/leaflet/README.md index add1f0e5..9d512e18 100644 --- a/www/plugins/gis/lib/leaflet/README.md +++ b/www/plugins/gis/lib/leaflet/README.md @@ -1,33 +1,27 @@ -Sources utilisées dans la lib : +# Sources utilisées dans la lib : -* dist/ - * http://leafletjs.com/download.html -* plugins/ - * Bing.js - * https://github.com/shramov/leaflet-plugins/blob/master/layer/tile/Bing.js - * Control.FullScreen.js - * https://github.com/brunob/leaflet.fullscreen/blob/master/Control.FullScreen.js - * Control.MiniMap.js - * https://github.com/Norkart/Leaflet-MiniMap/blob/master/src/Control.MiniMap.js - * Google.js - * https://github.com/shramov/leaflet-plugins/blob/master/layer/tile/Google.js - * GPX.js - * https://github.com/shramov/leaflet-plugins/blob/master/layer/vector/GPX.js - * GPX.Speed.js - * https://github.com/shramov/leaflet-plugins/blob/master/layer/vector/GPX.Speed.js - * images - * mixed from all sources - * KML.js - * https://github.com/shramov/leaflet-plugins/blob/master/layer/vector/KML.js - * leaflet.markercluster.css - * https://github.com/Leaflet/Leaflet.markercluster/blob/master/dist/MarkerCluster.css - * https://github.com/Leaflet/Leaflet.markercluster/blob/master/dist/MarkerCluster.Default.css - * leaflet.markercluster-src.js - * https://github.com/Leaflet/Leaflet.markercluster/blob/master/dist/leaflet.markercluster-src.js - * leaflet-plugins.css - * https://github.com/brunob/leaflet.fullscreen/blob/master/Control.FullScreen.css - * https://github.com/Norkart/Leaflet-MiniMap/blob/master/src/Control.MiniMap.css - * leaflet-providers.js - * https://github.com/leaflet-extras/leaflet-providers/blob/master/leaflet-providers.js - * Marker.Rotate.js - * https://github.com/shramov/leaflet-plugins/blob/master/layer/Marker.Rotate.js +## dist/ + +* [http://leafletjs.com/download.html](http://leafletjs.com/download.html) + +## plugins/ + +* [Bing.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/tile/Bing.js) +* [Control.FullScreen.js](https://github.com/brunob/leaflet.fullscreen/blob/master/Control.FullScreen.js) +* [Control.MiniMap.js](https://github.com/Norkart/Leaflet-MiniMap/blob/master/src/Control.MiniMap.js) +* [Google.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/tile/Google.js) +* [GPX.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/vector/GPX.js) +* [GPX.Speed.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/vector/GPX.Speed.js) +* images + * mixed from all sources +* [KML.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/vector/KML.js) +* leaflet.markercluster.css + * [MarkerCluster.css](https://github.com/Leaflet/Leaflet.markercluster/blob/leaflet-0.7/dist/MarkerCluster.css) + * [MarkerCluster.Default.css](https://github.com/Leaflet/Leaflet.markercluster/blob/leaflet-0.7/dist/MarkerCluster.Default.css) +* [leaflet.markercluster-src.js](https://github.com/Leaflet/Leaflet.markercluster/blob/leaflet-0.7/dist/leaflet.markercluster-src.js) +* leaflet-plugins.css + * [Control.FullScreen.css](https://github.com/brunob/leaflet.fullscreen/blob/master/Control.FullScreen.css) + * [Control.MiniMap.css](https://github.com/Norkart/Leaflet-MiniMap/blob/master/src/Control.MiniMap.css) +* [leaflet-providers.js](https://github.com/leaflet-extras/leaflet-providers/blob/master/leaflet-providers.js) +* [Marker.Rotate.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/Marker.Rotate.js) +* [TOPOJSON.js](https://github.com/shramov/leaflet-plugins/blob/master/layer/vector/TOPOJSON.js) diff --git a/www/plugins/gis/lib/leaflet/plugins/Bing.js b/www/plugins/gis/lib/leaflet/plugins/Bing.js index 1a98f70a..8e2bd12a 100755 --- a/www/plugins/gis/lib/leaflet/plugins/Bing.js +++ b/www/plugins/gis/lib/leaflet/plugins/Bing.js @@ -6,15 +6,16 @@ L.BingLayer = L.TileLayer.extend({ culture: '' }, - initialize: function(key, options) { + initialize: function (key, options) { L.Util.setOptions(this, options); this._key = key; this._url = null; + this._providers = []; this.metaRequested = false; }, - tile2quad: function(x, y, z) { + tile2quad: function (x, y, z) { var quad = ''; for (var i = z; i > 0; i--) { var digit = 0; @@ -26,16 +27,16 @@ L.BingLayer = L.TileLayer.extend({ return quad; }, - getTileUrl: function(p, z) { + getTileUrl: function (tilePoint) { var zoom = this._getZoomForUrl(); var subdomains = this.options.subdomains, - s = this.options.subdomains[Math.abs((p.x + p.y) % subdomains.length)]; + s = this.options.subdomains[Math.abs((tilePoint.x + tilePoint.y) % subdomains.length)]; return this._url.replace('{subdomain}', s) - .replace('{quadkey}', this.tile2quad(p.x, p.y, zoom)) + .replace('{quadkey}', this.tile2quad(tilePoint.x, tilePoint.y, zoom)) .replace('{culture}', this.options.culture); }, - loadMetadata: function() { + loadMetadata: function () { if (this.metaRequested) return; this.metaRequested = true; var _this = this; @@ -45,6 +46,7 @@ L.BingLayer = L.TileLayer.extend({ var e = document.getElementById(cbid); e.parentNode.removeChild(e); if (meta.errorDetails) { + throw new Error(meta.errorDetails); return; } _this.initMetadata(meta); @@ -60,11 +62,10 @@ L.BingLayer = L.TileLayer.extend({ document.getElementsByTagName('head')[0].appendChild(script); }, - initMetadata: function(meta) { + initMetadata: function (meta) { var r = meta.resourceSets[0].resources[0]; this.options.subdomains = r.imageUrlSubdomains; this._url = r.imageUrl; - this._providers = []; if (r.imageryProviders) { for (var i = 0; i < r.imageryProviders.length; i++) { var p = r.imageryProviders[i]; @@ -84,14 +85,14 @@ L.BingLayer = L.TileLayer.extend({ this._update(); }, - _update: function() { + _update: function () { if (this._url === null || !this._map) return; this._update_attribution(); L.TileLayer.prototype._update.apply(this, []); }, - _update_attribution: function() { - var bounds = this._map.getBounds(); + _update_attribution: function () { + var bounds = L.latLngBounds(this._map.getBounds().getSouthWest().wrap(),this._map.getBounds().getNorthEast().wrap()); var zoom = this._map.getZoom(); for (var i = 0; i < this._providers.length; i++) { var p = this._providers[i]; @@ -107,13 +108,13 @@ L.BingLayer = L.TileLayer.extend({ } } }, - - onAdd: function(map) { + + onAdd: function (map) { this.loadMetadata(); L.TileLayer.prototype.onAdd.apply(this, [map]); }, - onRemove: function(map) { + onRemove: function (map) { for (var i = 0; i < this._providers.length; i++) { var p = this._providers[i]; if (p.active && this._map.attributionControl) { @@ -121,7 +122,7 @@ L.BingLayer = L.TileLayer.extend({ p.active = false; } } - L.TileLayer.prototype.onRemove.apply(this, [map]); + L.TileLayer.prototype.onRemove.apply(this, [map]); } }); diff --git a/www/plugins/gis/lib/leaflet/plugins/Control.FullScreen.js b/www/plugins/gis/lib/leaflet/plugins/Control.FullScreen.js index d356a4ea..093ea8b1 100644 --- a/www/plugins/gis/lib/leaflet/plugins/Control.FullScreen.js +++ b/www/plugins/gis/lib/leaflet/plugins/Control.FullScreen.js @@ -1,11 +1,13 @@ -(function() { +(function () { L.Control.FullScreen = L.Control.extend({ options: { position: 'topleft', title: 'Full Screen', + titleCancel: 'Exit Full Screen', forceSeparateButton: false, - forcePseudoFullscreen: false + forcePseudoFullscreen: false, + fullscreenElement: false }, onAdd: function (map) { @@ -25,19 +27,21 @@ L.Control.FullScreen = L.Control.extend({ this._createButton(this.options.title, className, content, container, this.toggleFullScreen, this); + this._map.on('enterFullscreen exitFullscreen', this._toggleTitle, this); + return container; }, - _createButton: function (title, className, content,container, fn, context) { - var link = L.DomUtil.create('a', className, container); - link.href = '#'; - link.title = title; - link.innerHTML = content; + _createButton: function (title, className, content, container, fn, context) { + this.link = L.DomUtil.create('a', className, container); + this.link.href = '#'; + this.link.title = title; + this.link.innerHTML = content; L.DomEvent - .addListener(link, 'click', L.DomEvent.stopPropagation) - .addListener(link, 'click', L.DomEvent.preventDefault) - .addListener(link, 'click', fn, context); + .addListener(this.link, 'click', L.DomEvent.stopPropagation) + .addListener(this.link, 'click', L.DomEvent.preventDefault) + .addListener(this.link, 'click', fn, context); L.DomEvent .addListener(container, fullScreenApi.fullScreenEventName, L.DomEvent.stopPropagation) @@ -49,7 +53,7 @@ L.Control.FullScreen = L.Control.extend({ .addListener(document, fullScreenApi.fullScreenEventName, L.DomEvent.preventDefault) .addListener(document, fullScreenApi.fullScreenEventName, this._handleEscKey, context); - return link; + return this.link; }, toggleFullScreen: function () { @@ -57,7 +61,7 @@ L.Control.FullScreen = L.Control.extend({ map._exitFired = false; if (map._isFullscreen) { if (fullScreenApi.supportsFullScreen && !this.options.forcePseudoFullscreen) { - fullScreenApi.cancelFullScreen(map._container); + fullScreenApi.cancelFullScreen(this.options.fullscreenElement ? this.options.fullscreenElement : map._container); } else { L.DomUtil.removeClass(map._container, 'leaflet-pseudo-fullscreen'); } @@ -68,7 +72,7 @@ L.Control.FullScreen = L.Control.extend({ } else { if (fullScreenApi.supportsFullScreen && !this.options.forcePseudoFullscreen) { - fullScreenApi.requestFullScreen(map._container); + fullScreenApi.requestFullScreen(this.options.fullscreenElement ? this.options.fullscreenElement : map._container); } else { L.DomUtil.addClass(map._container, 'leaflet-pseudo-fullscreen'); } @@ -78,6 +82,10 @@ L.Control.FullScreen = L.Control.extend({ } }, + _toggleTitle: function () { + this.link.title = this._map._isFullscreen ? this.options.title : this.options.titleCancel; + }, + _handleEscKey: function () { var map = this._map; if (!fullScreenApi.isFullScreen(map) && !map._exitFired) { @@ -111,9 +119,9 @@ source : http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugi var fullScreenApi = { supportsFullScreen: false, - isFullScreen: function() { return false; }, - requestFullScreen: function() {}, - cancelFullScreen: function() {}, + isFullScreen: function () { return false; }, + requestFullScreen: function () {}, + cancelFullScreen: function () {}, fullScreenEventName: '', prefix: '' }, @@ -124,40 +132,64 @@ source : http://johndyer.name/native-fullscreen-javascript-api-plus-jquery-plugi fullScreenApi.supportsFullScreen = true; } else { // check for fullscreen support by vendor prefix - for (var i = 0, il = browserPrefixes.length; i < il; i++ ) { + for (var i = 0, il = browserPrefixes.length; i < il; i++) { fullScreenApi.prefix = browserPrefixes[i]; - if (typeof document[fullScreenApi.prefix + 'CancelFullScreen' ] !== 'undefined' ) { + if (typeof document[fullScreenApi.prefix + 'CancelFullScreen'] !== 'undefined') { fullScreenApi.supportsFullScreen = true; break; } } + if (typeof document['msExitFullscreen'] !== 'undefined') { + fullScreenApi.prefix = 'ms'; + fullScreenApi.supportsFullScreen = true; + } } // update methods to do something useful if (fullScreenApi.supportsFullScreen) { - fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; - fullScreenApi.isFullScreen = function() { - switch (this.prefix) { + if (fullScreenApi.prefix === 'ms') { + fullScreenApi.fullScreenEventName = 'MSFullscreenChange'; + } else { + fullScreenApi.fullScreenEventName = fullScreenApi.prefix + 'fullscreenchange'; + } + fullScreenApi.isFullScreen = function () { + switch (this.prefix) { case '': return document.fullScreen; case 'webkit': return document.webkitIsFullScreen; + case 'ms': + return document.msFullscreenElement; default: return document[this.prefix + 'FullScreen']; } }; - fullScreenApi.requestFullScreen = function(el) { - return (this.prefix === '') ? el.requestFullscreen() : el[this.prefix + 'RequestFullScreen'](); + fullScreenApi.requestFullScreen = function (el) { + switch (this.prefix) { + case '': + return el.requestFullscreen(); + case 'ms': + return el.msRequestFullscreen(); + default: + return el[this.prefix + 'RequestFullScreen'](); + } }; - fullScreenApi.cancelFullScreen = function(el) { - return (this.prefix === '') ? document.exitFullscreen() : document[this.prefix + 'CancelFullScreen'](); + fullScreenApi.cancelFullScreen = function () { + switch (this.prefix) { + case '': + return document.exitFullscreen(); + case 'ms': + return document.msExitFullscreen(); + default: + return document[this.prefix + 'CancelFullScreen'](); + } }; } // jQuery plugin if (typeof jQuery !== 'undefined') { - jQuery.fn.requestFullScreen = function() { - return this.each(function() { + jQuery.fn.requestFullScreen = function () { + return this.each(function () { var el = jQuery(this); if (fullScreenApi.supportsFullScreen) { fullScreenApi.requestFullScreen(el); diff --git a/www/plugins/gis/lib/leaflet/plugins/Control.MiniMap.js b/www/plugins/gis/lib/leaflet/plugins/Control.MiniMap.js index 2baef61b..c2b05350 100644 --- a/www/plugins/gis/lib/leaflet/plugins/Control.MiniMap.js +++ b/www/plugins/gis/lib/leaflet/plugins/Control.MiniMap.js @@ -1,270 +1,323 @@ -L.Control.MiniMap = L.Control.extend({ - options: { - position: 'bottomright', - toggleDisplay: false, - zoomLevelOffset: -5, - zoomLevelFixed: false, - zoomAnimation: false, - autoToggleDisplay: false, - width: 150, - height: 150, - aimingRectOptions: {color: "#ff7800", weight: 1, clickable: false}, - shadowRectOptions: {color: "#000000", weight: 1, clickable: false, opacity:0, fillOpacity:0} - }, - - hideText: 'Hide MiniMap', - - showText: 'Show MiniMap', - - //layer is the map layer to be shown in the minimap - initialize: function (layer, options) { - L.Util.setOptions(this, options); - //Make sure the aiming rects are non-clickable even if the user tries to set them clickable (most likely by forgetting to specify them false) - this.options.aimingRectOptions.clickable = false; - this.options.shadowRectOptions.clickable = false; - this._layer = layer; - }, - - onAdd: function (map) { - - this._mainMap = map; - - //Creating the container and stopping events from spilling through to the main map. - this._container = L.DomUtil.create('div', 'leaflet-control-minimap'); - this._container.style.width = this.options.width + 'px'; - this._container.style.height = this.options.height + 'px'; - L.DomEvent.disableClickPropagation(this._container); - L.DomEvent.on(this._container, 'mousewheel', L.DomEvent.stopPropagation); - - - this._miniMap = new L.Map(this._container, - { - attributionControl: false, - zoomControl: false, - zoomAnimation: this.options.zoomAnimation, - autoToggleDisplay: this.options.autoToggleDisplay, - touchZoom: !this.options.zoomLevelFixed, - scrollWheelZoom: !this.options.zoomLevelFixed, - doubleClickZoom: !this.options.zoomLevelFixed, - boxZoom: !this.options.zoomLevelFixed, - crs: map.options.crs - }); - - this._miniMap.addLayer(this._layer); - - //These bools are used to prevent infinite loops of the two maps notifying each other that they've moved. - this._mainMapMoving = false; - this._miniMapMoving = false; - - //Keep a record of this to prevent auto toggling when the user explicitly doesn't want it. - this._userToggledDisplay = false; - this._minimized = false; - - if (this.options.toggleDisplay) { - this._addToggleButton(); - } +// Following https://github.com/Leaflet/Leaflet/blob/master/PLUGIN-GUIDE.md +(function (factory, window) { - this._miniMap.whenReady(L.Util.bind(function () { - this._aimingRect = L.rectangle(this._mainMap.getBounds(), this.options.aimingRectOptions).addTo(this._miniMap); - this._shadowRect = L.rectangle(this._mainMap.getBounds(), this.options.shadowRectOptions).addTo(this._miniMap); - this._mainMap.on('moveend', this._onMainMapMoved, this); - this._mainMap.on('move', this._onMainMapMoving, this); - this._miniMap.on('movestart', this._onMiniMapMoveStarted, this); - this._miniMap.on('move', this._onMiniMapMoving, this); - this._miniMap.on('moveend', this._onMiniMapMoved, this); - }, this)); - - return this._container; - }, - - addTo: function (map) { - L.Control.prototype.addTo.call(this, map); - this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true)); - this._setDisplay(this._decideMinimized()); - return this; - }, - - onRemove: function (map) { - this._mainMap.off('moveend', this._onMainMapMoved, this); - this._mainMap.off('move', this._onMainMapMoving, this); - this._miniMap.off('moveend', this._onMiniMapMoved, this); - - this._miniMap.removeLayer(this._layer); - }, - - _addToggleButton: function () { - this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton( - '', this.hideText, 'leaflet-control-minimap-toggle-display', this._container, this._toggleDisplayButtonClicked, this) : undefined; - }, - - _createButton: function (html, title, className, container, fn, context) { - var link = L.DomUtil.create('a', className, container); - link.innerHTML = html; - link.href = '#'; - link.title = title; - - var stop = L.DomEvent.stopPropagation; - - L.DomEvent - .on(link, 'click', stop) - .on(link, 'mousedown', stop) - .on(link, 'dblclick', stop) - .on(link, 'click', L.DomEvent.preventDefault) - .on(link, 'click', fn, context); - - return link; - }, - - _toggleDisplayButtonClicked: function () { - this._userToggledDisplay = true; - if (!this._minimized) { - this._minimize(); - this._toggleDisplayButton.title = this.showText; - } - else { - this._restore(); - this._toggleDisplayButton.title = this.hideText; - } - }, + // define an AMD module that relies on 'leaflet' + if (typeof define === 'function' && define.amd) { + define(['leaflet'], factory); + + // define a Common JS module that relies on 'leaflet' + } else if (typeof exports === 'object') { + module.exports = factory(require('leaflet')); + } + + // attach your plugin to the global 'L' variable + if (typeof window !== 'undefined' && window.L) { + window.L.Control.MiniMap = factory(L); + window.L.control.minimap = function (layer, options) { + return new window.L.Control.MiniMap(layer, options); + }; + } +}(function (L) { + + var MiniMap = L.Control.extend({ + options: { + position: 'bottomright', + toggleDisplay: false, + zoomLevelOffset: -5, + zoomLevelFixed: false, + centerFixed: false, + zoomAnimation: false, + autoToggleDisplay: false, + minimized: false, + width: 150, + height: 150, + collapsedWidth: 19, + collapsedHeight: 19, + aimingRectOptions: {color: '#ff7800', weight: 1, clickable: false}, + shadowRectOptions: {color: '#000000', weight: 1, clickable: false, opacity: 0, fillOpacity: 0}, + strings: {hideText: 'Hide MiniMap', showText: 'Show MiniMap'}, + mapOptions: {} // Allows definition / override of Leaflet map options. + }, + + // layer is the map layer to be shown in the minimap + initialize: function (layer, options) { + L.Util.setOptions(this, options); + // Make sure the aiming rects are non-clickable even if the user tries to set them clickable (most likely by forgetting to specify them false) + this.options.aimingRectOptions.clickable = false; + this.options.shadowRectOptions.clickable = false; + this._layer = layer; + }, + + onAdd: function (map) { + + this._mainMap = map; + + // Creating the container and stopping events from spilling through to the main map. + this._container = L.DomUtil.create('div', 'leaflet-control-minimap'); + this._container.style.width = this.options.width + 'px'; + this._container.style.height = this.options.height + 'px'; + L.DomEvent.disableClickPropagation(this._container); + L.DomEvent.on(this._container, 'mousewheel', L.DomEvent.stopPropagation); + + var mapOptions = { + attributionControl: false, + dragging: !this.options.centerFixed, + zoomControl: false, + zoomAnimation: this.options.zoomAnimation, + autoToggleDisplay: this.options.autoToggleDisplay, + touchZoom: this.options.centerFixed ? 'center' : !this._isZoomLevelFixed(), + scrollWheelZoom: this.options.centerFixed ? 'center' : !this._isZoomLevelFixed(), + doubleClickZoom: this.options.centerFixed ? 'center' : !this._isZoomLevelFixed(), + boxZoom: !this._isZoomLevelFixed(), + crs: map.options.crs + }; + mapOptions = L.Util.extend(this.options.mapOptions, mapOptions); // merge with priority of the local mapOptions object. + + this._miniMap = new L.Map(this._container, mapOptions); + + this._miniMap.addLayer(this._layer); + + // These bools are used to prevent infinite loops of the two maps notifying each other that they've moved. + this._mainMapMoving = false; + this._miniMapMoving = false; + + // Keep a record of this to prevent auto toggling when the user explicitly doesn't want it. + this._userToggledDisplay = false; + this._minimized = false; + + if (this.options.toggleDisplay) { + this._addToggleButton(); + } - _setDisplay: function (minimize) { - if (minimize != this._minimized) { + this._miniMap.whenReady(L.Util.bind(function () { + this._aimingRect = L.rectangle(this._mainMap.getBounds(), this.options.aimingRectOptions).addTo(this._miniMap); + this._shadowRect = L.rectangle(this._mainMap.getBounds(), this.options.shadowRectOptions).addTo(this._miniMap); + this._mainMap.on('moveend', this._onMainMapMoved, this); + this._mainMap.on('move', this._onMainMapMoving, this); + this._miniMap.on('movestart', this._onMiniMapMoveStarted, this); + this._miniMap.on('move', this._onMiniMapMoving, this); + this._miniMap.on('moveend', this._onMiniMapMoved, this); + }, this)); + + return this._container; + }, + + addTo: function (map) { + L.Control.prototype.addTo.call(this, map); + + var center = this.options.centerFixed || this._mainMap.getCenter(); + this._miniMap.setView(center, this._decideZoom(true)); + this._setDisplay(this.options.minimized); + return this; + }, + + onRemove: function (map) { + this._mainMap.off('moveend', this._onMainMapMoved, this); + this._mainMap.off('move', this._onMainMapMoving, this); + this._miniMap.off('moveend', this._onMiniMapMoved, this); + + this._miniMap.removeLayer(this._layer); + }, + + changeLayer: function (layer) { + this._miniMap.removeLayer(this._layer); + this._layer = layer; + this._miniMap.addLayer(this._layer); + }, + + _addToggleButton: function () { + this._toggleDisplayButton = this.options.toggleDisplay ? this._createButton( + '', this.options.strings.hideText, ('leaflet-control-minimap-toggle-display leaflet-control-minimap-toggle-display-' + + this.options.position), this._container, this._toggleDisplayButtonClicked, this) : undefined; + + this._toggleDisplayButton.style.width = this.options.collapsedWidth + 'px'; + this._toggleDisplayButton.style.height = this.options.collapsedHeight + 'px'; + }, + + _createButton: function (html, title, className, container, fn, context) { + var link = L.DomUtil.create('a', className, container); + link.innerHTML = html; + link.href = '#'; + link.title = title; + + var stop = L.DomEvent.stopPropagation; + + L.DomEvent + .on(link, 'click', stop) + .on(link, 'mousedown', stop) + .on(link, 'dblclick', stop) + .on(link, 'click', L.DomEvent.preventDefault) + .on(link, 'click', fn, context); + + return link; + }, + + _toggleDisplayButtonClicked: function () { + this._userToggledDisplay = true; if (!this._minimized) { this._minimize(); - } - else { + } else { this._restore(); } - } - }, - - _minimize: function () { - // hide the minimap - if (this.options.toggleDisplay) { - this._container.style.width = '19px'; - this._container.style.height = '19px'; - this._toggleDisplayButton.className += ' minimized'; - } - else { - this._container.style.display = 'none'; - } - this._minimized = true; - }, + }, - _restore: function () { - if (this.options.toggleDisplay) { - this._container.style.width = this.options.width + 'px'; - this._container.style.height = this.options.height + 'px'; - this._toggleDisplayButton.className = this._toggleDisplayButton.className - .replace(/(?:^|\s)minimized(?!\S)/g, ''); - } - else { - this._container.style.display = 'block'; - } - this._minimized = false; - }, - - _onMainMapMoved: function (e) { - if (!this._miniMapMoving) { - this._mainMapMoving = true; - this._miniMap.setView(this._mainMap.getCenter(), this._decideZoom(true)); - this._setDisplay(this._decideMinimized()); - } else { - this._miniMapMoving = false; - } - this._aimingRect.setBounds(this._mainMap.getBounds()); - }, - - _onMainMapMoving: function (e) { - this._aimingRect.setBounds(this._mainMap.getBounds()); - }, - - _onMiniMapMoveStarted:function (e) { - var lastAimingRect = this._aimingRect.getBounds(); - var sw = this._miniMap.latLngToContainerPoint(lastAimingRect.getSouthWest()); - var ne = this._miniMap.latLngToContainerPoint(lastAimingRect.getNorthEast()); - this._lastAimingRectPosition = {sw:sw,ne:ne}; - }, - - _onMiniMapMoving: function (e) { - if (!this._mainMapMoving && this._lastAimingRectPosition) { - this._shadowRect.setBounds(new L.LatLngBounds(this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.sw),this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.ne))); - this._shadowRect.setStyle({opacity:1,fillOpacity:0.3}); - } - }, - - _onMiniMapMoved: function (e) { - if (!this._mainMapMoving) { - this._miniMapMoving = true; - this._mainMap.setView(this._miniMap.getCenter(), this._decideZoom(false)); - this._shadowRect.setStyle({opacity:0,fillOpacity:0}); - } else { - this._mainMapMoving = false; - } - }, - - _decideZoom: function (fromMaintoMini) { - if (!this.options.zoomLevelFixed) { - if (fromMaintoMini) - return this._mainMap.getZoom() + this.options.zoomLevelOffset; - else { - var currentDiff = this._miniMap.getZoom() - this._mainMap.getZoom(); - var proposedZoom = this._miniMap.getZoom() - this.options.zoomLevelOffset; - var toRet; - - if (currentDiff > this.options.zoomLevelOffset && this._mainMap.getZoom() < this._miniMap.getMinZoom() - this.options.zoomLevelOffset) { - //This means the miniMap is zoomed out to the minimum zoom level and can't zoom any more. - if (this._miniMap.getZoom() > this._lastMiniMapZoom) { - //This means the user is trying to zoom in by using the minimap, zoom the main map. - toRet = this._mainMap.getZoom() + 1; - //Also we cheat and zoom the minimap out again to keep it visually consistent. - this._miniMap.setZoom(this._miniMap.getZoom() -1); + _setDisplay: function (minimize) { + if (minimize !== this._minimized) { + if (!this._minimized) { + this._minimize(); + } else { + this._restore(); + } + } + }, + + _minimize: function () { + // hide the minimap + if (this.options.toggleDisplay) { + this._container.style.width = this.options.collapsedWidth + 'px'; + this._container.style.height = this.options.collapsedHeight + 'px'; + this._toggleDisplayButton.className += (' minimized-' + this.options.position); + this._toggleDisplayButton.title = this.options.strings.showText; + } else { + this._container.style.display = 'none'; + } + this._minimized = true; + }, + + _restore: function () { + if (this.options.toggleDisplay) { + this._container.style.width = this.options.width + 'px'; + this._container.style.height = this.options.height + 'px'; + this._toggleDisplayButton.className = this._toggleDisplayButton.className + .replace('minimized-' + this.options.position, ''); + this._toggleDisplayButton.title = this.options.strings.hideText; + } else { + this._container.style.display = 'block'; + } + this._minimized = false; + }, + + _onMainMapMoved: function (e) { + if (!this._miniMapMoving) { + var center = this.options.centerFixed || this._mainMap.getCenter(); + + this._mainMapMoving = true; + this._miniMap.setView(center, this._decideZoom(true)); + this._setDisplay(this._decideMinimized()); + } else { + this._miniMapMoving = false; + } + this._aimingRect.setBounds(this._mainMap.getBounds()); + }, + + _onMainMapMoving: function (e) { + this._aimingRect.setBounds(this._mainMap.getBounds()); + }, + + _onMiniMapMoveStarted: function (e) { + if (!this.options.centerFixed) { + var lastAimingRect = this._aimingRect.getBounds(); + var sw = this._miniMap.latLngToContainerPoint(lastAimingRect.getSouthWest()); + var ne = this._miniMap.latLngToContainerPoint(lastAimingRect.getNorthEast()); + this._lastAimingRectPosition = {sw: sw, ne: ne}; + } + }, + + _onMiniMapMoving: function (e) { + if (!this.options.centerFixed) { + if (!this._mainMapMoving && this._lastAimingRectPosition) { + this._shadowRect.setBounds(new L.LatLngBounds(this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.sw), this._miniMap.containerPointToLatLng(this._lastAimingRectPosition.ne))); + this._shadowRect.setStyle({opacity: 1, fillOpacity: 0.3}); + } + } + }, + + _onMiniMapMoved: function (e) { + if (!this._mainMapMoving) { + this._miniMapMoving = true; + this._mainMap.setView(this._miniMap.getCenter(), this._decideZoom(false)); + this._shadowRect.setStyle({opacity: 0, fillOpacity: 0}); + } else { + this._mainMapMoving = false; + } + }, + + _isZoomLevelFixed: function () { + var zoomLevelFixed = this.options.zoomLevelFixed; + return this._isDefined(zoomLevelFixed) && this._isInteger(zoomLevelFixed); + }, + + _decideZoom: function (fromMaintoMini) { + if (!this._isZoomLevelFixed()) { + if (fromMaintoMini) { + return this._mainMap.getZoom() + this.options.zoomLevelOffset; + } else { + var currentDiff = this._miniMap.getZoom() - this._mainMap.getZoom(); + var proposedZoom = this._miniMap.getZoom() - this.options.zoomLevelOffset; + var toRet; + + if (currentDiff > this.options.zoomLevelOffset && this._mainMap.getZoom() < this._miniMap.getMinZoom() - this.options.zoomLevelOffset) { + // This means the miniMap is zoomed out to the minimum zoom level and can't zoom any more. + if (this._miniMap.getZoom() > this._lastMiniMapZoom) { + // This means the user is trying to zoom in by using the minimap, zoom the main map. + toRet = this._mainMap.getZoom() + 1; + // Also we cheat and zoom the minimap out again to keep it visually consistent. + this._miniMap.setZoom(this._miniMap.getZoom() - 1); + } else { + // Either the user is trying to zoom out past the mini map's min zoom or has just panned using it, we can't tell the difference. + // Therefore, we ignore it! + toRet = this._mainMap.getZoom(); + } } else { - //Either the user is trying to zoom out past the mini map's min zoom or has just panned using it, we can't tell the difference. - //Therefore, we ignore it! - toRet = this._mainMap.getZoom(); + // This is what happens in the majority of cases, and always if you configure the min levels + offset in a sane fashion. + toRet = proposedZoom; } + this._lastMiniMapZoom = this._miniMap.getZoom(); + return toRet; + } + } else { + if (fromMaintoMini) { + return this.options.zoomLevelFixed; } else { - //This is what happens in the majority of cases, and always if you configure the min levels + offset in a sane fashion. - toRet = proposedZoom; + return this._mainMap.getZoom(); } - this._lastMiniMapZoom = this._miniMap.getZoom(); - return toRet; } - } else { - if (fromMaintoMini) - return this.options.zoomLevelFixed; - else - return this._mainMap.getZoom(); - } - }, + }, - _decideMinimized: function () { - if (this._userToggledDisplay) { - return this._minimized; - } + _decideMinimized: function () { + if (this._userToggledDisplay) { + return this._minimized; + } - if (this.options.autoToggleDisplay) { - if (this._mainMap.getBounds().contains(this._miniMap.getBounds())) { - return true; + if (this.options.autoToggleDisplay) { + if (this._mainMap.getBounds().contains(this._miniMap.getBounds())) { + return true; + } + return false; } - return false; + + return this._minimized; + }, + + _isInteger: function (value) { + return typeof value === 'number'; + }, + + _isDefined: function (value) { + return typeof value !== 'undefined'; } + }); - return this._minimized; - } -}); + L.Map.mergeOptions({ + miniMapControl: false + }); -L.Map.mergeOptions({ - miniMapControl: false -}); + L.Map.addInitHook(function () { + if (this.options.miniMapControl) { + this.miniMapControl = (new MiniMap()).addTo(this); + } + }); -L.Map.addInitHook(function () { - if (this.options.miniMapControl) { - this.miniMapControl = (new L.Control.MiniMap()).addTo(this); - } -}); + return MiniMap; -L.control.minimap = function (options) { - return new L.Control.MiniMap(options); -}; +}, window)); diff --git a/www/plugins/gis/lib/leaflet/plugins/GPX.Speed.js b/www/plugins/gis/lib/leaflet/plugins/GPX.Speed.js index 9f4fbc96..d500d292 100755 --- a/www/plugins/gis/lib/leaflet/plugins/GPX.Speed.js +++ b/www/plugins/gis/lib/leaflet/plugins/GPX.Speed.js @@ -1,8 +1,8 @@ //#include 'GPX.js' -(function() { +(function () { -function d2h(d) { +function d2h (d) { var hex = '0123456789ABCDEF'; var r = ''; d = Math.floor(d); @@ -14,9 +14,9 @@ function d2h(d) { return r; } -function gradient(color) { +function gradient (color) { // First arc (0, PI) in HSV colorspace - function f2h(d) { return d2h(256 * d); } + function f2h (d) { return d2h(256 * d); } if (color < 0) return '#FF0000'; else if (color < 1.0/3) @@ -29,7 +29,7 @@ function gradient(color) { return '#00FFFF'; } -function gpx2time(s) { +function gpx2time (s) { // 2011-09-24T12:07:53Z if (s.length !== 10 + 1 + 8 + 1) return new Date(); @@ -42,16 +42,16 @@ L.GPX.include({ chunks: 200 }, - speedSplitEnable: function(options) { + speedSplitEnable: function (options) { L.Util.setOptions(this, options); return this.on('addline', this.speed_split, this); }, - speedSplitDisable: function() { + speedSplitDisable: function () { return this.off('addline', this.speed_split, this); }, - speed_split: function(e) { + speed_split: function (e) { var l = e.line.pop(), ll = l.getLatLngs(); var chunk = Math.floor(ll.length / this.options.chunks); if (chunk < 3) chunk = 3; diff --git a/www/plugins/gis/lib/leaflet/plugins/GPX.js b/www/plugins/gis/lib/leaflet/plugins/GPX.js index e2e7d6ae..f582d5a4 100755 --- a/www/plugins/gis/lib/leaflet/plugins/GPX.js +++ b/www/plugins/gis/lib/leaflet/plugins/GPX.js @@ -1,5 +1,5 @@ L.GPX = L.FeatureGroup.extend({ - initialize: function(gpx, options) { + initialize: function (gpx, options) { L.Util.setOptions(this, options); this._gpx = gpx; this._layers = {}; @@ -9,7 +9,7 @@ L.GPX = L.FeatureGroup.extend({ } }, - loadXML: function(url, cb, options, async) { + loadXML: function (url, cb, options, async) { if (async === undefined) async = this.options.async; if (options === undefined) options = this.options; @@ -17,48 +17,48 @@ L.GPX = L.FeatureGroup.extend({ req.open('GET', url, async); try { req.overrideMimeType('text/xml'); // unsupported by IE - } catch(e) {} - req.onreadystatechange = function() { + } catch (e) {} + req.onreadystatechange = function () { if (req.readyState !== 4) return; - if(req.status === 200) cb(req.responseXML, options); + if (req.status === 200) cb(req.responseXML, options); }; req.send(null); }, - _humanLen: function(l) { + _humanLen: function (l) { if (l < 2000) return l.toFixed(0) + ' m'; else return (l/1000).toFixed(1) + ' km'; }, - _polylineLen: function(line)//line is a L.Polyline() + _polylineLen: function (line)//line is a L.Polyline() { var ll = line._latlngs; var d = 0, p = null; for (var i = 0; i < ll.length; i++) { - if(i && p) + if (i && p) d += p.distanceTo(ll[i]); p = ll[i]; } return d; }, - addGPX: function(url, options, async) { + addGPX: function (url, options, async) { var _this = this; - var cb = function(gpx, options) { _this._addGPX(gpx, options); }; + var cb = function (gpx, options) { _this._addGPX(gpx, options); }; this.loadXML(url, cb, options, async); }, - _addGPX: function(gpx, options) { + _addGPX: function (gpx, options) { var layers = this.parseGPX(gpx, options); if (!layers) return; this.addLayer(layers); this.fire('loaded'); - }, + }, - parseGPX: function(xml, options) { + parseGPX: function (xml, options) { var j, i, el, layers = []; var named = false, tags = [['rte','rtept'], ['trkseg','trkpt']]; @@ -91,8 +91,8 @@ L.GPX = L.FeatureGroup.extend({ return layer; }, - parse_name: function(xml, layer) { - var i, el, txt='', name, descr='', len=0; + parse_name: function (xml, layer) { + var i, el, txt='', name, descr='', link, len=0; el = xml.getElementsByTagName('name'); if (el.length) name = el[0].childNodes[0].nodeValue; @@ -101,18 +101,22 @@ L.GPX = L.FeatureGroup.extend({ for (var j = 0; j < el[i].childNodes.length; j++) descr = descr + el[i].childNodes[j].nodeValue; } + el = xml.getElementsByTagName('link'); + if (el.length) + link = el[0].getAttribute('href'); - if(layer instanceof L.Path) + if (layer instanceof L.Path) len = this._polylineLen(layer); if (name) txt += '

                  ' + name + '

                  ' + descr; if (len) txt += '

                  ' + this._humanLen(len) + '

                  '; - + if (link) txt += '

                  [...]

                  '; + if (layer && layer._popup === undefined) layer.bindPopup(txt); return txt; }, - parse_trkseg: function(line, xml, options, tag) { + parse_trkseg: function (line, xml, options, tag) { var el = line.getElementsByTagName(tag); if (!el.length) return []; var coords = []; @@ -132,10 +136,17 @@ L.GPX = L.FeatureGroup.extend({ return l; }, - parse_wpt: function(e, xml, options) { + parse_wpt: function (e, xml, options) { var m = new L.Marker(new L.LatLng(e.getAttribute('lat'), e.getAttribute('lon')), options); - this.fire('addpoint', {point:m}); + var attributes = {}; + for (var i = 0; i < e.childNodes.length; i++) { + var ch = e.childNodes[i]; + if (ch.nodeName !== '#text') { + attributes[ch.nodeName] = ch.textContent; + } + } + this.fire('addpoint', {point:m, attributes:attributes}); return m; } }); diff --git a/www/plugins/gis/lib/leaflet/plugins/Google.js b/www/plugins/gis/lib/leaflet/plugins/Google.js index c919618e..418783bb 100755 --- a/www/plugins/gis/lib/leaflet/plugins/Google.js +++ b/www/plugins/gis/lib/leaflet/plugins/Google.js @@ -23,42 +23,56 @@ L.Google = L.Class.extend({ }, // Possible types: SATELLITE, ROADMAP, HYBRID, TERRAIN - initialize: function(type, options) { + initialize: function (type, options) { + var _this = this; + + this._ready = L.Google.isGoogleMapsReady(); + L.Util.setOptions(this, options); - this._ready = google.maps.Map !== undefined; - if (!this._ready) L.Google.asyncWait.push(this); + this._googleApiPromise = this._ready ? Promise.resolve(window.google) : L.Google.createGoogleApiPromise(); + + this._googleApiPromise + .then(function () { + _this._ready = true; + _this._initMapObject(); + _this._update(); + }); this._type = type || 'SATELLITE'; }, - onAdd: function(map, insertAtTheBottom) { - this._map = map; - this._insertAtTheBottom = insertAtTheBottom; + onAdd: function (map, insertAtTheBottom) { + var _this = this; + this._googleApiPromise + .then(function () { + _this._map = map; + _this._insertAtTheBottom = insertAtTheBottom; - // create a container div for tiles - this._initContainer(); - this._initMapObject(); + // create a container div for tiles + _this._initContainer(); + _this._initMapObject(); - // set up events - map.on('viewreset', this._resetCallback, this); + // set up events + map.on('viewreset', _this._reset, _this); - this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this); - map.on('move', this._update, this); + _this._limitedUpdate = L.Util.limitExecByInterval(_this._update, 150, _this); + map.on('move', _this._update, _this); - map.on('zoomanim', this._handleZoomAnim, this); + map.on('zoomanim', _this._handleZoomAnim, _this); - //20px instead of 1em to avoid a slight overlap with google's attribution - map._controlCorners.bottomright.style.marginBottom = '20px'; + //20px instead of 1em to avoid a slight overlap with google's attribution + map._controlCorners.bottomright.style.marginBottom = '20px'; - this._reset(); - this._update(); + _this._reset(); + _this._update(); + }); }, - onRemove: function(map) { + onRemove: function (map) { map._container.removeChild(this._container); - map.off('viewreset', this._resetCallback, this); + map.off('viewreset', this._reset, this); map.off('move', this._update, this); @@ -67,23 +81,23 @@ L.Google = L.Class.extend({ map._controlCorners.bottomright.style.marginBottom = '0em'; }, - getAttribution: function() { + getAttribution: function () { return this.options.attribution; }, - setOpacity: function(opacity) { + setOpacity: function (opacity) { this.options.opacity = opacity; if (opacity < 1) { L.DomUtil.setOpacity(this._container, opacity); } }, - setElementSize: function(e, size) { + setElementSize: function (e, size) { e.style.width = size.x + 'px'; e.style.height = size.y + 'px'; }, - _initContainer: function() { + _initContainer: function () { var tilePane = this._map._container, first = tilePane.firstChild; @@ -99,8 +113,8 @@ L.Google = L.Class.extend({ this.setElementSize(this._container, this._map.getSize()); }, - _initMapObject: function() { - if (!this._ready) return; + _initMapObject: function () { + if (!this._ready || !this._container) return; this._google_center = new google.maps.LatLng(0, 0); var map = new google.maps.Map(this._container, { center: this._google_center, @@ -119,36 +133,32 @@ L.Google = L.Class.extend({ var _this = this; this._reposition = google.maps.event.addListenerOnce(map, 'center_changed', - function() { _this.onReposition(); }); + function () { _this.onReposition(); }); this._google = map; google.maps.event.addListenerOnce(map, 'idle', - function() { _this._checkZoomLevels(); }); + function () { _this._checkZoomLevels(); }); google.maps.event.addListenerOnce(map, 'tilesloaded', - function() { _this.fire('load'); }); + function () { _this.fire('load'); }); //Reporting that map-object was initialized. - this.fire('MapObjectInitialized', { mapObject: map }); + this.fire('MapObjectInitialized', {mapObject: map}); }, - _checkZoomLevels: function() { + _checkZoomLevels: function () { //setting the zoom level on the Google map may result in a different zoom level than the one requested //(it won't go beyond the level for which they have data). // verify and make sure the zoom levels on both Leaflet and Google maps are consistent - if (this._google.getZoom() !== this._map.getZoom()) { + if ((this._map.getZoom() !== undefined) && (this._google.getZoom() !== this._map.getZoom())) { //zoom levels are out of sync. Set the leaflet zoom level to match the google one - this._map.setZoom( this._google.getZoom() ); + this._map.setZoom(this._google.getZoom()); } }, - _resetCallback: function(e) { - this._reset(e.hard); - }, - - _reset: function(clearOldContainer) { + _reset: function () { this._initContainer(); }, - _update: function(e) { + _update: function () { if (!this._google) return; this._resize(); @@ -156,12 +166,13 @@ L.Google = L.Class.extend({ var _center = new google.maps.LatLng(center.lat, center.lng); this._google.setCenter(_center); - this._google.setZoom(Math.round(this._map.getZoom())); + if (this._map.getZoom() !== undefined) + this._google.setZoom(Math.round(this._map.getZoom())); this._checkZoomLevels(); }, - _resize: function() { + _resize: function () { var size = this._map.getSize(); if (this._container.style.width === size.x && this._container.style.height === size.y) @@ -180,22 +191,38 @@ L.Google = L.Class.extend({ }, - onReposition: function() { + onReposition: function () { if (!this._google) return; google.maps.event.trigger(this._google, 'resize'); } }); -L.Google.asyncWait = []; -L.Google.asyncInitialize = function() { - var i; - for (i = 0; i < L.Google.asyncWait.length; i++) { - var o = L.Google.asyncWait[i]; - o._ready = true; - if (o._container) { - o._initMapObject(); - o._update(); - } - } - L.Google.asyncWait = []; +L.Google.isGoogleMapsReady = function () { + return !!window.google && !!window.google.maps && !!window.google.maps.Map; +}; + +// backwards compat +L.Google.asyncInitialize = L.Google.isGoogleMapsReady; + +L.Google.maxApiChecks = 10; + +L.Google.apiCheckIntervalMilliSecs = 500; + +L.Google.createGoogleApiPromise = function () { + var checkCounter = 0; + var intervalId = null; + + return new Promise(function (resolve, reject) { + intervalId = setInterval(function () { + if (checkCounter >= L.Google.maxApiChecks && !L.Google.isGoogleMapsReady()) { + clearInterval(intervalId); + return reject(new Error('window.google not found after max attempts')); + } + if (L.Google.isGoogleMapsReady()) { + clearInterval(intervalId); + return resolve(window.google); + } + checkCounter++; + }, L.Google.apiCheckIntervalMilliSecs); + }); }; diff --git a/www/plugins/gis/lib/leaflet/plugins/KML.js b/www/plugins/gis/lib/leaflet/plugins/KML.js index acdc4e8f..096c1c33 100755 --- a/www/plugins/gis/lib/leaflet/plugins/KML.js +++ b/www/plugins/gis/lib/leaflet/plugins/KML.js @@ -3,7 +3,7 @@ L.KML = L.FeatureGroup.extend({ async: true }, - initialize: function(kml, options) { + initialize: function (kml, options) { L.Util.setOptions(this, options); this._kml = kml; this._layers = {}; @@ -13,7 +13,7 @@ L.KML = L.FeatureGroup.extend({ } }, - loadXML: function(url, cb, options, async) { + loadXML: function (url, cb, options, async) { if (async === undefined) async = this.options.async; if (options === undefined) options = this.options; @@ -36,6 +36,7 @@ L.KML = L.FeatureGroup.extend({ setTimeout(function () { xdr.send(); }, 0); } else { req.open('GET', url, async); + req.setRequestHeader('Accept', 'application/vnd.google-earth.kml+xml'); try { req.overrideMimeType('text/xml'); // unsupported by IE } catch (e) { } @@ -47,13 +48,13 @@ L.KML = L.FeatureGroup.extend({ } }, - addKML: function(url, options, async) { + addKML: function (url, options, async) { var _this = this; - var cb = function(gpx, options) { _this._addKML(gpx, options); }; + var cb = function (kml) { _this._addKML(kml); }; this.loadXML(url, cb, options, async); }, - _addKML: function(xml, options) { + _addKML: function (xml) { var layers = L.KML.parseKML(xml); if (!layers || !layers.length) return; for (var i = 0; i < layers.length; i++) { @@ -106,7 +107,7 @@ L.Util.extend(L.KML, { return !e || e === folder; }, - parseStyles: function(xml) { + parseStyles: function (xml) { var styles = {}; var sl = xml.getElementsByTagName('Style'); for (var i=0, len=sl.length; i' + name + '' + descr); }); } @@ -399,7 +400,7 @@ L.Util.extend(L.KML, { ] ); var attributes = {Icon: true, href: true, color: true}; - function _parse(xml) { + function _parse (xml) { var options = {}, ioptions = {}; for (var i = 0; i < xml.childNodes.length; i++) { var e = xml.childNodes[i]; @@ -469,7 +470,7 @@ L.RotatedImageOverlay = L.ImageOverlay.extend({ if (L.DomUtil.TRANSFORM) { // use the CSS transform rule if available this._image.style[L.DomUtil.TRANSFORM] += ' rotate(' + this.options.angle + 'deg)'; - } else if(L.Browser.ie) { + } else if (L.Browser.ie) { // fallback for IE6, IE7, IE8 var rad = this.options.angle * (Math.PI / 180), costheta = Math.cos(rad), @@ -478,7 +479,7 @@ L.RotatedImageOverlay = L.ImageOverlay.extend({ costheta + ', M12=' + (-sintheta) + ', M21=' + sintheta + ', M22=' + costheta + ')'; } }, - getBounds: function() { + getBounds: function () { return this._bounds; } }); diff --git a/www/plugins/gis/lib/leaflet/plugins/Marker.Rotate.js b/www/plugins/gis/lib/leaflet/plugins/Marker.Rotate.js index 174d76b4..ab2b9bce 100755 --- a/www/plugins/gis/lib/leaflet/plugins/Marker.Rotate.js +++ b/www/plugins/gis/lib/leaflet/plugins/Marker.Rotate.js @@ -7,7 +7,7 @@ (function () { var _old__setPos = L.Marker.prototype._setPos; L.Marker.include({ - _updateImg: function(i, a, s) { + _updateImg: function (i, a, s) { a = L.point(s).divideBy(2)._subtract(L.point(a)); var transform = ''; transform += ' translate(' + -a.x + 'px, ' + -a.y + 'px)'; @@ -15,9 +15,18 @@ transform += ' translate(' + a.x + 'px, ' + a.y + 'px)'; i.style[L.DomUtil.TRANSFORM] += transform; }, + + _getShortestEndDegree: function (startDegrees, endDegrees) { + var turnAngle = Math.abs(endDegrees - startDegrees); + var turnAnglePositive = (endDegrees - startDegrees) >= 0; + if (turnAngle <= 180) return endDegrees; + var result = startDegrees + (360 - turnAngle) * (turnAnglePositive ? -1 : 1); + return result; + }, setIconAngle: function (iconAngle) { - this.options.iconAngle = iconAngle; + // find shortest angle to turn over + this.options.iconAngle = this._getShortestEndDegree(this.options.iconAngle || 0, iconAngle); if (this._map) this.update(); }, @@ -31,7 +40,7 @@ _old__setPos.apply(this,[pos]); if (this.options.iconAngle) { - var defaultIcon = new L.Icon.Default; + var defaultIcon = new L.Icon.Default(); var a = this.options.icon.options.iconAnchor || defaultIcon.options.iconAnchor; var s = this.options.icon.options.iconSize || defaultIcon.options.iconSize; var i; diff --git a/www/plugins/gis/lib/leaflet/plugins/TOPOJSON.js b/www/plugins/gis/lib/leaflet/plugins/TOPOJSON.js new file mode 100644 index 00000000..480aa734 --- /dev/null +++ b/www/plugins/gis/lib/leaflet/plugins/TOPOJSON.js @@ -0,0 +1,636 @@ +-/** +- * Embed of the topojson library from Mike Bostock v1.6.26 +- * https://github.com/mbostock/topojson +- * +- */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.topojson = global.topojson || {}))); +}(this, function (exports) { 'use strict'; + + function noop() {} + + function transformAbsolute(transform) { + if (!transform) return noop; + var x0, + y0, + kx = transform.scale[0], + ky = transform.scale[1], + dx = transform.translate[0], + dy = transform.translate[1]; + return function(point, i) { + if (!i) x0 = y0 = 0; + point[0] = (x0 += point[0]) * kx + dx; + point[1] = (y0 += point[1]) * ky + dy; + }; + } + + function transformRelative(transform) { + if (!transform) return noop; + var x0, + y0, + kx = transform.scale[0], + ky = transform.scale[1], + dx = transform.translate[0], + dy = transform.translate[1]; + return function(point, i) { + if (!i) x0 = y0 = 0; + var x1 = Math.round((point[0] - dx) / kx), + y1 = Math.round((point[1] - dy) / ky); + point[0] = x1 - x0; + point[1] = y1 - y0; + x0 = x1; + y0 = y1; + }; + } + + function reverse(array, n) { + var t, j = array.length, i = j - n; + while (i < --j) t = array[i], array[i++] = array[j], array[j] = t; + } + + function bisect(a, x) { + var lo = 0, hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (a[mid] < x) lo = mid + 1; + else hi = mid; + } + return lo; + } + + function feature(topology, o) { + return o.type === "GeometryCollection" ? { + type: "FeatureCollection", + features: o.geometries.map(function(o) { return feature$1(topology, o); }) + } : feature$1(topology, o); + } + + function feature$1(topology, o) { + var f = { + type: "Feature", + id: o.id, + properties: o.properties || {}, + geometry: object(topology, o) + }; + if (o.id == null) delete f.id; + return f; + } + + function object(topology, o) { + var absolute = transformAbsolute(topology.transform), + arcs = topology.arcs; + + function arc(i, points) { + if (points.length) points.pop(); + for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) { + points.push(p = a[k].slice()); + absolute(p, k); + } + if (i < 0) reverse(points, n); + } + + function point(p) { + p = p.slice(); + absolute(p, 0); + return p; + } + + function line(arcs) { + var points = []; + for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points); + if (points.length < 2) points.push(points[0].slice()); + return points; + } + + function ring(arcs) { + var points = line(arcs); + while (points.length < 4) points.push(points[0].slice()); + return points; + } + + function polygon(arcs) { + return arcs.map(ring); + } + + function geometry(o) { + var t = o.type; + return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)} + : t in geometryType ? {type: t, coordinates: geometryType[t](o)} + : null; + } + + var geometryType = { + Point: function(o) { return point(o.coordinates); }, + MultiPoint: function(o) { return o.coordinates.map(point); }, + LineString: function(o) { return line(o.arcs); }, + MultiLineString: function(o) { return o.arcs.map(line); }, + Polygon: function(o) { return polygon(o.arcs); }, + MultiPolygon: function(o) { return o.arcs.map(polygon); } + }; + + return geometry(o); + } + + function stitchArcs(topology, arcs) { + var stitchedArcs = {}, + fragmentByStart = {}, + fragmentByEnd = {}, + fragments = [], + emptyIndex = -1; + + // Stitch empty arcs first, since they may be subsumed by other arcs. + arcs.forEach(function(i, j) { + var arc = topology.arcs[i < 0 ? ~i : i], t; + if (arc.length < 3 && !arc[1][0] && !arc[1][1]) { + t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t; + } + }); + + arcs.forEach(function(i) { + var e = ends(i), + start = e[0], + end = e[1], + f, g; + + if (f = fragmentByEnd[start]) { + delete fragmentByEnd[f.end]; + f.push(i); + f.end = end; + if (g = fragmentByStart[end]) { + delete fragmentByStart[g.start]; + var fg = g === f ? f : f.concat(g); + fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg; + } else { + fragmentByStart[f.start] = fragmentByEnd[f.end] = f; + } + } else if (f = fragmentByStart[end]) { + delete fragmentByStart[f.start]; + f.unshift(i); + f.start = start; + if (g = fragmentByEnd[start]) { + delete fragmentByEnd[g.end]; + var gf = g === f ? f : g.concat(f); + fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf; + } else { + fragmentByStart[f.start] = fragmentByEnd[f.end] = f; + } + } else { + f = [i]; + fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f; + } + }); + + function ends(i) { + var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1; + if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; }); + else p1 = arc[arc.length - 1]; + return i < 0 ? [p1, p0] : [p0, p1]; + } + + function flush(fragmentByEnd, fragmentByStart) { + for (var k in fragmentByEnd) { + var f = fragmentByEnd[k]; + delete fragmentByStart[f.start]; + delete f.start; + delete f.end; + f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; }); + fragments.push(f); + } + } + + flush(fragmentByEnd, fragmentByStart); + flush(fragmentByStart, fragmentByEnd); + arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); }); + + return fragments; + } + + function mesh(topology) { + return object(topology, meshArcs.apply(this, arguments)); + } + + function meshArcs(topology, o, filter) { + var arcs = []; + + function arc(i) { + var j = i < 0 ? ~i : i; + (geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom}); + } + + function line(arcs) { + arcs.forEach(arc); + } + + function polygon(arcs) { + arcs.forEach(line); + } + + function geometry(o) { + if (o.type === "GeometryCollection") o.geometries.forEach(geometry); + else if (o.type in geometryType) geom = o, geometryType[o.type](o.arcs); + } + + if (arguments.length > 1) { + var geomsByArc = [], + geom; + + var geometryType = { + LineString: line, + MultiLineString: polygon, + Polygon: polygon, + MultiPolygon: function(arcs) { arcs.forEach(polygon); } + }; + + geometry(o); + + geomsByArc.forEach(arguments.length < 3 + ? function(geoms) { arcs.push(geoms[0].i); } + : function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); }); + } else { + for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i); + } + + return {type: "MultiLineString", arcs: stitchArcs(topology, arcs)}; + } + + function cartesianTriangleArea(triangle) { + var a = triangle[0], b = triangle[1], c = triangle[2]; + return Math.abs((a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1])); + } + + function ring(ring) { + var i = -1, + n = ring.length, + a, + b = ring[n - 1], + area = 0; + + while (++i < n) { + a = b; + b = ring[i]; + area += a[0] * b[1] - a[1] * b[0]; + } + + return area / 2; + } + + function merge(topology) { + return object(topology, mergeArcs.apply(this, arguments)); + } + + function mergeArcs(topology, objects) { + var polygonsByArc = {}, + polygons = [], + components = []; + + objects.forEach(function(o) { + if (o.type === "Polygon") register(o.arcs); + else if (o.type === "MultiPolygon") o.arcs.forEach(register); + }); + + function register(polygon) { + polygon.forEach(function(ring$$) { + ring$$.forEach(function(arc) { + (polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon); + }); + }); + polygons.push(polygon); + } + + function area(ring$$) { + return Math.abs(ring(object(topology, {type: "Polygon", arcs: [ring$$]}).coordinates[0])); + } + + polygons.forEach(function(polygon) { + if (!polygon._) { + var component = [], + neighbors = [polygon]; + polygon._ = 1; + components.push(component); + while (polygon = neighbors.pop()) { + component.push(polygon); + polygon.forEach(function(ring$$) { + ring$$.forEach(function(arc) { + polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) { + if (!polygon._) { + polygon._ = 1; + neighbors.push(polygon); + } + }); + }); + }); + } + } + }); + + polygons.forEach(function(polygon) { + delete polygon._; + }); + + return { + type: "MultiPolygon", + arcs: components.map(function(polygons) { + var arcs = [], n; + + // Extract the exterior (unique) arcs. + polygons.forEach(function(polygon) { + polygon.forEach(function(ring$$) { + ring$$.forEach(function(arc) { + if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) { + arcs.push(arc); + } + }); + }); + }); + + // Stitch the arcs into one or more rings. + arcs = stitchArcs(topology, arcs); + + // If more than one ring is returned, + // at most one of these rings can be the exterior; + // choose the one with the greatest absolute area. + if ((n = arcs.length) > 1) { + for (var i = 1, k = area(arcs[0]), ki, t; i < n; ++i) { + if ((ki = area(arcs[i])) > k) { + t = arcs[0], arcs[0] = arcs[i], arcs[i] = t, k = ki; + } + } + } + + return arcs; + }) + }; + } + + function neighbors(objects) { + var indexesByArc = {}, // arc index -> array of object indexes + neighbors = objects.map(function() { return []; }); + + function line(arcs, i) { + arcs.forEach(function(a) { + if (a < 0) a = ~a; + var o = indexesByArc[a]; + if (o) o.push(i); + else indexesByArc[a] = [i]; + }); + } + + function polygon(arcs, i) { + arcs.forEach(function(arc) { line(arc, i); }); + } + + function geometry(o, i) { + if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); }); + else if (o.type in geometryType) geometryType[o.type](o.arcs, i); + } + + var geometryType = { + LineString: line, + MultiLineString: polygon, + Polygon: polygon, + MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); } + }; + + objects.forEach(geometry); + + for (var i in indexesByArc) { + for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) { + for (var k = j + 1; k < m; ++k) { + var ij = indexes[j], ik = indexes[k], n; + if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik); + if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij); + } + } + } + + return neighbors; + } + + function compareArea(a, b) { + return a[1][2] - b[1][2]; + } + + function minAreaHeap() { + var heap = {}, + array = [], + size = 0; + + heap.push = function(object) { + up(array[object._ = size] = object, size++); + return size; + }; + + heap.pop = function() { + if (size <= 0) return; + var removed = array[0], object; + if (--size > 0) object = array[size], down(array[object._ = 0] = object, 0); + return removed; + }; + + heap.remove = function(removed) { + var i = removed._, object; + if (array[i] !== removed) return; // invalid request + if (i !== --size) object = array[size], (compareArea(object, removed) < 0 ? up : down)(array[object._ = i] = object, i); + return i; + }; + + function up(object, i) { + while (i > 0) { + var j = ((i + 1) >> 1) - 1, + parent = array[j]; + if (compareArea(object, parent) >= 0) break; + array[parent._ = i] = parent; + array[object._ = i = j] = object; + } + } + + function down(object, i) { + while (true) { + var r = (i + 1) << 1, + l = r - 1, + j = i, + child = array[j]; + if (l < size && compareArea(array[l], child) < 0) child = array[j = l]; + if (r < size && compareArea(array[r], child) < 0) child = array[j = r]; + if (j === i) break; + array[child._ = i] = child; + array[object._ = i = j] = object; + } + } + + return heap; + } + + function presimplify(topology, triangleArea) { + var absolute = transformAbsolute(topology.transform), + relative = transformRelative(topology.transform), + heap = minAreaHeap(); + + if (!triangleArea) triangleArea = cartesianTriangleArea; + + topology.arcs.forEach(function(arc) { + var triangles = [], + maxArea = 0, + triangle, + i, + n, + p; + + // To store each point’s effective area, we create a new array rather than + // extending the passed-in point to workaround a Chrome/V8 bug (getting + // stuck in smi mode). For midpoints, the initial effective area of + // Infinity will be computed in the next step. + for (i = 0, n = arc.length; i < n; ++i) { + p = arc[i]; + absolute(arc[i] = [p[0], p[1], Infinity], i); + } + + for (i = 1, n = arc.length - 1; i < n; ++i) { + triangle = arc.slice(i - 1, i + 2); + triangle[1][2] = triangleArea(triangle); + triangles.push(triangle); + heap.push(triangle); + } + + for (i = 0, n = triangles.length; i < n; ++i) { + triangle = triangles[i]; + triangle.previous = triangles[i - 1]; + triangle.next = triangles[i + 1]; + } + + while (triangle = heap.pop()) { + var previous = triangle.previous, + next = triangle.next; + + // If the area of the current point is less than that of the previous point + // to be eliminated, use the latter's area instead. This ensures that the + // current point cannot be eliminated without eliminating previously- + // eliminated points. + if (triangle[1][2] < maxArea) triangle[1][2] = maxArea; + else maxArea = triangle[1][2]; + + if (previous) { + previous.next = next; + previous[2] = triangle[2]; + update(previous); + } + + if (next) { + next.previous = previous; + next[0] = triangle[0]; + update(next); + } + } + + arc.forEach(relative); + }); + + function update(triangle) { + heap.remove(triangle); + triangle[1][2] = triangleArea(triangle); + heap.push(triangle); + } + + return topology; + } + + var version = "1.6.26"; + + exports.version = version; + exports.mesh = mesh; + exports.meshArcs = meshArcs; + exports.merge = merge; + exports.mergeArcs = mergeArcs; + exports.feature = feature; + exports.neighbors = neighbors; + exports.presimplify = presimplify; + +})); + +L.TOPOJSON = L.FeatureGroup.extend({ + options: { + async: true + }, + + initialize: function (data, options) { + L.Util.setOptions(this, options); + this._topojson = data; + this._layers = {}; + + if (data) { + this.addTOPOJSON(data, options, this.options.async); + } + }, + + loadJSON: function (url, cb, options, async) { + if (async === undefined) async = this.options.async; + if (options === undefined) options = this.options; + + var req = new window.XMLHttpRequest(); + + // Check for IE8 and IE9 Fix Cors for those browsers + if (req.withCredentials === undefined && typeof window.XDomainRequest !== 'undefined') { + var xdr = new window.XDomainRequest(); + xdr.open('GET', url, async); + xdr.onprogress = function () { }; + xdr.ontimeout = function () { }; + xdr.onerror = function () { }; + xdr.onload = function () { + if (xdr.responseText) { + //var xml = new window.ActiveXObject('Microsoft.XMLDOM'); + //xml.loadJSON(xdr.responseText); + cb(xdr.responseText, options); + } + }; + setTimeout(function () { xdr.send(); }, 0); + } else { + req.open('GET', url, async); + try { + req.overrideMimeType('application/json'); // unsupported by IE + } catch (e) { } + req.onreadystatechange = function () { + if (req.readyState !== 4) return; + if (req.status === 200) cb(req.response, options); + }; + req.send(null); + } + }, + + addTOPOJSON: function (url, options, async) { + var _this = this, + cb = function (data) { _this._addTOPOJSON(data); }; + this.loadJSON(url, cb, options, async); + }, + + _addTOPOJSON: function (data) { + var layers = this.parseTOPOJSON(data); + if (!layers || !layers.length) return; + for (var i = 0; i < layers.length; i++) { + this.fire('addlayer', { + layer: layers[i] + }); + this.addLayer(layers[i]); + } + this.fire('loaded'); + }, + _addData : function (l, d) { + if ('addData' in l) l.addData(d); + if ('setGeoJSON' in l) l.setGeoJSON(d); + }, + parseTOPOJSON : function (data) { + var layers = [], + o = typeof data === 'string' ? JSON.parse(data) : data; + for (var i in o.objects) { + var layer = L.geoJson(), + ft = topojson.feature(o, o.objects[i]); + if (ft.features) this._addData(layer, ft.features); + else _this._addData(layer, ft); + layers.push(layer); + } + + return layers; + } +}); \ No newline at end of file diff --git a/www/plugins/gis/lib/leaflet/plugins/images/icon-fullscreen-2x.png b/www/plugins/gis/lib/leaflet/plugins/images/icon-fullscreen-2x.png index 7320d953bcdaf9e2ae787dbedb4a1b44393538e4..efc0dfbe88abebfca73e6b8f85d394b18ed50906 100644 GIT binary patch delta 198 zcmV;%06G8U0oMVL8Gi%-003`s(_jDq0G>%iK~#7F?Uq#m12GTd81vUm50bh>9=$nAlq$MJQBtD5(Ogt@sz;$~1kt10svzd5KP2iy zMX92=d+1_a77w$jw78+!ytApmkyJHJ&!njeq-uIOq^eyNH9uiYZv?|4i@@^c7wkuF zLHwr59}^#S@bO1Ee>wSv>lS~3OCfG`XN9l_DuFe5oaN9YJu z{3ry`LQ3lc@8EqJI9p?z1poj50DeVz$sVY;H)@WhA+rYRtyM}$C_9;$R90IdTjH3` z3iV5w$~Tk;3gvl1z5&>PEoZJ#4Cmg>tVialPL=wY?M$j~yG)&QJtKveDUqm3r4FH_ zC{%ia5JCtcy@v31ch!ukf)1dNCji^0x1dB{|7(Vbls@z z&`|W{(@5ewlDVs2scim)WuJNY99-EnlGq#s*%$CIUSKd0XO#Bf;A4>yo5jJ-^3>7K lqDa%H!S~2LIiO4_{0&ssx(O;OXk;vd$@?2>|-4B<27B literal 389 zcmV;00eb$4P)RCwBi(!WcBK^VaCdtVh%#NKSu zA%i5SRRW>O!6nemL5GHLb#dz-XlS&}HG-N02bYE>hxSN<{(uaWB*@q5d+@w*#{1)e z&&$2<-E;Tcy=UzfcLqwS41UnZSOrH7r!w}#BH5)8!wAP%g(N5OfJ3-8k2&5@m6^k$ zfim9l8Ou4&jK&!@aVwK0q#DyVENq~KnJ(L$xq=JieO7%z7ZdM8+~~~6%G&`YmvDt6 z?_6x7Q?FKt*z+E;-i!UOa}|-i)^8?TA}rR%n8{y0mH370m;8#mh{S98m4Bzbg(>#Y z#)+J`xdnY4pKv3G_N>Rm<@Y?IhdKr!D|c{-b3ImHk_C-4?$MMgf})5a4zRH0pp=yF jMC@5#&6Kp4zXA*Zr=2xzRY*n700000NkvXXu0mjfN13r$ diff --git a/www/plugins/gis/lib/leaflet/plugins/images/toggle.png b/www/plugins/gis/lib/leaflet/plugins/images/toggle.png index 205e38b83fb4ea56b02ff85e69a04b970152e77f..7a55db43c4ee0aac369a43bd9d8d8f0be8d9ba08 100755 GIT binary patch delta 176 zcmV;h08jtf0^0$QGk*XHa7bBm000ie000ie0hKEb8vptFDtD7Av$Bk;m1DJimu3b ze32#GYDL@9=p)+)NiL~oHU1VB_(BCTwJ^p zW|*w3tZY+L)6QSNe#xTiVa8_Ap+krEYH4Y)$;!&wvaqm7ntz&_`n-Ab=1g5(-R3V} zz9_$a`}V={CzLf#JxJBm2a~#lNYjsJJpQF^QU+o2UN#`BR92fq?;=L0G*8 z1JkBW>*nC#IKa%z%<%W`UwlgO8`RU&(<3A#UCW%?*U0RU>CR3kiPs3iaZ002ovPDHLkV1lI{ BkB|TW diff --git a/www/plugins/gis/lib/leaflet/plugins/images/toggle.svg b/www/plugins/gis/lib/leaflet/plugins/images/toggle.svg new file mode 100644 index 00000000..e829952b --- /dev/null +++ b/www/plugins/gis/lib/leaflet/plugins/images/toggle.svg @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/www/plugins/gis/lib/leaflet/plugins/leaflet-plugins.css b/www/plugins/gis/lib/leaflet/plugins/leaflet-plugins.css index 88c58fd3..d9bdb14e 100755 --- a/www/plugins/gis/lib/leaflet/plugins/leaflet-plugins.css +++ b/www/plugins/gis/lib/leaflet/plugins/leaflet-plugins.css @@ -1,16 +1,28 @@ /* L.Control.FullScreen */ -.fullscreen-icon { background-image: url(images/icon-fullscreen.png); } -.leaflet-retina .fullscreen-icon { background-image: url(images/icon-fullscreen-2x.png); background-size: 26px 26px; } +.fullscreen-icon { background-image: url(icon-fullscreen.png); } +.leaflet-retina .fullscreen-icon { background-image: url(icon-fullscreen-2x.png); background-size: 26px 26px; } +/* one selector per rule as explained here : http://www.sitepoint.com/html5-full-screen-api/ */ .leaflet-container:-webkit-full-screen { width: 100% !important; height: 100% !important; z-index: 99999; } +.leaflet-container:-ms-fullscreen { width: 100% !important; height: 100% !important; z-index: 99999; } +.leaflet-container:full-screen { width: 100% !important; height: 100% !important; z-index: 99999; } +.leaflet-container:fullscreen { width: 100% !important; height: 100% !important; z-index: 99999; } .leaflet-pseudo-fullscreen { position: fixed !important; width: 100% !important; height: 100% !important; top: 0px !important; left: 0px !important; z-index: 99999; } /* MiniMap Plugin */ -.leaflet-control-minimap { border: solid rgba(255, 255, 255, 1.0) 4px; box-shadow: 0 1px 5px rgba(0,0,0,0.65); border-radius: 3px; background: #f8f8f9; transition: all .2s; } -.leaflet-control-minimap a { background-color: rgba(255, 255, 255, 1.0); background-repeat: no-repeat; z-index: 99999; transition: all .2s; border-radius: 3px 0px 0px 0px; } -.leaflet-control-minimap a.minimized { -webkit-transform: rotate(180deg); transform: rotate(180deg); border-radius: 0px; } -.leaflet-control-minimap-toggle-display { background-image: url("images/toggle.png"); height: 19px; width: 19px; position: absolute; bottom: 0; right: 0; } -/* Old IE */ -.leaflet-oldie .leaflet-control-minimap { border: 1px solid #999 } -.leaflet-oldie .leaflet-control-minimap a { background-color: #fff } -.leaflet-oldie .leaflet-control-minimap a.minimized { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2) } +.leaflet-control-minimap { border: solid rgba(255,255,255,1) 4px; box-shadow: 0 1px 5px rgba(0,0,0,0.65); border-radius: 3px; background: #f8f8f9; transition: all .6s; } +.leaflet-control-minimap a { background-color: rgba(255,255,255,1); background-repeat: no-repeat; z-index: 99999; transition: all .6s; } +.leaflet-control-minimap a.minimized-bottomright { -webkit-transform: rotate(180deg); transform: rotate(180deg); border-radius: 0px; } +.leaflet-control-minimap a.minimized-topleft { -webkit-transform: rotate(0deg); transform: rotate(0deg); border-radius: 0px; } +.leaflet-control-minimap a.minimized-bottomleft { -webkit-transform: rotate(270deg); transform: rotate(270deg); border-radius: 0px; } +.leaflet-control-minimap a.minimized-topright { -webkit-transform: rotate(90deg); transform: rotate(90deg); border-radius: 0px; } +.leaflet-control-minimap-toggle-display { background-image: url("images/toggle.svg"); background-size: cover; position: absolute; border-radius: 3px 0px 0px 0px; } +.leaflet-oldie .leaflet-control-minimap-toggle-display { background-image: url("images/toggle.png"); } +.leaflet-control-minimap-toggle-display-bottomright { bottom: 0; right: 0; } +.leaflet-control-minimap-toggle-display-topleft { top: 0; left: 0; -webkit-transform: rotate(180deg); transform: rotate(180deg); } +.leaflet-control-minimap-toggle-display-bottomleft { bottom: 0; left: 0; -webkit-transform: rotate(90deg); transform: rotate(90deg); } +.leaflet-control-minimap-toggle-display-topright { top: 0; right: 0; -webkit-transform: rotate(270deg); transform: rotate(270deg); } +/* Old IE */ +.leaflet-oldie .leaflet-control-minimap { border: 1px solid #999; } +.leaflet-oldie .leaflet-control-minimap a { background-color: #fff; } +.leaflet-oldie .leaflet-control-minimap a.minimized { filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); } diff --git a/www/plugins/gis/lib/leaflet/plugins/leaflet-providers.js b/www/plugins/gis/lib/leaflet/plugins/leaflet-providers.js index bc82990d..22e2cbdb 100644 --- a/www/plugins/gis/lib/leaflet/plugins/leaflet-providers.js +++ b/www/plugins/gis/lib/leaflet/plugins/leaflet-providers.js @@ -48,8 +48,6 @@ url: variant.url || provider.url, options: L.Util.extend({}, provider.options, variantOptions) }; - } else if (typeof provider.url === 'function') { - provider.url = provider.url(parts.splice(1, parts.length - 1).join('.')); } var forceHTTP = window.location.protocol === 'file:' || provider.options.forceHTTP; @@ -118,13 +116,14 @@ } }, France: { - url: 'http://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', + url: '//{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', options: { + maxZoom: 20, attribution: '© Openstreetmap France | {attribution.OpenStreetMap}' } }, HOT: { - url: 'http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', + url: '//{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', options: { attribution: '{attribution.OpenStreetMap}, Tiles courtesy of Humanitarian OpenStreetMap Team' } @@ -140,7 +139,7 @@ OpenTopoMap: { url: '//{s}.tile.opentopomap.org/{z}/{x}/{y}.png', options: { - maxZoom: 16, + maxZoom: 17, attribution: 'Map data: {attribution.OpenStreetMap}, SRTM | Map style: © OpenTopoMap (CC-BY-SA)' } }, @@ -200,7 +199,7 @@ } }, Hydda: { - url: 'http://{s}.tile.openstreetmap.se/hydda/{variant}/{z}/{x}/{y}.png', + url: '//{s}.tile.openstreetmap.se/hydda/{variant}/{z}/{x}/{y}.png', options: { variant: 'full', attribution: 'Tiles courtesy of OpenStreetMap Sweden — Map data {attribution.OpenStreetMap}' @@ -211,39 +210,6 @@ RoadsAndLabels: 'roads_and_labels' } }, - MapQuestOpen: { - /* Mapquest does support https, but with a different subdomain: - * https://otile{s}-s.mqcdn.com/tiles/1.0.0/{type}/{z}/{x}/{y}.{ext} - * which makes implementing protocol relativity impossible. - */ - url: 'http://otile{s}.mqcdn.com/tiles/1.0.0/{type}/{z}/{x}/{y}.{ext}', - options: { - type: 'map', - ext: 'jpg', - attribution: - 'Tiles Courtesy of MapQuest — ' + - 'Map data {attribution.OpenStreetMap}', - subdomains: '1234' - }, - variants: { - OSM: {}, - Aerial: { - options: { - type: 'sat', - attribution: - 'Tiles Courtesy of MapQuest — ' + - 'Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency' - } - }, - HybridOverlay: { - options: { - type: 'hyb', - ext: 'png', - opacity: 0.9 - } - } - } - }, MapBox: { url: '//api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', options: { @@ -283,17 +249,15 @@ Terrain: { options: { variant: 'terrain', - minZoom: 4, - maxZoom: 18, - bounds: [[22, -132], [70, -56]] + minZoom: 0, + maxZoom: 18 } }, TerrainBackground: { options: { variant: 'terrain-background', - minZoom: 4, - maxZoom: 18, - bounds: [[22, -132], [70, -56]] + minZoom: 0, + maxZoom: 18 } }, TopOSMRelief: { diff --git a/www/plugins/gis/lib/leaflet/plugins/leaflet.markercluster-src.js b/www/plugins/gis/lib/leaflet/plugins/leaflet.markercluster-src.js index 40433162..b7aad0e5 100644 --- a/www/plugins/gis/lib/leaflet/plugins/leaflet.markercluster-src.js +++ b/www/plugins/gis/lib/leaflet/plugins/leaflet.markercluster-src.js @@ -24,6 +24,11 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ // is the default behaviour for performance reasons. removeOutsideVisibleBounds: true, + // Set to false to disable all animations (zoom and spiderfy). + // If false, option animateAddingMarkers below has no effect. + // If L.DomUtil.TRANSITION is falsy, this option has no effect. + animate: true, + //Whether to animate adding markers after adding the MarkerClusterGroup to the map // If you are adding individual markers set to true, if adding bulk markers leave false for massive performance gains. animateAddingMarkers: false, @@ -31,6 +36,9 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ //Increase to increase the distance away that spiderfied markers appear from the center spiderfyDistanceMultiplier: 1, + // Make it possible to specify a polyline options on a spider leg + spiderLegPolylineOptions: { weight: 1.5, color: '#222', opacity: 0.5 }, + // When bulk adding layers, adds markers in chunks. Means addLayers may not add all the layers in the call, others will be loaded during setTimeouts chunkedLoading: false, chunkInterval: 200, // process markers for a maximum of ~ n milliseconds (then trigger the chunkProgress callback) @@ -60,6 +68,12 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ this._currentShownBounds = null; this._queue = []; + + // Hook the appropriate animation methods. + var animate = L.DomUtil.TRANSITION && this.options.animate; + L.extend(this, animate ? this._withAnimation : this._noAnimation); + // Remember which MarkerCluster class to instantiate (animated or not). + this._markerCluster = animate ? L.MarkerCluster : L.MarkerClusterNonAnimated; }, addLayer: function (layer) { @@ -96,6 +110,9 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ this._addLayer(layer, this._maxZoom); + // Refresh bounds and weighted positions. + this._topClusterLevel._recalculateBounds(); + //Work out what is visible var visibleLayer = layer, currentZoom = this._map.getZoom(); @@ -151,10 +168,13 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ //Remove the marker from clusters this._removeLayer(layer, true); + // Refresh bounds and weighted positions. + this._topClusterLevel._recalculateBounds(); + if (this._featureGroup.hasLayer(layer)) { this._featureGroup.removeLayer(layer); - if (layer.setOpacity) { - layer.setOpacity(1); + if (layer.clusterShow) { + layer.clusterShow(); } } @@ -213,7 +233,12 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ chunkProgress(offset, layersArray.length, (new Date()).getTime() - started); } + // Completed processing all markers. if (offset === layersArray.length) { + + // Refresh bounds and weighted positions. + this._topClusterLevel._recalculateBounds(); + //Update the icons of all those visible clusters that were affected this._featureGroup.eachLayer(function (c) { if (c instanceof L.MarkerCluster && c._iconNeedsUpdate) { @@ -261,10 +286,21 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ m = layersArray[i]; this._arraySplice(this._needsClustering, m); npg.removeLayer(m); + if (this.hasLayer(m)) { + this._needsRemoving.push(m); + } } return this; } + if (this._unspiderfy) { + this._unspiderfy(); + for (i = 0, l = layersArray.length; i < l; i++) { + m = layersArray[i]; + this._unspiderfyLayer(m); + } + } + for (i = 0, l = layersArray.length; i < l; i++) { m = layersArray[i]; @@ -277,12 +313,15 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ if (fg.hasLayer(m)) { fg.removeLayer(m); - if (m.setOpacity) { - m.setOpacity(1); + if (m.clusterShow) { + m.clusterShow(); } } } + // Refresh bounds and weighted positions. + this._topClusterLevel._recalculateBounds(); + //Fix up the clusters and markers on the map this._topClusterLevel._recursivelyAddChildrenToMap(null, this._zoom, this._currentShownBounds); @@ -371,6 +410,8 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ //Overrides LayerGroup.getLayer, WARNING: Really bad performance getLayer: function (id) { var result = null; + + id = parseInt(id, 10); this.eachLayer(function (l) { if (L.stamp(l) === id) { @@ -407,6 +448,10 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ //Zoom down to show the given layer (spiderfying if necessary) then calls the callback zoomToShowLayer: function (layer, callback) { + + if (typeof callback !== 'function') { + callback = function () {}; + } var showMarker = function () { if ((layer._icon || layer.__parent._icon) && !this._inZoomAnimation) { @@ -416,12 +461,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ if (layer._icon) { callback(); } else if (layer.__parent._icon) { - var afterSpiderfy = function () { - this.off('spiderfied', afterSpiderfy, this); - callback(); - }; - - this.on('spiderfied', afterSpiderfy, this); + this.once('spiderfied', callback, this); layer.__parent.spiderfy(); } } @@ -468,6 +508,8 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ this._generateInitialClusters(); } + this._maxLat = map.options.crs.projection.MAX_LATITUDE; + for (i = 0, l = this._needsRemoving.length; i < l; i++) { layer = this._needsRemoving[i]; this._removeLayer(layer, true); @@ -507,7 +549,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ this._spiderfierOnRemove(); } - + delete this._maxLat; //Clean up all the layers we added to the map this._hideCoverage(); @@ -537,6 +579,23 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ } }, + /** + * Removes a marker from all _gridUnclustered zoom levels, starting at the supplied zoom. + * @param marker to be removed from _gridUnclustered. + * @param z integer bottom start zoom level (included) + * @private + */ + _removeFromGridUnclustered: function (marker, z) { + var map = this._map, + gridUnclustered = this._gridUnclustered; + + for (; z >= 0; z--) { + if (!gridUnclustered[z].removeObject(marker, map.project(marker.getLatLng(), z))) { + break; + } + } + }, + //Internal function for removing a marker from everything. //dontUpdateMap: set to true if you will handle updating the map manually (for bulk functions) _removeLayer: function (marker, removeFromDistanceGrid, dontUpdateMap) { @@ -547,11 +606,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ //Remove the marker from distance clusters it might be in if (removeFromDistanceGrid) { - for (var z = this._maxZoom; z >= 0; z--) { - if (!gridUnclustered[z].removeObject(marker, map.project(marker.getLatLng(), z))) { - break; - } - } + this._removeFromGridUnclustered(marker, this._maxZoom); } //Work our way up the clusters removing them as we go if required @@ -564,6 +619,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ while (cluster) { cluster._childCount--; + cluster._boundsNeedUpdate = true; if (cluster._zoom < 0) { //Top level, do nothing @@ -589,7 +645,6 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ } } } else { - cluster._recalculateBounds(); if (!dontUpdateMap || !cluster._icon) { cluster._updateIcon(); } @@ -659,18 +714,25 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ }, _zoomOrSpiderfy: function (e) { - var map = this._map; - if (map.getMaxZoom() === map.getZoom()) { + var cluster = e.layer, + bottomCluster = cluster; + + while (bottomCluster._childClusters.length === 1) { + bottomCluster = bottomCluster._childClusters[0]; + } + + if (bottomCluster._zoom === this._maxZoom && bottomCluster._childCount === cluster._childCount) { + // All child markers are contained in a single cluster from this._maxZoom to this cluster. if (this.options.spiderfyOnMaxZoom) { - e.layer.spiderfy(); + cluster.spiderfy(); } } else if (this.options.zoomToBoundsOnClick) { - e.layer.zoomToBounds(); + cluster.zoomToBounds(); } // Focus the map again for keyboard users. if (e.originalEvent && e.originalEvent.keyCode === 13) { - map._container.focus(); + this._map._container.focus(); } }, @@ -760,7 +822,8 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ this._gridUnclustered[zoom] = new L.DistanceGrid(radiusFn(zoom)); } - this._topClusterLevel = new L.MarkerCluster(this, -1); + // Instantiate the appropriate L.MarkerCluster class (animated or not). + this._topClusterLevel = new this._markerCluster(this, -1); }, //Zoom: Zoom to start adding at (Pass this._maxZoom to start at the bottom) @@ -770,14 +833,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ markerPoint, z; if (this.options.singleMarkerMode) { - layer.options.icon = this.options.iconCreateFunction({ - getChildCount: function () { - return 1; - }, - getAllChildMarkers: function () { - return [layer]; - } - }); + this._overrideMarkerIcon(layer); } //Find the lowest zoom level to slot this one in @@ -802,7 +858,7 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ //Create new cluster with these 2 in it - var newCluster = new L.MarkerCluster(this, zoom, closest, layer); + var newCluster = new this._markerCluster(this, zoom, closest, layer); gridClusters[zoom].addObject(newCluster, this._map.project(newCluster._cLatLng, zoom)); closest.__parent = newCluster; layer.__parent = newCluster; @@ -810,17 +866,13 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ //First create any new intermediate parent clusters that don't exist var lastParent = newCluster; for (z = zoom - 1; z > parent._zoom; z--) { - lastParent = new L.MarkerCluster(this, z, lastParent); + lastParent = new this._markerCluster(this, z, lastParent); gridClusters[z].addObject(lastParent, this._map.project(closest.getLatLng(), z)); } parent._addChild(lastParent); //Remove closest from this zoom level and any above that it is in, replace with newCluster - for (z = zoom; z >= 0; z--) { - if (!gridUnclustered[z].removeObject(closest, this._map.project(closest.getLatLng(), z))) { - break; - } - } + this._removeFromGridUnclustered(closest, zoom); return; } @@ -876,19 +928,37 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ //Gets the maps visible bounds expanded in each direction by the size of the screen (so the user cannot see an area we do not cover in one pan) _getExpandedVisibleBounds: function () { if (!this.options.removeOutsideVisibleBounds) { - return this._map.getBounds(); + return this._mapBoundsInfinite; + } else if (L.Browser.mobile) { + return this._checkBoundsMaxLat(this._map.getBounds()); + } + + return this._checkBoundsMaxLat(this._map.getBounds().pad(1)); // Padding expands the bounds by its own dimensions but scaled with the given factor. + }, + + /** + * Expands the latitude to Infinity (or -Infinity) if the input bounds reach the map projection maximum defined latitude + * (in the case of Web/Spherical Mercator, it is 85.0511287798 / see https://en.wikipedia.org/wiki/Web_Mercator#Formulas). + * Otherwise, the removeOutsideVisibleBounds option will remove markers beyond that limit, whereas the same markers without + * this option (or outside MCG) will have their position floored (ceiled) by the projection and rendered at that limit, + * making the user think that MCG "eats" them and never displays them again. + * @param bounds L.LatLngBounds + * @returns {L.LatLngBounds} + * @private + */ + _checkBoundsMaxLat: function (bounds) { + var maxLat = this._maxLat; + + if (maxLat !== undefined) { + if (bounds.getNorth() >= maxLat) { + bounds._northEast.lat = Infinity; + } + if (bounds.getSouth() <= -maxLat) { + bounds._southWest.lat = -Infinity; + } } - var map = this._map, - bounds = map.getBounds(), - sw = bounds._southWest, - ne = bounds._northEast, - latDiff = L.Browser.mobile ? 0 : Math.abs(sw.lat - ne.lat), - lngDiff = L.Browser.mobile ? 0 : Math.abs(sw.lng - ne.lng); - - return new L.LatLngBounds( - new L.LatLng(sw.lat - latDiff, sw.lng - lngDiff, true), - new L.LatLng(ne.lat + latDiff, ne.lng + lngDiff, true)); + return bounds; }, //Shared animation code @@ -904,117 +974,167 @@ L.MarkerClusterGroup = L.FeatureGroup.extend({ } else { newCluster._updateIcon(); } + }, + + /** + * Implements the singleMarkerMode option. + * @param layer Marker to re-style using the Clusters iconCreateFunction. + * @returns {L.Icon} The newly created icon. + * @private + */ + _overrideMarkerIcon: function (layer) { + var icon = layer.options.icon = this.options.iconCreateFunction({ + getChildCount: function () { + return 1; + }, + getAllChildMarkers: function () { + return [layer]; + } + }); + + return icon; } }); -L.MarkerClusterGroup.include(!L.DomUtil.TRANSITION ? { - - //Non Animated versions of everything - _animationStart: function () { - //Do nothing... - }, - _animationZoomIn: function (previousZoomLevel, newZoomLevel) { - this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel); - this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); +// Constant bounds used in case option "removeOutsideVisibleBounds" is set to false. +L.MarkerClusterGroup.include({ + _mapBoundsInfinite: new L.LatLngBounds(new L.LatLng(-Infinity, -Infinity), new L.LatLng(Infinity, Infinity)) +}); - //We didn't actually animate, but we use this event to mean "clustering animations have finished" - this.fire('animationend'); - }, - _animationZoomOut: function (previousZoomLevel, newZoomLevel) { - this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel); - this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); +L.MarkerClusterGroup.include({ + _noAnimation: { + //Non Animated versions of everything + _animationStart: function () { + //Do nothing... + }, + _animationZoomIn: function (previousZoomLevel, newZoomLevel) { + this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel); + this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); - //We didn't actually animate, but we use this event to mean "clustering animations have finished" - this.fire('animationend'); - }, - _animationAddLayer: function (layer, newCluster) { - this._animationAddLayerNonAnimated(layer, newCluster); - } -} : { + //We didn't actually animate, but we use this event to mean "clustering animations have finished" + this.fire('animationend'); + }, + _animationZoomOut: function (previousZoomLevel, newZoomLevel) { + this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel); + this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); - //Animated versions here - _animationStart: function () { - this._map._mapPane.className += ' leaflet-cluster-anim'; - this._inZoomAnimation++; - }, - _animationEnd: function () { - if (this._map) { - this._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', ''); + //We didn't actually animate, but we use this event to mean "clustering animations have finished" + this.fire('animationend'); + }, + _animationAddLayer: function (layer, newCluster) { + this._animationAddLayerNonAnimated(layer, newCluster); } - this._inZoomAnimation--; - this.fire('animationend'); }, - _animationZoomIn: function (previousZoomLevel, newZoomLevel) { - var bounds = this._getExpandedVisibleBounds(), - fg = this._featureGroup, - i; - - //Add all children of current clusters to map and remove those clusters from map - this._topClusterLevel._recursively(bounds, previousZoomLevel, 0, function (c) { - var startPos = c._latlng, - markers = c._markers, - m; + _withAnimation: { + //Animated versions here + _animationStart: function () { + this._map._mapPane.className += ' leaflet-cluster-anim'; + this._inZoomAnimation++; + }, + _animationZoomIn: function (previousZoomLevel, newZoomLevel) { + var bounds = this._getExpandedVisibleBounds(), + fg = this._featureGroup, + i; - if (!bounds.contains(startPos)) { - startPos = null; - } + //Add all children of current clusters to map and remove those clusters from map + this._topClusterLevel._recursively(bounds, previousZoomLevel, 0, function (c) { + var startPos = c._latlng, + markers = c._markers, + m; - if (c._isSingleParent() && previousZoomLevel + 1 === newZoomLevel) { //Immediately add the new child and remove us - fg.removeLayer(c); - c._recursivelyAddChildrenToMap(null, newZoomLevel, bounds); - } else { - //Fade out old cluster - c.setOpacity(0); - c._recursivelyAddChildrenToMap(startPos, newZoomLevel, bounds); - } + if (!bounds.contains(startPos)) { + startPos = null; + } - //Remove all markers that aren't visible any more - //TODO: Do we actually need to do this on the higher levels too? - for (i = markers.length - 1; i >= 0; i--) { - m = markers[i]; - if (!bounds.contains(m._latlng)) { - fg.removeLayer(m); + if (c._isSingleParent() && previousZoomLevel + 1 === newZoomLevel) { //Immediately add the new child and remove us + fg.removeLayer(c); + c._recursivelyAddChildrenToMap(null, newZoomLevel, bounds); + } else { + //Fade out old cluster + c.clusterHide(); + c._recursivelyAddChildrenToMap(startPos, newZoomLevel, bounds); } - } - }); + //Remove all markers that aren't visible any more + //TODO: Do we actually need to do this on the higher levels too? + for (i = markers.length - 1; i >= 0; i--) { + m = markers[i]; + if (!bounds.contains(m._latlng)) { + fg.removeLayer(m); + } + } - this._forceLayout(); + }); - //Update opacities - this._topClusterLevel._recursivelyBecomeVisible(bounds, newZoomLevel); - //TODO Maybe? Update markers in _recursivelyBecomeVisible - fg.eachLayer(function (n) { - if (!(n instanceof L.MarkerCluster) && n._icon) { - n.setOpacity(1); - } - }); + this._forceLayout(); - //update the positions of the just added clusters/markers - this._topClusterLevel._recursively(bounds, previousZoomLevel, newZoomLevel, function (c) { - c._recursivelyRestoreChildPositions(newZoomLevel); - }); + //Update opacities + this._topClusterLevel._recursivelyBecomeVisible(bounds, newZoomLevel); + //TODO Maybe? Update markers in _recursivelyBecomeVisible + fg.eachLayer(function (n) { + if (!(n instanceof L.MarkerCluster) && n._icon) { + n.clusterShow(); + } + }); - //Remove the old clusters and close the zoom animation - this._enqueue(function () { //update the positions of the just added clusters/markers - this._topClusterLevel._recursively(bounds, previousZoomLevel, 0, function (c) { - fg.removeLayer(c); - c.setOpacity(1); + this._topClusterLevel._recursively(bounds, previousZoomLevel, newZoomLevel, function (c) { + c._recursivelyRestoreChildPositions(newZoomLevel); }); - this._animationEnd(); - }); - }, + //Remove the old clusters and close the zoom animation + this._enqueue(function () { + //update the positions of the just added clusters/markers + this._topClusterLevel._recursively(bounds, previousZoomLevel, 0, function (c) { + fg.removeLayer(c); + c.clusterShow(); + }); + + this._animationEnd(); + }); + }, + + _animationZoomOut: function (previousZoomLevel, newZoomLevel) { + this._animationZoomOutSingle(this._topClusterLevel, previousZoomLevel - 1, newZoomLevel); + + //Need to add markers for those that weren't on the map before but are now + this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); + //Remove markers that were on the map before but won't be now + this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel, this._getExpandedVisibleBounds()); + }, + _animationAddLayer: function (layer, newCluster) { + var me = this, + fg = this._featureGroup; + + fg.addLayer(layer); + if (newCluster !== layer) { + if (newCluster._childCount > 2) { //Was already a cluster - _animationZoomOut: function (previousZoomLevel, newZoomLevel) { - this._animationZoomOutSingle(this._topClusterLevel, previousZoomLevel - 1, newZoomLevel); + newCluster._updateIcon(); + this._forceLayout(); + this._animationStart(); - //Need to add markers for those that weren't on the map before but are now - this._topClusterLevel._recursivelyAddChildrenToMap(null, newZoomLevel, this._getExpandedVisibleBounds()); - //Remove markers that were on the map before but won't be now - this._topClusterLevel._recursivelyRemoveChildrenFromMap(this._currentShownBounds, previousZoomLevel, this._getExpandedVisibleBounds()); + layer._setPos(this._map.latLngToLayerPoint(newCluster.getLatLng())); + layer.clusterHide(); + + this._enqueue(function () { + fg.removeLayer(layer); + layer.clusterShow(); + + me._animationEnd(); + }); + + } else { //Just became a cluster + this._forceLayout(); + + me._animationStart(); + me._animationZoomOutSingle(newCluster, this._map.getMaxZoom(), this._map.getZoom()); + } + } + } }, + + // Private methods for animated versions. _animationZoomOutSingle: function (cluster, previousZoomLevel, newZoomLevel) { var bounds = this._getExpandedVisibleBounds(); @@ -1036,8 +1156,8 @@ L.MarkerClusterGroup.include(!L.DomUtil.TRANSITION ? { var m = cluster._markers[0]; //If we were in a cluster animation at the time then the opacity and position of our child could be wrong now, so fix it m.setLatLng(m.getLatLng()); - if (m.setOpacity) { - m.setOpacity(1); + if (m.clusterShow) { + m.clusterShow(); } } else { cluster._recursively(bounds, newZoomLevel, 0, function (c) { @@ -1047,35 +1167,13 @@ L.MarkerClusterGroup.include(!L.DomUtil.TRANSITION ? { me._animationEnd(); }); }, - _animationAddLayer: function (layer, newCluster) { - var me = this, - fg = this._featureGroup; - - fg.addLayer(layer); - if (newCluster !== layer) { - if (newCluster._childCount > 2) { //Was already a cluster - - newCluster._updateIcon(); - this._forceLayout(); - this._animationStart(); - - layer._setPos(this._map.latLngToLayerPoint(newCluster.getLatLng())); - layer.setOpacity(0); - - this._enqueue(function () { - fg.removeLayer(layer); - layer.setOpacity(1); - me._animationEnd(); - }); - - } else { //Just became a cluster - this._forceLayout(); - - me._animationStart(); - me._animationZoomOutSingle(newCluster, this._map.getMaxZoom(), this._map.getZoom()); - } + _animationEnd: function () { + if (this._map) { + this._map._mapPane.className = this._map._mapPane.className.replace(' leaflet-cluster-anim', ''); } + this._inZoomAnimation--; + this.fire('animationend'); }, //Force a browser layout of stuff in the map @@ -1106,6 +1204,7 @@ L.MarkerCluster = L.Marker.extend({ this._childClusters = []; this._childCount = 0; this._iconNeedsUpdate = true; + this._boundsNeedUpdate = true; this._bounds = new L.LatLngBounds(); @@ -1194,7 +1293,9 @@ L.MarkerCluster = L.Marker.extend({ _addChild: function (new1, isNotificationFromChild) { this._iconNeedsUpdate = true; - this._expandBounds(new1); + + this._boundsNeedUpdate = true; + this._setClusterCenter(new1); if (new1 instanceof L.MarkerCluster) { if (!isNotificationFromChild) { @@ -1214,34 +1315,85 @@ L.MarkerCluster = L.Marker.extend({ } }, - //Expand our bounds and tell our parent to - _expandBounds: function (marker) { - var addedCount, - addedLatLng = marker._wLatLng || marker._latlng; + /** + * Makes sure the cluster center is set. If not, uses the child center if it is a cluster, or the marker position. + * @param child L.MarkerCluster|L.Marker that will be used as cluster center if not defined yet. + * @private + */ + _setClusterCenter: function (child) { + if (!this._cLatLng) { + // when clustering, take position of the first point as the cluster center + this._cLatLng = child._cLatLng || child._latlng; + } + }, + + /** + * Assigns impossible bounding values so that the next extend entirely determines the new bounds. + * This method avoids having to trash the previous L.LatLngBounds object and to create a new one, which is much slower for this class. + * As long as the bounds are not extended, most other methods would probably fail, as they would with bounds initialized but not extended. + * @private + */ + _resetBounds: function () { + var bounds = this._bounds; - if (marker instanceof L.MarkerCluster) { - this._bounds.extend(marker._bounds); - addedCount = marker._childCount; - } else { - this._bounds.extend(addedLatLng); - addedCount = 1; + if (bounds._southWest) { + bounds._southWest.lat = Infinity; + bounds._southWest.lng = Infinity; } + if (bounds._northEast) { + bounds._northEast.lat = -Infinity; + bounds._northEast.lng = -Infinity; + } + }, - if (!this._cLatLng) { - // when clustering, take position of the first point as the cluster center - this._cLatLng = marker._cLatLng || addedLatLng; + _recalculateBounds: function () { + var markers = this._markers, + childClusters = this._childClusters, + latSum = 0, + lngSum = 0, + totalCount = this._childCount, + i, child, childLatLng, childCount; + + // Case where all markers are removed from the map and we are left with just an empty _topClusterLevel. + if (totalCount === 0) { + return; } - // when showing clusters, take weighted average of all points as cluster center - var totalCount = this._childCount + addedCount; + // Reset rather than creating a new object, for performance. + this._resetBounds(); - //Calculate weighted latlng for display - if (!this._wLatLng) { - this._latlng = this._wLatLng = new L.LatLng(addedLatLng.lat, addedLatLng.lng); - } else { - this._wLatLng.lat = (addedLatLng.lat * addedCount + this._wLatLng.lat * this._childCount) / totalCount; - this._wLatLng.lng = (addedLatLng.lng * addedCount + this._wLatLng.lng * this._childCount) / totalCount; + // Child markers. + for (i = 0; i < markers.length; i++) { + childLatLng = markers[i]._latlng; + + this._bounds.extend(childLatLng); + + latSum += childLatLng.lat; + lngSum += childLatLng.lng; + } + + // Child clusters. + for (i = 0; i < childClusters.length; i++) { + child = childClusters[i]; + + // Re-compute child bounds and weighted position first if necessary. + if (child._boundsNeedUpdate) { + child._recalculateBounds(); + } + + this._bounds.extend(child._bounds); + + childLatLng = child._wLatLng; + childCount = child._childCount; + + latSum += childLatLng.lat * childCount; + lngSum += childLatLng.lng * childCount; } + + this._latlng = this._wLatLng = new L.LatLng(latSum / totalCount, lngSum / totalCount); + + // Reset dirty flag. + this._boundsNeedUpdate = false; }, //Set our markers position as given and add it to the map @@ -1264,7 +1416,7 @@ L.MarkerCluster = L.Marker.extend({ //Only do it if the icon is still on the map if (m._icon) { m._setPos(center); - m.setOpacity(0); + m.clusterHide(); } } }, @@ -1275,7 +1427,7 @@ L.MarkerCluster = L.Marker.extend({ cm = childClusters[j]; if (cm._icon) { cm._setPos(center); - cm.setOpacity(0); + cm.clusterHide(); } } } @@ -1290,10 +1442,10 @@ L.MarkerCluster = L.Marker.extend({ //TODO: depthToAnimateIn affects _isSingleParent, if there is a multizoom we may/may not be. //As a hack we only do a animation free zoom on a single level zoom, if someone does multiple levels then we always animate if (c._isSingleParent() && previousZoomLevel - 1 === newZoomLevel) { - c.setOpacity(1); + c.clusterShow(); c._recursivelyRemoveChildrenFromMap(bounds, previousZoomLevel); //Immediately remove our children as we are replacing them. TODO previousBounds not bounds } else { - c.setOpacity(0); + c.clusterHide(); } c._addToMap(); @@ -1303,7 +1455,7 @@ L.MarkerCluster = L.Marker.extend({ _recursivelyBecomeVisible: function (bounds, zoomLevel) { this._recursively(bounds, 0, zoomLevel, null, function (c) { - c.setOpacity(1); + c.clusterShow(); }); }, @@ -1326,8 +1478,8 @@ L.MarkerCluster = L.Marker.extend({ nm._backupLatlng = nm.getLatLng(); nm.setLatLng(startPos); - if (nm.setOpacity) { - nm.setOpacity(0); + if (nm.clusterHide) { + nm.clusterHide(); } } @@ -1379,8 +1531,8 @@ L.MarkerCluster = L.Marker.extend({ m = c._markers[i]; if (!exceptBounds || !exceptBounds.contains(m._latlng)) { c._group._featureGroup.removeLayer(m); - if (m.setOpacity) { - m.setOpacity(1); + if (m.clusterShow) { + m.clusterShow(); } } } @@ -1391,8 +1543,8 @@ L.MarkerCluster = L.Marker.extend({ m = c._childClusters[i]; if (!exceptBounds || !exceptBounds.contains(m._latlng)) { c._group._featureGroup.removeLayer(m); - if (m.setOpacity) { - m.setOpacity(1); + if (m.clusterShow) { + m.clusterShow(); } } } @@ -1409,7 +1561,7 @@ L.MarkerCluster = L.Marker.extend({ _recursively: function (boundsToApplyTo, zoomLevelToStart, zoomLevelToStop, runAtEveryLevel, runAtBottomLevel) { var childClusters = this._childClusters, zoom = this._zoom, - i, c; + i, c; if (zoomLevelToStart > zoom) { //Still going down to required depth, just recurse to child clusters for (i = childClusters.length - 1; i >= 0; i--) { @@ -1439,23 +1591,6 @@ L.MarkerCluster = L.Marker.extend({ } }, - _recalculateBounds: function () { - var markers = this._markers, - childClusters = this._childClusters, - i; - - this._bounds = new L.LatLngBounds(); - delete this._wLatLng; - - for (i = markers.length - 1; i >= 0; i--) { - this._expandBounds(markers[i]); - } - for (i = childClusters.length - 1; i >= 0; i--) { - this._expandBounds(childClusters[i]); - } - }, - - //Returns true if we are the parent of only one cluster and that cluster is the same as us _isSingleParent: function () { //Don't need to check this._markers as the rest won't work if there are any @@ -1465,6 +1600,34 @@ L.MarkerCluster = L.Marker.extend({ +/* +* Extends L.Marker to include two extra methods: clusterHide and clusterShow. +* +* They work as setOpacity(0) and setOpacity(1) respectively, but +* they will remember the marker's opacity when hiding and showing it again. +* +*/ + + +L.Marker.include({ + + clusterHide: function () { + this.options.opacityWhenUnclustered = this.options.opacity || 1; + return this.setOpacity(0); + }, + + clusterShow: function () { + var ret = this.setOpacity(this.options.opacity || this.options.opacityWhenUnclustered); + delete this.options.opacityWhenUnclustered; + return ret; + } + +}); + + + + + L.DistanceGrid = function (cellSize) { this._cellSize = cellSize; this._sqCellSize = cellSize * cellSize; @@ -1692,20 +1855,40 @@ Retrieved from: http://en.literateprograms.org/Quickhull_(Javascript)?oldid=1843 getConvexHull: function (latLngs) { // find first baseline var maxLat = false, minLat = false, + maxLng = false, minLng = false, + maxLatPt = null, minLatPt = null, + maxLngPt = null, minLngPt = null, maxPt = null, minPt = null, i; for (i = latLngs.length - 1; i >= 0; i--) { var pt = latLngs[i]; if (maxLat === false || pt.lat > maxLat) { - maxPt = pt; + maxLatPt = pt; maxLat = pt.lat; } if (minLat === false || pt.lat < minLat) { - minPt = pt; + minLatPt = pt; minLat = pt.lat; } + if (maxLng === false || pt.lng > maxLng) { + maxLngPt = pt; + maxLng = pt.lng; + } + if (minLng === false || pt.lng < minLng) { + minLngPt = pt; + minLng = pt.lng; + } + } + + if (minLat !== maxLat) { + minPt = minLatPt; + maxPt = maxLatPt; + } else { + minPt = minLngPt; + maxPt = maxLngPt; } + var ch = [].concat(this.buildConvexHull([minPt, maxPt], latLngs), this.buildConvexHull([maxPt, minPt], latLngs)); return ch; @@ -1764,7 +1947,7 @@ L.MarkerCluster.include({ if (childMarkers.length >= this._circleSpiralSwitchover) { positions = this._generatePointsSpiral(childMarkers.length, center); } else { - center.y += 10; //Otherwise circles look wrong + center.y += 10; // Otherwise circles look wrong => hack for standard blue icon, renders differently for other icons. positions = this._generatePointsCircle(childMarkers.length, center); } @@ -1799,19 +1982,21 @@ L.MarkerCluster.include({ }, _generatePointsSpiral: function (count, centerPt) { - var legLength = this._group.options.spiderfyDistanceMultiplier * this._spiralLengthStart, - separation = this._group.options.spiderfyDistanceMultiplier * this._spiralFootSeparation, - lengthFactor = this._group.options.spiderfyDistanceMultiplier * this._spiralLengthFactor, + var spiderfyDistanceMultiplier = this._group.options.spiderfyDistanceMultiplier, + legLength = spiderfyDistanceMultiplier * this._spiralLengthStart, + separation = spiderfyDistanceMultiplier * this._spiralFootSeparation, + lengthFactor = spiderfyDistanceMultiplier * this._spiralLengthFactor * this._2PI, angle = 0, res = [], i; res.length = count; + // Higher index, closer position to cluster center. for (i = count - 1; i >= 0; i--) { angle += separation / legLength + i * 0.0005; res[i] = new L.Point(centerPt.x + legLength * Math.cos(angle), centerPt.y + legLength * Math.sin(angle))._round(); - legLength += this._2PI * lengthFactor / angle; + legLength += lengthFactor / angle; } return res; }, @@ -1842,23 +2027,36 @@ L.MarkerCluster.include({ delete m._spiderLeg; } } - + + group.fire('unspiderfied', { + cluster: this, + markers: childMarkers + }); group._spiderfied = null; } }); -L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { - //Non Animated versions of everything +//Non Animated versions of everything +L.MarkerClusterNonAnimated = L.MarkerCluster.extend({ _animationSpiderfy: function (childMarkers, positions) { var group = this._group, map = group._map, fg = group._featureGroup, + legOptions = this._group.options.spiderLegPolylineOptions, i, m, leg, newPos; - for (i = childMarkers.length - 1; i >= 0; i--) { + // Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition. + // The reverse order trick no longer improves performance on modern browsers. + for (i = 0; i < childMarkers.length; i++) { newPos = map.layerPointToLatLng(positions[i]); m = childMarkers[i]; + // Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it. + leg = new L.Polyline([this._latlng, newPos], legOptions); + map.addLayer(leg); + m._spiderLeg = leg; + + // Now add the marker. m._preSpiderfyLatlng = m._latlng; m.setLatLng(newPos); if (m.setZIndexOffset) { @@ -1866,58 +2064,91 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { } fg.addLayer(m); - - - leg = new L.Polyline([this._latlng, newPos], { weight: 1.5, color: '#222' }); - map.addLayer(leg); - m._spiderLeg = leg; } this.setOpacity(0.3); - group.fire('spiderfied'); + group.fire('spiderfied', { + cluster: this, + markers: childMarkers + }); }, _animationUnspiderfy: function () { this._noanimationUnspiderfy(); } -} : { - //Animated versions here - SVG_ANIMATION: (function () { - return document.createElementNS('http://www.w3.org/2000/svg', 'animate').toString().indexOf('SVGAnimate') > -1; - }()), +}); + +//Animated versions here +L.MarkerCluster.include({ _animationSpiderfy: function (childMarkers, positions) { var me = this, group = this._group, map = group._map, fg = group._featureGroup, - thisLayerPos = map.latLngToLayerPoint(this._latlng), - i, m, leg, newPos; + thisLayerLatLng = this._latlng, + thisLayerPos = map.latLngToLayerPoint(thisLayerLatLng), + svg = L.Path.SVG, + legOptions = L.extend({}, this._group.options.spiderLegPolylineOptions), // Copy the options so that we can modify them for animation. + finalLegOpacity = legOptions.opacity, + i, m, leg, legPath, legLength, newPos; - //Add markers to map hidden at our center point - for (i = childMarkers.length - 1; i >= 0; i--) { + if (finalLegOpacity === undefined) { + finalLegOpacity = L.MarkerClusterGroup.prototype.options.spiderLegPolylineOptions.opacity; + } + + if (svg) { + // If the initial opacity of the spider leg is not 0 then it appears before the animation starts. + legOptions.opacity = 0; + + // Add the class for CSS transitions. + legOptions.className = (legOptions.className || '') + ' leaflet-cluster-spider-leg'; + } else { + // Make sure we have a defined opacity. + legOptions.opacity = finalLegOpacity; + } + + // Add markers and spider legs to map, hidden at our center point. + // Traverse in ascending order to make sure that inner circleMarkers are on top of further legs. Normal markers are re-ordered by newPosition. + // The reverse order trick no longer improves performance on modern browsers. + for (i = 0; i < childMarkers.length; i++) { m = childMarkers[i]; - //If it is a marker, add it now and we'll animate it out - if (m.setOpacity) { - m.setZIndexOffset(1000000); //Make these appear on top of EVERYTHING - m.setOpacity(0); - - fg.addLayer(m); + newPos = map.layerPointToLatLng(positions[i]); + + // Add the leg before the marker, so that in case the latter is a circleMarker, the leg is behind it. + leg = new L.Polyline([thisLayerLatLng, newPos], legOptions); + map.addLayer(leg); + m._spiderLeg = leg; + // Explanations: https://jakearchibald.com/2013/animated-line-drawing-svg/ + // In our case the transition property is declared in the CSS file. + if (svg) { + legPath = leg._path; + legLength = legPath.getTotalLength() + 0.1; // Need a small extra length to avoid remaining dot in Firefox. + legPath.style.strokeDasharray = legLength; // Just 1 length is enough, it will be duplicated. + legPath.style.strokeDashoffset = legLength; + } + + // If it is a marker, add it now and we'll animate it out + if (m.setZIndexOffset) { + m.setZIndexOffset(1000000); // Make normal markers appear on top of EVERYTHING + } + if (m.clusterHide) { + m.clusterHide(); + } + + // Vectors just get immediately added + fg.addLayer(m); + + if (m._setPos) { m._setPos(thisLayerPos); - } else { - //Vectors just get immediately added - fg.addLayer(m); } } group._forceLayout(); group._animationStart(); - var initialLegOpacity = L.Path.SVG ? 0 : 0.3, - xmlns = L.Path.SVG_NS; - - + // Reveal markers and spider legs. for (i = childMarkers.length - 1; i >= 0; i--) { newPos = map.layerPointToLatLng(positions[i]); m = childMarkers[i]; @@ -1926,79 +2157,39 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { m._preSpiderfyLatlng = m._latlng; m.setLatLng(newPos); - if (m.setOpacity) { - m.setOpacity(1); + if (m.clusterShow) { + m.clusterShow(); } - - //Add Legs. - leg = new L.Polyline([me._latlng, newPos], { weight: 1.5, color: '#222', opacity: initialLegOpacity }); - map.addLayer(leg); - m._spiderLeg = leg; - - //Following animations don't work for canvas - if (!L.Path.SVG || !this.SVG_ANIMATION) { - continue; - } - - //How this works: - //http://stackoverflow.com/questions/5924238/how-do-you-animate-an-svg-path-in-ios - //http://dev.opera.com/articles/view/advanced-svg-animation-techniques/ - - //Animate length - var length = leg._path.getTotalLength(); - leg._path.setAttribute("stroke-dasharray", length + "," + length); - - var anim = document.createElementNS(xmlns, "animate"); - anim.setAttribute("attributeName", "stroke-dashoffset"); - anim.setAttribute("begin", "indefinite"); - anim.setAttribute("from", length); - anim.setAttribute("to", 0); - anim.setAttribute("dur", 0.25); - leg._path.appendChild(anim); - anim.beginElement(); - - //Animate opacity - anim = document.createElementNS(xmlns, "animate"); - anim.setAttribute("attributeName", "stroke-opacity"); - anim.setAttribute("attributeName", "stroke-opacity"); - anim.setAttribute("begin", "indefinite"); - anim.setAttribute("from", 0); - anim.setAttribute("to", 0.5); - anim.setAttribute("dur", 0.25); - leg._path.appendChild(anim); - anim.beginElement(); - } - me.setOpacity(0.3); - - //Set the opacity of the spiderLegs back to their correct value - // The animations above override this until they complete. - // If the initial opacity of the spiderlegs isn't 0 then they appear before the animation starts. - if (L.Path.SVG) { - this._group._forceLayout(); - - for (i = childMarkers.length - 1; i >= 0; i--) { - m = childMarkers[i]._spiderLeg; - - m.options.opacity = 0.5; - m._path.setAttribute('stroke-opacity', 0.5); + // Animate leg (animation is actually delegated to CSS transition). + if (svg) { + leg = m._spiderLeg; + legPath = leg._path; + legPath.style.strokeDashoffset = 0; + //legPath.style.strokeOpacity = finalLegOpacity; + leg.setStyle({opacity: finalLegOpacity}); } } + this.setOpacity(0.3); setTimeout(function () { group._animationEnd(); - group.fire('spiderfied'); + group.fire('spiderfied', { + cluster: me, + markers: childMarkers + }); }, 200); }, _animationUnspiderfy: function (zoomDetails) { - var group = this._group, + var me = this, + group = this._group, map = group._map, fg = group._featureGroup, thisLayerPos = zoomDetails ? map._latLngToNewLayerPoint(this._latlng, zoomDetails.zoom, zoomDetails.center) : map.latLngToLayerPoint(this._latlng), childMarkers = this.getAllChildMarkers(), - svg = L.Path.SVG && this.SVG_ANIMATION, - m, i, a; + svg = L.Path.SVG, + m, i, leg, legPath, legLength, nonAnimatable; group._animationStart(); @@ -2007,7 +2198,7 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { for (i = childMarkers.length - 1; i >= 0; i--) { m = childMarkers[i]; - //Marker was added to us after we were spidified + //Marker was added to us after we were spiderfied if (!m._preSpiderfyLatlng) { continue; } @@ -2015,28 +2206,28 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { //Fix up the location to the real one m.setLatLng(m._preSpiderfyLatlng); delete m._preSpiderfyLatlng; + //Hack override the location to be our center - if (m.setOpacity) { + nonAnimatable = true; + if (m._setPos) { m._setPos(thisLayerPos); - m.setOpacity(0); - } else { + nonAnimatable = false; + } + if (m.clusterHide) { + m.clusterHide(); + nonAnimatable = false; + } + if (nonAnimatable) { fg.removeLayer(m); } - //Animate the spider legs back in + // Animate the spider leg back in (animation is actually delegated to CSS transition). if (svg) { - a = m._spiderLeg._path.childNodes[0]; - a.setAttribute('to', a.getAttribute('from')); - a.setAttribute('from', 0); - a.beginElement(); - - a = m._spiderLeg._path.childNodes[1]; - a.setAttribute('from', 0.5); - a.setAttribute('to', 0); - a.setAttribute('stroke-opacity', 0); - a.beginElement(); - - m._spiderLeg._path.setAttribute('stroke-opacity', 0); + leg = m._spiderLeg; + legPath = leg._path; + legLength = legPath.getTotalLength() + 0.1; + legPath.style.strokeDashoffset = legLength; + leg.setStyle({opacity: 0}); } } @@ -2058,9 +2249,10 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { continue; } - - if (m.setOpacity) { - m.setOpacity(1); + if (m.clusterShow) { + m.clusterShow(); + } + if (m.setZIndexOffset) { m.setZIndexOffset(0); } @@ -2072,6 +2264,10 @@ L.MarkerCluster.include(!L.DomUtil.TRANSITION ? { delete m._spiderLeg; } group._animationEnd(); + group.fire('unspiderfied', { + cluster: me, + markers: childMarkers + }); }, 200); } }); @@ -2089,24 +2285,19 @@ L.MarkerClusterGroup.include({ } //Browsers without zoomAnimation or a big zoom don't fire zoomstart this._map.on('zoomend', this._noanimationUnspiderfy, this); - - if (L.Path.SVG && !L.Browser.touch) { - this._map._initPathRoot(); - //Needs to happen in the pageload, not after, or animations don't work in webkit - // http://stackoverflow.com/questions/8455200/svg-animate-with-dynamically-added-elements - //Disable on touch browsers as the animation messes up on a touch zoom and isn't very noticable - } }, _spiderfierOnRemove: function () { this._map.off('click', this._unspiderfyWrapper, this); this._map.off('zoomstart', this._unspiderfyZoomStart, this); this._map.off('zoomanim', this._unspiderfyZoomAnim, this); + this._map.off('zoomend', this._noanimationUnspiderfy, this); - this._unspiderfy(); //Ensure that markers are back where they should be + //Ensure that markers are back where they should be + // Use no animation to avoid a sticky leaflet-cluster-anim class on mapPane + this._noanimationUnspiderfy(); }, - //On zoom start we add a zoomanim handler so that we are guaranteed to be last (after markers are animated) //This means we can define the animation they do rather than Markers doing an animation to their actual location _unspiderfyZoomStart: function () { @@ -2116,6 +2307,7 @@ L.MarkerClusterGroup.include({ this._map.on('zoomanim', this._unspiderfyZoomAnim, this); }, + _unspiderfyZoomAnim: function (zoomDetails) { //Wait until the first zoomanim after the user has finished touch-zooming before running the animation if (L.DomUtil.hasClass(this._map._mapPane, 'leaflet-touching')) { @@ -2126,7 +2318,6 @@ L.MarkerClusterGroup.include({ this._unspiderfy(zoomDetails); }, - _unspiderfyWrapper: function () { /// _unspiderfy but passes no arguments this._unspiderfy(); @@ -2149,9 +2340,13 @@ L.MarkerClusterGroup.include({ if (layer._spiderLeg) { this._featureGroup.removeLayer(layer); - layer.setOpacity(1); + if (layer.clusterShow) { + layer.clusterShow(); + } //Position will be fixed up immediately in _animationUnspiderfy - layer.setZIndexOffset(0); + if (layer.setZIndexOffset) { + layer.setZIndexOffset(0); + } this._map.removeLayer(layer._spiderLeg); delete layer._spiderLeg; @@ -2160,4 +2355,129 @@ L.MarkerClusterGroup.include({ }); +/** + * Adds 1 public method to MCG and 1 to L.Marker to facilitate changing + * markers' icon options and refreshing their icon and their parent clusters + * accordingly (case where their iconCreateFunction uses data of childMarkers + * to make up the cluster icon). + */ + + +L.MarkerClusterGroup.include({ + /** + * Updates the icon of all clusters which are parents of the given marker(s). + * In singleMarkerMode, also updates the given marker(s) icon. + * @param layers L.MarkerClusterGroup|L.LayerGroup|Array(L.Marker)|Map(L.Marker)| + * L.MarkerCluster|L.Marker (optional) list of markers (or single marker) whose parent + * clusters need to be updated. If not provided, retrieves all child markers of this. + * @returns {L.MarkerClusterGroup} + */ + refreshClusters: function (layers) { + if (!layers) { + layers = this._topClusterLevel.getAllChildMarkers(); + } else if (layers instanceof L.MarkerClusterGroup) { + layers = layers._topClusterLevel.getAllChildMarkers(); + } else if (layers instanceof L.LayerGroup) { + layers = layers._layers; + } else if (layers instanceof L.MarkerCluster) { + layers = layers.getAllChildMarkers(); + } else if (layers instanceof L.Marker) { + layers = [layers]; + } // else: must be an Array(L.Marker)|Map(L.Marker) + this._flagParentsIconsNeedUpdate(layers); + this._refreshClustersIcons(); + + // In case of singleMarkerMode, also re-draw the markers. + if (this.options.singleMarkerMode) { + this._refreshSingleMarkerModeMarkers(layers); + } + + return this; + }, + + /** + * Simply flags all parent clusters of the given markers as having a "dirty" icon. + * @param layers Array(L.Marker)|Map(L.Marker) list of markers. + * @private + */ + _flagParentsIconsNeedUpdate: function (layers) { + var id, parent; + + // Assumes layers is an Array or an Object whose prototype is non-enumerable. + for (id in layers) { + // Flag parent clusters' icon as "dirty", all the way up. + // Dumb process that flags multiple times upper parents, but still + // much more efficient than trying to be smart and make short lists, + // at least in the case of a hierarchy following a power law: + // http://jsperf.com/flag-nodes-in-power-hierarchy/2 + parent = layers[id].__parent; + while (parent) { + parent._iconNeedsUpdate = true; + parent = parent.__parent; + } + } + }, + + /** + * Refreshes the icon of all "dirty" visible clusters. + * Non-visible "dirty" clusters will be updated when they are added to the map. + * @private + */ + _refreshClustersIcons: function () { + this._featureGroup.eachLayer(function (c) { + if (c instanceof L.MarkerCluster && c._iconNeedsUpdate) { + c._updateIcon(); + } + }); + }, + + /** + * Re-draws the icon of the supplied markers. + * To be used in singleMarkerMode only. + * @param layers Array(L.Marker)|Map(L.Marker) list of markers. + * @private + */ + _refreshSingleMarkerModeMarkers: function (layers) { + var id, layer; + + for (id in layers) { + layer = layers[id]; + + // Make sure we do not override markers that do not belong to THIS group. + if (this.hasLayer(layer)) { + // Need to re-create the icon first, then re-draw the marker. + layer.setIcon(this._overrideMarkerIcon(layer)); + } + } + } +}); + +L.Marker.include({ + /** + * Updates the given options in the marker's icon and refreshes the marker. + * @param options map object of icon options. + * @param directlyRefreshClusters boolean (optional) true to trigger + * MCG.refreshClustersOf() right away with this single marker. + * @returns {L.Marker} + */ + refreshIconOptions: function (options, directlyRefreshClusters) { + var icon = this.options.icon; + + L.setOptions(icon, options); + + this.setIcon(icon); + + // Shortcut to refresh the associated MCG clusters right away. + // To be used when refreshing a single marker. + // Otherwise, better use MCG.refreshClusters() once at the end with + // the list of modified markers. + if (directlyRefreshClusters && this.__parent) { + this.__parent._group.refreshClusters(this); + } + + return this; + } +}); + + }(window, document)); \ No newline at end of file diff --git a/www/plugins/gis/lib/leaflet/plugins/leaflet.markercluster.css b/www/plugins/gis/lib/leaflet/plugins/leaflet.markercluster.css index 789c8a34..2aae5fe5 100755 --- a/www/plugins/gis/lib/leaflet/plugins/leaflet.markercluster.css +++ b/www/plugins/gis/lib/leaflet/plugins/leaflet.markercluster.css @@ -5,6 +5,14 @@ transition: transform 0.3s ease-out, opacity 0.3s ease-in; } +.leaflet-cluster-spider-leg { + /* stroke-dashoffset (duration and function) should match with leaflet-marker-icon transform in order to track it exactly */ + -webkit-transition: -webkit-stroke-dashoffset 0.3s ease-out, -webkit-stroke-opacity 0.3s ease-in; + -moz-transition: -moz-stroke-dashoffset 0.3s ease-out, -moz-stroke-opacity 0.3s ease-in; + -o-transition: -o-stroke-dashoffset 0.3s ease-out, -o-stroke-opacity 0.3s ease-in; + transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in; +} + .marker-cluster-small { background-color: rgba(181, 226, 140, 0.6); } diff --git a/www/plugins/gis/modeles/carte_gis.html b/www/plugins/gis/modeles/carte_gis.html index ee3d588a..9f48f227 100644 --- a/www/plugins/gis/modeles/carte_gis.html +++ b/www/plugins/gis/modeles/carte_gis.html @@ -12,7 +12,7 @@ Parametres possibles : - maxZoom = 13 zoom maximum autorisé - minZoom = 13 zoom minimum autorisé -- default_layer = acetate nom de la couche affichée par défaut +- default_layer = acetate nom de la couche affichée par défaut, "none" si on ne souhaite pas affiche de couche spécifique - affiche_layers = openmapsurfer/acetate noms des couches proposées séparés par des / - sw_lat = lat - 10° latitude du sud-ouest de la bounding box @@ -39,15 +39,18 @@ Parametres possibles : - objets = gis type d'objets à afficher (fichier json/gis_xx qui génère la source de donnees) - limit|limite = 500 nombre max de marqueurs à afficher, 500 par defaut +- langue = null langue des objets à récupérer (utile pour les multis notamment) - kml = 12 kml à superposer à la carte (id_document ou url ou liste d'url) - gpx = 12 gpx à superposer à la carte (id_document ou url ou liste d'url) -- geojson = 12 geojson à superposer à la carte (id_document ou url ou liste d'url) +- geojson = 12 geojson à superposer à la carte (id_document ou url ou liste d'url) +- topojson = 12 topojson à superposer à la carte (id_document ou url ou liste d'url) - centrer_fichier = non permet de ne pas centrer la carte automatiquement sur les fichiers kml/gpx surperposés - point = non si elle vaut "non" cette option n'affichera pas de points du tout (utile pour n'afficher qu'un kml par exemple) - media = non permet de passer le critère 'media' (pour les documents) - mots = #LISTE{1,4,7} plugin critere {mots} http://contrib.spip.net/Critere-mots - path_styles=#ARRAY{color,#fff} options de style des éléments de la couche GeoJSON (voir http://leafletjs.com/reference.html#path-options) +- options=#ARRAY{option1,valeur1} options ajoutées à la carte (qui peuvent être récupérées dans la fonction de callback par exemple par la suite) Uniquement si objets = point_libre : - icone = chemin/vers/image image utilisée pour le marker @@ -118,9 +121,10 @@ var jQgisloader; ne_lat: (#GET{ne_lat})][, sw_lon: (#GET{sw_lon})][, ne_lon: (#GET{ne_lon})], - affiche_points: [(#ENV{point,''}|=={non}|?{false,true})], + affiche_points: [(#ENV{point,''}|=={non}|?{false,true})][, + langue:'(#ENV{langue})'], json_points:{ - url: '[(#URL_PAGE{gis_json}|url_absolue)]'[, + url: '[(#URL_PAGE{gis_json}|parametre_url{lang,#ENV{langue},&}|url_absolue)]'[, objets: '(#ENV{objets,#ENV{class}}|trim)'], limit: [(#ENV{limit,#ENV{limite,500}}|trim)], env: [(#ENV*{args,#ENV*}|gis_modele_url_json_env|json_encode)][, @@ -136,14 +140,16 @@ var jQgisloader; maxClusterRadius: [(#ENV{maxClusterRadius,80})] }, pathStyles: [(#ENV*{path_styles}|json_encode)], - autocenterandzoom: [(#ENV{autocenterandzoom,#ENV{centrer_auto}}|?{true,false})], + autocenterandzoom: [(#ENV{autocenterandzoom,#ENV{centrer_auto,non}}|=={non}|?{false,true})], openId: [(#ENV{id_a_ouvrir,false})], localize_visitor: [(#ENV{localize_visitor,#ENV{localiser_visiteur}}|?{true,false})], localize_visitor_zoom: [(#ENV{localize_visitor_zoom,#ENV{zoom,#CONFIG{gis/zoom,0}}})], centrer_fichier: [(#ENV{centrer_fichier,oui}|=={oui}|?{true,false})], - kml: [(#ENV{kml,''}|?{[(#ENV{kml}|is_array|?{#ENV{kml},#LISTE{#ENV{kml}}}|gis_kml_to_urls|json_encode)],false})], - gpx: [(#ENV{gpx,''}|?{[(#ENV{gpx}|is_array|?{#ENV{gpx},#LISTE{#ENV{gpx}}}|gis_kml_to_urls|json_encode)],false})], - geojson: [(#ENV{geojson,''}|?{[(#ENV{geojson}|is_array|?{#ENV{geojson},#LISTE{#ENV{geojson}}}|gis_kml_to_urls|json_encode)],false})] + kml: [(#ENV{kml,''}|?{[(#ENV{kml}|gis_param_to_array|gis_kml_to_urls|json_encode)],false})], + gpx: [(#ENV{gpx,''}|?{[(#ENV{gpx}|gis_param_to_array|gis_kml_to_urls|json_encode)],false})], + geojson: [(#ENV{geojson,''}|?{[(#ENV{geojson}|gis_param_to_array|gis_kml_to_urls|json_encode)],false})], + topojson: [(#ENV{topojson,''}|?{[(#ENV{topojson}|gis_param_to_array|gis_kml_to_urls|json_encode)],false})], + options: [(#ENV*{options,#ARRAY}|json_encode)] }); }); }); diff --git a/www/plugins/gis/modeles/carte_gis_preview.html b/www/plugins/gis/modeles/carte_gis_preview.html index 52f1193b..ed83889e 100755 --- a/www/plugins/gis/modeles/carte_gis_preview.html +++ b/www/plugins/gis/modeles/carte_gis_preview.html @@ -12,9 +12,11 @@ map_preview = new L.Map(map_preview_container); map_preview.attributionControl.setPrefix(''); - - var base_layer = [new (#EVAL{$GLOBALS\['gis_layers'\]}|table_valeur{[(#REM|gis_layer_defaut)]/layer})]; - map_preview.addLayer(base_layer); + + var base_layer = [(#ENV{layer_defaut}|=={none}|?{"'none'",[new (#EVAL{$GLOBALS\['gis_layers'\]}|table_valeur{[(#ENV{layer_defaut,[(#REM|gis_layer_defaut)]})]/layer})]})]; + if(base_layer != 'none'){ + map_preview.addLayer(base_layer); + } map_preview.setView(new L.LatLng([(#LAT)],[(#LON)]),[(#ZOOM|sinon{#CONFIG{gis/zoom,0}})]); diff --git a/www/plugins/gis/paquet.xml b/www/plugins/gis/paquet.xml index 2397680e..10ea5a86 100644 --- a/www/plugins/gis/paquet.xml +++ b/www/plugins/gis/paquet.xml @@ -1,8 +1,8 @@ Leaflet fullscreen Leaflet minimap Nominatim + Photon Icône de mattrich sous licence CC BY-NC-SA - 2011-2015 + 2011-2016 GPL v3 diff --git a/www/plugins/gis/prive/contenu/gis_objet.html b/www/plugins/gis/prive/contenu/gis_objet.html index 74dbd338..ade5c650 100644 --- a/www/plugins/gis/prive/contenu/gis_objet.html +++ b/www/plugins/gis/prive/contenu/gis_objet.html @@ -1,6 +1 @@ -[(#SET{titre, #VAL{gis:info_geolocalisation}|_T})] -[(#BOITE_OUVRIR{#CHEMIN_IMAGE{gis-24.png}|balise_img{'',cadre-icone}|concat{#GET{titre}}, 'simple'})] -
                  - [(#INCLURE{fond=prive/inclure/gis_objet_formulaires,env,ajax})] -
                  -#BOITE_FERMER \ No newline at end of file +[(#INCLURE{fond=prive/inclure/gis_objet_formulaires,env,ajax})] \ No newline at end of file diff --git a/www/plugins/gis/prive/inclure/gis_objet_formulaires.html b/www/plugins/gis/prive/inclure/gis_objet_formulaires.html index 32332bbd..b8618c4c 100644 --- a/www/plugins/gis/prive/inclure/gis_objet_formulaires.html +++ b/www/plugins/gis/prive/inclure/gis_objet_formulaires.html @@ -1,42 +1,3 @@
                  -#SET{gis_defaut,''} - -#SET{gis_defaut,nouveau} -#SET{gis_defaut,glop} - - -#SET{bloc_gis, #ENV{bloc_gis,#GET{gis_defaut}|=={nouveau}|?{editer,lier}}} - - - -[(#GET{bloc_gis}|=={editer}|oui) - #FORMULAIRE_EDITER_GIS{#ENV{id_gis,#GET{gis_defaut}},#ENV{objet},#ENV{id_objet},#SELF,'non',#ENV{options_formulaire_editer_gis}} -] - -[(#GET{bloc_gis}|=={lier}|oui) - [(#INCLURE{fond=prive/objets/liste/gis_lies,sinon=<:gis:aucun_gis:>,env})] -] - - [(#GET{bloc_gis}|=={rechercher}|oui) -
                  - #FORMULAIRE_RECHERCHER_GIS{#ENV{objet},#ENV{id_objet},#SELF|parametre_url{bloc_gis,lier}} -
                  ] -
                  + #FORMULAIRE_EDITER_LIENS{gis,#ENV{objet},#ENV{id_objet},oui} + \ No newline at end of file diff --git a/www/plugins/gis/prive/objets/liste/gis_associer.html b/www/plugins/gis/prive/objets/liste/gis_associer.html index 1770b5e8..39538d8a 100644 --- a/www/plugins/gis/prive/objets/liste/gis_associer.html +++ b/www/plugins/gis/prive/objets/liste/gis_associer.html @@ -34,7 +34,7 @@ a mis a jour la valeur avec la page reelle]
    [(#CHEMIN_IMAGE{gis-16.png}|balise_img)] [(#LOGO_GIS|image_reduire{20,20})][(#TITRE|sinon{<:ecrire:info_sans_titre:>})]
    [(#LOGO_GIS|image_reduire{20,20})][(#TITRE|sinon{<:ecrire:info_sans_titre:>})] - [(#BOUTON_ACTION{ - <:gis:info_supprimer_lien:> [(#CHEMIN_IMAGE{supprimer-12.png}|balise_img{'X'})], - #URL_ACTION_AUTEUR{editer_lien_gis,delier/#ID_GIS/#OBJET/#ID_OBJET,#SELF}, - ajax})] + [(#ENV{editable}|oui) + ]
    "; // debug - for ($i = 0; $i < $raw_length; $i++) { - $token = $email[$i]; -//-echo ""; // debug - - switch ($context) { - //------------------------------------------------------------- - // local-part - //------------------------------------------------------------- - case ISEMAIL_COMPONENT_LOCALPART: - // http://tools.ietf.org/html/rfc5322#section-3.4.1 - // local-part = dot-atom / quoted-string / obs-local-part - // - // dot-atom = [CFWS] dot-atom-text [CFWS] - // - // dot-atom-text = 1*atext *("." 1*atext) - // - // quoted-string = [CFWS] - // DQUOTE *([FWS] qcontent) [FWS] DQUOTE - // [CFWS] - // - // obs-local-part = word *("." word) - // - // word = atom / quoted-string - // - // atom = [CFWS] 1*atext [CFWS] - switch ($token) { - // Comment - case ISEMAIL_STRING_OPENPARENTHESIS: - if ($element_len === 0) - // Comments are OK at the beginning of an element - $return_status[] = ($element_count === 0) ? ISEMAIL_CFWS_COMMENT : ISEMAIL_DEPREC_COMMENT; - else { - $return_status[] = ISEMAIL_CFWS_COMMENT; - $end_or_die = true; // We can't start a comment in the middle of an element, so this better be the end - } - - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_COMMENT; - break; - // Next dot-atom element - case ISEMAIL_STRING_DOT: - if ($element_len === 0) - // Another dot, already? - $return_status[] = ($element_count === 0) ? ISEMAIL_ERR_DOT_START : ISEMAIL_ERR_CONSECUTIVEDOTS; // Fatal error - else - // The entire local-part can be a quoted string for RFC 5321 - // If it's just one atom that is quoted then it's an RFC 5322 obsolete form - if ($end_or_die) $return_status[] = ISEMAIL_DEPREC_LOCALPART; - - $end_or_die = false; // CFWS & quoted strings are OK again now we're at the beginning of an element (although they are obsolete forms) - $element_len = 0; - $element_count++; - $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; - $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] = ''; - - break; - // Quoted string - case ISEMAIL_STRING_DQUOTE: - if ($element_len === 0) { - // The entire local-part can be a quoted string for RFC 5321 - // If it's just one atom that is quoted then it's an RFC 5322 obsolete form - $return_status[] = ($element_count === 0) ? ISEMAIL_RFC5321_QUOTEDSTRING : ISEMAIL_DEPREC_LOCALPART; - - $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; - $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= $token; - $element_len++; - $end_or_die = true; // Quoted string must be the entire element - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_QUOTEDSTRING; - } else { - $return_status[] = ISEMAIL_ERR_EXPECTING_ATEXT; // Fatal error - } - - break; - // Folding White Space - case ISEMAIL_STRING_CR: - case ISEMAIL_STRING_SP: - case ISEMAIL_STRING_HTAB: - if (($token === ISEMAIL_STRING_CR) && ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF))) {$return_status[] = ISEMAIL_ERR_CR_NO_LF; break;} // Fatal error - - if ($element_len === 0) - $return_status[] = ($element_count === 0) ? ISEMAIL_CFWS_FWS : ISEMAIL_DEPREC_FWS; - else - $end_or_die = true; // We can't start FWS in the middle of an element, so this better be the end - - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_FWS; - $token_prior = $token; - - break; - // @ - case ISEMAIL_STRING_AT: - // At this point we should have a valid local-part - if (count($context_stack) !== 1) die('Unexpected item on context stack'); - - if ($parsedata[ISEMAIL_COMPONENT_LOCALPART] === '') - $return_status[] = ISEMAIL_ERR_NOLOCALPART; // Fatal error - elseif ($element_len === 0) $return_status[] = ISEMAIL_ERR_DOT_END; // Fatal error - // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.1 - // The maximum total length of a user name or other local-part is 64 - // octets. - elseif (strlen($parsedata[ISEMAIL_COMPONENT_LOCALPART]) > 64) - $return_status[] = ISEMAIL_RFC5322_LOCAL_TOOLONG; - // http://tools.ietf.org/html/rfc5322#section-3.4.1 - // Comments and folding white space - // SHOULD NOT be used around the "@" in the addr-spec. - // - // http://tools.ietf.org/html/rfc2119 - // 4. SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean that - // there may exist valid reasons in particular circumstances when the - // particular behavior is acceptable or even useful, but the full - // implications should be understood and the case carefully weighed - // before implementing any behavior described with this label. - elseif (($context_prior === ISEMAIL_CONTEXT_COMMENT) || ($context_prior === ISEMAIL_CONTEXT_FWS)) - $return_status[] = ISEMAIL_DEPREC_CFWS_NEAR_AT; - - // Clear everything down for the domain parsing - $context = ISEMAIL_COMPONENT_DOMAIN; // Where we are - $context_stack = array($context); // Where we have been - $element_count = 0; - $element_len = 0; - $end_or_die = false; // CFWS can only appear at the end of the element - - break; - // atext - default: - // http://tools.ietf.org/html/rfc5322#section-3.2.3 - // atext = ALPHA / DIGIT / ; Printable US-ASCII - // "!" / "#" / ; characters not including - // "$" / "%" / ; specials. Used for atoms. - // "&" / "'" / - // "*" / "+" / - // "-" / "/" / - // "=" / "?" / - // "^" / "_" / - // "`" / "{" / - // "|" / "}" / - // "~" - if ($end_or_die) { - // We have encountered atext where it is no longer valid - switch ($context_prior) { - case ISEMAIL_CONTEXT_COMMENT: - case ISEMAIL_CONTEXT_FWS: - $return_status[] = ISEMAIL_ERR_ATEXT_AFTER_CFWS; - break; - case ISEMAIL_CONTEXT_QUOTEDSTRING: - $return_status[] = ISEMAIL_ERR_ATEXT_AFTER_QS; - break; - default: - die ("More atext found where none is allowed, but unrecognised prior context: $context_prior"); - } - } else { - $context_prior = $context; - $ord = ord($token); - - if (($ord < 33) || ($ord > 126) || ($ord === 10) || (!is_bool(strpos(ISEMAIL_STRING_SPECIALS, $token)))) - $return_status[] = ISEMAIL_ERR_EXPECTING_ATEXT; // Fatal error - - $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; - $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= $token; - $element_len++; - } - } - - break; - //------------------------------------------------------------- - // Domain - //------------------------------------------------------------- - case ISEMAIL_COMPONENT_DOMAIN: - // http://tools.ietf.org/html/rfc5322#section-3.4.1 - // domain = dot-atom / domain-literal / obs-domain - // - // dot-atom = [CFWS] dot-atom-text [CFWS] - // - // dot-atom-text = 1*atext *("." 1*atext) - // - // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] - // - // dtext = %d33-90 / ; Printable US-ASCII - // %d94-126 / ; characters not including - // obs-dtext ; "[", "]", or "\" - // - // obs-domain = atom *("." atom) - // - // atom = [CFWS] 1*atext [CFWS] - - - // http://tools.ietf.org/html/rfc5321#section-4.1.2 - // Mailbox = Local-part "@" ( Domain / address-literal ) - // - // Domain = sub-domain *("." sub-domain) - // - // address-literal = "[" ( IPv4-address-literal / - // IPv6-address-literal / - // General-address-literal ) "]" - // ; See Section 4.1.3 - - // http://tools.ietf.org/html/rfc5322#section-3.4.1 - // Note: A liberal syntax for the domain portion of addr-spec is - // given here. However, the domain portion contains addressing - // information specified by and used in other protocols (e.g., - // [RFC1034], [RFC1035], [RFC1123], [RFC5321]). It is therefore - // incumbent upon implementations to conform to the syntax of - // addresses for the context in which they are used. - // is_email() author's note: it's not clear how to interpret this in - // the context of a general email address validator. The conclusion I - // have reached is this: "addressing information" must comply with - // RFC 5321 (and in turn RFC 1035), anything that is "semantically - // invisible" must comply only with RFC 5322. - switch ($token) { - // Comment - case ISEMAIL_STRING_OPENPARENTHESIS: - if ($element_len === 0) - // Comments at the start of the domain are deprecated in the text - // Comments at the start of a subdomain are obs-domain - // (http://tools.ietf.org/html/rfc5322#section-3.4.1) - $return_status[] = ($element_count === 0) ? ISEMAIL_DEPREC_CFWS_NEAR_AT : ISEMAIL_DEPREC_COMMENT; - else { - $return_status[] = ISEMAIL_CFWS_COMMENT; - $end_or_die = true; // We can't start a comment in the middle of an element, so this better be the end - } - - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_COMMENT; - break; - // Next dot-atom element - case ISEMAIL_STRING_DOT: - if ($element_len === 0) - // Another dot, already? - $return_status[] = ($element_count === 0) ? ISEMAIL_ERR_DOT_START : ISEMAIL_ERR_CONSECUTIVEDOTS; // Fatal error - elseif ($hyphen_flag) - // Previous subdomain ended in a hyphen - $return_status[] = ISEMAIL_ERR_DOMAINHYPHENEND; // Fatal error - else - // Nowhere in RFC 5321 does it say explicitly that the - // domain part of a Mailbox must be a valid domain according - // to the DNS standards set out in RFC 1035, but this *is* - // implied in several places. For instance, wherever the idea - // of host routing is discussed the RFC says that the domain - // must be looked up in the DNS. This would be nonsense unless - // the domain was designed to be a valid DNS domain. Hence we - // must conclude that the RFC 1035 restriction on label length - // also applies to RFC 5321 domains. - // - // http://tools.ietf.org/html/rfc1035#section-2.3.4 - // labels 63 octets or less - if ($element_len > 63) $return_status[] = ISEMAIL_RFC5322_LABEL_TOOLONG; - - $end_or_die = false; // CFWS is OK again now we're at the beginning of an element (although it may be obsolete CFWS) - $element_len = 0; - $element_count++; - $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] = ''; - $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; - - break; - // Domain literal - case ISEMAIL_STRING_OPENSQBRACKET: - if ($parsedata[ISEMAIL_COMPONENT_DOMAIN] === '') { - $end_or_die = true; // Domain literal must be the only component - $element_len++; - $context_stack[] = $context; - $context = ISEMAIL_COMPONENT_LITERAL; - $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; - $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] .= $token; - $parsedata[ISEMAIL_COMPONENT_LITERAL] = ''; - } else { - $return_status[] = ISEMAIL_ERR_EXPECTING_ATEXT; // Fatal error - } - - break; - // Folding White Space - case ISEMAIL_STRING_CR: - case ISEMAIL_STRING_SP: - case ISEMAIL_STRING_HTAB: - if (($token === ISEMAIL_STRING_CR) && ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF))) {$return_status[] = ISEMAIL_ERR_CR_NO_LF; break;} // Fatal error - - if ($element_len === 0) - $return_status[] = ($element_count === 0) ? ISEMAIL_DEPREC_CFWS_NEAR_AT : ISEMAIL_DEPREC_FWS; - else { - $return_status[] = ISEMAIL_CFWS_FWS; - $end_or_die = true; // We can't start FWS in the middle of an element, so this better be the end - } - - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_FWS; - $token_prior = $token; - break; - // atext - default: - // RFC 5322 allows any atext... - // http://tools.ietf.org/html/rfc5322#section-3.2.3 - // atext = ALPHA / DIGIT / ; Printable US-ASCII - // "!" / "#" / ; characters not including - // "$" / "%" / ; specials. Used for atoms. - // "&" / "'" / - // "*" / "+" / - // "-" / "/" / - // "=" / "?" / - // "^" / "_" / - // "`" / "{" / - // "|" / "}" / - // "~" - - // But RFC 5321 only allows letter-digit-hyphen to comply with DNS rules (RFCs 1034 & 1123) - // http://tools.ietf.org/html/rfc5321#section-4.1.2 - // sub-domain = Let-dig [Ldh-str] - // - // Let-dig = ALPHA / DIGIT - // - // Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig - // - if ($end_or_die) { - // We have encountered atext where it is no longer valid - switch ($context_prior) { - case ISEMAIL_CONTEXT_COMMENT: - case ISEMAIL_CONTEXT_FWS: - $return_status[] = ISEMAIL_ERR_ATEXT_AFTER_CFWS; - break; - case ISEMAIL_COMPONENT_LITERAL: - $return_status[] = ISEMAIL_ERR_ATEXT_AFTER_DOMLIT; - break; - default: - die ("More atext found where none is allowed, but unrecognised prior context: $context_prior"); - } - } - - $ord = ord($token); - $hyphen_flag = false; // Assume this token isn't a hyphen unless we discover it is - - if (($ord < 33) || ($ord > 126) || (!is_bool(strpos(ISEMAIL_STRING_SPECIALS, $token)))) { - $return_status[] = ISEMAIL_ERR_EXPECTING_ATEXT; // Fatal error - } elseif ($token === ISEMAIL_STRING_HYPHEN) { - if ($element_len === 0) { - // Hyphens can't be at the beginning of a subdomain - $return_status[] = ISEMAIL_ERR_DOMAINHYPHENSTART; // Fatal error - } - - $hyphen_flag = true; - } elseif (!(($ord > 47 && $ord < 58) || ($ord > 64 && $ord < 91) || ($ord > 96 && $ord < 123))) { - // Not an RFC 5321 subdomain, but still OK by RFC 5322 - $return_status[] = ISEMAIL_RFC5322_DOMAIN; - } - - $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; - $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] .= $token; - $element_len++; - } - - break; - //------------------------------------------------------------- - // Domain literal - //------------------------------------------------------------- - case ISEMAIL_COMPONENT_LITERAL: - // http://tools.ietf.org/html/rfc5322#section-3.4.1 - // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] - // - // dtext = %d33-90 / ; Printable US-ASCII - // %d94-126 / ; characters not including - // obs-dtext ; "[", "]", or "\" - // - // obs-dtext = obs-NO-WS-CTL / quoted-pair - switch ($token) { - // End of domain literal - case ISEMAIL_STRING_CLOSESQBRACKET: - if ((int) max($return_status) < ISEMAIL_DEPREC) { - // Could be a valid RFC 5321 address literal, so let's check - - // http://tools.ietf.org/html/rfc5321#section-4.1.2 - // address-literal = "[" ( IPv4-address-literal / - // IPv6-address-literal / - // General-address-literal ) "]" - // ; See Section 4.1.3 - // - // http://tools.ietf.org/html/rfc5321#section-4.1.3 - // IPv4-address-literal = Snum 3("." Snum) - // - // IPv6-address-literal = "IPv6:" IPv6-addr - // - // General-address-literal = Standardized-tag ":" 1*dcontent - // - // Standardized-tag = Ldh-str - // ; Standardized-tag MUST be specified in a - // ; Standards-Track RFC and registered with IANA - // - // dcontent = %d33-90 / ; Printable US-ASCII - // %d94-126 ; excl. "[", "\", "]" - // - // Snum = 1*3DIGIT - // ; representing a decimal integer - // ; value in the range 0 through 255 - // - // IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp - // - // IPv6-hex = 1*4HEXDIG - // - // IPv6-full = IPv6-hex 7(":" IPv6-hex) - // - // IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::" - // [IPv6-hex *5(":" IPv6-hex)] - // ; The "::" represents at least 2 16-bit groups of - // ; zeros. No more than 6 groups in addition to the - // ; "::" may be present. - // - // IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal - // - // IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::" - // [IPv6-hex *3(":" IPv6-hex) ":"] - // IPv4-address-literal - // ; The "::" represents at least 2 16-bit groups of - // ; zeros. No more than 4 groups in addition to the - // ; "::" and IPv4-address-literal may be present. - // - // is_email() author's note: We can't use ip2long() to validate - // IPv4 addresses because it accepts abbreviated addresses - // (xxx.xxx.xxx), expanding the last group to complete the address. - // filter_var() validates IPv6 address inconsistently (up to PHP 5.3.3 - // at least) -- see http://bugs.php.net/bug.php?id=53236 for example - $max_groups = 8; - $matchesIP = array(); - /*.mixed.*/ $index = false; - $addressliteral = $parsedata[ISEMAIL_COMPONENT_LITERAL]; - - // Extract IPv4 part from the end of the address-literal (if there is one) - if (preg_match('/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', $addressliteral, $matchesIP) > 0) { - $index = strrpos($addressliteral, $matchesIP[0]); - if ($index !== 0) $addressliteral = substr($addressliteral, 0, $index) . '0:0'; // Convert IPv4 part to IPv6 format for further testing - } - - if ($index === 0) { - // Nothing there except a valid IPv4 address, so... - $return_status[] = ISEMAIL_RFC5321_ADDRESSLITERAL; - } elseif (strncasecmp($addressliteral, ISEMAIL_STRING_IPV6TAG, 5) !== 0) { - $return_status[] = ISEMAIL_RFC5322_DOMAINLITERAL; - } else { - $IPv6 = substr($addressliteral, 5); - $matchesIP = explode(ISEMAIL_STRING_COLON, $IPv6); // Revision 2.7: Daniel Marschall's new IPv6 testing strategy - $groupCount = count($matchesIP); - $index = strpos($IPv6,ISEMAIL_STRING_DOUBLECOLON); - - if ($index === false) { - // We need exactly the right number of groups - if ($groupCount !== $max_groups) - $return_status[] = ISEMAIL_RFC5322_IPV6_GRPCOUNT; - } else { - if ($index !== strrpos($IPv6,ISEMAIL_STRING_DOUBLECOLON)) - $return_status[] = ISEMAIL_RFC5322_IPV6_2X2XCOLON; - else { - if ($index === 0 || $index === (strlen($IPv6) - 2)) $max_groups++; // RFC 4291 allows :: at the start or end of an address with 7 other groups in addition - - if ($groupCount > $max_groups) - $return_status[] = ISEMAIL_RFC5322_IPV6_MAXGRPS; - elseif ($groupCount === $max_groups) - $return_status[] = ISEMAIL_RFC5321_IPV6DEPRECATED; // Eliding a single "::" - } - } - - // Revision 2.7: Daniel Marschall's new IPv6 testing strategy - if ((substr($IPv6, 0, 1) === ISEMAIL_STRING_COLON) && (substr($IPv6, 1, 1) !== ISEMAIL_STRING_COLON)) - $return_status[] = ISEMAIL_RFC5322_IPV6_COLONSTRT; // Address starts with a single colon - elseif ((substr($IPv6, -1) === ISEMAIL_STRING_COLON) && (substr($IPv6, -2, 1) !== ISEMAIL_STRING_COLON)) - $return_status[] = ISEMAIL_RFC5322_IPV6_COLONEND; // Address ends with a single colon - elseif (count(preg_grep('/^[0-9A-Fa-f]{0,4}$/', $matchesIP, PREG_GREP_INVERT)) !== 0) - $return_status[] = ISEMAIL_RFC5322_IPV6_BADCHAR; // Check for unmatched characters - else - $return_status[] = ISEMAIL_RFC5321_ADDRESSLITERAL; - } - } else - $return_status[] = ISEMAIL_RFC5322_DOMAINLITERAL; - - - $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; - $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] .= $token; - $element_len++; - $context_prior = $context; - $context = (int) array_pop($context_stack); - break; - case ISEMAIL_STRING_BACKSLASH: - $return_status[] = ISEMAIL_RFC5322_DOMLIT_OBSDTEXT; - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_QUOTEDPAIR; - break; - // Folding White Space - case ISEMAIL_STRING_CR: - case ISEMAIL_STRING_SP: - case ISEMAIL_STRING_HTAB: - if (($token === ISEMAIL_STRING_CR) && ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF))) {$return_status[] = ISEMAIL_ERR_CR_NO_LF; break;} // Fatal error - - $return_status[] = ISEMAIL_CFWS_FWS; - - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_FWS; - $token_prior = $token; - break; - // dtext - default: - // http://tools.ietf.org/html/rfc5322#section-3.4.1 - // dtext = %d33-90 / ; Printable US-ASCII - // %d94-126 / ; characters not including - // obs-dtext ; "[", "]", or "\" - // - // obs-dtext = obs-NO-WS-CTL / quoted-pair - // - // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - // %d11 / ; characters that do not - // %d12 / ; include the carriage - // %d14-31 / ; return, line feed, and - // %d127 ; white space characters - $ord = ord($token); - - // CR, LF, SP & HTAB have already been parsed above - if (($ord > 127) || ($ord === 0) || ($token === ISEMAIL_STRING_OPENSQBRACKET)) { - $return_status[] = ISEMAIL_ERR_EXPECTING_DTEXT; // Fatal error - break; - } elseif (($ord < 33) || ($ord === 127)) { - $return_status[] = ISEMAIL_RFC5322_DOMLIT_OBSDTEXT; - } - - $parsedata[ISEMAIL_COMPONENT_LITERAL] .= $token; - $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; - $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] .= $token; - $element_len++; - } - - break; - //------------------------------------------------------------- - // Quoted string - //------------------------------------------------------------- - case ISEMAIL_CONTEXT_QUOTEDSTRING: - // http://tools.ietf.org/html/rfc5322#section-3.2.4 - // quoted-string = [CFWS] - // DQUOTE *([FWS] qcontent) [FWS] DQUOTE - // [CFWS] - // - // qcontent = qtext / quoted-pair - switch ($token) { - // Quoted pair - case ISEMAIL_STRING_BACKSLASH: - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_QUOTEDPAIR; - break; - // Folding White Space - // Inside a quoted string, spaces are allowed as regular characters. - // It's only FWS if we include HTAB or CRLF - case ISEMAIL_STRING_CR: - case ISEMAIL_STRING_HTAB: - if (($token === ISEMAIL_STRING_CR) && ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF))) {$return_status[] = ISEMAIL_ERR_CR_NO_LF; break;} // Fatal error - - // http://tools.ietf.org/html/rfc5322#section-3.2.2 - // Runs of FWS, comment, or CFWS that occur between lexical tokens in a - // structured header field are semantically interpreted as a single - // space character. - - // http://tools.ietf.org/html/rfc5322#section-3.2.4 - // the CRLF in any FWS/CFWS that appears within the quoted-string [is] - // semantically "invisible" and therefore not part of the quoted-string - $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= ISEMAIL_STRING_SP; - $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= ISEMAIL_STRING_SP; - $element_len++; - - $return_status[] = ISEMAIL_CFWS_FWS; - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_FWS; - $token_prior = $token; - break; - // End of quoted string - case ISEMAIL_STRING_DQUOTE: - $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; - $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= $token; - $element_len++; - $context_prior = $context; - $context = (int) array_pop($context_stack); - break; - // qtext - default: - // http://tools.ietf.org/html/rfc5322#section-3.2.4 - // qtext = %d33 / ; Printable US-ASCII - // %d35-91 / ; characters not including - // %d93-126 / ; "\" or the quote character - // obs-qtext - // - // obs-qtext = obs-NO-WS-CTL - // - // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - // %d11 / ; characters that do not - // %d12 / ; include the carriage - // %d14-31 / ; return, line feed, and - // %d127 ; white space characters - $ord = ord($token); - - if (($ord > 127) || ($ord === 0) || ($ord === 10)) { - $return_status[] = ISEMAIL_ERR_EXPECTING_QTEXT; // Fatal error - } elseif (($ord < 32) || ($ord === 127)) - $return_status[] = ISEMAIL_DEPREC_QTEXT; - - $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; - $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= $token; - $element_len++; - } - - // http://tools.ietf.org/html/rfc5322#section-3.4.1 - // If the - // string can be represented as a dot-atom (that is, it contains no - // characters other than atext characters or "." surrounded by atext - // characters), then the dot-atom form SHOULD be used and the quoted- - // string form SHOULD NOT be used. -// To do - break; - //------------------------------------------------------------- - // Quoted pair - //------------------------------------------------------------- - case ISEMAIL_CONTEXT_QUOTEDPAIR: - // http://tools.ietf.org/html/rfc5322#section-3.2.1 - // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp - // - // VCHAR = %d33-126 ; visible (printing) characters - // WSP = SP / HTAB ; white space - // - // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) - // - // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - // %d11 / ; characters that do not - // %d12 / ; include the carriage - // %d14-31 / ; return, line feed, and - // %d127 ; white space characters - // - // i.e. obs-qp = "\" (%d0-8, %d10-31 / %d127) - $ord = ord($token); - - if ($ord > 127) - $return_status[] = ISEMAIL_ERR_EXPECTING_QPAIR; // Fatal error - elseif ((($ord < 31) && ($ord !== 9)) || ($ord === 127)) // SP & HTAB are allowed - $return_status[] = ISEMAIL_DEPREC_QP; - - // At this point we know where this qpair occurred so - // we could check to see if the character actually - // needed to be quoted at all. - // http://tools.ietf.org/html/rfc5321#section-4.1.2 - // the sending system SHOULD transmit the - // form that uses the minimum quoting possible. -// To do: check whether the character needs to be quoted (escaped) in this context - $context_prior = $context; - $context = (int) array_pop($context_stack); // End of qpair - $token = ISEMAIL_STRING_BACKSLASH . $token; - - switch ($context) { - case ISEMAIL_CONTEXT_COMMENT: - break; - case ISEMAIL_CONTEXT_QUOTEDSTRING: - $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; - $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= $token; - $element_len += 2; // The maximum sizes specified by RFC 5321 are octet counts, so we must include the backslash - break; - case ISEMAIL_COMPONENT_LITERAL: - $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; - $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] .= $token; - $element_len += 2; // The maximum sizes specified by RFC 5321 are octet counts, so we must include the backslash - break; - default: - die("Quoted pair logic invoked in an invalid context: $context"); - } - - break; - //------------------------------------------------------------- - // Comment - //------------------------------------------------------------- - case ISEMAIL_CONTEXT_COMMENT: - // http://tools.ietf.org/html/rfc5322#section-3.2.2 - // comment = "(" *([FWS] ccontent) [FWS] ")" - // - // ccontent = ctext / quoted-pair / comment - switch ($token) { - // Nested comment - case ISEMAIL_STRING_OPENPARENTHESIS: - // Nested comments are OK - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_COMMENT; - break; - // End of comment - case ISEMAIL_STRING_CLOSEPARENTHESIS: - $context_prior = $context; - $context = (int) array_pop($context_stack); - - // http://tools.ietf.org/html/rfc5322#section-3.2.2 - // Runs of FWS, comment, or CFWS that occur between lexical tokens in a - // structured header field are semantically interpreted as a single - // space character. - // - // is_email() author's note: This *cannot* mean that we must add a - // space to the address wherever CFWS appears. This would result in - // any addr-spec that had CFWS outside a quoted string being invalid - // for RFC 5321. -// if (($context === ISEMAIL_COMPONENT_LOCALPART) || ($context === ISEMAIL_COMPONENT_DOMAIN)) { -// $parsedata[$context] .= ISEMAIL_STRING_SP; -// $atomlist[$context][$element_count] .= ISEMAIL_STRING_SP; -// $element_len++; -// } - - break; - // Quoted pair - case ISEMAIL_STRING_BACKSLASH: - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_QUOTEDPAIR; - break; - // Folding White Space - case ISEMAIL_STRING_CR: - case ISEMAIL_STRING_SP: - case ISEMAIL_STRING_HTAB: - if (($token === ISEMAIL_STRING_CR) && ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF))) {$return_status[] = ISEMAIL_ERR_CR_NO_LF; break;} // Fatal error - - $return_status[] = ISEMAIL_CFWS_FWS; - - $context_stack[] = $context; - $context = ISEMAIL_CONTEXT_FWS; - $token_prior = $token; - break; - // ctext - default: - // http://tools.ietf.org/html/rfc5322#section-3.2.3 - // ctext = %d33-39 / ; Printable US-ASCII - // %d42-91 / ; characters not including - // %d93-126 / ; "(", ")", or "\" - // obs-ctext - // - // obs-ctext = obs-NO-WS-CTL - // - // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control - // %d11 / ; characters that do not - // %d12 / ; include the carriage - // %d14-31 / ; return, line feed, and - // %d127 ; white space characters - $ord = ord($token); - - if (($ord > 127) || ($ord === 0) || ($ord === 10)) { - $return_status[] = ISEMAIL_ERR_EXPECTING_CTEXT; // Fatal error - break; - } elseif (($ord < 32) || ($ord === 127)) { - $return_status[] = ISEMAIL_DEPREC_CTEXT; - } - } - - break; - //------------------------------------------------------------- - // Folding White Space - //------------------------------------------------------------- - case ISEMAIL_CONTEXT_FWS: - // http://tools.ietf.org/html/rfc5322#section-3.2.2 - // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS - // ; Folding white space - - // But note the erratum: - // http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908: - // In the obsolete syntax, any amount of folding white space MAY be - // inserted where the obs-FWS rule is allowed. This creates the - // possibility of having two consecutive "folds" in a line, and - // therefore the possibility that a line which makes up a folded header - // field could be composed entirely of white space. - // - // obs-FWS = 1*([CRLF] WSP) - if ($token_prior === ISEMAIL_STRING_CR) { - if ($token === ISEMAIL_STRING_CR) { - $return_status[] = ISEMAIL_ERR_FWS_CRLF_X2; // Fatal error - break; - } - - if (isset($crlf_count)) { - if (++$crlf_count > 1) - $return_status[] = ISEMAIL_DEPREC_FWS; // Multiple folds = obsolete FWS - } else $crlf_count = 1; - } - - switch ($token) { - case ISEMAIL_STRING_CR: - if ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF)) - $return_status[] = ISEMAIL_ERR_CR_NO_LF; // Fatal error - - break; - case ISEMAIL_STRING_SP: - case ISEMAIL_STRING_HTAB: - break; - default: - if ($token_prior === ISEMAIL_STRING_CR) { - $return_status[] = ISEMAIL_ERR_FWS_CRLF_END; // Fatal error - break; - } - - if (isset($crlf_count)) unset($crlf_count); - - $context_prior = $context; - $context = (int) array_pop($context_stack); // End of FWS - - // http://tools.ietf.org/html/rfc5322#section-3.2.2 - // Runs of FWS, comment, or CFWS that occur between lexical tokens in a - // structured header field are semantically interpreted as a single - // space character. - // - // is_email() author's note: This *cannot* mean that we must add a - // space to the address wherever CFWS appears. This would result in - // any addr-spec that had CFWS outside a quoted string being invalid - // for RFC 5321. -// if (($context === ISEMAIL_COMPONENT_LOCALPART) || ($context === ISEMAIL_COMPONENT_DOMAIN)) { -// $parsedata[$context] .= ISEMAIL_STRING_SP; -// $atomlist[$context][$element_count] .= ISEMAIL_STRING_SP; -// $element_len++; -// } - - $i--; // Look at this token again in the parent context - } - - $token_prior = $token; - break; - //------------------------------------------------------------- - // A context we aren't expecting - //------------------------------------------------------------- - default: - die("Unknown context: $context"); - } - -//-echo ""; // debug - if ((int) max($return_status) > ISEMAIL_RFC5322) break; // No point going on if we've got a fatal error - } - - // Some simple final tests - if ((int) max($return_status) < ISEMAIL_RFC5322) { - if ($context === ISEMAIL_CONTEXT_QUOTEDSTRING) $return_status[] = ISEMAIL_ERR_UNCLOSEDQUOTEDSTR; // Fatal error - elseif ($context === ISEMAIL_CONTEXT_QUOTEDPAIR) $return_status[] = ISEMAIL_ERR_BACKSLASHEND; // Fatal error - elseif ($context === ISEMAIL_CONTEXT_COMMENT) $return_status[] = ISEMAIL_ERR_UNCLOSEDCOMMENT; // Fatal error - elseif ($context === ISEMAIL_COMPONENT_LITERAL) $return_status[] = ISEMAIL_ERR_UNCLOSEDDOMLIT; // Fatal error - elseif ($token === ISEMAIL_STRING_CR) $return_status[] = ISEMAIL_ERR_FWS_CRLF_END; // Fatal error - elseif ($parsedata[ISEMAIL_COMPONENT_DOMAIN] === '') $return_status[] = ISEMAIL_ERR_NODOMAIN; // Fatal error - elseif ($element_len === 0) $return_status[] = ISEMAIL_ERR_DOT_END; // Fatal error - elseif ($hyphen_flag) $return_status[] = ISEMAIL_ERR_DOMAINHYPHENEND; // Fatal error - // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.2 - // The maximum total length of a domain name or number is 255 octets. - elseif (strlen($parsedata[ISEMAIL_COMPONENT_DOMAIN]) > 255) - $return_status[] = ISEMAIL_RFC5322_DOMAIN_TOOLONG; - // http://tools.ietf.org/html/rfc5321#section-4.1.2 - // Forward-path = Path - // - // Path = "<" [ A-d-l ":" ] Mailbox ">" - // - // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3 - // The maximum total length of a reverse-path or forward-path is 256 - // octets (including the punctuation and element separators). - // - // Thus, even without (obsolete) routing information, the Mailbox can - // only be 254 characters long. This is confirmed by this verified - // erratum to RFC 3696: - // - // http://www.rfc-editor.org/errata_search.php?rfc=3696&eid=1690 - // However, there is a restriction in RFC 2821 on the length of an - // address in MAIL and RCPT commands of 254 characters. Since addresses - // that do not fit in those fields are not normally useful, the upper - // limit on address lengths should normally be considered to be 254. - elseif (strlen($parsedata[ISEMAIL_COMPONENT_LOCALPART] . ISEMAIL_STRING_AT . $parsedata[ISEMAIL_COMPONENT_DOMAIN]) > 254) - $return_status[] = ISEMAIL_RFC5322_TOOLONG; - // http://tools.ietf.org/html/rfc1035#section-2.3.4 - // labels 63 octets or less - elseif ($element_len > 63) $return_status[] = ISEMAIL_RFC5322_LABEL_TOOLONG; - } - - // Check DNS? - $dns_checked = false; - - if ($checkDNS && ((int) max($return_status) < ISEMAIL_DNSWARN) && function_exists('dns_get_record')) { - // http://tools.ietf.org/html/rfc5321#section-2.3.5 - // Names that can - // be resolved to MX RRs or address (i.e., A or AAAA) RRs (as discussed - // in Section 5) are permitted, as are CNAME RRs whose targets can be - // resolved, in turn, to MX or address RRs. - // - // http://tools.ietf.org/html/rfc5321#section-5.1 - // The lookup first attempts to locate an MX record associated with the - // name. If a CNAME record is found, the resulting name is processed as - // if it were the initial name. ... If an empty list of MXs is returned, - // the address is treated as if it was associated with an implicit MX - // RR, with a preference of 0, pointing to that host. - // - // is_email() author's note: We will regard the existence of a CNAME to be - // sufficient evidence of the domain's existence. For performance reasons - // we will not repeat the DNS lookup for the CNAME's target, but we will - // raise a warning because we didn't immediately find an MX record. - if ($element_count === 0) $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= '.'; // Checking TLD DNS seems to work only if you explicitly check from the root - - $result = @dns_get_record($parsedata[ISEMAIL_COMPONENT_DOMAIN], DNS_MX); // Not using checkdnsrr because of a suspected bug in PHP 5.3 (http://bugs.php.net/bug.php?id=51844) - - if ((is_bool($result) && !(bool) $result)) - $return_status[] = ISEMAIL_DNSWARN_NO_RECORD; // Domain can't be found in DNS - else { - if (count($result) === 0) { - $return_status[] = ISEMAIL_DNSWARN_NO_MX_RECORD; // MX-record for domain can't be found - $result = @dns_get_record($parsedata[ISEMAIL_COMPONENT_DOMAIN], DNS_A + DNS_CNAME); - - if (count($result) === 0) - $return_status[] = ISEMAIL_DNSWARN_NO_RECORD; // No usable records for the domain can be found - } else $dns_checked = true; - } - } - - // Check for TLD addresses - // ----------------------- - // TLD addresses are specifically allowed in RFC 5321 but they are - // unusual to say the least. We will allocate a separate - // status to these addresses on the basis that they are more likely - // to be typos than genuine addresses (unless we've already - // established that the domain does have an MX record) - // - // http://tools.ietf.org/html/rfc5321#section-2.3.5 - // In the case - // of a top-level domain used by itself in an email address, a single - // string is used without any dots. This makes the requirement, - // described in more detail below, that only fully-qualified domain - // names appear in SMTP transactions on the public Internet, - // particularly important where top-level domains are involved. - // - // TLD format - // ---------- - // The format of TLDs has changed a number of times. The standards - // used by IANA have been largely ignored by ICANN, leading to - // confusion over the standards being followed. These are not defined - // anywhere, except as a general component of a DNS host name (a label). - // However, this could potentially lead to 123.123.123.123 being a - // valid DNS name (rather than an IP address) and thereby creating - // an ambiguity. The most authoritative statement on TLD formats that - // the author can find is in a (rejected!) erratum to RFC 1123 - // submitted by John Klensin, the author of RFC 5321: - // - // http://www.rfc-editor.org/errata_search.php?rfc=1123&eid=1353 - // However, a valid host name can never have the dotted-decimal - // form #.#.#.#, since this change does not permit the highest-level - // component label to start with a digit even if it is not all-numeric. - if (!$dns_checked && ((int) max($return_status) < ISEMAIL_DNSWARN)) { - if ($element_count === 0) $return_status[] = ISEMAIL_RFC5321_TLD; - - if (is_numeric($atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count][0])) - $return_status[] = ISEMAIL_RFC5321_TLDNUMERIC; - } - - $return_status = array_unique($return_status); - $final_status = (int) max($return_status); - - if (count($return_status) !== 1) array_shift($return_status); // remove redundant ISEMAIL_VALID - - $parsedata['status'] = $return_status; - - if ($final_status < $threshold) $final_status = ISEMAIL_VALID; - - return ($diagnose) ? $final_status : ($final_status < ISEMAIL_THRESHOLD); -} -?> + + * @copyright 2008-2011 Dominic Sayers + * @license http://www.opensource.org/licenses/bsd-license.php BSD License + * @link http://www.dominicsayers.com/isemail + * @version 3.04.1 - Changed my link to http://isemail.info throughout + */ + +// The quality of this code has been improved greatly by using PHPLint +// Copyright (c) 2010 Umberto Salsi +// This is free software; see the license for copying conditions. +// More info: http://www.icosaedro.it/phplint/ +/*. + require_module 'standard'; + require_module 'pcre'; +.*/ + +if (!defined('ISEMAIL_VALID')) { +/*:diagnostic constants start:*/ +// This part of the code is generated using data from test/meta.xml. Beware of making manual alterations + // Categories + define('ISEMAIL_VALID_CATEGORY', 1); + define('ISEMAIL_DNSWARN', 7); + define('ISEMAIL_RFC5321', 15); + define('ISEMAIL_CFWS', 31); + define('ISEMAIL_DEPREC', 63); + define('ISEMAIL_RFC5322', 127); + define('ISEMAIL_ERR', 255); + + // Diagnoses + // Address is valid + define('ISEMAIL_VALID', 0); + // Address is valid but a DNS check was not successful + define('ISEMAIL_DNSWARN_NO_MX_RECORD', 5); + define('ISEMAIL_DNSWARN_NO_RECORD', 6); + // Address is valid for SMTP but has unusual elements + define('ISEMAIL_RFC5321_TLD', 9); + define('ISEMAIL_RFC5321_TLDNUMERIC', 10); + define('ISEMAIL_RFC5321_QUOTEDSTRING', 11); + define('ISEMAIL_RFC5321_ADDRESSLITERAL', 12); + define('ISEMAIL_RFC5321_IPV6DEPRECATED', 13); + // Address is valid within the message but cannot be used unmodified for the envelope + define('ISEMAIL_CFWS_COMMENT', 17); + define('ISEMAIL_CFWS_FWS', 18); + // Address contains deprecated elements but may still be valid in restricted contexts + define('ISEMAIL_DEPREC_LOCALPART', 33); + define('ISEMAIL_DEPREC_FWS', 34); + define('ISEMAIL_DEPREC_QTEXT', 35); + define('ISEMAIL_DEPREC_QP', 36); + define('ISEMAIL_DEPREC_COMMENT', 37); + define('ISEMAIL_DEPREC_CTEXT', 38); + define('ISEMAIL_DEPREC_CFWS_NEAR_AT', 49); + // The address is only valid according to the broad definition of RFC 5322. It is otherwise invalid. + define('ISEMAIL_RFC5322_DOMAIN', 65); + define('ISEMAIL_RFC5322_TOOLONG', 66); + define('ISEMAIL_RFC5322_LOCAL_TOOLONG', 67); + define('ISEMAIL_RFC5322_DOMAIN_TOOLONG', 68); + define('ISEMAIL_RFC5322_LABEL_TOOLONG', 69); + define('ISEMAIL_RFC5322_DOMAINLITERAL', 70); + define('ISEMAIL_RFC5322_DOMLIT_OBSDTEXT', 71); + define('ISEMAIL_RFC5322_IPV6_GRPCOUNT', 72); + define('ISEMAIL_RFC5322_IPV6_2X2XCOLON', 73); + define('ISEMAIL_RFC5322_IPV6_BADCHAR', 74); + define('ISEMAIL_RFC5322_IPV6_MAXGRPS', 75); + define('ISEMAIL_RFC5322_IPV6_COLONSTRT', 76); + define('ISEMAIL_RFC5322_IPV6_COLONEND', 77); + // Address is invalid for any purpose + define('ISEMAIL_ERR_EXPECTING_DTEXT', 129); + define('ISEMAIL_ERR_NOLOCALPART', 130); + define('ISEMAIL_ERR_NODOMAIN', 131); + define('ISEMAIL_ERR_CONSECUTIVEDOTS', 132); + define('ISEMAIL_ERR_ATEXT_AFTER_CFWS', 133); + define('ISEMAIL_ERR_ATEXT_AFTER_QS', 134); + define('ISEMAIL_ERR_ATEXT_AFTER_DOMLIT', 135); + define('ISEMAIL_ERR_EXPECTING_QPAIR', 136); + define('ISEMAIL_ERR_EXPECTING_ATEXT', 137); + define('ISEMAIL_ERR_EXPECTING_QTEXT', 138); + define('ISEMAIL_ERR_EXPECTING_CTEXT', 139); + define('ISEMAIL_ERR_BACKSLASHEND', 140); + define('ISEMAIL_ERR_DOT_START', 141); + define('ISEMAIL_ERR_DOT_END', 142); + define('ISEMAIL_ERR_DOMAINHYPHENSTART', 143); + define('ISEMAIL_ERR_DOMAINHYPHENEND', 144); + define('ISEMAIL_ERR_UNCLOSEDQUOTEDSTR', 145); + define('ISEMAIL_ERR_UNCLOSEDCOMMENT', 146); + define('ISEMAIL_ERR_UNCLOSEDDOMLIT', 147); + define('ISEMAIL_ERR_FWS_CRLF_X2', 148); + define('ISEMAIL_ERR_FWS_CRLF_END', 149); + define('ISEMAIL_ERR_CR_NO_LF', 150); +// End of generated code +/*:diagnostic constants end:*/ + + // function control + define('ISEMAIL_THRESHOLD', 16); + + // Email parts + define('ISEMAIL_COMPONENT_LOCALPART', 0); + define('ISEMAIL_COMPONENT_DOMAIN', 1); + define('ISEMAIL_COMPONENT_LITERAL', 2); + define('ISEMAIL_CONTEXT_COMMENT', 3); + define('ISEMAIL_CONTEXT_FWS', 4); + define('ISEMAIL_CONTEXT_QUOTEDSTRING', 5); + define('ISEMAIL_CONTEXT_QUOTEDPAIR', 6); + + // Miscellaneous string constants + define('ISEMAIL_STRING_AT', '@'); + define('ISEMAIL_STRING_BACKSLASH', '\\'); + define('ISEMAIL_STRING_DOT', '.'); + define('ISEMAIL_STRING_DQUOTE', '"'); + define('ISEMAIL_STRING_OPENPARENTHESIS', '('); + define('ISEMAIL_STRING_CLOSEPARENTHESIS', ')'); + define('ISEMAIL_STRING_OPENSQBRACKET', '['); + define('ISEMAIL_STRING_CLOSESQBRACKET', ']'); + define('ISEMAIL_STRING_HYPHEN', '-'); + define('ISEMAIL_STRING_COLON', ':'); + define('ISEMAIL_STRING_DOUBLECOLON', '::'); + define('ISEMAIL_STRING_SP', ' '); + define('ISEMAIL_STRING_HTAB', "\t"); + define('ISEMAIL_STRING_CR', "\r"); + define('ISEMAIL_STRING_LF', "\n"); + define('ISEMAIL_STRING_IPV6TAG', 'IPv6:'); + // US-ASCII visible characters not valid for atext (http://tools.ietf.org/html/rfc5322#section-3.2.3) + define('ISEMAIL_STRING_SPECIALS', '()<>[]:;@\\,."'); +} + +/** + * Check that an email address conforms to RFCs 5321, 5322 and others + * + * As of Version 3.0, we are now distinguishing clearly between a Mailbox + * as defined by RFC 5321 and an addr-spec as defined by RFC 5322. Depending + * on the context, either can be regarded as a valid email address. The + * RFC 5321 Mailbox specification is more restrictive (comments, white space + * and obsolete forms are not allowed) + * + * @param string $email The email address to check + * @param boolean $checkDNS If true then a DNS check for MX records will be made + * @param mixed $errorlevel Determines the boundary between valid and invalid addresses. + * Status codes above this number will be returned as-is, + * status codes below will be returned as ISEMAIL_VALID. Thus the + * calling program can simply look for ISEMAIL_VALID if it is + * only interested in whether an address is valid or not. The + * errorlevel will determine how "picky" is_email() is about + * the address. + * + * If omitted or passed as false then is_email() will return + * true or false rather than an integer error or warning. + * + * NB Note the difference between $errorlevel = false and + * $errorlevel = 0 + * @param array $parsedata If passed, returns the parsed address components + */ +/*.mixed.*/ function is_email($email, $checkDNS = false, $errorlevel = false, &$parsedata = array()) { + // Check that $email is a valid address. Read the following RFCs to understand the constraints: + // (http://tools.ietf.org/html/rfc5321) + // (http://tools.ietf.org/html/rfc5322) + // (http://tools.ietf.org/html/rfc4291#section-2.2) + // (http://tools.ietf.org/html/rfc1123#section-2.1) + // (http://tools.ietf.org/html/rfc3696) (guidance only) + // version 2.0: Enhance $diagnose parameter to $errorlevel + // version 3.0: Introduced status categories + // revision 3.1: BUG: $parsedata was passed by value instead of by reference + + if (is_bool($errorlevel)) { + $threshold = ISEMAIL_VALID; + $diagnose = (bool) $errorlevel; + } else { + $diagnose = true; + + switch ((int) $errorlevel) { + case E_WARNING: + $threshold = ISEMAIL_THRESHOLD; + break; // For backward compatibility + case E_ERROR: + $threshold = ISEMAIL_VALID; + break; // For backward compatibility + default: + $threshold = (int) $errorlevel; + } + } + + $return_status = array(ISEMAIL_VALID); + + // Parse the address into components, character by character + $raw_length = strlen($email); + $context = ISEMAIL_COMPONENT_LOCALPART; // Where we are + $context_stack = array($context); // Where we have been + $context_prior = ISEMAIL_COMPONENT_LOCALPART; // Where we just came from + $token = ''; // The current character + $token_prior = ''; // The previous character + $parsedata = array( + ISEMAIL_COMPONENT_LOCALPART => '', + ISEMAIL_COMPONENT_DOMAIN => '' + ); // For the components of the address + + $atomlist = array( + ISEMAIL_COMPONENT_LOCALPART => array(''), + ISEMAIL_COMPONENT_DOMAIN => array('') + ); // For the dot-atom elements of the address + $element_count = 0; + $element_len = 0; + $hyphen_flag = false; // Hyphen cannot occur at the end of a subdomain + $end_or_die = false; // CFWS can only appear at the end of the element + +//-echo "
    $context|",(($end_or_die) ? 'true' : 'false'),"|$token|" . max($return_status) . "$context|",(($end_or_die) ? 'true' : 'false'),"|$token|" . max($return_status) . "
    "; // debug + for ($i = 0; $i < $raw_length; $i++) { + $token = $email[$i]; +//-echo ""; // debug + + switch ($context) { + //------------------------------------------------------------- + // local-part + //------------------------------------------------------------- + case ISEMAIL_COMPONENT_LOCALPART: + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // local-part = dot-atom / quoted-string / obs-local-part + // + // dot-atom = [CFWS] dot-atom-text [CFWS] + // + // dot-atom-text = 1*atext *("." 1*atext) + // + // quoted-string = [CFWS] + // DQUOTE *([FWS] qcontent) [FWS] DQUOTE + // [CFWS] + // + // obs-local-part = word *("." word) + // + // word = atom / quoted-string + // + // atom = [CFWS] 1*atext [CFWS] + switch ($token) { + // Comment + case ISEMAIL_STRING_OPENPARENTHESIS: + if ($element_len === 0) { + // Comments are OK at the beginning of an element + $return_status[] = ($element_count === 0) ? + ISEMAIL_CFWS_COMMENT : ISEMAIL_DEPREC_COMMENT; + } else { + $return_status[] = ISEMAIL_CFWS_COMMENT; + $end_or_die = true; + // We can't start a comment in the middle of an element, so this better be the end + } + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_COMMENT; + break; + // Next dot-atom element + case ISEMAIL_STRING_DOT: + if ($element_len === 0) { + // Another dot, already? + // Fatal error + $return_status[] = ($element_count === 0) + ? ISEMAIL_ERR_DOT_START : ISEMAIL_ERR_CONSECUTIVEDOTS; + } else { + // The entire local-part can be a quoted string for RFC 5321 + // If it's just one atom that is quoted then it's an RFC 5322 obsolete form + if ($end_or_die) { + $return_status[] = ISEMAIL_DEPREC_LOCALPART; + } + } + // CFWS & quoted strings are OK again now we're at the beginning of an element + // (although they are obsolete forms) + $end_or_die = false; + $element_len = 0; + $element_count++; + $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; + $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] = ''; + break; + // Quoted string + case ISEMAIL_STRING_DQUOTE: + if ($element_len === 0) { + // The entire local-part can be a quoted string for RFC 5321 + // If it's just one atom that is quoted then it's an RFC 5322 obsolete form + $return_status[] = ($element_count === 0) + ? ISEMAIL_RFC5321_QUOTEDSTRING : ISEMAIL_DEPREC_LOCALPART; + + $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; + $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= $token; + $element_len++; + $end_or_die = true; // Quoted string must be the entire element + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_QUOTEDSTRING; + } else { + $return_status[] = ISEMAIL_ERR_EXPECTING_ATEXT; // Fatal error + } + + break; + // Folding White Space + case ISEMAIL_STRING_CR: + case ISEMAIL_STRING_SP: + case ISEMAIL_STRING_HTAB: + if (($token === ISEMAIL_STRING_CR) + && ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF))) { + $return_status[] = ISEMAIL_ERR_CR_NO_LF; + break; + } // Fatal error + + if ($element_len === 0) { + $return_status[] = ($element_count === 0) ? ISEMAIL_CFWS_FWS : ISEMAIL_DEPREC_FWS; + } else { + // We can't start FWS in the middle of an element, so this better be the end + $end_or_die = true; + } + + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_FWS; + $token_prior = $token; + + break; + // @ + case ISEMAIL_STRING_AT: + // At this point we should have a valid local-part + if (count($context_stack) !== 1) { + die('Unexpected item on context stack'); + } + + if ($parsedata[ISEMAIL_COMPONENT_LOCALPART] === '') { + $return_status[] = ISEMAIL_ERR_NOLOCALPART; // Fatal error + } elseif ($element_len === 0) { + $return_status[] = ISEMAIL_ERR_DOT_END; // Fatal error + } elseif (strlen($parsedata[ISEMAIL_COMPONENT_LOCALPART]) > 64) { + // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.1 + // The maximum total length of a user name or other local-part is 64 + // octets. + $return_status[] = ISEMAIL_RFC5322_LOCAL_TOOLONG; + } elseif (($context_prior === ISEMAIL_CONTEXT_COMMENT) || ($context_prior === ISEMAIL_CONTEXT_FWS)) { + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // Comments and folding white space + // SHOULD NOT be used around the "@" in the addr-spec. + // + // http://tools.ietf.org/html/rfc2119 + // 4. SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean that + // there may exist valid reasons in particular circumstances when the + // particular behavior is acceptable or even useful, but the full + // implications should be understood and the case carefully weighed + // before implementing any behavior described with this label. + $return_status[] = ISEMAIL_DEPREC_CFWS_NEAR_AT; + } + // Clear everything down for the domain parsing + $context = ISEMAIL_COMPONENT_DOMAIN; // Where we are + $context_stack = array($context); // Where we have been + $element_count = 0; + $element_len = 0; + $end_or_die = false; // CFWS can only appear at the end of the element + + break; + // atext + default: + // http://tools.ietf.org/html/rfc5322#section-3.2.3 + // atext = ALPHA / DIGIT / ; Printable US-ASCII + // "!" / "#" / ; characters not including + // "$" / "%" / ; specials. Used for atoms. + // "&" / "'" / + // "*" / "+" / + // "-" / "/" / + // "=" / "?" / + // "^" / "_" / + // "`" / "{" / + // "|" / "}" / + // "~" + if ($end_or_die) { + // We have encountered atext where it is no longer valid + switch ($context_prior) { + case ISEMAIL_CONTEXT_COMMENT: + case ISEMAIL_CONTEXT_FWS: + $return_status[] = ISEMAIL_ERR_ATEXT_AFTER_CFWS; + break; + case ISEMAIL_CONTEXT_QUOTEDSTRING: + $return_status[] = ISEMAIL_ERR_ATEXT_AFTER_QS; + break; + default: + die("More atext found where none is allowed, but unrecognised prior context: $context_prior"); + } + } else { + $context_prior = $context; + $ord = ord($token); + if (($ord < 33) || ($ord > 126) || ($ord === 10) + || (!is_bool(strpos(ISEMAIL_STRING_SPECIALS, $token)))) { + $return_status[] = ISEMAIL_ERR_EXPECTING_ATEXT; // Fatal error + } + + $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; + $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= $token; + $element_len++; + } + } + break; + //------------------------------------------------------------- + // Domain + //------------------------------------------------------------- + case ISEMAIL_COMPONENT_DOMAIN: + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // domain = dot-atom / domain-literal / obs-domain + // + // dot-atom = [CFWS] dot-atom-text [CFWS] + // + // dot-atom-text = 1*atext *("." 1*atext) + // + // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] + // + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + // + // obs-domain = atom *("." atom) + // + // atom = [CFWS] 1*atext [CFWS] + + + // http://tools.ietf.org/html/rfc5321#section-4.1.2 + // Mailbox = Local-part "@" ( Domain / address-literal ) + // + // Domain = sub-domain *("." sub-domain) + // + // address-literal = "[" ( IPv4-address-literal / + // IPv6-address-literal / + // General-address-literal ) "]" + // ; See Section 4.1.3 + + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // Note: A liberal syntax for the domain portion of addr-spec is + // given here. However, the domain portion contains addressing + // information specified by and used in other protocols (e.g., + // [RFC1034], [RFC1035], [RFC1123], [RFC5321]). It is therefore + // incumbent upon implementations to conform to the syntax of + // addresses for the context in which they are used. + // is_email() author's note: it's not clear how to interpret this in + // the context of a general email address validator. The conclusion I + // have reached is this: "addressing information" must comply with + // RFC 5321 (and in turn RFC 1035), anything that is "semantically + // invisible" must comply only with RFC 5322. + switch ($token) { + // Comment + case ISEMAIL_STRING_OPENPARENTHESIS: + if ($element_len === 0) { + // Comments at the start of the domain are deprecated in the text + // Comments at the start of a subdomain are obs-domain + // (http://tools.ietf.org/html/rfc5322#section-3.4.1) + $return_status[] = ($element_count === 0) ? + ISEMAIL_DEPREC_CFWS_NEAR_AT : ISEMAIL_DEPREC_COMMENT; + } else { + $return_status[] = ISEMAIL_CFWS_COMMENT; + // We can't start a comment in the middle of an element, so this better be the end + $end_or_die = true; + } + + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_COMMENT; + break; + // Next dot-atom element + case ISEMAIL_STRING_DOT: + if ($element_len === 0) { + // Another dot, already? + $return_status[] = ($element_count === 0) ? + ISEMAIL_ERR_DOT_START : ISEMAIL_ERR_CONSECUTIVEDOTS; // Fatal error + } elseif ($hyphen_flag) { + // Previous subdomain ended in a hyphen + $return_status[] = ISEMAIL_ERR_DOMAINHYPHENEND; // Fatal error + } else { + // Nowhere in RFC 5321 does it say explicitly that the + // domain part of a Mailbox must be a valid domain according + // to the DNS standards set out in RFC 1035, but this *is* + // implied in several places. For instance, wherever the idea + // of host routing is discussed the RFC says that the domain + // must be looked up in the DNS. This would be nonsense unless + // the domain was designed to be a valid DNS domain. Hence we + // must conclude that the RFC 1035 restriction on label length + // also applies to RFC 5321 domains. + // + // http://tools.ietf.org/html/rfc1035#section-2.3.4 + // labels 63 octets or less + if ($element_len > 63) { + $return_status[] = ISEMAIL_RFC5322_LABEL_TOOLONG; + } + } + // CFWS is OK again now we're at the beginning of an element + // (although it may be obsolete CFWS) + $end_or_die = false; + $element_len = 0; + $element_count++; + $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] = ''; + $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; + + break; + // Domain literal + case ISEMAIL_STRING_OPENSQBRACKET: + if ($parsedata[ISEMAIL_COMPONENT_DOMAIN] === '') { + $end_or_die = true; // Domain literal must be the only component + $element_len++; + $context_stack[] = $context; + $context = ISEMAIL_COMPONENT_LITERAL; + $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; + $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] .= $token; + $parsedata[ISEMAIL_COMPONENT_LITERAL] = ''; + } else { + $return_status[] = ISEMAIL_ERR_EXPECTING_ATEXT; // Fatal error + } + + break; + // Folding White Space + case ISEMAIL_STRING_CR: + case ISEMAIL_STRING_SP: + case ISEMAIL_STRING_HTAB: + if (($token === ISEMAIL_STRING_CR) && ((++$i === $raw_length) + || ($email[$i] !== ISEMAIL_STRING_LF))) { + $return_status[] = ISEMAIL_ERR_CR_NO_LF; + break; + } // Fatal error + + if ($element_len === 0) { + $return_status[] = ($element_count === 0) ? + ISEMAIL_DEPREC_CFWS_NEAR_AT : ISEMAIL_DEPREC_FWS; + } else { + $return_status[] = ISEMAIL_CFWS_FWS; + // We can't start FWS in the middle of an element, so this better be the end + $end_or_die = true; + } + + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_FWS; + $token_prior = $token; + break; + // atext + default: + // RFC 5322 allows any atext... + // http://tools.ietf.org/html/rfc5322#section-3.2.3 + // atext = ALPHA / DIGIT / ; Printable US-ASCII + // "!" / "#" / ; characters not including + // "$" / "%" / ; specials. Used for atoms. + // "&" / "'" / + // "*" / "+" / + // "-" / "/" / + // "=" / "?" / + // "^" / "_" / + // "`" / "{" / + // "|" / "}" / + // "~" + + // But RFC 5321 only allows letter-digit-hyphen to comply with DNS rules (RFCs 1034 & 1123) + // http://tools.ietf.org/html/rfc5321#section-4.1.2 + // sub-domain = Let-dig [Ldh-str] + // + // Let-dig = ALPHA / DIGIT + // + // Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig + // + if ($end_or_die) { + // We have encountered atext where it is no longer valid + switch ($context_prior) { + case ISEMAIL_CONTEXT_COMMENT: + case ISEMAIL_CONTEXT_FWS: + $return_status[] = ISEMAIL_ERR_ATEXT_AFTER_CFWS; + break; + case ISEMAIL_COMPONENT_LITERAL: + $return_status[] = ISEMAIL_ERR_ATEXT_AFTER_DOMLIT; + break; + default: + die("More atext found where none is allowed, but unrecognised prior context: $context_prior"); + } + } + + $ord = ord($token); + $hyphen_flag = false; // Assume this token isn't a hyphen unless we discover it is + + if (($ord < 33) || ($ord > 126) || (!is_bool(strpos(ISEMAIL_STRING_SPECIALS, $token)))) { + $return_status[] = ISEMAIL_ERR_EXPECTING_ATEXT; // Fatal error + } elseif ($token === ISEMAIL_STRING_HYPHEN) { + if ($element_len === 0) { + // Hyphens can't be at the beginning of a subdomain + $return_status[] = ISEMAIL_ERR_DOMAINHYPHENSTART; // Fatal error + } + + $hyphen_flag = true; + } elseif (!(($ord > 47 && $ord < 58) + || ($ord > 64 && $ord < 91) + || ($ord > 96 && $ord < 123))) { + // Not an RFC 5321 subdomain, but still OK by RFC 5322 + $return_status[] = ISEMAIL_RFC5322_DOMAIN; + } + + $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; + $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] .= $token; + $element_len++; + } + break; + //------------------------------------------------------------- + // Domain literal + //------------------------------------------------------------- + case ISEMAIL_COMPONENT_LITERAL: + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS] + // + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + // + // obs-dtext = obs-NO-WS-CTL / quoted-pair + switch ($token) { + // End of domain literal + case ISEMAIL_STRING_CLOSESQBRACKET: + if ((int) max($return_status) < ISEMAIL_DEPREC) { + // Could be a valid RFC 5321 address literal, so let's check + + // http://tools.ietf.org/html/rfc5321#section-4.1.2 + // address-literal = "[" ( IPv4-address-literal / + // IPv6-address-literal / + // General-address-literal ) "]" + // ; See Section 4.1.3 + // + // http://tools.ietf.org/html/rfc5321#section-4.1.3 + // IPv4-address-literal = Snum 3("." Snum) + // + // IPv6-address-literal = "IPv6:" IPv6-addr + // + // General-address-literal = Standardized-tag ":" 1*dcontent + // + // Standardized-tag = Ldh-str + // ; Standardized-tag MUST be specified in a + // ; Standards-Track RFC and registered with IANA + // + // dcontent = %d33-90 / ; Printable US-ASCII + // %d94-126 ; excl. "[", "\", "]" + // + // Snum = 1*3DIGIT + // ; representing a decimal integer + // ; value in the range 0 through 255 + // + // IPv6-addr = IPv6-full / IPv6-comp / IPv6v4-full / IPv6v4-comp + // + // IPv6-hex = 1*4HEXDIG + // + // IPv6-full = IPv6-hex 7(":" IPv6-hex) + // + // IPv6-comp = [IPv6-hex *5(":" IPv6-hex)] "::" + // [IPv6-hex *5(":" IPv6-hex)] + // ; The "::" represents at least 2 16-bit groups of + // ; zeros. No more than 6 groups in addition to the + // ; "::" may be present. + // + // IPv6v4-full = IPv6-hex 5(":" IPv6-hex) ":" IPv4-address-literal + // + // IPv6v4-comp = [IPv6-hex *3(":" IPv6-hex)] "::" + // [IPv6-hex *3(":" IPv6-hex) ":"] + // IPv4-address-literal + // ; The "::" represents at least 2 16-bit groups of + // ; zeros. No more than 4 groups in addition to the + // ; "::" and IPv4-address-literal may be present. + // + // is_email() author's note: We can't use ip2long() to validate + // IPv4 addresses because it accepts abbreviated addresses + // (xxx.xxx.xxx), expanding the last group to complete the address. + // filter_var() validates IPv6 address inconsistently (up to PHP 5.3.3 + // at least) -- see http://bugs.php.net/bug.php?id=53236 for example + $max_groups = 8; + $matchesIP = array(); + /*.mixed.*/ $index = false; + $addressliteral = $parsedata[ISEMAIL_COMPONENT_LITERAL]; + + // Extract IPv4 part from the end of the address-literal (if there is one) + if (preg_match( + '/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', + $addressliteral, + $matchesIP + ) > 0) { + $index = strrpos($addressliteral, $matchesIP[0]); + if ($index !== 0) { + // Convert IPv4 part to IPv6 format for further testing + $addressliteral = substr($addressliteral, 0, $index) . '0:0'; + } + } + + if ($index === 0) { + // Nothing there except a valid IPv4 address, so... + $return_status[] = ISEMAIL_RFC5321_ADDRESSLITERAL; + } elseif (strncasecmp($addressliteral, ISEMAIL_STRING_IPV6TAG, 5) !== 0) { + $return_status[] = ISEMAIL_RFC5322_DOMAINLITERAL; + } else { + $IPv6 = substr($addressliteral, 5); + // Revision 2.7: Daniel Marschall's new IPv6 testing strategy + $matchesIP = explode(ISEMAIL_STRING_COLON, $IPv6); + $groupCount = count($matchesIP); + $index = strpos($IPv6, ISEMAIL_STRING_DOUBLECOLON); + + if ($index === false) { + // We need exactly the right number of groups + if ($groupCount !== $max_groups) { + $return_status[] = ISEMAIL_RFC5322_IPV6_GRPCOUNT; + } + } else { + if ($index !== strrpos($IPv6, ISEMAIL_STRING_DOUBLECOLON)) { + $return_status[] = ISEMAIL_RFC5322_IPV6_2X2XCOLON; + } else { + if ($index === 0 || $index === (strlen($IPv6) - 2)) { + $max_groups++; + // RFC 4291 allows :: at the start or end of an address with 7 other groups in addition + } + + if ($groupCount > $max_groups) { + $return_status[] = ISEMAIL_RFC5322_IPV6_MAXGRPS; + } elseif ($groupCount === $max_groups) { + $return_status[] = ISEMAIL_RFC5321_IPV6DEPRECATED; // Eliding a single "::" + } + } + } + + // Revision 2.7: Daniel Marschall's new IPv6 testing strategy + if ((substr($IPv6, 0, 1) === ISEMAIL_STRING_COLON) && (substr($IPv6, 1, 1) !== ISEMAIL_STRING_COLON)) { + $return_status[] = ISEMAIL_RFC5322_IPV6_COLONSTRT; // Address starts with a single colon + } elseif ((substr($IPv6, -1) === ISEMAIL_STRING_COLON) && (substr($IPv6, -2, 1) !== ISEMAIL_STRING_COLON)) { + $return_status[] = ISEMAIL_RFC5322_IPV6_COLONEND; // Address ends with a single colon + } elseif (count(preg_grep('/^[0-9A-Fa-f]{0,4}$/', $matchesIP, PREG_GREP_INVERT)) !== 0) { + $return_status[] = ISEMAIL_RFC5322_IPV6_BADCHAR; // Check for unmatched characters + } else { + $return_status[] = ISEMAIL_RFC5321_ADDRESSLITERAL; + } + } + } else { + $return_status[] = ISEMAIL_RFC5322_DOMAINLITERAL; + } + + $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; + $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] .= $token; + $element_len++; + $context_prior = $context; + $context = (int) array_pop($context_stack); + break; + case ISEMAIL_STRING_BACKSLASH: + $return_status[] = ISEMAIL_RFC5322_DOMLIT_OBSDTEXT; + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_QUOTEDPAIR; + break; + // Folding White Space + case ISEMAIL_STRING_CR: + case ISEMAIL_STRING_SP: + case ISEMAIL_STRING_HTAB: + if (($token === ISEMAIL_STRING_CR) + && ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF))) { + $return_status[] = ISEMAIL_ERR_CR_NO_LF; + break; + } // Fatal error + + $return_status[] = ISEMAIL_CFWS_FWS; + + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_FWS; + $token_prior = $token; + break; + // dtext + default: + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // dtext = %d33-90 / ; Printable US-ASCII + // %d94-126 / ; characters not including + // obs-dtext ; "[", "]", or "\" + // + // obs-dtext = obs-NO-WS-CTL / quoted-pair + // + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + $ord = ord($token); + + // CR, LF, SP & HTAB have already been parsed above + if (($ord > 127) || ($ord === 0) || ($token === ISEMAIL_STRING_OPENSQBRACKET)) { + $return_status[] = ISEMAIL_ERR_EXPECTING_DTEXT; // Fatal error + break; + } elseif (($ord < 33) || ($ord === 127)) { + $return_status[] = ISEMAIL_RFC5322_DOMLIT_OBSDTEXT; + } + + $parsedata[ISEMAIL_COMPONENT_LITERAL] .= $token; + $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; + $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] .= $token; + $element_len++; + } + break; + //------------------------------------------------------------- + // Quoted string + //------------------------------------------------------------- + case ISEMAIL_CONTEXT_QUOTEDSTRING: + // http://tools.ietf.org/html/rfc5322#section-3.2.4 + // quoted-string = [CFWS] + // DQUOTE *([FWS] qcontent) [FWS] DQUOTE + // [CFWS] + // + // qcontent = qtext / quoted-pair + switch ($token) { + // Quoted pair + case ISEMAIL_STRING_BACKSLASH: + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_QUOTEDPAIR; + break; + // Folding White Space + // Inside a quoted string, spaces are allowed as regular characters. + // It's only FWS if we include HTAB or CRLF + case ISEMAIL_STRING_CR: + case ISEMAIL_STRING_HTAB: + if (($token === ISEMAIL_STRING_CR) + && ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF))) { + $return_status[] = ISEMAIL_ERR_CR_NO_LF; + break; + }// Fatal error + + // http://tools.ietf.org/html/rfc5322#section-3.2.2 + // Runs of FWS, comment, or CFWS that occur between lexical tokens in a + // structured header field are semantically interpreted as a single + // space character. + + // http://tools.ietf.org/html/rfc5322#section-3.2.4 + // the CRLF in any FWS/CFWS that appears within the quoted-string [is] + // semantically "invisible" and therefore not part of the quoted-string + $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= ISEMAIL_STRING_SP; + $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= ISEMAIL_STRING_SP; + $element_len++; + + $return_status[] = ISEMAIL_CFWS_FWS; + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_FWS; + $token_prior = $token; + break; + // End of quoted string + case ISEMAIL_STRING_DQUOTE: + $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; + $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= $token; + $element_len++; + $context_prior = $context; + $context = (int) array_pop($context_stack); + break; + // qtext + default: + // http://tools.ietf.org/html/rfc5322#section-3.2.4 + // qtext = %d33 / ; Printable US-ASCII + // %d35-91 / ; characters not including + // %d93-126 / ; "\" or the quote character + // obs-qtext + // + // obs-qtext = obs-NO-WS-CTL + // + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + $ord = ord($token); + + if (($ord > 127) || ($ord === 0) || ($ord === 10)) { + $return_status[] = ISEMAIL_ERR_EXPECTING_QTEXT; // Fatal error + } elseif (($ord < 32) || ($ord === 127)) { + $return_status[] = ISEMAIL_DEPREC_QTEXT; + } + + $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; + $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= $token; + $element_len++; + } + + // http://tools.ietf.org/html/rfc5322#section-3.4.1 + // If the + // string can be represented as a dot-atom (that is, it contains no + // characters other than atext characters or "." surrounded by atext + // characters), then the dot-atom form SHOULD be used and the quoted- + // string form SHOULD NOT be used. + // To do + break; + //------------------------------------------------------------- + // Quoted pair + //------------------------------------------------------------- + case ISEMAIL_CONTEXT_QUOTEDPAIR: + // http://tools.ietf.org/html/rfc5322#section-3.2.1 + // quoted-pair = ("\" (VCHAR / WSP)) / obs-qp + // + // VCHAR = %d33-126 ; visible (printing) characters + // WSP = SP / HTAB ; white space + // + // obs-qp = "\" (%d0 / obs-NO-WS-CTL / LF / CR) + // + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + // + // i.e. obs-qp = "\" (%d0-8, %d10-31 / %d127) + $ord = ord($token); + + if ($ord > 127) { + $return_status[] = ISEMAIL_ERR_EXPECTING_QPAIR; // Fatal error + } elseif ((($ord < 31) && ($ord !== 9)) || ($ord === 127)) { + // SP & HTAB are allowed + $return_status[] = ISEMAIL_DEPREC_QP; + } + + // At this point we know where this qpair occurred so + // we could check to see if the character actually + // needed to be quoted at all. + // http://tools.ietf.org/html/rfc5321#section-4.1.2 + // the sending system SHOULD transmit the + // form that uses the minimum quoting possible. + // To do: check whether the character needs to be quoted (escaped) in this context + $context_prior = $context; + $context = (int) array_pop($context_stack); // End of qpair + $token = ISEMAIL_STRING_BACKSLASH . $token; + + switch ($context) { + case ISEMAIL_CONTEXT_COMMENT: + break; + case ISEMAIL_CONTEXT_QUOTEDSTRING: + $parsedata[ISEMAIL_COMPONENT_LOCALPART] .= $token; + $atomlist[ISEMAIL_COMPONENT_LOCALPART][$element_count] .= $token; + $element_len += 2; + // The maximum sizes specified by RFC 5321 are octet counts, so we must include the backslash + break; + case ISEMAIL_COMPONENT_LITERAL: + $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= $token; + $atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count] .= $token; + $element_len += 2; + // The maximum sizes specified by RFC 5321 are octet counts, so we must include the backslash + break; + default: + die("Quoted pair logic invoked in an invalid context: $context"); + } + + break; + //------------------------------------------------------------- + // Comment + //------------------------------------------------------------- + case ISEMAIL_CONTEXT_COMMENT: + // http://tools.ietf.org/html/rfc5322#section-3.2.2 + // comment = "(" *([FWS] ccontent) [FWS] ")" + // + // ccontent = ctext / quoted-pair / comment + switch ($token) { + // Nested comment + case ISEMAIL_STRING_OPENPARENTHESIS: + // Nested comments are OK + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_COMMENT; + break; + // End of comment + case ISEMAIL_STRING_CLOSEPARENTHESIS: + $context_prior = $context; + $context = (int) array_pop($context_stack); + + // http://tools.ietf.org/html/rfc5322#section-3.2.2 + // Runs of FWS, comment, or CFWS that occur between lexical tokens in a + // structured header field are semantically interpreted as a single + // space character. + // + // is_email() author's note: This *cannot* mean that we must add a + // space to the address wherever CFWS appears. This would result in + // any addr-spec that had CFWS outside a quoted string being invalid + // for RFC 5321. + // if (($context === ISEMAIL_COMPONENT_LOCALPART) || ($context === ISEMAIL_COMPONENT_DOMAIN)) { + // $parsedata[$context] .= ISEMAIL_STRING_SP; + // $atomlist[$context][$element_count] .= ISEMAIL_STRING_SP; + // $element_len++; + // } + + break; + // Quoted pair + case ISEMAIL_STRING_BACKSLASH: + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_QUOTEDPAIR; + break; + // Folding White Space + case ISEMAIL_STRING_CR: + case ISEMAIL_STRING_SP: + case ISEMAIL_STRING_HTAB: + if (($token === ISEMAIL_STRING_CR) + && ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF))) { + $return_status[] = ISEMAIL_ERR_CR_NO_LF; + break; + } // Fatal error + + $return_status[] = ISEMAIL_CFWS_FWS; + + $context_stack[] = $context; + $context = ISEMAIL_CONTEXT_FWS; + $token_prior = $token; + break; + // ctext + default: + // http://tools.ietf.org/html/rfc5322#section-3.2.3 + // ctext = %d33-39 / ; Printable US-ASCII + // %d42-91 / ; characters not including + // %d93-126 / ; "(", ")", or "\" + // obs-ctext + // + // obs-ctext = obs-NO-WS-CTL + // + // obs-NO-WS-CTL = %d1-8 / ; US-ASCII control + // %d11 / ; characters that do not + // %d12 / ; include the carriage + // %d14-31 / ; return, line feed, and + // %d127 ; white space characters + $ord = ord($token); + + if (($ord > 127) || ($ord === 0) || ($ord === 10)) { + $return_status[] = ISEMAIL_ERR_EXPECTING_CTEXT; // Fatal error + break; + } elseif (($ord < 32) || ($ord === 127)) { + $return_status[] = ISEMAIL_DEPREC_CTEXT; + } + } + break; + //------------------------------------------------------------- + // Folding White Space + //------------------------------------------------------------- + case ISEMAIL_CONTEXT_FWS: + // http://tools.ietf.org/html/rfc5322#section-3.2.2 + // FWS = ([*WSP CRLF] 1*WSP) / obs-FWS + // ; Folding white space + + // But note the erratum: + // http://www.rfc-editor.org/errata_search.php?rfc=5322&eid=1908: + // In the obsolete syntax, any amount of folding white space MAY be + // inserted where the obs-FWS rule is allowed. This creates the + // possibility of having two consecutive "folds" in a line, and + // therefore the possibility that a line which makes up a folded header + // field could be composed entirely of white space. + // + // obs-FWS = 1*([CRLF] WSP) + if ($token_prior === ISEMAIL_STRING_CR) { + if ($token === ISEMAIL_STRING_CR) { + $return_status[] = ISEMAIL_ERR_FWS_CRLF_X2; // Fatal error + break; + } + if (isset($crlf_count)) { + if (++$crlf_count > 1) { + $return_status[] = ISEMAIL_DEPREC_FWS; // Multiple folds = obsolete FWS + } + } else { + $crlf_count = 1; + } + } + + switch ($token) { + case ISEMAIL_STRING_CR: + if ((++$i === $raw_length) || ($email[$i] !== ISEMAIL_STRING_LF)) { + $return_status[] = ISEMAIL_ERR_CR_NO_LF; // Fatal error + } + break; + case ISEMAIL_STRING_SP: + case ISEMAIL_STRING_HTAB: + break; + default: + if ($token_prior === ISEMAIL_STRING_CR) { + $return_status[] = ISEMAIL_ERR_FWS_CRLF_END; // Fatal error + break; + } + + if (isset($crlf_count)) { + unset($crlf_count); + } + + $context_prior = $context; + $context = (int) array_pop($context_stack); // End of FWS + + // http://tools.ietf.org/html/rfc5322#section-3.2.2 + // Runs of FWS, comment, or CFWS that occur between lexical tokens in a + // structured header field are semantically interpreted as a single + // space character. + // + // is_email() author's note: This *cannot* mean that we must add a + // space to the address wherever CFWS appears. This would result in + // any addr-spec that had CFWS outside a quoted string being invalid + // for RFC 5321. + // if (($context === ISEMAIL_COMPONENT_LOCALPART) || ($context === ISEMAIL_COMPONENT_DOMAIN)) { + // $parsedata[$context] .= ISEMAIL_STRING_SP; + // $atomlist[$context][$element_count] .= ISEMAIL_STRING_SP; + // $element_len++; + // } + + $i--; // Look at this token again in the parent context + } + + $token_prior = $token; + break; + //------------------------------------------------------------- + // A context we aren't expecting + //------------------------------------------------------------- + default: + die("Unknown context: $context"); + } + +//-echo ""; // debug + if ((int) max($return_status) > ISEMAIL_RFC5322) { + break; // No point going on if we've got a fatal error + } + } + + // Some simple final tests + if ((int) max($return_status) < ISEMAIL_RFC5322) { + if ($context === ISEMAIL_CONTEXT_QUOTEDSTRING) { + $return_status[] = ISEMAIL_ERR_UNCLOSEDQUOTEDSTR; // Fatal error + } elseif ($context === ISEMAIL_CONTEXT_QUOTEDPAIR) { + $return_status[] = ISEMAIL_ERR_BACKSLASHEND; // Fatal error + } elseif ($context === ISEMAIL_CONTEXT_COMMENT) { + $return_status[] = ISEMAIL_ERR_UNCLOSEDCOMMENT; // Fatal error + } elseif ($context === ISEMAIL_COMPONENT_LITERAL) { + $return_status[] = ISEMAIL_ERR_UNCLOSEDDOMLIT; // Fatal error + } elseif ($token === ISEMAIL_STRING_CR) { + $return_status[] = ISEMAIL_ERR_FWS_CRLF_END; // Fatal error + } elseif ($parsedata[ISEMAIL_COMPONENT_DOMAIN] === '') { + $return_status[] = ISEMAIL_ERR_NODOMAIN; // Fatal error + } elseif ($element_len === 0) { + $return_status[] = ISEMAIL_ERR_DOT_END; // Fatal error + } elseif ($hyphen_flag) { + $return_status[] = ISEMAIL_ERR_DOMAINHYPHENEND; // Fatal error + } elseif (strlen($parsedata[ISEMAIL_COMPONENT_DOMAIN]) > 255) { + // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.2 + // The maximum total length of a domain name or number is 255 octets. + $return_status[] = ISEMAIL_RFC5322_DOMAIN_TOOLONG; + } elseif (strlen( + $parsedata[ISEMAIL_COMPONENT_LOCALPART] . ISEMAIL_STRING_AT . $parsedata[ISEMAIL_COMPONENT_DOMAIN] + ) > 254) { + // http://tools.ietf.org/html/rfc5321#section-4.1.2 + // Forward-path = Path + // + // Path = "<" [ A-d-l ":" ] Mailbox ">" + // + // http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3 + // The maximum total length of a reverse-path or forward-path is 256 + // octets (including the punctuation and element separators). + // + // Thus, even without (obsolete) routing information, the Mailbox can + // only be 254 characters long. This is confirmed by this verified + // erratum to RFC 3696: + // + // http://www.rfc-editor.org/errata_search.php?rfc=3696&eid=1690 + // However, there is a restriction in RFC 2821 on the length of an + // address in MAIL and RCPT commands of 254 characters. Since addresses + // that do not fit in those fields are not normally useful, the upper + // limit on address lengths should normally be considered to be 254. + $return_status[] = ISEMAIL_RFC5322_TOOLONG; + } elseif ($element_len > 63) { + // http://tools.ietf.org/html/rfc1035#section-2.3.4 + // labels 63 octets or less + $return_status[] = ISEMAIL_RFC5322_LABEL_TOOLONG; + } + } + + // Check DNS? + $dns_checked = false; + + if ($checkDNS && ((int) max($return_status) < ISEMAIL_DNSWARN) && function_exists('dns_get_record')) { + // http://tools.ietf.org/html/rfc5321#section-2.3.5 + // Names that can + // be resolved to MX RRs or address (i.e., A or AAAA) RRs (as discussed + // in Section 5) are permitted, as are CNAME RRs whose targets can be + // resolved, in turn, to MX or address RRs. + // + // http://tools.ietf.org/html/rfc5321#section-5.1 + // The lookup first attempts to locate an MX record associated with the + // name. If a CNAME record is found, the resulting name is processed as + // if it were the initial name. ... If an empty list of MXs is returned, + // the address is treated as if it was associated with an implicit MX + // RR, with a preference of 0, pointing to that host. + // + // is_email() author's note: We will regard the existence of a CNAME to be + // sufficient evidence of the domain's existence. For performance reasons + // we will not repeat the DNS lookup for the CNAME's target, but we will + // raise a warning because we didn't immediately find an MX record. + if ($element_count === 0) { + $parsedata[ISEMAIL_COMPONENT_DOMAIN] .= '.'; + // Checking TLD DNS seems to work only if you explicitly check from the root + } + // Not using checkdnsrr because of a suspected bug in PHP 5.3 (http://bugs.php.net/bug.php?id=51844) + $result = @dns_get_record($parsedata[ISEMAIL_COMPONENT_DOMAIN], DNS_MX); + + if ((is_bool($result) && !(bool) $result)) { + $return_status[] = ISEMAIL_DNSWARN_NO_RECORD; + // Domain can't be found in DNS + } else { + if (count($result) === 0) { + $return_status[] = ISEMAIL_DNSWARN_NO_MX_RECORD; // MX-record for domain can't be found + $result = @dns_get_record($parsedata[ISEMAIL_COMPONENT_DOMAIN], DNS_A + DNS_CNAME); + + if (count($result) === 0) { + $return_status[] = ISEMAIL_DNSWARN_NO_RECORD; + // No usable records for the domain can be found + } + } else { + $dns_checked = true; + } + } + } + + // Check for TLD addresses + // ----------------------- + // TLD addresses are specifically allowed in RFC 5321 but they are + // unusual to say the least. We will allocate a separate + // status to these addresses on the basis that they are more likely + // to be typos than genuine addresses (unless we've already + // established that the domain does have an MX record) + // + // http://tools.ietf.org/html/rfc5321#section-2.3.5 + // In the case + // of a top-level domain used by itself in an email address, a single + // string is used without any dots. This makes the requirement, + // described in more detail below, that only fully-qualified domain + // names appear in SMTP transactions on the public Internet, + // particularly important where top-level domains are involved. + // + // TLD format + // ---------- + // The format of TLDs has changed a number of times. The standards + // used by IANA have been largely ignored by ICANN, leading to + // confusion over the standards being followed. These are not defined + // anywhere, except as a general component of a DNS host name (a label). + // However, this could potentially lead to 123.123.123.123 being a + // valid DNS name (rather than an IP address) and thereby creating + // an ambiguity. The most authoritative statement on TLD formats that + // the author can find is in a (rejected!) erratum to RFC 1123 + // submitted by John Klensin, the author of RFC 5321: + // + // http://www.rfc-editor.org/errata_search.php?rfc=1123&eid=1353 + // However, a valid host name can never have the dotted-decimal + // form #.#.#.#, since this change does not permit the highest-level + // component label to start with a digit even if it is not all-numeric. + if (!$dns_checked && ((int) max($return_status) < ISEMAIL_DNSWARN)) { + if ($element_count === 0) { + $return_status[] = ISEMAIL_RFC5321_TLD; + } + + if (is_numeric($atomlist[ISEMAIL_COMPONENT_DOMAIN][$element_count][0])) { + $return_status[] = ISEMAIL_RFC5321_TLDNUMERIC; + } + } + + $return_status = array_unique($return_status); + $final_status = (int) max($return_status); + + if (count($return_status) !== 1) { + array_shift($return_status); // remove redundant ISEMAIL_VALID + } + + $parsedata['status'] = $return_status; + + if ($final_status < $threshold) { + $final_status = ISEMAIL_VALID; + } + + return ($diagnose) ? $final_status : ($final_status < ISEMAIL_THRESHOLD); +} diff --git a/www/plugins/verifier/inc/verifier.php b/www/plugins/verifier/inc/verifier.php index 7c118640..03ec6b3a 100644 --- a/www/plugins/verifier/inc/verifier.php +++ b/www/plugins/verifier/inc/verifier.php @@ -1,7 +1,9 @@ $chemin){ + if (count($liste)) { + foreach ($liste as $fichier => $chemin) { $type = preg_replace(',[.]yaml$,i', '', $fichier); $dossier = str_replace($fichier, '', $chemin); // On ne garde que les vérifications qui ont bien la fonction ! @@ -85,22 +92,20 @@ function verifier_lister_disponibles($repertoire='verifier'){ * * @param string $type_verif * Le type de la vérification - * + * * @param string $repertoire * Dans quel repertoire chercher les yaml. - * + * * @return array Un tableau contenant le YAML décodé */ -function verifier_charger_infos($type_verif, $repertoire='verifier'){ +function verifier_charger_infos($type_verif, $repertoire = 'verifier') { include_spip('inc/yaml'); $fichier = find_in_path("$repertoire/$type_verif.yaml"); $verif = yaml_decode_file($fichier); - if (is_array($verif)){ + if (is_array($verif)) { $verif['titre'] = (isset($verif['titre']) and $verif['titre']) ? _T_ou_typo($verif['titre']) : $type_verif; $verif['description'] = (isset($verif['description']) and $verif['description']) ? _T_ou_typo($verif['description']) : ''; $verif['icone'] = (isset($verif['icone']) and $verif['icone']) ? _T_ou_typo($verif['icone']) : ''; } return $verif; } - -?> diff --git a/www/plugins/verifier/lang/paquet-verifier.xml b/www/plugins/verifier/lang/paquet-verifier.xml index 8df661fc..d0377082 100644 --- a/www/plugins/verifier/lang/paquet-verifier.xml +++ b/www/plugins/verifier/lang/paquet-verifier.xml @@ -13,6 +13,9 @@ + + + diff --git a/www/plugins/verifier/lang/paquet-verifier_de.php b/www/plugins/verifier/lang/paquet-verifier_de.php index 9bcbc7b0..8a8381c5 100644 --- a/www/plugins/verifier/lang/paquet-verifier_de.php +++ b/www/plugins/verifier/lang/paquet-verifier_de.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-verifier?lang_cible=de // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'verifier_nom' => 'API Wertprüfung', 'verifier_slogan' => 'API zur Prüfung von Werten' ); - -?> diff --git a/www/plugins/verifier/lang/paquet-verifier_en.php b/www/plugins/verifier/lang/paquet-verifier_en.php index 84b56a36..4ca6a67c 100644 --- a/www/plugins/verifier/lang/paquet-verifier_en.php +++ b/www/plugins/verifier/lang/paquet-verifier_en.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-verifier?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'verifier_nom' => 'Control API', 'verifier_slogan' => 'A generic API to control a value' ); - -?> diff --git a/www/plugins/verifier/lang/paquet-verifier_es.php b/www/plugins/verifier/lang/paquet-verifier_es.php index d2983be2..8284b241 100644 --- a/www/plugins/verifier/lang/paquet-verifier_es.php +++ b/www/plugins/verifier/lang/paquet-verifier_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-verifier?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'verifier_nom' => 'API de verificación', 'verifier_slogan' => 'Una API genérica para verificar un valor' ); - -?> diff --git a/www/plugins/verifier/lang/paquet-verifier_fr.php b/www/plugins/verifier/lang/paquet-verifier_fr.php index 4968c257..b9f5dd51 100644 --- a/www/plugins/verifier/lang/paquet-verifier_fr.php +++ b/www/plugins/verifier/lang/paquet-verifier_fr.php @@ -1,7 +1,9 @@ 'API de vérification', 'verifier_slogan' => 'Une API générique pour vérifier une valeur' ); - -?> diff --git a/www/plugins/verifier/lang/paquet-verifier_fr_tu.php b/www/plugins/verifier/lang/paquet-verifier_fr_tu.php index 4bcba909..e05d2f47 100644 --- a/www/plugins/verifier/lang/paquet-verifier_fr_tu.php +++ b/www/plugins/verifier/lang/paquet-verifier_fr_tu.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-verifier?lang_cible=fr_tu // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'verifier_nom' => 'API de vérification', 'verifier_slogan' => 'Une API générique pour vérifier une valeur' ); - -?> diff --git a/www/plugins/verifier/lang/paquet-verifier_nl.php b/www/plugins/verifier/lang/paquet-verifier_nl.php new file mode 100644 index 00000000..a0cc05e8 --- /dev/null +++ b/www/plugins/verifier/lang/paquet-verifier_nl.php @@ -0,0 +1,16 @@ + 'Levert de functie verifier($waarde, $type, $opties, &$valeur_normalisee) om de geldigheid van een waarde te controleren.', + 'verifier_nom' => 'Verificatie API', + 'verifier_slogan' => 'Een generieke API om een waarde te controleren' +); diff --git a/www/plugins/verifier/lang/paquet-verifier_ru.php b/www/plugins/verifier/lang/paquet-verifier_ru.php index b43eab82..8b648fc7 100644 --- a/www/plugins/verifier/lang/paquet-verifier_ru.php +++ b/www/plugins/verifier/lang/paquet-verifier_ru.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-verifier?lang_cible=ru // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'verifier_nom' => 'API для валидации данных (verifier)', 'verifier_slogan' => 'Плагин обеспечивает API для валидации данных. Необходим для работы многих плагинов.' ); - -?> diff --git a/www/plugins/verifier/lang/paquet-verifier_sk.php b/www/plugins/verifier/lang/paquet-verifier_sk.php index 17d95e4a..b7efcecb 100644 --- a/www/plugins/verifier/lang/paquet-verifier_sk.php +++ b/www/plugins/verifier/lang/paquet-verifier_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-verifier?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'verifier_nom' => 'Aplikácia na overenie', 'verifier_slogan' => 'Spoločná aplikácia na overenie hodnoty' ); - -?> diff --git a/www/plugins/verifier/lang/verifier.xml b/www/plugins/verifier/lang/verifier.xml index c2097b30..126de851 100644 --- a/www/plugins/verifier/lang/verifier.xml +++ b/www/plugins/verifier/lang/verifier.xml @@ -1,39 +1,45 @@ - + - + - + + + - + + - + - + - + - + - + + + + - + - + diff --git a/www/plugins/verifier/lang/verifier_ca.php b/www/plugins/verifier/lang/verifier_ca.php index 17e53ead..4626409c 100644 --- a/www/plugins/verifier/lang/verifier_ca.php +++ b/www/plugins/verifier/lang/verifier_ca.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/verifier?lang_cible=ca // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -61,5 +63,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_telephone' => 'Número de telèfon', 'type_telephone_description' => 'Verifica que el número de telèfon correspon a un esquema reconegut.' ); - -?> diff --git a/www/plugins/verifier/lang/verifier_de.php b/www/plugins/verifier/lang/verifier_de.php index 741fd149..c4c9ed2d 100644 --- a/www/plugins/verifier/lang/verifier_de.php +++ b/www/plugins/verifier/lang/verifier_de.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/verifier?lang_cible=de // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -83,5 +85,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_url' => 'URL', 'type_url_description' => 'Prüft ob der URL einem anerkannten Schema entspricht.' ); - -?> diff --git a/www/plugins/verifier/lang/verifier_en.php b/www/plugins/verifier/lang/verifier_en.php index ded99507..07af8f40 100644 --- a/www/plugins/verifier/lang/verifier_en.php +++ b/www/plugins/verifier/lang/verifier_en.php @@ -3,12 +3,14 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/verifier?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // E - 'erreur_code_postal' => 'This post code is invalid.', + 'erreur_code_postal' => 'This postcode is invalid.', 'erreur_comparaison_egal' => 'The value must be equal to the field "@nom_champ@"', 'erreur_comparaison_egal_type' => 'The value must be equal and the same type as the field "@nom_champ@"', 'erreur_comparaison_grand' => 'The value must be greater than the field "@nom_champ@"', @@ -29,6 +31,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'erreur_heure' => 'The timetable specified does not exist.', 'erreur_heure_format' => 'The time format is not valid.', 'erreur_id_document' => 'This document identifier is not valid.', + 'erreur_id_objet' => 'This identifier is not valid.', 'erreur_inconnue_generique' => 'The format is invalid.', 'erreur_isbn' => 'the ISBN number is not valid (ex: 978-2-1234-5680-3 or 2-1234-5680-X)', 'erreur_isbn_13_X' => 'Un numéro ISBN-13 ne peut pas se terminer par X.', # a 13 digits ISBN number must not end with an X. @@ -38,6 +41,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'erreur_isbn_segment' => 'the segment "@segment@" has @nb@ exceeding caracter(s).', 'erreur_isbn_segment_lettre' => 'the segment "@segment@" must not have any letter.', 'erreur_numerique' => 'The number format is invalid.', + 'erreur_objet' => 'This object is not valid', 'erreur_regex' => 'The regex string is incorrectly formatted.', 'erreur_siren' => 'The SIREN number is invalid.', 'erreur_siret' => 'The SIRET number is invalid.', @@ -56,6 +60,20 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'normaliser_option_date_en_datetime' => '"Datetime" format (for SQL)', // O + 'option_code_postal_pays_explication' => 'Two-letter country code : FR, DZ, DE, etc.', + 'option_code_postal_pays_label' => 'Country', + 'option_comparaison_champ_champ_explication' => 'Field identifier (« name » attribute)', + 'option_comparaison_champ_champ_label' => 'Field', + 'option_comparaison_champ_comparaison_explication' => 'Type of comparison', + 'option_comparaison_champ_comparaison_label' => 'Comparison', + 'option_comparaison_champ_egal' => '== Equal', + 'option_comparaison_champ_egal_type' => '=== Identical (same kind)', + 'option_comparaison_champ_grand' => '> Greater than', + 'option_comparaison_champ_grand_egal' => '>= Greater than or equal to ', + 'option_comparaison_champ_nom_champ_explication' => 'Field name for human beings', + 'option_comparaison_champ_nom_champ_label' => 'Field name', + 'option_comparaison_champ_petit' => '< Less than', + 'option_comparaison_champ_petit_egal' => '<= Less than or equal to', 'option_couleur_normaliser_label' => 'Normalize the color code?', 'option_couleur_type_hexa' => 'Color code in hexadecimal format', 'option_couleur_type_label' => 'Checking type to be made', @@ -87,6 +105,10 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'option_url_type_protocole_web' => 'Web protocols: HTTP or HTTPS', // T + 'type_code_postal' => 'Postal code', + 'type_code_postal_description' => 'Check that the value is a valid postal code.', + 'type_comparaison_champ' => 'Comparison', + 'type_comparaison_champ_description' => 'Compare the value with another field from _request().', 'type_couleur' => 'Colour', 'type_couleur_description' => 'Check if the value is a color code.', 'type_date' => 'Date', @@ -99,6 +121,10 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_email_disponible_description' => 'Check that the email address has not already been used by another system user.', 'type_entier' => 'Integer', 'type_entier_description' => 'Check that the value is an integer, with the option of being restricted between two range values.', + 'type_id_document' => 'Document number', + 'type_id_document_description' => 'Check that the value matches an existing document number.', + 'type_isbn' => 'ISBN', + 'type_isbn_description' => 'Check that the value is a 10 or 13 digits long ISBN', 'type_regex' => 'Regular expression', 'type_regex_description' => 'Check that the value matches the defined expression. For more information on using regular expressions, please refer to the online PHP help.', 'type_siren_siret' => 'SIREN or SIRET', @@ -110,5 +136,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_url' => 'URL', 'type_url_description' => 'Verify that the URL matches a recognised format.' ); - -?> diff --git a/www/plugins/verifier/lang/verifier_es.php b/www/plugins/verifier/lang/verifier_es.php index a03a6c07..b33166f1 100644 --- a/www/plugins/verifier/lang/verifier_es.php +++ b/www/plugins/verifier/lang/verifier_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/verifier?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -56,6 +58,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'normaliser_option_date_en_datetime' => 'En formato «Datetime» (para SQL)', // O + 'option_code_postal_pays_explication' => 'Two-letters country code: FR, DZ, DE, etc.', 'option_couleur_normaliser_label' => '¿Normalizar el código color?', 'option_couleur_type_hexa' => 'Código color en formato hexadecimal', 'option_couleur_type_label' => 'Tipo de verificación a efectuar', @@ -110,5 +113,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_url' => 'URL', 'type_url_description' => 'Verifica que la url corresponde a un patrón conocido.' ); - -?> diff --git a/www/plugins/verifier/lang/verifier_fa.php b/www/plugins/verifier/lang/verifier_fa.php index 1d057de9..f0f20c6d 100644 --- a/www/plugins/verifier/lang/verifier_fa.php +++ b/www/plugins/verifier/lang/verifier_fa.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/verifier?lang_cible=fa // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -101,5 +103,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_url' => 'يو.آر.ال ', 'type_url_description' => 'چك كنيد كه يو.آر.ال با يك فرمت شناخته شده جور باشد. ' ); - -?> diff --git a/www/plugins/verifier/lang/verifier_fr.php b/www/plugins/verifier/lang/verifier_fr.php index 45bd84b3..f6a42941 100644 --- a/www/plugins/verifier/lang/verifier_fr.php +++ b/www/plugins/verifier/lang/verifier_fr.php @@ -1,7 +1,9 @@ 'L’horaire indiqué n’existe pas.', 'erreur_heure_format' => 'Le format de l’heure n’est pas accepté.', 'erreur_id_document' => 'Cet identifiant de document n’est pas valide.', + 'erreur_id_objet' => 'Cet identifiant n’est pas valide.', 'erreur_inconnue_generique' => 'Le format n’est pas correct.', 'erreur_isbn' => 'Le numéro ISBN n’est pas valide (ex : 978-2-1234-5680-3 ou 2-1234-5680-X)', 'erreur_isbn_13_X' => 'Un numéro ISBN-13 ne peut pas se terminer par X.', @@ -36,6 +39,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'erreur_isbn_segment' => 'Le segment "@segment@" comprend @nb@ chiffre(s) en trop.', 'erreur_isbn_segment_lettre' => 'Le segment "@segment@" ne doit pas contenir de lettre.', 'erreur_numerique' => 'Le format du nombre n’est pas valide.', + 'erreur_objet' => 'Cet objet n’est pas valide', 'erreur_regex' => 'Le format de la chaîne n’est pas valide.', 'erreur_siren' => 'Le numéro de SIREN n’est pas valide.', 'erreur_siret' => 'Le numéro de SIRET n’est pas valide.', @@ -54,6 +58,20 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'normaliser_option_date_en_datetime' => 'Au format « Datetime » (pour SQL)', // O + 'option_code_postal_pays_explication' => 'Code à 2 chiffres d’un pays : FR, DZ, DE, etc.', + 'option_code_postal_pays_label' => 'Pays', + 'option_comparaison_champ_champ_explication' => 'Identifiant du champ (attribut « name »)', + 'option_comparaison_champ_champ_label' => 'Champ', + 'option_comparaison_champ_comparaison_explication' => 'Type de comparaison à effectuer', + 'option_comparaison_champ_comparaison_label' => 'Comparaison', + 'option_comparaison_champ_egal' => '== Égal', + 'option_comparaison_champ_egal_type' => '=== Identique (même type)', + 'option_comparaison_champ_grand' => '> Plus grand', + 'option_comparaison_champ_grand_egal' => '>= Plus grand ou égal', + 'option_comparaison_champ_nom_champ_explication' => 'Nom du champ pour les humains', + 'option_comparaison_champ_nom_champ_label' => 'Nom du champ', + 'option_comparaison_champ_petit' => '< Plus petit', + 'option_comparaison_champ_petit_egal' => '<= Plus petit ou égal', 'option_couleur_normaliser_label' => 'Normaliser le code couleur ?', 'option_couleur_type_hexa' => 'Code couleur au format héxadécimal', 'option_couleur_type_label' => 'Type de vérification à effectuer', @@ -85,6 +103,10 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'option_url_type_protocole_web' => 'Protocoles web : http ou https', // T + 'type_code_postal' => 'Code postal', + 'type_code_postal_description' => 'Vérifie que la valeur est un code postal valide.', + 'type_comparaison_champ' => 'Comparaison', + 'type_comparaison_champ_description' => 'Compare la valeur avec un autre champ du _request().', 'type_couleur' => 'Couleur', 'type_couleur_description' => 'Vérifie que la valeur est un code couleur.', 'type_date' => 'Date', @@ -97,6 +119,10 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_email_disponible_description' => 'Vérifie que l’adresse de courriel n’est pas déjà utilisé par un autre utilisateur du système.', 'type_entier' => 'Nombre entier', 'type_entier_description' => 'Vérifie que la valeur est un entier, avec la possibilité de restreindre entre deux valeurs.', + 'type_id_document' => 'Numéro d’un document', + 'type_id_document_description' => 'Vérifie que la valeur correspond à un numéro de document existant.', + 'type_isbn' => 'Numéro ISBN', + 'type_isbn_description' => 'Vérifie que la valeur correspond à un numéro ISBN à 10 ou 13 chiffres.', 'type_regex' => 'Expression régulière', 'type_regex_description' => 'Vérifie que la valeur correspond au masque demandé. Pour l’utilisation des masques, reportez-vous à l’aide en ligne de PHP.', 'type_siren_siret' => 'SIREN ou SIRET', @@ -108,5 +134,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_url' => 'URL', 'type_url_description' => 'Vérifie que l’url correspond à un schéma reconnu.' ); - -?> diff --git a/www/plugins/verifier/lang/verifier_fr_tu.php b/www/plugins/verifier/lang/verifier_fr_tu.php index a847061e..1db9f308 100644 --- a/www/plugins/verifier/lang/verifier_fr_tu.php +++ b/www/plugins/verifier/lang/verifier_fr_tu.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/verifier?lang_cible=fr_tu // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -110,5 +112,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_url' => 'URL', 'type_url_description' => 'Vérifie que l’url correspond à un schéma reconnu.' ); - -?> diff --git a/www/plugins/verifier/lang/verifier_it.php b/www/plugins/verifier/lang/verifier_it.php index 1e21a26c..73398a5e 100644 --- a/www/plugins/verifier/lang/verifier_it.php +++ b/www/plugins/verifier/lang/verifier_it.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/verifier?lang_cible=it // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -83,5 +85,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_url' => 'URL', 'type_url_description' => 'Verifica che l’url corrisponda ad uno schema riconosciuto.' ); - -?> diff --git a/www/plugins/verifier/lang/verifier_nl.php b/www/plugins/verifier/lang/verifier_nl.php new file mode 100644 index 00000000..b2f33280 --- /dev/null +++ b/www/plugins/verifier/lang/verifier_nl.php @@ -0,0 +1,138 @@ + 'Deze postcode is ongeldig.', + 'erreur_comparaison_egal' => 'De waarde moet gelijk zijn aan het veld "@nom_champ@"', + 'erreur_comparaison_egal_type' => 'De waarde moet gelijk zijn aan en hetzelfde type hebben als het veld "@nom_champ@"', + 'erreur_comparaison_grand' => 'De waarde moet groter zijn dan het veld "@nom_champ@"', + 'erreur_comparaison_grand_egal' => 'De waarde moet gelijk zijn aan of groter zijn dan het veld "@nom_champ@"', + 'erreur_comparaison_petit' => 'De waarde moet kleiner zijn dan het veld "@nom_champ@"', + 'erreur_comparaison_petit_egal' => 'De waarde moet gelijk zijn aan of kleiner zijn dan het veld "@nom_champ@"', + 'erreur_couleur' => 'De kleurcode is ongeldig.', + 'erreur_date' => 'De datum is ongeldig.', + 'erreur_date_format' => 'Het datumformaat is ongeldig.', + 'erreur_decimal' => 'De waarde moet een decimaal getal zijn.', + 'erreur_decimal_nb_decimales' => 'Het getal moet meer dan @nb_decimales@ decimalen na de punt hebben.', + 'erreur_email' => 'Het e-mailadres @email@ is niet correct geformatteerd.', + 'erreur_email_nondispo' => 'Het e-mailadres @email@ werd al gebruikt.', + 'erreur_entier' => 'De waarde moet een geheel getal zijn.', + 'erreur_entier_entre' => 'De waarde moet liggen tussen @min@ en @max@.', + 'erreur_entier_max' => 'De waarde moet kleiner zijn dan @max@.', + 'erreur_entier_min' => 'De waarde moet groter zijn dan @min@.', + 'erreur_heure' => 'De vermelde tijd bestaat niet.', + 'erreur_heure_format' => 'Het tijdformaat is niet geldig.', + 'erreur_id_document' => 'Deze document-identificatie is niet geldig.', + 'erreur_id_objet' => 'Deze identificatie is ongeldig.', + 'erreur_inconnue_generique' => 'Het formaat is ongeldig.', + 'erreur_isbn' => 'de ISBN code is niet geldig (bv: 978-2-1234-5680-3 of 2-1234-5680-X)', + 'erreur_isbn_13_X' => 'Een ISBN-13 code kan niet eindigen met een X.', + 'erreur_isbn_G' => 'Het eerste segment moet gelijk zijn aan 978 of 979.', + 'erreur_isbn_nb_caracteres' => 'de ISBN code moet 10 of 13 tekens bevatten (momenteel @nb@), de streepjes niet meegeteld.', + 'erreur_isbn_nb_segments' => 'de ISBN code moet uit 4 of 5 segmenten bestaan (momenteel @nb@).', + 'erreur_isbn_segment' => 'het segment "@segment@" heeft @nb@ teveel teken(s).', + 'erreur_isbn_segment_lettre' => 'het segment "@segment@" mag geen letters bevatten.', + 'erreur_numerique' => 'Het nummerformaat is ongeldig.', + 'erreur_objet' => 'Dit object is niet geldig', + 'erreur_regex' => 'De regex string is incorrect geformatteerd.', + 'erreur_siren' => 'Het SIREN nummer is ongeldig.', + 'erreur_siret' => 'Het SIRET number is ongeldig.', + 'erreur_taille_egal' => 'De waarde moet uit exact @egal@ tekens bestaan (momenteel @nb@).', + 'erreur_taille_entre' => 'De waarde moet tussen de @min@ en @max@ tekens bevatten (momenteel @nb@).', + 'erreur_taille_max' => 'De waarde mag niet meer dan @max@ tekens bevatten (momenteel @nb@).', + 'erreur_taille_min' => 'De waarde moet minimaal @min@ ctekens bevatten (momenteel @nb@).', + 'erreur_telephone' => 'Het telefoonnummer is ongeldig.', + 'erreur_url' => 'Het URL-adres @url@ is ongeldig.', + 'erreur_url_protocole' => 'Het ingevoerde adres (@url@) moet beginnen met @protocole@', + 'erreur_url_protocole_exact' => 'Het ingevoerde adres (@url@) begint niet met een geldig protocol (bv. http://)', + + // N + 'normaliser_option_date' => 'De datum normaliseren?', + 'normaliser_option_date_aucune' => 'Nee', + 'normaliser_option_date_en_datetime' => '"Datetime" formaat (voor SQL)', + + // O + 'option_code_postal_pays_explication' => 'Tweeletterige landcode: FR, DE, NL, enz.', + 'option_code_postal_pays_label' => 'Land', + 'option_comparaison_champ_champ_explication' => 'Veld identificatie («name» attribuut)', + 'option_comparaison_champ_champ_label' => 'Veld', + 'option_comparaison_champ_comparaison_explication' => 'Soort vergelijking', + 'option_comparaison_champ_comparaison_label' => 'Vergelijking', + 'option_comparaison_champ_egal' => '== Gelijk', + 'option_comparaison_champ_egal_type' => '=== Identiek (zelfde soort)', + 'option_comparaison_champ_grand' => '> Groter dan', + 'option_comparaison_champ_grand_egal' => '>= Groter dan of gelijk aan ', + 'option_comparaison_champ_nom_champ_explication' => 'Veldnaam voor mensen', + 'option_comparaison_champ_nom_champ_label' => 'Veldnaam', + 'option_comparaison_champ_petit' => '< Kleiner dan', + 'option_comparaison_champ_petit_egal' => '<= Kleiner dan of gelijk aan', + 'option_couleur_normaliser_label' => 'De kleurcode normaliseren?', + 'option_couleur_type_hexa' => 'Kleurcode in hexadecimaal formaat', + 'option_couleur_type_label' => 'Uit te voeren type verificatie', + 'option_decimal_nb_decimales_label' => 'Aantal decimale plaatsen', + 'option_email_disponible_label' => 'Beschikbaar adres', + 'option_email_disponible_label_case' => 'Controleer of het adres niet al door een andere gebruiker wordt gebruikt', + 'option_email_mode_5322' => 'Controleer tegen de meest stricte beschikbare standaard', + 'option_email_mode_label' => 'Email verificatiemethode', + 'option_email_mode_normal' => 'Normale SPIP verificatie', + 'option_email_mode_strict' => 'Minder tolerante verificatie', + 'option_entier_max_label' => 'Maximum waarde', + 'option_entier_min_label' => 'Minimum waarde', + 'option_regex_modele_label' => 'De waarde moet met de volgende expressie overeen komen', + 'option_siren_siret_mode_label' => 'Wat controleer je?', + 'option_siren_siret_mode_siren' => 'SIREN nummer', + 'option_siren_siret_mode_siret' => 'SIRET nummer', + 'option_taille_max_label' => 'Maximum grootte', + 'option_taille_min_label' => 'Minimum grootte', + 'option_url_mode_complet' => 'Volledige verificatie van de URL', + 'option_url_mode_label' => 'URL verificatiemethode', + 'option_url_mode_php_filter' => 'Volledige URL verificatie met het PHP filter FILTER_VALIDATE_URL', + 'option_url_mode_protocole_seul' => 'Uitsluitend verificatie van het protocol', + 'option_url_protocole_label' => 'Naam van het te verifiëren protocol', + 'option_url_type_protocole_exact' => 'Geef hieronder een protocol aan:', + 'option_url_type_protocole_ftp' => 'File transfer protocols: FTP of SFTP', + 'option_url_type_protocole_label' => 'Te verifiëren type protocol', + 'option_url_type_protocole_mail' => 'Mail protocols: IMAP, POP3 of SMTP', + 'option_url_type_protocole_tous' => 'Alle toegelaten protocols', + 'option_url_type_protocole_web' => 'Web protocols: HTTP of HTTPS', + + // T + 'type_code_postal' => 'Postcode', + 'type_code_postal_description' => 'Controleer of de waarde een geldige postcode is.', + 'type_comparaison_champ' => 'Vergelijking', + 'type_comparaison_champ_description' => 'Vergelijk de waarde met een ander veld uit _request().', + 'type_couleur' => 'Kleur', + 'type_couleur_description' => 'Controleer of de waarde een kleurcode is.', + 'type_date' => 'Datum', + 'type_date_description' => 'Controleer of de waarde een datum is in formaat DD/MM/YYYY. Het scheidingsteken kan van alles zijn (".", "/", enz).', + 'type_decimal' => 'Decimaal getal', + 'type_decimal_description' => 'Controleer of de waarde een decimaal getal is, met opties voor een bepaalde reeks en het aaantal decimale plaatsen.', + 'type_email' => 'E-mailadres', + 'type_email_description' => 'Controleer of het e-mailadres juist is geformatteerd.', + 'type_email_disponible' => 'Beschikbaarheid van een e-mailadres', + 'type_email_disponible_description' => 'Controleer of het e-mailadres niet al door een andere systeemgebruiker wordt gebruikt.', + 'type_entier' => 'Geheel getal', + 'type_entier_description' => 'Controleer of de waarde een geheel getal is, met de optie van een bepaalde reeks.', + 'type_id_document' => 'Documentnummer', + 'type_id_document_description' => 'Controleer of de waarde met een bestaand documentnummer overeen komt.', + 'type_isbn' => 'ISBN', + 'type_isbn_description' => 'Controleer of de waarde een 10 of 13 teks lange ISBN code is', + 'type_regex' => 'Regular expression', + 'type_regex_description' => 'Controleer of de waarde met de expressie overeen komt.', + 'type_siren_siret' => 'SIREN or SIRET', + 'type_siren_siret_description' => 'Check that the value is a valid number from the French Système d’Identification du Répertoire des ENtreprises (Company Registry ID System).', + 'type_taille' => 'Grootte', + 'type_taille_description' => 'Controleer of de grootte van de waarde binnen een bepaald minimum en/of maximum valt.', + 'type_telephone' => 'Telefoonnumber', + 'type_telephone_description' => 'Controleer of het telefoonnummer met een herkend formaat overeen komt.', + 'type_url' => 'URL', + 'type_url_description' => 'Controleer of de URL een herkend formaat heeft.' +); diff --git a/www/plugins/verifier/lang/verifier_pt_br.php b/www/plugins/verifier/lang/verifier_pt_br.php index 8f1f555b..5a9f1fdf 100644 --- a/www/plugins/verifier/lang/verifier_pt_br.php +++ b/www/plugins/verifier/lang/verifier_pt_br.php @@ -3,12 +3,21 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/verifier?lang_cible=pt_br // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( // E 'erreur_code_postal' => 'Este Cep está incorreto.', + 'erreur_comparaison_egal' => 'O valor deve ser igual ao campo "@nom_champ@"', + 'erreur_comparaison_egal_type' => 'O valor deve ser igual e do mesmo tipo que o campo "@nom_champ@"', + 'erreur_comparaison_grand' => 'O valor deve ser superior ao campo "@nom_champ@"', + 'erreur_comparaison_grand_egal' => 'O valor deve ser superior ou igual ao campo "@nom_champ@"', + 'erreur_comparaison_petit' => 'O valor deve ser inferior ao campo "@nom_champ@"', + 'erreur_comparaison_petit_egal' => 'O valor deve ser inferior ou igual ao campo "@nom_champ@"', + 'erreur_couleur' => 'O código de cor não é válido.', 'erreur_date' => 'A data não é válida.', 'erreur_date_format' => 'O formato da data não é aceitável.', 'erreur_decimal' => 'O valor deve ser um número decimal.', @@ -19,7 +28,17 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'erreur_entier_entre' => 'O valor dever ser entre @min@ e @max@.', 'erreur_entier_max' => 'O valor deve ser inferior a @max@.', 'erreur_entier_min' => 'O valor deve ser superior a @min@.', + 'erreur_heure' => 'O horário indicado não existe.', + 'erreur_heure_format' => 'O formato de hora não é aceitável.', 'erreur_id_document' => 'Esta extensão de documento não é válida.', + 'erreur_inconnue_generique' => 'O formato não está correto.', + 'erreur_isbn' => 'O número ISBN não é válido (ex: 978-2-1234-5680-3 ou 2-1234-5680-X)', + 'erreur_isbn_13_X' => 'Um número ISBN-13 não pode terminar em X.', + 'erreur_isbn_G' => 'O primeiro segmento deve ser igual a 978 ou 979.', + 'erreur_isbn_nb_caracteres' => 'O número ISBN deve ter 10 ou 13 caractéres, sem contar os traços (atualmente @nb@).', + 'erreur_isbn_nb_segments' => 'O número ISBN deve ter 4 ou 5 segmentos (atualmente @nb@).', + 'erreur_isbn_segment' => 'O segmento "@segment@" tem @nb@ número(s) a mais.', + 'erreur_isbn_segment_lettre' => 'O segmento "@segment@" não pode conter letras.', 'erreur_numerique' => 'O formato do número não é válido.', 'erreur_regex' => 'O formato da expressão não é válido.', 'erreur_siren' => 'O número SIREN não é válido.', @@ -33,7 +52,16 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'erreur_url_protocole' => 'O endereço informado (@url@) deve começar com @protocole@', 'erreur_url_protocole_exact' => 'O endereço informado (@url@) não começa com um protocolo válido (http:// por exemplo)', + // N + 'normaliser_option_date' => 'Normalizar a data?', + 'normaliser_option_date_aucune' => 'Não', + 'normaliser_option_date_en_datetime' => 'No formato «Datetime» (para SQL)', + // O + 'option_code_postal_pays_explication' => 'C´odigo de dois caractéres de país: BR, PT, FR etc.', + 'option_code_postal_pays_label' => 'País', + 'option_comparaison_champ_champ_explication' => 'Identificador do campos (atributo « nome »)', + 'option_comparaison_champ_champ_label' => 'Campo', 'option_decimal_nb_decimales_label' => 'Número de décimais depois da vírgula', 'option_email_disponible_label' => 'Endereço disponível', 'option_email_disponible_label_case' => 'Verificar se o endereço já não está sendo utilizado por um usuário', @@ -83,5 +111,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_url' => 'URL', 'type_url_description' => 'Verifica se o url corresponde a um esquema reconhecido.' ); - -?> diff --git a/www/plugins/verifier/lang/verifier_ru.php b/www/plugins/verifier/lang/verifier_ru.php index 77a43762..53c27fe5 100644 --- a/www/plugins/verifier/lang/verifier_ru.php +++ b/www/plugins/verifier/lang/verifier_ru.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/verifier?lang_cible=ru // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -101,5 +103,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_url' => 'URL', 'type_url_description' => 'Проверить соответствие ли URL формат ввода.' ); - -?> diff --git a/www/plugins/verifier/lang/verifier_sk.php b/www/plugins/verifier/lang/verifier_sk.php index 6b8ce9fd..69aad93c 100644 --- a/www/plugins/verifier/lang/verifier_sk.php +++ b/www/plugins/verifier/lang/verifier_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/verifier?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -110,5 +112,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'type_url' => 'Internetová adresa', 'type_url_description' => 'Overí, či sa internetová adresa zhoduje s rozoznávaným formátom.' ); - -?> diff --git a/www/plugins/verifier/paquet.xml b/www/plugins/verifier/paquet.xml index 01304d24..ed23b792 100644 --- a/www/plugins/verifier/paquet.xml +++ b/www/plugins/verifier/paquet.xml @@ -1,11 +1,11 @@ API de vérification diff --git a/www/plugins/verifier/plugin.xml b/www/plugins/verifier/plugin.xml index 4aca7527..e77b0418 100644 --- a/www/plugins/verifier/plugin.xml +++ b/www/plugins/verifier/plugin.xml @@ -9,7 +9,7 @@ [Les Développements Durables->http://www.ldd.fr] images/verifier-128.png GPL v3 - 1.0.5 + 1.0.11 stable @@ -18,14 +18,13 @@ verifier - http://contrib.spip.net/Verifier,1505 + http://contrib.spip.net/Verifier verifier - - + + outil - diff --git a/www/plugins/verifier/svn.revision b/www/plugins/verifier/svn.revision index 83ba0ac1..e9f5e9f8 100644 --- a/www/plugins/verifier/svn.revision +++ b/www/plugins/verifier/svn.revision @@ -1,10 +1,10 @@ Origine: file:///home/svn/repository/spip-zone/_plugins_/verifier -Revision: 84141 -Dernier commit: 2014-08-11 09:06:34 +0200 +Revision: 99301 +Dernier commit: 2016-08-31 06:04:07 +0200 file:///home/svn/repository/spip-zone/_plugins_/verifier -84141 -2014-08-11 09:06:34 +0200 +99301 +2016-08-31 06:04:07 +0200 \ No newline at end of file diff --git a/www/plugins/verifier/verifier/code_postal.php b/www/plugins/verifier/verifier/code_postal.php index 90705cf0..71b96c04 100644 --- a/www/plugins/verifier/verifier/code_postal.php +++ b/www/plugins/verifier/verifier/code_postal.php @@ -1,19 +1,21 @@ ' +description: '<:verifier:type_code_postal_description:>' +options: + - + saisie: 'input' + options: + nom: 'pays' + label: '<:verifier:option_code_postal_pays_label:>' + explication: '<:verifier:option_code_postal_pays_explication:>' diff --git a/www/plugins/verifier/verifier/comparaison_champ.php b/www/plugins/verifier/verifier/comparaison_champ.php index d04e34ad..e4eeae78 100644 --- a/www/plugins/verifier/verifier/comparaison_champ.php +++ b/www/plugins/verifier/verifier/comparaison_champ.php @@ -1,7 +1,9 @@ $nom_champ)); break; @@ -44,4 +49,3 @@ function verifier_comparaison_champ_dist($valeur, $options=array()){ break; } } - diff --git a/www/plugins/verifier/verifier/comparaison_champ.yaml b/www/plugins/verifier/verifier/comparaison_champ.yaml new file mode 100644 index 00000000..0f824ab9 --- /dev/null +++ b/www/plugins/verifier/verifier/comparaison_champ.yaml @@ -0,0 +1,29 @@ + +titre: '<:verifier:type_comparaison_champ:>' +description: '<:verifier:type_comparaison_champ_description:>' +options: + - + saisie: 'input' + options: + nom: 'champ' + label: '<:verifier:option_comparaison_champ_champ_label:>' + explication: '<:verifier:option_comparaison_champ_champ_explication:>' + - + saisie: 'input' + options: + nom: 'nom_champ' + label: '<:verifier:option_comparaison_champ_nom_champ_label:>' + explication: '<:verifier:option_comparaison_champ_nom_champ_explication:>' + - + saisie: 'radio' + options: + nom: 'comparaison' + label: '<:verifier:option_comparaison_champ_comparaison_label:>' + explication: '<:verifier:option_comparaison_champ_comparaison_explication:>' + datas: + '': '<:verifier:option_comparaison_champ_egal:>' + egal_type: '<:verifier:option_comparaison_champ_egal_type:>' + petit: '<:verifier:option_comparaison_champ_petit:>' + petit_egal: '<:verifier:option_comparaison_champ_petit_egal:>' + grand: '<:verifier:option_comparaison_champ_grand:>' + grand_egal: '<:verifier:option_comparaison_champ_grand_egal:>' diff --git a/www/plugins/verifier/verifier/couleur.php b/www/plugins/verifier/verifier/couleur.php index 24453926..887a2dcd 100644 --- a/www/plugins/verifier/verifier/couleur.php +++ b/www/plugins/verifier/verifier/couleur.php @@ -1,11 +1,13 @@ \ No newline at end of file diff --git a/www/plugins/verifier/verifier/date.php b/www/plugins/verifier/verifier/date.php index 184efdaf..bd628c56 100644 --- a/www/plugins/verifier/verifier/date.php +++ b/www/plugins/verifier/verifier/date.php @@ -1,13 +1,15 @@ 23 or $minutes < 0 or $minutes > 59){ + if ($heures < 0 or $heures > 23 or $minutes < 0 or $minutes > 59) { return _T('verifier:erreur_heure'); - } - // Si tout est bon pour l'heure, on recompose en ajoutant des 0 si besoin - else { + } else { + // Si tout est bon pour l'heure, on recompose en ajoutant des 0 si besoin $options['heure'] = sprintf('%02d:%02d', $heures, $minutes); } } @@ -96,11 +102,8 @@ function verifier_date_dist($valeur, $options=array(), &$valeur_normalisee=null) return $ok; } - - - /** - * Convertir une date en datetime + * Convertir une date en datetime * **/ function normaliser_date_datetime_dist($valeur, $options, &$erreur) { @@ -125,11 +128,11 @@ function normaliser_date_datetime_dist($valeur, $options, &$erreur) { if (!($date = mktime($date[3], $date[4], 0, (int)$date[1], (int)$date[2], (int)$date[0]))) { // mauvais format de date - $erreur = "Impossible de normaliser la date..."; + $erreur = 'Impossible de normaliser la date...'; return false; } - $date = date("Y-m-d H:i:s", $date); + $date = date('Y-m-d H:i:s', $date); $date = vider_date($date); // enlever les valeurs considerees comme nulles (1 1 1970, etc...) if (!$date) { @@ -138,4 +141,3 @@ function normaliser_date_datetime_dist($valeur, $options, &$erreur) { return $date; } - diff --git a/www/plugins/verifier/verifier/decimal.php b/www/plugins/verifier/verifier/decimal.php index b144ead9..55061e06 100644 --- a/www/plugins/verifier/verifier/decimal.php +++ b/www/plugins/verifier/verifier/decimal.php @@ -1,7 +1,9 @@ = $options['min'])); - - if (isset($options['max'])){ + } + + if (isset($options['max'])) { $ok = ($ok and ($valeur <= $options['max'])); } - - if (!$ok){ - if (isset($options['min']) and isset($options['max'])) + + if (!$ok) { + if (isset($options['min']) and isset($options['max'])) { $erreur = _T('verifier:erreur_entier_entre', $options); - elseif (isset($options['max'])) + } elseif (isset($options['max'])) { $erreur = _T('verifier:erreur_entier_max', $options); - else + } else { $erreur = _T('verifier:erreur_entier_min', $options); + } } } - + // On vérifie le nombre de décimales après la virgule - if ($nb_decimales = $options['nb_decimales'] and round($valeur, $nb_decimales) != $valeur){ + if (isset($options['nb_decimales']) and $nb_decimales = $options['nb_decimales'] and round($valeur, $nb_decimales) != $valeur) { $erreur = _T('verifier:erreur_decimal_nb_decimales', array('nb_decimales' => $nb_decimales)); } - + return $erreur; } - -?> diff --git a/www/plugins/verifier/verifier/email.php b/www/plugins/verifier/verifier/email.php index b525c315..286f4551 100644 --- a/www/plugins/verifier/verifier/email.php +++ b/www/plugins/verifier/verifier/email.php @@ -1,11 +1,13 @@ echapper_tags($valeur))); } - + // Choix du mode de verification de la syntaxe des courriels - if (!$options['mode'] or !in_array($options['mode'], array('normal','rfc5322','strict'))){ + if (empty($options['mode']) or !in_array($options['mode'], array('normal','rfc5322','strict'))) { $mode = 'normal'; - } - else{ + } else { $mode = $options['mode']; } - - $fonctions_disponibles = array('normal' => 'email_valide', 'rfc5322' => 'verifier_email_rfc5322', 'strict' => 'verifier_email_de_maniere_stricte'); + + $fonctions_disponibles = array( + 'normal' => 'email_valide', + 'rfc5322' => 'verifier_email_rfc5322', + 'strict' => 'verifier_email_de_maniere_stricte' + ); $fonction_verif = $fonctions_disponibles[$mode]; - - if (!$fonction_verif($valeur)) + + if (!$fonction_verif($valeur)) { return _T('verifier:erreur_email', array('email' => echapper_tags($valeur))); - else + } else { return ''; + } } /** * Changement de la RegExp d'origine * - * Respect de la RFC5322 + * Respect de la RFC5322 * * @link (phraseur détaillé ici : http://www.dominicsayers.com/isemail/) * @param string $valeur La valeur à vérifier * @return boolean Retourne true uniquement lorsque le mail est valide */ -function verifier_email_rfc5322($valeur){ +function verifier_email_rfc5322($valeur) { // Si c'est un spammeur autant arreter tout de suite if (preg_match(",[\n\r].*(MIME|multipart|Content-),i", $valeur)) { spip_log("Tentative d'injection de mail : $valeur"); @@ -61,8 +68,9 @@ function verifier_email_rfc5322($valeur){ } include_spip('inc/is_email'); foreach (explode(',', $valeur) as $adresse) { - if (!is_email(trim($adresse))) + if (!is_email(trim($adresse))) { return false; + } } return true; } @@ -77,7 +85,7 @@ function verifier_email_rfc5322($valeur){ * @param string $valeur La valeur à vérifier * @return boolean Retourne true uniquement lorsque le mail est valide */ -function verifier_email_de_maniere_stricte($valeur){ +function verifier_email_de_maniere_stricte($valeur) { // Si c'est un spammeur autant arreter tout de suite if (preg_match(",[\n\r].*(MIME|multipart|Content-),i", $valeur)) { spip_log("Tentative d'injection de mail : $valeur"); @@ -86,11 +94,12 @@ function verifier_email_de_maniere_stricte($valeur){ foreach (explode(',', $valeur) as $adresse) { // nettoyer certains formats // "Marie Toto " - $adresse = trim(preg_replace(",^[^<>\"]*<([^<>\"]+)>$,i", "\\1", $adresse)); - if (!preg_match('/^([A-Za-z0-9]){1}([A-Za-z0-9]|-|_|\.)*@[A-Za-z0-9]([A-Za-z0-9]|-|\.){1,}\.[A-Za-z]{2,4}$/', $adresse)) + $adresse = trim(preg_replace(',^[^<>\"]*<([^<>\"]+)>$,i', '\\1', $adresse)); + if (!preg_match('/^([A-Za-z0-9]){1}([A-Za-z0-9]|-|_|\.)*@[A-Za-z0-9]([A-Za-z0-9]|-|\.){1,}\.[A-Za-z]{2,4}$/', $adresse)) { return false; + } } - return true; + return true; } /** @@ -100,11 +109,12 @@ function verifier_email_de_maniere_stricte($valeur){ * @param string $valeur La valeur à vérifier * @return boolean Retourne false lorsque le mail est déjà utilisé */ -function verifier_disponibilite_email($valeur,$exclure_id_auteur=null){ +function verifier_disponibilite_email($valeur, $exclure_id_auteur = null) { include_spip('base/abstract_sql'); - if(sql_getfetsel('id_auteur', 'spip_auteurs', 'email='.sql_quote($valeur).(!is_null($exclure_id_auteur)?"AND statut<>'5poubelle' AND id_auteur<>".intval($exclure_id_auteur):''))) + if (sql_getfetsel('id_auteur', 'spip_auteurs', 'email='.sql_quote($valeur).(!is_null($exclure_id_auteur)?"AND statut<>'5poubelle' AND id_auteur<>".intval($exclure_id_auteur):''))) { return false; - else + } else { return true; + } } diff --git a/www/plugins/verifier/verifier/entier.php b/www/plugins/verifier/verifier/entier.php index 2a82b73c..22d3cabf 100644 --- a/www/plugins/verifier/verifier/entier.php +++ b/www/plugins/verifier/verifier/entier.php @@ -1,7 +1,9 @@ = $options['min'])); - - if (isset($options['max'])){ + } + if (isset($options['max'])) { $ok = ($ok and ($valeur <= $options['max'])); } - - if (!$ok){ - if (isset($options['min']) and isset($options['max'])) + + if (!$ok) { + if (isset($options['min']) and isset($options['max'])) { $erreur = _T('verifier:erreur_entier_entre', $options); - elseif (isset($options['max'])) + } elseif (isset($options['max'])) { $erreur = _T('verifier:erreur_entier_max', $options); - else + } else { $erreur = _T('verifier:erreur_entier_min', $options); + } } } - + return $erreur; } - -?> diff --git a/www/plugins/verifier/verifier/id_document.php b/www/plugins/verifier/verifier/id_document.php index e0909db1..08bdb612 100644 --- a/www/plugins/verifier/verifier/id_document.php +++ b/www/plugins/verifier/verifier/id_document.php @@ -1,7 +1,9 @@ diff --git a/www/plugins/verifier/verifier/id_document.yaml b/www/plugins/verifier/verifier/id_document.yaml new file mode 100644 index 00000000..f922b726 --- /dev/null +++ b/www/plugins/verifier/verifier/id_document.yaml @@ -0,0 +1,3 @@ + +titre: '<:verifier:type_id_document:>' +description: '<:verifier:type_id_document_description:>' diff --git a/www/plugins/verifier/verifier/id_objet.php b/www/plugins/verifier/verifier/id_objet.php new file mode 100644 index 00000000..d14edebd --- /dev/null +++ b/www/plugins/verifier/verifier/id_objet.php @@ -0,0 +1,38 @@ +' +description: '<:verifier:type_id_document_description:>' diff --git a/www/plugins/verifier/verifier/isbn.php b/www/plugins/verifier/verifier/isbn.php index ba0a2ce3..34946b11 100644 --- a/www/plugins/verifier/verifier/isbn.php +++ b/www/plugins/verifier/verifier/isbn.php @@ -1,10 +1,12 @@ 5) { + if ($nbA = strlen($A) and $nbA > 5) { $val['nb'] = $nbA - 5; $val['segment'] = $A; return _T('verifier:erreur_isbn_segment', $val); } // B (code editeur) : 7 caracteres max - if ($nbB = strlen($B) AND $nbB > 7) { + if ($nbB = strlen($B) and $nbB > 7) { $val['nb'] = $nbB - 7; $val['segment'] = $B; return _T('verifier:erreur_isbn_segment', $val); } // C (code livre) : 6 caracteres max - if ($nbC = strlen($C) AND $nbC > 6) { + if ($nbC = strlen($C) and $nbC > 6) { $val['nb'] = $nbC - 6; $val['segment'] = $C; return _T('verifier:erreur_isbn_segment', $val); } // K (cle de controle) : 1 caractere max - if ($nbK = strlen($K) AND $nbK > 1) { + if ($nbK = strlen($K) and $nbK > 1) { $val['nb'] = $nbK - 1; $val['segment'] = $K; return _T('verifier:erreur_isbn_segment', $val); } - } - - // si le numero ISBN n a pas de tiret, on verifie au moyen d une regex - else { + } else { + // si le numero ISBN n a pas de tiret, on verifie au moyen d une regex // verification generique [978 ou 979] [9 chiffres] [1 chiffre ou lettre X] - if (!preg_match("/^(97[89]){0,1}[0-9]{1,9}[0-9X]$/", $valeur)) + if (!preg_match('/^(97[89]){0,1}[0-9]{1,9}[0-9X]$/', $valeur)) { return _T('verifier:erreur_isbn'); + } } } diff --git a/www/plugins/verifier/verifier/isbn.yaml b/www/plugins/verifier/verifier/isbn.yaml new file mode 100644 index 00000000..738ff279 --- /dev/null +++ b/www/plugins/verifier/verifier/isbn.yaml @@ -0,0 +1,3 @@ + +titre: '<:verifier:type_isbn:>' +description: '<:verifier:type_isbn_description:>' diff --git a/www/plugins/verifier/verifier/regex.php b/www/plugins/verifier/verifier/regex.php index 8ba86055..21570495 100644 --- a/www/plugins/verifier/verifier/regex.php +++ b/www/plugins/verifier/verifier/regex.php @@ -1,7 +1,9 @@ diff --git a/www/plugins/verifier/verifier/siren_siret.php b/www/plugins/verifier/verifier/siren_siret.php index 04f0f716..6ff2fd32 100644 --- a/www/plugins/verifier/verifier/siren_siret.php +++ b/www/plugins/verifier/verifier/siren_siret.php @@ -1,10 +1,12 @@ 9) $somme += (2*$valeur[$i])-9; else $somme += 2*$valeur[$i]; $i+=2; } - - if ($somme % 10) return $erreur; - } - // Test de SIRET - else{ + while ($i < 9) { + if ((2*$valeur[$i])>9) { + $somme += (2*$valeur[$i])-9; + } else { + $somme += 2*$valeur[$i]; + $i+=2; + } + } + + if ($somme % 10) { + return $erreur; + } + } else { + // Test de SIRET $erreur = _T('verifier:erreur_siret'); - if (!is_string($valeur)) + if (!is_string($valeur)) { return $erreur; + } // Si pas 14 caractère, c'est déjà foiré ! - if(!preg_match('/^[0-9]{14}$/',$valeur)) return $erreur; - if(preg_match('/[0]{8}/',$valeur)) return $erreur; + if (!preg_match('/^[0-9]{14}$/', $valeur)) { + return $erreur; + } + if (preg_match('/[0]{8}/', $valeur)) { + return $erreur; + } // Pour le SIRET on vérifie la clef de controle "1-2" avec les impaires *2 // (vs pairs*2 pour SIREN, parce qu'on part de la fin) $somme = 0; $i = 1; // Les paires - while($i < 14){ $somme += $valeur[$i]; $i+=2; } + while ($i < 14) { + $somme += $valeur[$i]; + $i+=2; + } $i = 0; // Les impaires ! - while($i < 14){ if((2*$valeur[$i])>9) $somme += (2*$valeur[$i])-9; else $somme += 2*$valeur[$i]; $i+=2; } - - if($somme % 10) return $erreur; + while ($i < 14) { + if ((2*$valeur[$i])>9) { + $somme += (2*$valeur[$i])-9; + } else { + $somme += 2*$valeur[$i]; + $i+=2; + } + } + + if ($somme % 10) { + return $erreur; + } } - + return ''; } diff --git a/www/plugins/verifier/verifier/taille.php b/www/plugins/verifier/verifier/taille.php index b55ad1f0..f74a61c0 100644 --- a/www/plugins/verifier/verifier/taille.php +++ b/www/plugins/verifier/verifier/taille.php @@ -1,7 +1,9 @@ = $options['min'])); - - if (isset($options['max'])){ + } + + if (isset($options['max'])) { $ok = ($ok and ($taille <= $options['max'])); } - if (isset($options['egal'])){ + if (isset($options['egal'])) { $ok = ($ok and ($taille == $options['egal'])); } - - if (!$ok){ + + if (!$ok) { // On ajoute la taille actuelle aux valeurs de remplacement $options['nb'] = $taille; - if (isset($options['min']) and isset($options['max'])) + if (isset($options['min']) and isset($options['max'])) { $erreur = _T('verifier:erreur_taille_entre', $options); - elseif (isset($options['max'])) + } elseif (isset($options['max'])) { $erreur = _T('verifier:erreur_taille_max', $options); - elseif (isset($options['egal'])) + } elseif (isset($options['egal'])) { $erreur = _T('verifier:erreur_taille_egal', $options); - else + } else { $erreur = _T('verifier:erreur_taille_min', $options); + } } - + return $erreur; } diff --git a/www/plugins/verifier/verifier/telephone.php b/www/plugins/verifier/verifier/telephone.php index 2051e24f..70ed47ad 100644 --- a/www/plugins/verifier/verifier/telephone.php +++ b/www/plugins/verifier/verifier/telephone.php @@ -1,7 +1,9 @@ 'verifier_url_protocole', 'php_filter' => 'verifier_php_filter', 'complet' => 'verifier_url_complet'); $fonction_verif = $fonctions_disponibles[$mode]; - - return $fonction_verif($valeur,$type_protocole,$protocole) ; + return $fonction_verif($valeur,$type_protocole,$protocole) ; } /** @@ -56,23 +56,27 @@ function verifier_url_dist($valeur, $options=array()){ * @param string $protocole : nom du protocole (si type_protocole=exact) * @return boolean Retourne true uniquement lorsque l'url est valide */ -function verifier_url_protocole($url,$type_protocole,$protocole){ - - $urlregex = array('tous' => "#^([a-z0-9]*)\:\/\/.*$# i", - 'web' => "#^(https?)\:\/\/.*$# i", - 'ftp' => "#^(s?ftp)\:\/\/.*$# i", - 'mail' => "#^(pop3|smtp|imap)\:\/\/.*$# i", - 'exact' => "#^(".$protocole.")\:\/\/.*$# i"); - - $msg_erreur = array('tous' => "", - 'web' => "http://, https://", - 'ftp' => "^ftp://, sftp://", - 'mail' => "pop3://, smtp://, imap://", - 'exact' => $protocole."://" ); - +function verifier_url_protocole($url, $type_protocole, $protocole) { + + $urlregex = array( + 'tous' => '#^([a-z0-9]*)\:\/\/.*$# i', + 'web' => '#^(https?)\:\/\/.*$# i', + 'ftp' => '#^(s?ftp)\:\/\/.*$# i', + 'mail' => '#^(pop3|smtp|imap)\:\/\/.*$# i', + 'exact' => '#^(".$protocole.")\:\/\/.*$# i' + ); + + $msg_erreur = array( + 'tous' => '', + 'web' => 'http://, https://', + 'ftp' => '^ftp://, sftp://', + 'mail' => 'pop3://, smtp://, imap://', + 'exact' => $protocole.'://' + ); + if (!preg_match($urlregex[$type_protocole], $url)) { - if($type_protocole=="tous") { + if ($type_protocole == 'tous') { return _T('verifier:erreur_url_protocole_exact', array('url' => echapper_tags($url))); } else { return _T('verifier:erreur_url_protocole', array('url' => echapper_tags($url),'protocole' => $msg_erreur[$type_protocole])); @@ -89,10 +93,11 @@ function verifier_url_protocole($url,$type_protocole,$protocole){ * @param string $protocole : nom du protocole (si type_protocole=exact) * @return boolean Retourne true uniquement lorsque l'url est valide */ -function verifier_php_filter($url,$type_protocole,$protocole){ +function verifier_php_filter($url, $type_protocole, $protocole) { - if (!filter_var($url, FILTER_VALIDATE_URL)) + if (!filter_var($url, FILTER_VALIDATE_URL)) { return _T('verifier:erreur_url', array('url' => echapper_tags($valeur))); + } return ''; } @@ -107,33 +112,34 @@ function verifier_php_filter($url,$type_protocole,$protocole){ * @param string $protocole : nom du protocole (si type_protocole=exact) * @return boolean Retourne true uniquement lorsque l'url est valide */ -function verifier_url_complet($url,$type_protocole,$protocole){ - - if($msg=verifier_url_protocole($url,$type_protocole,$protocole)!=''){ +function verifier_url_complet($url, $type_protocole, $protocole) { + + if ($msg = verifier_url_protocole($url, $type_protocole, $protocole) != '') { return $msg; } // SCHEME - $urlregex = "#^(.*)\:\/\/"; - + $urlregex = '#^(.*)\:\/\/'; + // USER AND PASS (optional) - $urlregex .= "([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)?"; - + $urlregex .= '([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)?'; + // HOSTNAME OR IP - $urlregex .= "[a-z0-9+\$_-]+(\.[a-z0-9+\$_-]+)*"; // http://x = allowed (ex. http://localhost, http://routerlogin) + $urlregex .= '[a-z0-9+\$_-]+(\.[a-z0-9+\$_-]+)*'; // http://x = allowed (ex. http://localhost, http://routerlogin) //$urlregex .= "[a-z0-9+\$_-]+(\.[a-z0-9+\$_-]+)+"; // http://x.x = minimum //$urlregex .= "([a-z0-9+\$_-]+\.)*[a-z0-9+\$_-]{2,3}"; // http://x.xx(x) = minimum //use only one of the above - + // PORT (optional) - $urlregex .= "(\:[0-9]{2,5})?"; + $urlregex .= '(\:[0-9]{2,5})?'; // PATH (optional) - $urlregex .= "(\/([a-z0-9+\$_%,-]\.?)+)*\/?"; + $urlregex .= '(\/([a-z0-9+\$_%,-]\.?)+)*\/?'; // GET Query (optional) - $urlregex .= "(\?[a-z+&\$_.-][a-z0-9;:@/&%=+\$_.-]*)?"; + $urlregex .= '(\?[a-z+&\$_.-][a-z0-9;:@/&%=+\$_.-]*)?'; // ANCHOR (optional) - $urlregex .= "(\#[a-z_.-][a-z0-9+\$_.-]*)?\$# i"; - - if (!preg_match($urlregex, $url)) + $urlregex .= '(\#[a-z_.-][a-z0-9+\$_.-]*)?\$# i'; + + if (!preg_match($urlregex, $url)) { return _T('verifier:erreur_url', array('url' => echapper_tags($valeur))); + } return ''; -} \ No newline at end of file +} diff --git a/www/plugins/yaml/experimental/yaml_fonctions.php b/www/plugins/yaml/experimental/yaml_fonctions.php index a9f27e5f..4b95e907 100644 --- a/www/plugins/yaml/experimental/yaml_fonctions.php +++ b/www/plugins/yaml/experimental/yaml_fonctions.php @@ -1,16 +1,17 @@ $valeur) { - if (is_string($valeur) && substr($valeur,0,8)=='inclure:' && substr($valeur,-5)=='.yaml') - $retour = array_merge($retour,yaml_charger_inclusions(yaml_decode_file(find_in_path(substr($valeur,8))))); - elseif (is_array($valeur)) - $retour = array_merge($retour,array($cle => yaml_charger_inclusions($valeur))); - else - $retour = array_merge($retour,array($cle => $valeur)); + foreach ($tableau as $cle => $valeur) { + if (is_string($valeur) && substr($valeur, 0, 8) == 'inclure:' && substr($valeur, -5) == '.yaml') { + $retour = array_merge($retour, yaml_charger_inclusions(yaml_decode_file(find_in_path(substr($valeur, 8))))); + } elseif (is_array($valeur)) { + $retour = array_merge($retour, array($cle => yaml_charger_inclusions($valeur))); + } else { + $retour = array_merge($retour, array($cle => $valeur)); + } } return $retour; - } - elseif (is_string($tableau) && substr($tableau,0,8)=='inclure:' && substr($tableau,-5)=='.yaml') - return yaml_charger_inclusions(yaml_decode_file(find_in_path(substr($tableau,8)))); - else + } elseif (is_string($tableau) && substr($tableau, 0, 8) == 'inclure:' && substr($tableau, -5) == '.yaml') { + return yaml_charger_inclusions(yaml_decode_file(find_in_path(substr($tableau, 8)))); + } else { return $tableau; + } } - -?> diff --git a/www/plugins/yaml/inc/yaml_sfyaml.php b/www/plugins/yaml/inc/yaml_sfyaml.php index 1d94844d..02b4bb45 100644 --- a/www/plugins/yaml/inc/yaml_sfyaml.php +++ b/www/plugins/yaml/inc/yaml_sfyaml.php @@ -1,36 +1,31 @@ - 2 - ), $opt); - $yaml = new sfYamlDumper(); - return $yaml->dump($struct, $opt['inline']); -} - -function yaml_sfyaml_decode($input,$show_error=true) { - require_once _DIR_PLUGIN_YAML.'sfyaml/sfYaml.php'; - require_once _DIR_PLUGIN_YAML.'sfyaml/sfYamlParser.php'; - - $yaml = new sfYamlParser(); - - try - { - $ret = $yaml->parse($input); - } - catch (Exception $e) - { - if ($show_error) - throw new InvalidArgumentException(sprintf('Unable to parse string: %s', $e->getMessage())); - else - return false; - } - - return $ret; -} - -?> \ No newline at end of file + 2), $opt); + $yaml = new sfYamlDumper(); + return $yaml->dump($struct, $opt['inline']); +} + +function yaml_sfyaml_decode($input, $show_error = true) { + require_once _DIR_PLUGIN_YAML.'sfyaml/sfYaml.php'; + require_once _DIR_PLUGIN_YAML.'sfyaml/sfYamlParser.php'; + + $yaml = new sfYamlParser(); + + try { + $ret = $yaml->parse($input); + } catch (Exception $e) { + if ($show_error) { + throw new InvalidArgumentException(sprintf('Unable to parse string: %s', $e->getMessage())); + } else { + return false; + } + } + + return $ret; +} diff --git a/www/plugins/yaml/inc/yaml_to_array.php b/www/plugins/yaml/inc/yaml_to_array.php index 75969ef6..bcebb836 100644 --- a/www/plugins/yaml/inc/yaml_to_array.php +++ b/www/plugins/yaml/inc/yaml_to_array.php @@ -1,15 +1,16 @@ diff --git a/www/plugins/yaml/lang/paquet-yaml.xml b/www/plugins/yaml/lang/paquet-yaml.xml index 1f1c505d..c6839436 100644 --- a/www/plugins/yaml/lang/paquet-yaml.xml +++ b/www/plugins/yaml/lang/paquet-yaml.xml @@ -10,6 +10,9 @@ + + + diff --git a/www/plugins/yaml/lang/paquet-yaml_en.php b/www/plugins/yaml/lang/paquet-yaml_en.php index 7bae3523..520009f3 100644 --- a/www/plugins/yaml/lang/paquet-yaml_en.php +++ b/www/plugins/yaml/lang/paquet-yaml_en.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-yaml?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( yaml_decode() and yaml_encode(). It also provides the yaml format for the (DATA) loop.', 'yaml_slogan' => 'A simple file format for editing lists of data' ); - -?> diff --git a/www/plugins/yaml/lang/paquet-yaml_es.php b/www/plugins/yaml/lang/paquet-yaml_es.php index 90af6ebc..38f5857b 100644 --- a/www/plugins/yaml/lang/paquet-yaml_es.php +++ b/www/plugins/yaml/lang/paquet-yaml_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-yaml?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'yaml_description' => 'Este plugin proporciona las funciones de lectura/escritura del formato YAML: yaml_decode() y yaml_encode(). También proporciona el formato yaml para el bucle (DATA).', 'yaml_slogan' => 'Un formato de archivo simple para editar listas de datos' ); - -?> diff --git a/www/plugins/yaml/lang/paquet-yaml_fa.php b/www/plugins/yaml/lang/paquet-yaml_fa.php index 9d298e7c..ebb1ecb2 100644 --- a/www/plugins/yaml/lang/paquet-yaml_fa.php +++ b/www/plugins/yaml/lang/paquet-yaml_fa.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-yaml?lang_cible=fa // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'yaml_description' => 'اين پلاگين كاركردهاي خواندن/نوشتن فرمت يا.اي.ام.ال را فراهم مي‌آورد: yaml_decode() وyaml_encode(). همچنين فرمت يا.اي.ام.ال را براي حلقه‌ي (DATA) فراهم مي‌سازد.', 'yaml_slogan' => 'فرمتي براي پروند‌ه ساده براي ويرايش فهرست‌هاي داده‌ها' ); - -?> diff --git a/www/plugins/yaml/lang/paquet-yaml_fr.php b/www/plugins/yaml/lang/paquet-yaml_fr.php index 9933ac5b..66a6a9e1 100644 --- a/www/plugins/yaml/lang/paquet-yaml_fr.php +++ b/www/plugins/yaml/lang/paquet-yaml_fr.php @@ -1,7 +1,9 @@ yaml_decode() et yaml_encode(). Il fournit aussi le format yaml pour la boucle (DATA).', 'yaml_slogan' => 'Un format de fichier simple pour éditer des listes de données' ); - -?> diff --git a/www/plugins/yaml/lang/paquet-yaml_nl.php b/www/plugins/yaml/lang/paquet-yaml_nl.php new file mode 100644 index 00000000..39ec5b5b --- /dev/null +++ b/www/plugins/yaml/lang/paquet-yaml_nl.php @@ -0,0 +1,16 @@ + 'Met behulp van deze plugin komt de functie van het lezen/schrijven in YAML-formaat beschikbaar: + yaml_decode() en yaml_encode(). Het formaat kan ook in de (DATA) lus worden gebruikt.', + 'yaml_slogan' => 'Een eenvoudig bestandsformaat om gegevenslijsten te redigeren' +); diff --git a/www/plugins/yaml/lang/paquet-yaml_ru.php b/www/plugins/yaml/lang/paquet-yaml_ru.php index 86916233..e4374359 100644 --- a/www/plugins/yaml/lang/paquet-yaml_ru.php +++ b/www/plugins/yaml/lang/paquet-yaml_ru.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-yaml?lang_cible=ru // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( yaml_decode() и yaml_encode(). И позволяет использовать YAML в запросе BOUCLE(DATA).', 'yaml_slogan' => 'Позволяет работать с YAML форматом' ); - -?> diff --git a/www/plugins/yaml/lang/paquet-yaml_sk.php b/www/plugins/yaml/lang/paquet-yaml_sk.php index 4b44dfb1..0bf17d24 100644 --- a/www/plugins/yaml/lang/paquet-yaml_sk.php +++ b/www/plugins/yaml/lang/paquet-yaml_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-yaml?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -12,5 +14,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( yaml_decode() a yaml_encode(). Poskytuje formát yaml aj pre cyklus (DATA).', 'yaml_slogan' => 'Jednoduchý formát súborov na upravovanie zoznamov dát' ); - -?> diff --git a/www/plugins/yaml/paquet.xml b/www/plugins/yaml/paquet.xml index 3b0b6138..7507ae81 100644 --- a/www/plugins/yaml/paquet.xml +++ b/www/plugins/yaml/paquet.xml @@ -1,11 +1,11 @@ YAML @@ -16,4 +16,4 @@ Symfony YAML - Fabien Potencier MIT - \ No newline at end of file + diff --git a/www/plugins/yaml/plugin.xml b/www/plugins/yaml/plugin.xml index c2e63a64..05bbe02b 100644 --- a/www/plugins/yaml/plugin.xml +++ b/www/plugins/yaml/plugin.xml @@ -3,17 +3,17 @@ Un format de fichier simple pour éditer des listes de données. format défini par yaml.org, librairie php développée par Fabien Potencier pour Symfony MIT - 1.5.1 + 1.5.2 stable Ce plugin fournit les fonctions de lecture/écriture du format YAML. yaml_decode() et yaml_encode(). Il fournit aussi le format yaml pour la boucle (DATA). YAML - http://www.spip-contrib.net/Le-plugin-YAML + http://contrib.spip.net/Le-plugin-YAML yaml.png yaml_fonctions.php - + outil diff --git a/www/plugins/yaml/svn.revision b/www/plugins/yaml/svn.revision index 4049a97a..9b0df0b0 100644 --- a/www/plugins/yaml/svn.revision +++ b/www/plugins/yaml/svn.revision @@ -1,10 +1,10 @@ Origine: file:///home/svn/repository/spip-zone/_plugins_/yaml -Revision: 78336 -Dernier commit: 2013-11-11 00:00:50 +0100 +Revision: 97676 +Dernier commit: 2016-05-10 19:19:02 +0200 file:///home/svn/repository/spip-zone/_plugins_/yaml -78336 -2013-11-11 00:00:50 +0100 +97676 +2016-05-10 19:19:02 +0200 \ No newline at end of file diff --git a/www/plugins/yaml/yaml_fonctions.php b/www/plugins/yaml/yaml_fonctions.php index 0880d9a0..ef2c1fb8 100644 --- a/www/plugins/yaml/yaml_fonctions.php +++ b/www/plugins/yaml/yaml_fonctions.php @@ -1,10 +1,12 @@ diff --git a/www/plugins/zen-garden-2/images/themes-128.png b/www/plugins/zen-garden-2/images/themes-128.png index 05da9de102cd039464a6e9c88f3f80b66e1e002c..853616df81223cee341a03c6b15a65808b2b6e80 100644 GIT binary patch literal 32123 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 AS^xk5 diff --git a/www/plugins/zen-garden-2/images/themes-32.png b/www/plugins/zen-garden-2/images/themes-32.png index 7b6e426eccc88c4ddedd4969fb57d20fae22cc31..79d027c9527442a57af163185ddd15ff9fab4a6d 100644 GIT binary patch delta 2632 zcmV-O3b*yy70?urBYz4PNklOi#~_cXqFK_v8JHYumPM z+qP}nwr#Jyvpec(mn-wn$m`$@{~7VtImPoHW=Z~s_2n;r`8LLwms&i*;@-!O9KX4h zS6b{keDH8PP13*u3ts)ESH2i{2mj+z{Ku-*YxN{fJZ-;>F@GR1p68*I|B}4Ouh|`* zLdhEKxkDFyw(2EJd# zc^hSxKth(~tbeVpvA({JhvcG5FCiR7yz|YkVsU$e_Cy`LDt>K}EH{W;P%XE|FMjdM zo(sHQwcE1*Tb;!)H==*eDp z;65&-#PcK=2+9FM3v6cam7>&W0D{yKiG?IhGKyT2XE{ll5Ck464K_wqysjqkrU>OC zLLX!KSHFg(E-RglEdXg1p8xzumC`I#_Cw^>Bb#^YRfQre$n%0qtxBm}LVA*Fy-L~Y zMUh*$`+sOF?RzLsfe`pU9ADYu_*zUM%d{$*xii0J`>DfBjC06CPM%)rS)l9zpk$X{ zE|(EPu+{0Zw7iJ)JZwFHF_eQcjfn=s{?J}aT_lXJNzyp7N#8|lK#z{C7gfd@ zoZt$*7w_aD27fq3^LooLwT(fq*9TBmangp@AAb#p&QPgTrr#SN1kUp~jIFmCqm9eE zHX4Z{juWCVL`vx*Azj)OMnK%#B2^KczZ~GNf9x?|hiVE3e%WQmjWvVe#@`88#YqgR z-e_Q>KsXA?^US89N|t80+?Nz#7&(GzoYL#|&|2gBKG8Tr3W4n$3RNN)c32QwEL&2) zIDeGzs}PnOFgFhityyY4W7bxV4gr)^oD`l=h0a~ITaRf?Pca&f07Fm-@O;InKcdKU zgcR6}VZCs~@x1tik8 zlPXMs?KUC#3~1%IHh1Z?hI6g=foveFj?r$!LcshtiZLWBcYUM-wD|YH3e|lgkY{=P#QW_&4>5G0}jp5y~=P1`tJllqx`aJwSQV( z7>zl0VuNkrFM=6CT1!Wm+lYP`v2)HN zJO$+h9({#tOMWrZ#CssP#WuozG6E6+31Iu$&vfCPSs%FY-uZeH-0fOr_RM=sO_jOv zxq^yUkYu>t*A`il5{^Sh#=;e#r+*Zp$gOWF+o$2QZ+OEWVUP&gQZnqrd~=rZI2-~g zfC8}LQ{|FJv!S^0rER|Oi;(aC;WSGv!DoM-(kR8$%7QF*;ig)v5{0oF)zVXrKoC@1 z4diLU)*vMh;F{NfSi%QR8&n0(|235M&2p^2`QHShgwoQKVAsqfU;Luv*net5UP$%_ zk{z>(PTwar0_EkT1*B=_@?Wwcx8v6lu!GD+AS-g}Ww60vx&iG;_|oqTyM5Rg!%#L! z!?oe7Kk#7#AgzMdX=TllI=+!{WHqGf8zw6TPZs1xQt}`UBWKhWB5@P}xLIM1yA3G_ z%GfZXM+vH;n7W$B-oD@`e}6PADJbXQPe5&<$%Zv%fd$GQDEYFs()BoRamd|l{=fYz zpS6uGJikm7Ym_Ib)vIm{OCf1A8`wO$da#7h|L6kSNuVS~Xr^+5wEBi8c}fFL9nC1G zAZrbdoIEiE0Fd?s`(kAj_SrtWgGb-@t_;JF+uv{pSDw?tml>*5c7JVW^AA#>wINF~ zFu2idw01;F7BcXm6%fao+R1{O%o?;sJ_&#GAd=Rp&gRGh3zR)zv?(>J0a9sF@F{-yjtAk%KhfJf!PkF2q$D+Y z>V7_4r~v>shB07_YeS?|WW|`Qmr#lg>r;X+1p$@7UKc~Iwlo8w{jrVWh)@1tot0h*>4g+VxI(iX;3AP(S$`B7Z2@j?K=~fy?wHdn zhW4xgRc3U|kS##tQV_KnMq{J9o10;;yDk7Dj~@IR*STn?gc{RLpSkHeFL~c@dDi<@ z`NVfOx!ySqp7W3kSy}B7=U79^MZ#0c8Mm7kzSU>v=7^IRX*5zmnm|@StC}-G$m%y> zGR{aVUNjo^B7Z>q#~jdgqZQx%)iJ*Rn|8dOlDJZwvyy%rrV0rhASUGhj0usRdD*~0W*Eq8|q)yIEqe{0k z;9j@bMSl?T=Y8w+Zo15053jMgHKtip7%h-OxbWLZP_0zh*x2MNU-%L-3<+~Md<=F0 zX9Ig~nSb)}Z@(So%@PEy2uS~nfbV%hoWjnfNuK$j>+tSR{eUaapXHKk?chCc`!N^a z`QyxOt1#K{F>dnZ?q4C#+-xApQqXYQ+uVk`-}ZJKK6H%JXIAL+tM1vuwQh7n8np)HYK0U*G0quw*O{7b^V{EiECdVy zfB=}^KL57GrTIs0ZH*X(F^!61I8NyfB0H2??AbZV?+dIt`5q|cYnm4 z&3{djB(fbb!}8KRvokG%N{xDbg1vt`V7)*1$6l}Z?a^rTZQxq~0^FbP!|jB7hwXEw z+f#r5!1DydFeOeh=e;)Cc`gM=&;1Eg=mL!Smp|I-T5D=mpNV=v6vZgzx$ms5ja~@+ z95@Ob;9r)o5v$j3?|Ew4=2Ur}^bGhIgh4fmy(a8O9jsAp delta 2770 zcmV;@3N7`}6xkJ!BYyxHbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU+ zdr3q=RCwCNS8I%1Wf^|XZRX77%yoBX_QLK0v0bg96$+N7X}G9h0`h~1iNt7#i9txL zCPwi_)bfLnAZRQ#8e$+?z!153Arb;euu$64qGj8qTef?h-G80?<(xTZ&c)|DyWO(C z{OOsT%*>fN-}k)F`@GNl9t1&v|8>0h;)}QNe-H57$MepabLVg3`?Wl`On)$)cWg%& z>xlEAUq1MA-g0pN{{6Uct=Vj%TCHw;FPF=>_uhNM&+11vN+c6WyK5`{+CKpafubl- zRc*iPx!Y^4d4H&K0{LPF)mjC%?ZB6P>-fpzomQ(=o;^QXI(GEk>xRY$@xAZ=(C3oN zJS#@hSals#__-;*%d%RPWwiOZw*lb(2Yzz@?!CMBJ^bjys@?4d+*ANS;0Ji@$zL14 z`NIJ;nyb*XI2bV;t49DfdObI`Tw0E;tgQ4YkSDIZdVeQ!xjr0u`=z^wFENl$Cjli6 zEs;Uj4IsG^GMRiQpD+BF+x}t$z@F>&>`SGMOe&j1*U}(MG9;ejST2=#t&2!Rhuy89 z+wFqC!gXB&=pi0YAe+i!XlNKIBaK?w!fUTTiP2FDg^?tZc>*x<2<$eZy=h#r?TG}C z&xy4+0DpAbRt1uusn?p};u1Mh6aru-^r+6Cq%dcisv=?-5cD_%(j`d8?!j|?xIGuP zV?);!I54oH;iwiW|Cz$6lXVPIi*W~- zdb@_P8+|letD6CkYcqzy%6}G+s0YFF!iO!fv3vo5q)4jgyP?`e#Hn;T zjL`GFP!D=Mh91jLfRkj2ENR?O4H*(z5Qm-++F=?y4V;-Yac0U!AKhSp(Jz0;P()Qf%-q0#F%tHk(yUtAm-@Re$s+J$&`%L5vP*Xwk#}{4W=0W^E)RUKq8=y`W!V zDjd3@Pl1Xwv5e55PR5H0%y}Sc1NZD&E6caqKDrZ3)6M-b8@8a|-q1ia8qs>br!1{B zLwaxDo5mfxqnH>}Xsc1&_(=&dGC;ox^DP(%_0TaxFl&HB8dOLgtEA)Ll7Bv6Q48?M zNj3mmLZ0bsQTKzX0y-U22++Bh0x}SdD6~-(H(s5`b8ne=^~54ZvJ##>Oizn+k%&s@ zb=T;Q)0iv@RamvmvJ(JwnwQXkODC*09SRND{xOy#L;U?B(+~r$pb17!7ckQ(Zw6r5 zh>YYUY#GSl`R8TKlx(=3jDIt_jIn}>N<)Lg;#L(G4wLJ!G)4X+q+Hmq06-%P8R(IL zBn^n0DRwxEfbVX?>|>E5hrzWgdLfRb^{G0 zhoxzWRE0upH(Q}u39k^F3yaq252O)(+h(*Xazh>_8&u!<03+Nb%72Q`(ro!dDXbnp z)wy`PrqGJTx$488~j$X8gH;ymj?`(bO^#v`QBNgc@kH+JEY<9a}LyKa2Ywc?Pc^ zyo)vd9_r;;{QWTVEptg{ZTJvWUpU0LCRhl9wKC+WMGyp&p?)O?Zq*2u)OgU_vx0 z(IJHiiQy#d4S$+~POXE*g#h^iTO#{$dxq&60*tHqufzb_oxrb^%Vu~Jv4<(xbLBYS z6X;86DE1|>|M6q^!Q&-7^-39gw;A}+*FS}YQk^rM7#!4)2~l!lbJ4uSY)~i`(X~0M ziB`>}X$NG3a)`S~!$j#NAk(F_#}upGs$1&-F8F|-41atTuN;}dt4Gfvonjm2;@`b< z2R^r}AA5J?(5!tL2cLZ(wT8n@+;H=-Rr4jPXm}*lN{mYnL^+PHa6^XHnDnr7 z`vkuItzTiKRI*&xu{MeD*qPY--4NQ;Oc{qyl{uW)xN2g6xt2oF z3F-w4!heiJVTeBP%%P|8-n%D}X}SGV{^>AJPKcP=0Kg~=KA7Idk-CrHRX!0ZT#^ar!%GY| ztQK?J-#A$(IzB<$~qFci-gqx%G!sYykLw9{&|! Y0FbwrY2-q{{{R3007*qoM6N<$g7P0hZU6uP diff --git a/www/plugins/zen-garden-2/images/themes-64.png b/www/plugins/zen-garden-2/images/themes-64.png index 28d544a1f5e3cdacf0247ed68f5a61fedbcb66a9..5cbc66f0ae18896c38741063de177ccdc91d06a9 100644 GIT binary patch literal 8557 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 diff --git a/www/plugins/zen-garden-2/inclure/zengarden_switcher.js b/www/plugins/zen-garden-2/inclure/zengarden_switcher.js index 4fc2029e..146a6f71 100644 --- a/www/plugins/zen-garden-2/inclure/zengarden_switcher.js +++ b/www/plugins/zen-garden-2/inclure/zengarden_switcher.js @@ -3,6 +3,6 @@ jQuery(function() { .change(function(){ jQuery(this).parents('form').get(0).submit(); }) - .attr('value',theme_selected) - .siblings("input[type=submit]").hide(); -}); \ No newline at end of file + .val(theme_selected) + .siblings("input[type=submit]").hide(); +}); diff --git a/www/plugins/zen-garden-2/lang/paquet-zengarden.xml b/www/plugins/zen-garden-2/lang/paquet-zengarden.xml index b077dbfc..705c3450 100644 --- a/www/plugins/zen-garden-2/lang/paquet-zengarden.xml +++ b/www/plugins/zen-garden-2/lang/paquet-zengarden.xml @@ -1,4 +1,7 @@ + + + diff --git a/www/plugins/zen-garden-2/lang/paquet-zengarden_de.php b/www/plugins/zen-garden-2/lang/paquet-zengarden_de.php new file mode 100644 index 00000000..196f7a6c --- /dev/null +++ b/www/plugins/zen-garden-2/lang/paquet-zengarden_de.php @@ -0,0 +1,15 @@ + ' ', + 'zengarden_slogan' => 'Ein Zen-Garten für Skelette' +); diff --git a/www/plugins/zen-garden-2/lang/paquet-zengarden_en.php b/www/plugins/zen-garden-2/lang/paquet-zengarden_en.php index 4a7a4631..4933fa5f 100644 --- a/www/plugins/zen-garden-2/lang/paquet-zengarden_en.php +++ b/www/plugins/zen-garden-2/lang/paquet-zengarden_en.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-zengarden?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'zengarden_description' => ' ', 'zengarden_slogan' => 'A Zen garden for the skeletons' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/paquet-zengarden_es.php b/www/plugins/zen-garden-2/lang/paquet-zengarden_es.php index 2f4b473e..d5349b26 100644 --- a/www/plugins/zen-garden-2/lang/paquet-zengarden_es.php +++ b/www/plugins/zen-garden-2/lang/paquet-zengarden_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-zengarden?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'zengarden_description' => ' ', 'zengarden_slogan' => 'Un jardín Zen para los esqueletos' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/paquet-zengarden_fa.php b/www/plugins/zen-garden-2/lang/paquet-zengarden_fa.php index 197f2511..d1d30aa2 100644 --- a/www/plugins/zen-garden-2/lang/paquet-zengarden_fa.php +++ b/www/plugins/zen-garden-2/lang/paquet-zengarden_fa.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-zengarden?lang_cible=fa // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'zengarden_description' => ' ', 'zengarden_slogan' => 'باغ ذن براي اسپيپ ' # MODIF ); - -?> diff --git a/www/plugins/zen-garden-2/lang/paquet-zengarden_fr.php b/www/plugins/zen-garden-2/lang/paquet-zengarden_fr.php index ce52b90a..a834945a 100644 --- a/www/plugins/zen-garden-2/lang/paquet-zengarden_fr.php +++ b/www/plugins/zen-garden-2/lang/paquet-zengarden_fr.php @@ -1,7 +1,9 @@ ' ', 'zengarden_slogan' => 'Un jardin Zen pour les squelettes' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/paquet-zengarden_nl.php b/www/plugins/zen-garden-2/lang/paquet-zengarden_nl.php index 085ef1e0..44475178 100644 --- a/www/plugins/zen-garden-2/lang/paquet-zengarden_nl.php +++ b/www/plugins/zen-garden-2/lang/paquet-zengarden_nl.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-zengarden?lang_cible=nl // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'zengarden_description' => 'Bekijk, probeer en kies het juiste thema voor je site. ', 'zengarden_slogan' => 'SPIP in Zen-sferen' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/paquet-zengarden_ru.php b/www/plugins/zen-garden-2/lang/paquet-zengarden_ru.php index a9e8233c..f554b220 100644 --- a/www/plugins/zen-garden-2/lang/paquet-zengarden_ru.php +++ b/www/plugins/zen-garden-2/lang/paquet-zengarden_ru.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-zengarden?lang_cible=ru // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'zengarden_description' => ' ', 'zengarden_slogan' => 'Плагин "Zengarden" для SPIP' # MODIF ); - -?> diff --git a/www/plugins/zen-garden-2/lang/paquet-zengarden_sk.php b/www/plugins/zen-garden-2/lang/paquet-zengarden_sk.php index 638f449c..f5a6825c 100644 --- a/www/plugins/zen-garden-2/lang/paquet-zengarden_sk.php +++ b/www/plugins/zen-garden-2/lang/paquet-zengarden_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/paquet-zengarden?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -11,5 +13,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'zengarden_description' => ' ', 'zengarden_slogan' => 'Zenová záhrada pre Å¡ablóny' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/zengarden_de.php b/www/plugins/zen-garden-2/lang/zengarden_de.php index 29266263..172068be 100644 --- a/www/plugins/zen-garden-2/lang/zengarden_de.php +++ b/www/plugins/zen-garden-2/lang/zengarden_de.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/zengarden?lang_cible=de // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -34,5 +36,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'theme_actif' => 'Dieses Thema wird zur Zeit verwendet', 'themes' => 'Themen' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/zengarden_en.php b/www/plugins/zen-garden-2/lang/zengarden_en.php index 64cb417e..8aa20d6b 100644 --- a/www/plugins/zen-garden-2/lang/zengarden_en.php +++ b/www/plugins/zen-garden-2/lang/zengarden_en.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/zengarden?lang_cible=en // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -33,5 +35,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'theme_actif' => 'This theme is currently used', 'themes' => 'Themes' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/zengarden_es.php b/www/plugins/zen-garden-2/lang/zengarden_es.php index b2d1a987..048d5d2e 100644 --- a/www/plugins/zen-garden-2/lang/zengarden_es.php +++ b/www/plugins/zen-garden-2/lang/zengarden_es.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/zengarden?lang_cible=es // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -33,5 +35,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'theme_actif' => 'Este tema se utiliza actualmente', 'themes' => 'Temas' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/zengarden_fa.php b/www/plugins/zen-garden-2/lang/zengarden_fa.php index b92bad32..02a23152 100644 --- a/www/plugins/zen-garden-2/lang/zengarden_fa.php +++ b/www/plugins/zen-garden-2/lang/zengarden_fa.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/zengarden?lang_cible=fa // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -33,5 +35,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'theme_actif' => 'در حال حاضر اين تم مورد استفاده است', 'themes' => 'تم‌ها' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/zengarden_fr.php b/www/plugins/zen-garden-2/lang/zengarden_fr.php index b06a5549..bfbd2d60 100644 --- a/www/plugins/zen-garden-2/lang/zengarden_fr.php +++ b/www/plugins/zen-garden-2/lang/zengarden_fr.php @@ -1,7 +1,9 @@ 'Ce thème est actuellement utilisé', 'themes' => 'Thèmes' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/zengarden_nl.php b/www/plugins/zen-garden-2/lang/zengarden_nl.php index d5fadba8..4355bfeb 100644 --- a/www/plugins/zen-garden-2/lang/zengarden_nl.php +++ b/www/plugins/zen-garden-2/lang/zengarden_nl.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/zengarden?lang_cible=nl // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -33,5 +35,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'theme_actif' => 'Dit thema wordt momenteel gebruikt', 'themes' => 'Thema’s' ); - -?> diff --git a/www/plugins/zen-garden-2/lang/zengarden_sk.php b/www/plugins/zen-garden-2/lang/zengarden_sk.php index 7ef76c63..7e4b7b49 100644 --- a/www/plugins/zen-garden-2/lang/zengarden_sk.php +++ b/www/plugins/zen-garden-2/lang/zengarden_sk.php @@ -3,7 +3,9 @@ // extrait automatiquement de http://trad.spip.net/tradlang_module/zengarden?lang_cible=sk // ** ne pas modifier le fichier ** -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} $GLOBALS[$GLOBALS['idx_lang']] = array( @@ -33,5 +35,3 @@ $GLOBALS[$GLOBALS['idx_lang']] = array( 'theme_actif' => 'Tento farebný motív sa používa teraz', 'themes' => 'Farebné motívy' ); - -?> diff --git a/www/plugins/zen-garden-2/paquet.xml b/www/plugins/zen-garden-2/paquet.xml index a35b28a2..2a6d395e 100644 --- a/www/plugins/zen-garden-2/paquet.xml +++ b/www/plugins/zen-garden-2/paquet.xml @@ -1,11 +1,11 @@ Zen-Garden diff --git a/www/plugins/zen-garden-2/prive/squelettes/inclure/zengarden_theme.html b/www/plugins/zen-garden-2/prive/squelettes/inclure/zengarden_theme.html index e25fb4b7..6e518fb0 100644 --- a/www/plugins/zen-garden-2/prive/squelettes/inclure/zengarden_theme.html +++ b/www/plugins/zen-garden-2/prive/squelettes/inclure/zengarden_theme.html @@ -14,8 +14,8 @@
    [(#VALEUR{description}|propre)]
    -
    [(#VAL{info_les_auteurs_1}|_T{#ARRAY{les_auteurs,#VALEUR{auteur}|implode{', '}|propre|PtoBR}})]
    -
    [<:intitule_licence:> (#VALEUR{licence}|implode{','}|propre|PtoBR)]
    +
    [(#VAL{info_les_auteurs_1}|_T{#ARRAY{les_auteurs,#VALEUR{auteur}|zengarden_affiche_info|propre|PtoBR}})]
    +
    [<:intitule_licence:> (#VALEUR{licence}|zengarden_affiche_info|propre|PtoBR)]
    <:zengarden:intitule_compatiblite_squelette:> diff --git a/www/plugins/zen-garden-2/prive/squelettes/inclure/zengarden_theme_actif.html b/www/plugins/zen-garden-2/prive/squelettes/inclure/zengarden_theme_actif.html index 593170fa..643b0c28 100644 --- a/www/plugins/zen-garden-2/prive/squelettes/inclure/zengarden_theme_actif.html +++ b/www/plugins/zen-garden-2/prive/squelettes/inclure/zengarden_theme_actif.html @@ -6,8 +6,8 @@

    <:zengarden:theme_actif:>

    [(#VALEUR{nom}|typo|extraire_multi)]

    [(#VALEUR{description}|propre)]
    -
    [(#VAL{info_les_auteurs_1}|_T{#ARRAY{les_auteurs,#VALEUR{auteur}|implode{', '}|propre|PtoBR}})]
    -
    [<:intitule_licence:> (#VALEUR{licence}|implode{','}|propre|PtoBR)]
    +
    [(#VAL{info_les_auteurs_1}|_T{#ARRAY{les_auteurs,#VALEUR{auteur}|zengarden_affiche_info|propre|PtoBR}})]
    +
    [<:intitule_licence:> (#VALEUR{licence}|zengarden_affiche_info|propre|PtoBR)]

    \[<:zengarden:desactiver_ce_theme:>\]

    diff --git a/www/plugins/zen-garden-2/prive/themes/spip/images/themes-16.png b/www/plugins/zen-garden-2/prive/themes/spip/images/themes-16.png index ebfc1037df2a81d6a2da8d19b2e1317010499d48..a31825f183927b145adaf4d6eb89f71b58e13b6f 100644 GIT binary patch delta 820 zcmV-41IzrV2g(MJBYy)CNklgn$B%(MN@cIa%|wrvN_M(Aua ze70?Sy*qBJZg)cO&&)tttcv&EefJ`*^}~~L{iIyxy6!1yn(lwr1!vs2?*Ru)*=lL5 z6{|oTdcwh<|NPT06p95_Uv1^amT55=M6c`OxgNj$`a7+*!+#0K9>}RD?2_5#YFp*< zZZWs8b<&9!TqQ2O;UfLb*WXes75VL#-*FrVG6kCm&h%W5m@?6uEKDyz*V z6a(zDWE)OD|BrLj8tbio^+cmV5~o;}MYU2PZxygD8!}KR=FFK*JI$!gtFX^vkEL(F zO{KOLcfUGzuYa`iHc6C_B~y|j5NMqdg%L@dpfzM7haHTQeEB-xJn$StZ;mkZdxw!m zW6%&8gi(S}2Bu}=bR6O+B93FSEJG-XX)EF%|Kiu*1AY^*^J=g|waCc8P+LYRB$;L^ zQ`d=*QlJq?DG@?o+ZKk>eD-h1NE4RN5zMMUn9NK(zklZ&X&i9LA+xAf4DNq%&4&SLxIwe+$py1Zyzym+Ctm9?(S@8$(U}J5??M?0 zLkMI7-RW@KFgV|sSOeNkf(cKiX~J{wbouO;m>>}#GL-7K-yg-!7cg@MW?A5x0)G_D zR+(Omi+_#+xzpyWvBkP|He0)j5RfJrTI>E5!XThtt6{Nu>^a|r-E|5tt zt?=A+>#*ZS5#RpQAc>-W5-BBFnqgTsQb#mA7#4!ZOYr_`v+&c@1(4tU_$~K7`xh^~ z?XYZKkw(k!&z@ zqw>FTdwKce7tfwOE|!nQ9N4zKZx}}N!)qU$uI)71-(SD}O&l_iRifej#l`bT?<~Fb z$Nlxc8Ow|@Up;n8*L0#NV$ip+Et}1aEjnG3rOOw%vh+r5&m)c!%H=ZSr4qgy;A9;-?G7n4a#@2~*JEQ3u2!EQ-@Hxg3`8^x9h4DgC_taMMcv!%$`Z$ z`vgHi9LM5ZMl%$Gd)sVmxok@CdKF$RWN7R@>dL*Kea#V^}hlP0N+cAcWD9TAq)Tj002ovPDHLkV1i!ZxFi4o diff --git a/www/plugins/zen-garden-2/svn.revision b/www/plugins/zen-garden-2/svn.revision index 40ae7b45..13e83358 100644 --- a/www/plugins/zen-garden-2/svn.revision +++ b/www/plugins/zen-garden-2/svn.revision @@ -1,10 +1,10 @@ Origine: file:///home/svn/repository/spip-zone/_plugins_/zen-garden/trunk -Revision: 79166 -Dernier commit: 2013-12-05 06:02:09 +0100 +Revision: 97593 +Dernier commit: 2016-05-07 23:04:16 +0200 file:///home/svn/repository/spip-zone/_plugins_/zen-garden/trunk -79166 -2013-12-05 06:02:09 +0100 +97593 +2016-05-07 23:04:16 +0200 \ No newline at end of file diff --git a/www/plugins/zen-garden-2/zengarden_fonctions.php b/www/plugins/zen-garden-2/zengarden_fonctions.php index 715edd86..058f8fef 100644 --- a/www/plugins/zen-garden-2/zengarden_fonctions.php +++ b/www/plugins/zen-garden-2/zengarden_fonctions.php @@ -6,8 +6,9 @@ * @package SPIP\Zen-Garden\Fonctions */ -if (!defined("_ECRIRE_INC_VERSION")) return; - +if (!defined("_ECRIRE_INC_VERSION")) { + return; +} function zengarden_affiche_version_compatible($intervalle){ if (!strlen($intervalle)) return ''; @@ -45,9 +46,13 @@ function zengarden_liste_themes($tous){ $themes = array(); + // charger les themes de themes-dist/ + if (is_dir(_DIR_THEMES_DIST)) + $themes = array_merge($themes, zengarden_charge_themes(_DIR_THEMES_DIST, $tous)); + // charger les themes de themes/ if (is_dir(_DIR_THEMES)) - $themes = array_merge($themes,zengarden_charge_themes(_DIR_THEMES,$tous)); + $themes = array_merge($themes, zengarden_charge_themes(_DIR_THEMES, $tous)); // ceux de squelettes/themes/ if (is_dir($skels=_DIR_RACINE."squelettes/themes/")) @@ -77,7 +82,7 @@ function zengarden_liste_themes($tous){ * * Pour être compatible un thème doit avoir un du squelette en question dans son paquet.xml */ - $search = ""; + $search = "dist"; if (defined('_ZENGARDEN_FILTRE_THEMES')) $search=_ZENGARDEN_FILTRE_THEMES; elseif (defined('_DIR_PLUGIN_ZPIP')) $search="zpip"; elseif (defined('_DIR_PLUGIN_Z')) $search="z"; @@ -119,4 +124,27 @@ function zengarden_filtrer_liste_plugins($flux){ return $flux; } -?> \ No newline at end of file + + +/** + * Afficher les auteurs ou licences + * + * Vient de plugin.xml ou paquet.xml + * + * @param array $donnees + * @return string +**/ +function zengarden_affiche_info($donnees) { + if (is_array($donnees) AND count($donnees)) { + $liste = array(); + foreach ($donnees as $d) { + if (!is_array($d)) { + $liste[] = $d; + } else { + $liste[] = $d['nom']; + } + } + return implode(',', $liste); + } + return ''; +} diff --git a/www/plugins/zen-garden-2/zengarden_options.php b/www/plugins/zen-garden-2/zengarden_options.php index fe0e710a..fb318111 100644 --- a/www/plugins/zen-garden-2/zengarden_options.php +++ b/www/plugins/zen-garden-2/zengarden_options.php @@ -8,7 +8,9 @@ * @package SPIP\Zen-Garden\Options */ -if (!defined("_ECRIRE_INC_VERSION")) return; +if (!defined("_ECRIRE_INC_VERSION")) { + return; +} if (!defined('_DIR_PLUGIN_THEME')){ // si on est en mode apercu, il suffit de repasser dans l'espace prive pour desactiver l'apercu @@ -65,11 +67,12 @@ if (!defined('_DIR_PLUGIN_THEME')){ * Le contenu html de la page modifié */ function zengarden_affichage_final($texte){ - if ($GLOBALS['html'] and isset($GLOBALS['meta']['zengarden_switcher'])){ + if ((!isset($GLOBALS['flag_preserver']) || $GLOBALS['flag_preserver'] != 1) && $GLOBALS['html'] and isset($GLOBALS['meta']['zengarden_switcher'])){ include_spip('prive/zengarden_theme_fonctions'); // on passe le theme selectionne en js pour ne pas polluer le cache du switcher + $theme = isset($_COOKIE['spip_zengarden_theme']) ? $_COOKIE['spip_zengarden_theme'] : ''; $code = - "" + "" . recuperer_fond('inclure/zengarden_switcher'); // On rajoute le code du selecteur de squelettes avant la balise $texte=str_replace("",$code."",$texte); @@ -77,4 +80,3 @@ function zengarden_affichage_final($texte){ return $texte; } -?> diff --git a/www/plugins/zen-garden-2/zengarden_pipelines.php b/www/plugins/zen-garden-2/zengarden_pipelines.php index 44f5ee2a..7b750828 100644 --- a/www/plugins/zen-garden-2/zengarden_pipelines.php +++ b/www/plugins/zen-garden-2/zengarden_pipelines.php @@ -8,7 +8,9 @@ * @package SPIP\Zen-Garden\Pipelines */ -if (!defined('_ECRIRE_INC_VERSION')) return; +if (!defined('_ECRIRE_INC_VERSION')) { + return; +} /** * Insertion dans le pipeline header_prive @@ -28,5 +30,3 @@ function zengarden_header_prive($flux){ return $flux; } - -?> -- 2.20.1
    $context|",(($end_or_die) ? 'true' : 'false'), +//"|$token|" . max($return_status) . "$context|",(($end_or_die) ? 'true' : 'false'),"|$token|" . max($return_status) . "