From 82f431b3ae1eb2f0016ff2af4ec9fb849da863be Mon Sep 17 00:00:00 2001 From: Pierre Date: Mon, 28 Sep 2026 08:04:25 +0000 Subject: [PATCH] Import initial du site ship2net.fr : pages PHP, config, traductions t(), composer.json --- .gitignore | 9 + config/definitions.php | 175 + config/fonctions.php | 12 + config/fonctions_bdd.php | 585 +++ config/fonctions_fichiers.php | 250 ++ config/fonctions_ftp.php | 108 + config/fonctions_html.php | 338 ++ config/fonctions_mail.php | 103 + config/fonctions_pdf.php | 353 ++ config/fonctions_traductions.php | 123 + config/fonctions_utilitaires.php | 585 +++ config/lang/en.php | 219 + extraire_traductions.php | 89 + html/.htaccess | 2 + html/administration.php | 461 +++ html/bateaux.php | 3684 +++++++++++++++++ html/cartes.php | 712 ++++ html/data_archive_treatment.php | 2 + html/data_treatment.php | 2 + html/format.css | 1071 +++++ html/format__telephone.css | 742 ++++ html/format_administration.css | 51 + html/format_bateaux.css | 604 +++ html/format_cartes.css | 106 + html/format_contact.css | 152 + html/format_mentions_legales.css | 23 + html/format_shipmembers.css | 306 ++ html/format_textes.css | 90 + html/format_uploads.css | 38 + html/format_versions.css | 138 + html/images/Facebook_signature.png | Bin 0 -> 1661 bytes html/images/Instagram_signature.png | Bin 0 -> 2292 bytes html/images/Linkedin_signature.png | Bin 0 -> 1730 bytes html/images/Pascal_rond.png | Bin 0 -> 9277 bytes html/images/Youtube_signature.png | Bin 0 -> 1632 bytes html/images/avatar.png | Bin 0 -> 365264 bytes html/images/backup_shipheart.png | Bin 0 -> 30470 bytes html/images/bandeau_accueil.jpg | Bin 0 -> 518606 bytes html/images/centrale_de_vie_a_bord.png | Bin 0 -> 7490 bytes html/images/configuration_shipheart.png | Bin 0 -> 12491 bytes html/images/consommations_shipheart.png | Bin 0 -> 15267 bytes html/images/corbeille_logo.png | Bin 0 -> 12415 bytes html/images/courbe_shipheart.png | Bin 0 -> 9693 bytes html/images/croix_carre.png | Bin 0 -> 10244 bytes html/images/drapeau_en.png | Bin 0 -> 6458 bytes html/images/drapeau_fr.png | Bin 0 -> 1625 bytes html/images/drapeau_it.png | Bin 0 -> 12110 bytes html/images/eau_shipheart.png | Bin 0 -> 8272 bytes html/images/edit_pen_logo.png | Bin 0 -> 16209 bytes html/images/faq_caracteristiques.png | Bin 0 -> 18261 bytes html/images/faq_installation.png | Bin 0 -> 43089 bytes html/images/faq_shipheart.png | Bin 0 -> 29608 bytes html/images/faq_utilisation.png | Bin 0 -> 14907 bytes html/images/favicon.png | Bin 0 -> 1974 bytes html/images/fb.png | Bin 0 -> 17956 bytes html/images/fermer_aide.png | Bin 0 -> 3068 bytes html/images/fleche_bas_dans_carre.png | Bin 0 -> 12212 bytes html/images/fleche_bas_sans_carre.png | Bin 0 -> 263 bytes html/images/fleche_droite_dans_carre.png | Bin 0 -> 12505 bytes html/images/fleche_droite_dans_carre_over.png | Bin 0 -> 11047 bytes html/images/fleche_haut_dans_carre.png | Bin 0 -> 12010 bytes html/images/hamburger_menu.png | Bin 0 -> 353 bytes html/images/homepage_shipheart.png | Bin 0 -> 364612 bytes html/images/homme_jumelles.jpg | Bin 0 -> 55420 bytes html/images/icone_avatar.png | Bin 0 -> 22705 bytes html/images/icone_avatar_hover.png | Bin 0 -> 17783 bytes html/images/icone_consommation_electrique.png | Bin 0 -> 2390 bytes html/images/icone_contact.png | Bin 0 -> 10886 bytes html/images/icone_contact_hover.png | Bin 0 -> 10422 bytes html/images/icone_croix.png | Bin 0 -> 9273 bytes html/images/icone_croix_hover.png | Bin 0 -> 8807 bytes html/images/icone_home.png | Bin 0 -> 10285 bytes html/images/icone_home_hover.png | Bin 0 -> 8631 bytes html/images/icone_menu.png | Bin 0 -> 6350 bytes html/images/icone_menu_hover.png | Bin 0 -> 5682 bytes html/images/icone_panier.png | Bin 0 -> 17946 bytes html/images/icone_panier_hover.png | Bin 0 -> 15452 bytes html/images/ig.png | Bin 0 -> 933127 bytes html/images/linkedin.png | Bin 0 -> 5823 bytes html/images/location-pointer.png | Bin 0 -> 6333 bytes html/images/logo-bpifrance.webp | Bin 0 -> 17564 bytes html/images/logo_FIN.png | Bin 0 -> 33461 bytes html/images/logo_axe_sail.png | Bin 0 -> 5880 bytes .../logo_chantier_naval_de_la_plaisance.png | Bin 0 -> 7021 bytes html/images/logo_cs_refit.png | Bin 0 -> 2867 bytes .../images/logo_elec_yachting_engineering.png | Bin 0 -> 21586 bytes html/images/logo_inter_action.png | Bin 0 -> 11216 bytes html/images/logo_koriolan.png | Bin 0 -> 28467 bytes html/images/logo_koriolan_rvb.png | Bin 0 -> 18096 bytes html/images/logo_membre_fin 2024.png | Bin 0 -> 333781 bytes html/images/logo_meta_services.png | Bin 0 -> 17396 bytes html/images/logo_nautic_elec.png | Bin 0 -> 59332 bytes html/images/logo_nav_elec.png | Bin 0 -> 14316 bytes html/images/logo_shipheart.png | Bin 0 -> 83374 bytes html/images/logo_shipheart_heart.png | Bin 0 -> 35537 bytes html/images/logo_shipheart_plus_koriolan.png | Bin 0 -> 87119 bytes html/images/logo_shipheart_sans_texte.png | Bin 0 -> 30922 bytes html/images/logo_shipheart_signatures.png | Bin 0 -> 8161 bytes html/images/logo_shipheart_text.png | Bin 0 -> 38284 bytes html/images/logo_vega_voile_au_sud.png | Bin 0 -> 8017 bytes html/images/made_in_france.png | Bin 0 -> 14572 bytes html/images/menu_burger_logo.png | Bin 0 -> 205 bytes html/images/moins.png | Bin 0 -> 2640 bytes html/images/moins_carre.png | Bin 0 -> 9861 bytes html/images/moins_carre_clair.png | Bin 0 -> 8465 bytes html/images/nautic2021.png | Bin 0 -> 36596 bytes html/images/noPhoto.png | Bin 0 -> 2921551 bytes html/images/parametres_shipheart.png | Bin 0 -> 13113 bytes html/images/personnalisation_shipheart.png | Bin 0 -> 1365449 bytes html/images/phase_inversee.png | Bin 0 -> 628126 bytes html/images/photo_pierre.png | Bin 0 -> 186128 bytes html/images/picto_affichage.png | Bin 0 -> 3036 bytes html/images/picto_circuits.png | Bin 0 -> 4632 bytes html/images/picto_environnement.png | Bin 0 -> 5038 bytes html/images/picto_installation.png | Bin 0 -> 2088 bytes html/images/picto_interfaces.png | Bin 0 -> 1933 bytes html/images/picto_journal_de_bord.png | Bin 0 -> 3021 bytes html/images/picto_lte.png | Bin 0 -> 3186 bytes html/images/picto_niveaux.png | Bin 0 -> 4023 bytes html/images/picto_pour_quel_bateau.png | Bin 0 -> 2869 bytes html/images/picto_securite.png | Bin 0 -> 3564 bytes html/images/picto_temperatures.png | Bin 0 -> 4868 bytes html/images/picto_utilisatrices.png | Bin 0 -> 3979 bytes html/images/pierre_rond.png | Bin 0 -> 41999 bytes html/images/plus.png | Bin 0 -> 5471 bytes html/images/plus_carre.png | Bin 0 -> 11096 bytes html/images/plus_carre_clair.png | Bin 0 -> 11302 bytes html/images/puce_bleu_koriolan_clair.png | Bin 0 -> 169 bytes html/images/puce_bleu_koriolan_clair_24.png | Bin 0 -> 189 bytes html/images/puce_bleu_koriolan_fonce.png | Bin 0 -> 167 bytes html/images/puce_bleu_koriolan_fonce_24.png | Bin 0 -> 189 bytes html/images/puce_shipheart.png | Bin 0 -> 695 bytes html/images/question.png | Bin 0 -> 3772 bytes html/images/selection.png | Bin 0 -> 7138 bytes html/images/selection_blanc.png | Bin 0 -> 5936 bytes html/images/selection_carre.png | Bin 0 -> 12788 bytes html/images/selection_hover.png | Bin 0 -> 6909 bytes html/images/show_less.png | Bin 0 -> 8439 bytes html/images/show_more.png | Bin 0 -> 4805 bytes html/images/signature_koriolan.png | Bin 0 -> 14660 bytes html/images/signature_koriolan_enrichie.png | Bin 0 -> 14268 bytes html/images/stylo.png | Bin 0 -> 5391 bytes html/images/ytb.png | Bin 0 -> 9530 bytes html/index.html | 16 + html/index.php | 139 + html/mentions_legales.php | 127 + html/shipmembers.php | 1933 +++++++++ html/textes.php | 497 +++ html/uploads.php | 198 + html/versions.php | 1531 +++++++ vendor/phpqrcode/CHANGELOG | 38 + vendor/phpqrcode/INSTALL | 67 + vendor/phpqrcode/LICENSE | 165 + vendor/phpqrcode/README | 45 + vendor/phpqrcode/VERSION | 2 + vendor/phpqrcode/bindings/tcpdf/qrcode.php | 2874 +++++++++++++ vendor/phpqrcode/index.php | 94 + vendor/phpqrcode/phpqrcode.php | 3312 +++++++++++++++ vendor/phpqrcode/qrbitstream.php | 180 + vendor/phpqrcode/qrconfig.php | 17 + vendor/phpqrcode/qrconst.php | 54 + vendor/phpqrcode/qrencode.php | 502 +++ vendor/phpqrcode/qrimage.php | 95 + vendor/phpqrcode/qrinput.php | 729 ++++ vendor/phpqrcode/qrlib.php | 43 + vendor/phpqrcode/qrmask.php | 328 ++ vendor/phpqrcode/qrrscode.php | 210 + vendor/phpqrcode/qrspec.php | 592 +++ vendor/phpqrcode/qrsplit.php | 311 ++ vendor/phpqrcode/qrtools.php | 172 + vendor/phpqrcode/tools/merge.bat | 2 + vendor/phpqrcode/tools/merge.php | 70 + vendor/phpqrcode/tools/merge.sh | 2 + vendor/phpqrcode/tools/merged_config.php | 17 + vendor/phpqrcode/tools/merged_header.php | 36 + 175 files changed, 25531 insertions(+) create mode 100644 .gitignore create mode 100644 config/definitions.php create mode 100644 config/fonctions.php create mode 100644 config/fonctions_bdd.php create mode 100644 config/fonctions_fichiers.php create mode 100644 config/fonctions_ftp.php create mode 100644 config/fonctions_html.php create mode 100644 config/fonctions_mail.php create mode 100644 config/fonctions_pdf.php create mode 100644 config/fonctions_traductions.php create mode 100644 config/fonctions_utilitaires.php create mode 100644 config/lang/en.php create mode 100644 extraire_traductions.php create mode 100644 html/.htaccess create mode 100644 html/administration.php create mode 100644 html/bateaux.php create mode 100644 html/cartes.php create mode 100644 html/data_archive_treatment.php create mode 100644 html/data_treatment.php create mode 100644 html/format.css create mode 100644 html/format__telephone.css create mode 100644 html/format_administration.css create mode 100644 html/format_bateaux.css create mode 100644 html/format_cartes.css create mode 100644 html/format_contact.css create mode 100644 html/format_mentions_legales.css create mode 100644 html/format_shipmembers.css create mode 100644 html/format_textes.css create mode 100644 html/format_uploads.css create mode 100644 html/format_versions.css create mode 100644 html/images/Facebook_signature.png create mode 100644 html/images/Instagram_signature.png create mode 100644 html/images/Linkedin_signature.png create mode 100644 html/images/Pascal_rond.png create mode 100644 html/images/Youtube_signature.png create mode 100644 html/images/avatar.png create mode 100644 html/images/backup_shipheart.png create mode 100644 html/images/bandeau_accueil.jpg create mode 100644 html/images/centrale_de_vie_a_bord.png create mode 100644 html/images/configuration_shipheart.png create mode 100644 html/images/consommations_shipheart.png create mode 100644 html/images/corbeille_logo.png create mode 100644 html/images/courbe_shipheart.png create mode 100644 html/images/croix_carre.png create mode 100644 html/images/drapeau_en.png create mode 100644 html/images/drapeau_fr.png create mode 100644 html/images/drapeau_it.png create mode 100644 html/images/eau_shipheart.png create mode 100644 html/images/edit_pen_logo.png create mode 100644 html/images/faq_caracteristiques.png create mode 100644 html/images/faq_installation.png create mode 100644 html/images/faq_shipheart.png create mode 100644 html/images/faq_utilisation.png create mode 100644 html/images/favicon.png create mode 100644 html/images/fb.png create mode 100644 html/images/fermer_aide.png create mode 100644 html/images/fleche_bas_dans_carre.png create mode 100644 html/images/fleche_bas_sans_carre.png create mode 100644 html/images/fleche_droite_dans_carre.png create mode 100644 html/images/fleche_droite_dans_carre_over.png create mode 100644 html/images/fleche_haut_dans_carre.png create mode 100644 html/images/hamburger_menu.png create mode 100644 html/images/homepage_shipheart.png create mode 100644 html/images/homme_jumelles.jpg create mode 100644 html/images/icone_avatar.png create mode 100644 html/images/icone_avatar_hover.png create mode 100644 html/images/icone_consommation_electrique.png create mode 100644 html/images/icone_contact.png create mode 100644 html/images/icone_contact_hover.png create mode 100644 html/images/icone_croix.png create mode 100644 html/images/icone_croix_hover.png create mode 100644 html/images/icone_home.png create mode 100644 html/images/icone_home_hover.png create mode 100644 html/images/icone_menu.png create mode 100644 html/images/icone_menu_hover.png create mode 100644 html/images/icone_panier.png create mode 100644 html/images/icone_panier_hover.png create mode 100644 html/images/ig.png create mode 100644 html/images/linkedin.png create mode 100644 html/images/location-pointer.png create mode 100644 html/images/logo-bpifrance.webp create mode 100644 html/images/logo_FIN.png create mode 100644 html/images/logo_axe_sail.png create mode 100644 html/images/logo_chantier_naval_de_la_plaisance.png create mode 100644 html/images/logo_cs_refit.png create mode 100644 html/images/logo_elec_yachting_engineering.png create mode 100644 html/images/logo_inter_action.png create mode 100644 html/images/logo_koriolan.png create mode 100644 html/images/logo_koriolan_rvb.png create mode 100644 html/images/logo_membre_fin 2024.png create mode 100644 html/images/logo_meta_services.png create mode 100644 html/images/logo_nautic_elec.png create mode 100644 html/images/logo_nav_elec.png create mode 100644 html/images/logo_shipheart.png create mode 100644 html/images/logo_shipheart_heart.png create mode 100644 html/images/logo_shipheart_plus_koriolan.png create mode 100644 html/images/logo_shipheart_sans_texte.png create mode 100644 html/images/logo_shipheart_signatures.png create mode 100644 html/images/logo_shipheart_text.png create mode 100644 html/images/logo_vega_voile_au_sud.png create mode 100644 html/images/made_in_france.png create mode 100644 html/images/menu_burger_logo.png create mode 100644 html/images/moins.png create mode 100644 html/images/moins_carre.png create mode 100644 html/images/moins_carre_clair.png create mode 100644 html/images/nautic2021.png create mode 100644 html/images/noPhoto.png create mode 100644 html/images/parametres_shipheart.png create mode 100644 html/images/personnalisation_shipheart.png create mode 100644 html/images/phase_inversee.png create mode 100644 html/images/photo_pierre.png create mode 100644 html/images/picto_affichage.png create mode 100644 html/images/picto_circuits.png create mode 100644 html/images/picto_environnement.png create mode 100644 html/images/picto_installation.png create mode 100644 html/images/picto_interfaces.png create mode 100644 html/images/picto_journal_de_bord.png create mode 100644 html/images/picto_lte.png create mode 100644 html/images/picto_niveaux.png create mode 100644 html/images/picto_pour_quel_bateau.png create mode 100644 html/images/picto_securite.png create mode 100644 html/images/picto_temperatures.png create mode 100644 html/images/picto_utilisatrices.png create mode 100644 html/images/pierre_rond.png create mode 100644 html/images/plus.png create mode 100644 html/images/plus_carre.png create mode 100644 html/images/plus_carre_clair.png create mode 100644 html/images/puce_bleu_koriolan_clair.png create mode 100644 html/images/puce_bleu_koriolan_clair_24.png create mode 100644 html/images/puce_bleu_koriolan_fonce.png create mode 100644 html/images/puce_bleu_koriolan_fonce_24.png create mode 100644 html/images/puce_shipheart.png create mode 100644 html/images/question.png create mode 100644 html/images/selection.png create mode 100644 html/images/selection_blanc.png create mode 100644 html/images/selection_carre.png create mode 100644 html/images/selection_hover.png create mode 100644 html/images/show_less.png create mode 100644 html/images/show_more.png create mode 100644 html/images/signature_koriolan.png create mode 100644 html/images/signature_koriolan_enrichie.png create mode 100644 html/images/stylo.png create mode 100644 html/images/ytb.png create mode 100644 html/index.html create mode 100644 html/index.php create mode 100644 html/mentions_legales.php create mode 100644 html/shipmembers.php create mode 100644 html/textes.php create mode 100644 html/uploads.php create mode 100644 html/versions.php create mode 100644 vendor/phpqrcode/CHANGELOG create mode 100644 vendor/phpqrcode/INSTALL create mode 100644 vendor/phpqrcode/LICENSE create mode 100644 vendor/phpqrcode/README create mode 100644 vendor/phpqrcode/VERSION create mode 100644 vendor/phpqrcode/bindings/tcpdf/qrcode.php create mode 100644 vendor/phpqrcode/index.php create mode 100644 vendor/phpqrcode/phpqrcode.php create mode 100644 vendor/phpqrcode/qrbitstream.php create mode 100644 vendor/phpqrcode/qrconfig.php create mode 100644 vendor/phpqrcode/qrconst.php create mode 100644 vendor/phpqrcode/qrencode.php create mode 100644 vendor/phpqrcode/qrimage.php create mode 100644 vendor/phpqrcode/qrinput.php create mode 100644 vendor/phpqrcode/qrlib.php create mode 100644 vendor/phpqrcode/qrmask.php create mode 100644 vendor/phpqrcode/qrrscode.php create mode 100644 vendor/phpqrcode/qrspec.php create mode 100644 vendor/phpqrcode/qrsplit.php create mode 100644 vendor/phpqrcode/qrtools.php create mode 100644 vendor/phpqrcode/tools/merge.bat create mode 100644 vendor/phpqrcode/tools/merge.php create mode 100644 vendor/phpqrcode/tools/merge.sh create mode 100644 vendor/phpqrcode/tools/merged_config.php create mode 100644 vendor/phpqrcode/tools/merged_header.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2ccc8f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +config/config.php +config/confidentiel.php +config/lang/*.bak +temp/ +*.bak +vendor/* +!vendor/phpqrcode/ +vendor/phpqrcode/cache/ +html/vendor_OLD/ diff --git a/config/definitions.php b/config/definitions.php new file mode 100644 index 0000000..168cbb1 --- /dev/null +++ b/config/definitions.php @@ -0,0 +1,175 @@ +connect_error) + { + $_SESSION['erreurs_connexion_db'][$i] = $_SESSION['db']->connect_errno; + $_SESSION['db'] = NULL; + sleep($i+1); // Attente avant de recommencer (en secondes). NB : le délai d'attente augmente à chaque tentative... + } + else break; + } + + + if ($_SESSION['db'] == NULL) // Erreur de la fonction de connexion, malgré plusieurs tentatives : + { + if (PRODUCTION) + { + // Préparation du texte d'erreur en dur et dans les 2 langues car si la BDD n'est pas accessible, on aura du mal à aller y chercher les messages d'erreur... : + $message_erreur = '

Oups ! Une erreur est survenue.

+

Essayez de rafraichir la page mais si le problème persiste, n\'hésitez pas à nous contacter à : '.$_SESSION['Config__Adresse_email_contact'].'

+

NB : Ce message a été automatiquement envoyé aux services techniques de Koriolan pour être traité.
Car vous offrir un service irréprochable est notre priorité !

'; + $message_erreur .= '
'; + $message_erreur .= '

Oops! An error occurred.

+

Try to refresh the page but if the problem persists, please contact us at : '.$_SESSION['Config__Adresse_email_contact'].'

+

NB: This message has automatically been sent to Koriolan technical services for processing.
Because offering you an irreproachable service is our permanent concern !

'; + + // Affichage du message d'erreur : + echo '
'.$message_erreur.'
'; + + Enregistrement_log("\tOups ! Erreur de connexion à MYSQL", __FILE__, __LINE__); + } + else + { + $message_erreur = '

Oups ! Une erreur est survenue lors de l\'ouverture de la BDD.

+

'.MAX_TENTATIVES_CONNEXIONS_BDD.' tentatives ont été effectuées et ont toutes échouées

'; + echo '

Les erreurs récupérées sont :'; + for ($i=0; $i'; + echo '

'; + } + + exit(); // Arrêt du script. + } + else + { + if ($_SESSION['erreurs_connexion_db'][0] != 0) // Si on s'est connecté mais qu'au moins une erreur a été détectée, on enregistre dans l'historique l'évènement). + { + for ($i=0; (($_SESSION['erreurs_connexion_db'][$i] != 0) AND ($i'.$message_erreur.''; + + // Enregistrement dans le fichier de logs : + Enregistrement_log("\tOups ! Erreur MYSQL. Requête = [".$requete."], message d'erreur = [".mysqli_error($_SESSION['db'])."]", $fichier, $ligne); + + exit(); // Arrêt du script. + } + else return($retour); // Requete revenue sans erreur... + +} + +//************************************************************************************************************ +// Fonction : Exécution d'une requête préparée dans la BDD +// Reçoit : La requête à exécuter, un array avec les paramètres de la requête, le fichier d'origine et la ligne d'origine +// Retour : Le retour de la requête si aucune erreur. En cas d'erreur, le script est arrêté après l'affichage d'une page d'erreur +//************************************************************************************************************ +function Requete_preparee_bdd($requete, $parametres, $fichier, $ligne) +{ + $texte_erreur = ""; + + + if ($stmt = mysqli_prepare($_SESSION['db'], $requete)) // Création de la requête préparée + { + // Récupération des éléments du tableau de paramètres reçu : + $types = ""; + $nb = 0; + foreach ($parametres as $parametre) + { + $types .= $parametre[0]; // Concaténation des types pour obtenir une chaine de tous les types, les uns derrière les autres + $valeurs[$nb ++] = $parametre[1]; // Récupération de la valeur de chaque paramètre dans un tableau temporaire + } + + // Création d'un tableau avec tous les paramètres de la fonction 'mysqli_stmt_bind_param' : + if ($nb > 0) + { + $params[] = $stmt; // Premier paramètre : identifiant de la requête préparée + $params[] = &$types; // Second paramètre : chaine de caractère avec tous les types + for ($i=0; $i<$nb; $i++) $params[] = &$valeurs[$i]; // Troisième et au-delà : une valeur par paramètre + + // Appel de la fonction 'mysqli_stmt_bind_param' à travers 'call_user_func_array' qui permet de passer un tableau en argument : + if (call_user_func_array("mysqli_stmt_bind_param", $params) == false) // NB : le retour de 'call_user_func_array' est celui de 'mysqli_stmt_bind_param' + { + $texte_erreur = "\tOups ! Le binding de la requête préparée [".$requete."] a échoué avec le message d'erreur [".mysqli_error($_SESSION['db'])."]"; + } + } // Si le nombre de paramètres est nul, c'est qu'il n'y a pas de variable dans la requet et qu'on peut donc l'exécuter sans binding... + + // exécution de la requête préparée avec le binding des variables fait : + if (mysqli_stmt_execute($stmt) == false) // Exécution de la requête + { + $texte_erreur = "\tOups ! L'exécution de la requête préparée [".$requete."] a échoué avec le message d'erreur [".mysqli_error($_SESSION['db'])."]"; + } + + // Récupération du jeu de résultats : + $retour = mysqli_stmt_get_result($stmt); + if (($retour == false) AND (mysqli_error($_SESSION['db']) != "")) // Il se peut que 'mysqli_stmt_get_result' renvoie 'false' si la requête exécutée n'attend pas de réponse (UPDATE, INSERT). On vériife donc si une erreur MySql a été déclenchée avant de passer en erreur... + { + $texte_erreur = "\tOups ! La recherche des résultats de la requête préparée [".$requete."] a échoué avec le message d'erreur [".mysqli_error($_SESSION['db'])."]"; + } + + } + else $texte_erreur = "\tOups ! La création de la requête préparée [".$requete."] a échoué avec le message d'erreur [".mysqli_error($_SESSION['db'])."]"; + + mysqli_stmt_close($stmt); // Libération de la requête préparée + + // Traitement des cas d'erreur : + // (NB : $texte_erreur est différent de $message_erreur !!) + if ($texte_erreur != "") + { + // Préparation du texte d'erreur : + $message_erreur = nl2br($_SESSION['textes']['fonctions_bdd']['all']['retour']['message_erreur']); + + // Mise à jour des parametres du texte : + $message_erreur = str_replace("[[Email]]", $_SESSION['Config__Adresse_email_contact'], $message_erreur); + + // Affichage du message d'erreur : + echo '
'.$message_erreur.'
'; + + // Enregistrement dans le fichier de logs : + Enregistrement_log($texte_erreur, $fichier, $ligne); + + exit(); // Arrêt du script. + } + else return($retour); // Requete revenue sans erreur... +} + + +//************************************************************************************************************ +// Fonction : Fetch de ligne de résultat MYSQL +// Reçoit : La réponse complète de la requête (au sein de laquelle la ligne doit être cherchée) +// Retour : La ligne de resultat suivante ou FALSE si aucune ligne supplémentaire n'existe. +//************************************************************************************************************ +function Recherche_ligne_bdd($reponse) +{ + // Récupération du type de retour à renvoyer : + if (func_num_args() > 1) + { + $resulttype = func_get_arg(1); + switch(func_get_arg(1)) + { + case MYSQLI_ASSOC : {$resulttype = MYSQLI_ASSOC; break;} // ne renvoi que la version associative du tableau de retour + case MYSQLI_NUM : {$resulttype = MYSQLI_NUM; break;} // ne renvoi que la version numérique du tableau de retour + case MYSQLI_BOTH : + default : {$resulttype = MYSQLI_BOTH; break;} // renvoi les deux versions (associative et numérique) du tableau de retour + } + } + else $resulttype = MYSQLI_BOTH; // Valeur par défaut de la fonction. + + // Recherche de la ligne + return(mysqli_fetch_array($reponse, $resulttype)); + +} + + +//************************************************************************************************************ +// Fonction : Libération de jeu de résultat MYSQL +// Reçoit : La variable à libérer +// Retour : Rien +//************************************************************************************************************ +function Liberation_jeu_de_resultat_bdd($reponse) +{ + mysqli_free_result($reponse); + +} + + +//************************************************************************************************************ +// Fonction : Récupération de l'id créé +// Reçoit : Rien +// Retour : L'ID de l'enregistrement qui vient d'être ajouté +//************************************************************************************************************ +function Recuperation_id_cree_bdd() +{ + return(mysqli_insert_id($_SESSION['db'])); + +} + + +//************************************************************************************************************ +// Fonction : Liste des champs de base de données +// Reçoit : Rien +// Retour : La liste des champs +//************************************************************************************************************ +function Champs_bdd($reponse) +{ + return(mysqli_fetch_fields($reponse)); +} + + +//************************************************************************************************************ +// Fonction : Comptage des résultats de la requête +// Reçoit : La requête dont le comptage est recherché +// Retour : Le nombre de lignes de résultats de la requête +//************************************************************************************************************ +function Comptage_resultats_requete($requete) +{ + + $reponse = Requete_bdd('SELECT COUNT(*) AS total FROM ('.$requete.') AS Total', __FILE__, __LINE__); // Le second AS est nécessaire mais ne sert pas... + $donnees = Recherche_ligne_bdd($reponse); + Liberation_jeu_de_resultat_bdd($reponse); + return($donnees['total']); + +} + + +//************************************************************************************************************ +// Fonction : Protection d'une requête contre les injections SQL +// Reçoit : La requête à traiter +// Retour : La requête après traitement +//************************************************************************************************************ +function Protection_mysql($requete) +{ + + return(mysqli_real_escape_string($_SESSION['db'], $requete)); +} + + +//************************************************************************************************************ +// Fonction : Fermeture de base de données +// Reçoit : Rien +// Retour : Rien +//************************************************************************************************************ +function Fermeture_bdd() +{ + if ($_SESSION['db'] != NULL) // SDIR # 289 + { + mysqli_close($_SESSION['db']); + $_SESSION['db'] = NULL; // SDIR # 289 + } +} + + +//************************************************************************************************************ +// Fonction : Encryptage d'un message +// Reçoit : Le message à encrypter +// Retour : Le message encrypté +//************************************************************************************************************ +function Encryptage($message) +{ + // La clé (secrète) est le mdp du user : + $key = $_SESSION['login_key']; + // algorythme choisi selon http://fr.php.net/manual/fr/mcrypt.ciphers.php + $algo = MCRYPT_BLOWFISH; + // mode choisi selon http://fr.php.net/manual/fr/mcrypt.constants.php + $mode = MCRYPT_MODE_CBC ; + + //Réduction de la taille de la clé selon la taille maximale supportée par l'algorythme mcrypt choisi : + $key = substr($key, 0, mcrypt_module_get_algo_key_size($algo)); + // Création d'un vecteur d'initialisation selon la taille maximale possible : + $iv = mcrypt_create_iv(mcrypt_get_iv_size($algo, $mode), MCRYPT_DEV_URANDOM); + + // Chiffrage du message : + $data = mcrypt_encrypt($algo, $key, $message, $mode, $iv); + + // Retour du message après ajouté devant l'IV qui sera nécessaire au décodage (l'IV n'est pas confidentiel) + // puis avoir encodé le tout en base64 (utile si l'on veut mettre le résultat dans une base de donnée) + return(base64_encode($iv.$data)); +} + + +//************************************************************************************************************ +// Fonction : Décryptage d'un message +// Reçoit : Le message crypté +// Retour : Le message décrypté +//************************************************************************************************************ +function Decryptage($message_crypte) +{ + + // La clé (secrète) est le mdp du user : + $key = $_SESSION['login_key']; + // algorythme choisi selon http://fr.php.net/manual/fr/mcrypt.ciphers.php + $algo = MCRYPT_BLOWFISH; + // mode choisi selon http://fr.php.net/manual/fr/mcrypt.constants.php + $mode = MCRYPT_MODE_CBC ; + + //Réduction de la taille de la clé selon la taille maximale supportée par l'algorythme mcrypt choisi : + $key = substr($key, 0, mcrypt_module_get_algo_key_size($algo)); + // Rechjerche de la taille du vecteur d'initialisation (dépend uniquement du mode de cryptage) : + $size = mcrypt_get_iv_size($algo, $mode); + // Désencodage en base64 : + $message_crypte = base64_decode($message_crypte); + // Extraction de l'IV qui est stocké en début de message : + $iv = substr($message_crypte, 0, $size); // On extrait l'IV (qui est de longueur connue) du début du message. + // Extraction du message crypté proprement dit : + $message_crypte = substr($message_crypte, $size); // On ne garde que la fin du message (sans l'IV). + // Retour du message décrypté : + return(trim(mcrypt_decrypt($algo, $key, $message_crypte, $mode, $iv))); // Le TRIM permet de supprimer les 0x00 qui sont ajoutés à la fin pour former des blocs de 8 octets... +} + + +//************************************************************************************************************ +// Fonction : Rencryptage d'un message +// Reçoit : Le message à encrypter (les variables de session $_SESSION['login_key'] et $_SESSION['new_login_key'] sont utilisées pour assurer le décryptage puis le rencryptage) +// Retour : Le message encrypté +//************************************************************************************************************ +function Rencryptage($message_crypte) +{ + // Décodage avec ancienne clé : + + // La clé (secrète) est l'ancien mdp du user : + $key = $_SESSION['login_key']; + // algorythme choisi selon http://fr.php.net/manual/fr/mcrypt.ciphers.php + $algo = MCRYPT_BLOWFISH; + // mode choisi selon http://fr.php.net/manual/fr/mcrypt.constants.php + $mode = MCRYPT_MODE_CBC ; + + //Réduction de la taille de la clé selon la taille maximale supportée par l'algorythme mcrypt choisi : + $key = substr($key, 0, mcrypt_module_get_algo_key_size($algo)); + // Rechjerche de la taille du vecteur d'initialisation (dépend uniquement du mode de cryptage) : + $size = mcrypt_get_iv_size($algo, $mode); + // Désencodage en base64 : + $message_crypte = base64_decode($message_crypte); + // Extraction de l'IV qui est stocké en début de message : + $iv = substr($message_crypte, 0, $size); // On extrait l'IV (qui est de longueur connue) du début du message. + // Extraction du message crypté proprement dit : + $message_crypte = substr($message_crypte, $size); // On ne garde que la fin du message (sans l'IV). + // Retour du message décrypté : + $message_decrypte = trim(mcrypt_decrypt($algo, $key, $message_crypte, $mode, $iv)); // Le TRIM permet de supprimer les 0x00 qui sont ajoutés à la fin pour former des blocs de 8 octets... + + + // Encodage avec nouvelle clé : + + // La clé (secrète) est le nouveau mdp du user : + $key = $_SESSION['new_login_key']; + + //Réduction de la taille de la clé selon la taille maximale supportée par l'algorythme mcrypt choisi : + $key = substr($key, 0, mcrypt_module_get_algo_key_size($algo)); + // Création d'un vecteur d'initialisation selon la taille maximale possible : + $iv = mcrypt_create_iv(mcrypt_get_iv_size($algo, $mode), MCRYPT_DEV_URANDOM); + + // Chiffrage du message : + $data = mcrypt_encrypt($algo, $key, $message_decrypte, $mode, $iv); + + // Retour du message après ajouté devant l'IV qui sera nécessaire au décodage (l'IV n'est pas confidentiel) + // puis avoir encodé le tout en base64 (utile si l'on veut mettre le résultat dans une base de donnée) + return(base64_encode($iv.$data)); +} + + +//************************************************************************************************************ +// Fonction : Génération de mot de passe aléatoire +// Reçoit : La longueur du mot de passe à générer +// Retour : Le mot de passe généré +//************************************************************************************************************ +function Mdp_aleatoire($longueur) +{ + + $password = ""; + $prec = 0; + for($i = 0; $i < $longueur; $i++) + { + $random = rand(48,122); // chiffres de 48 à 57, maj de 65 à 90 et min de 97 à 122 + + // Suppression des caractères non alphanumériques : + if (($random == ord("0")) OR + (($random >= 58) AND ($random <= 64)) OR + ($random == ord("I")) OR + ($random == ord("O")) OR + ($random == ord("l")) OR + ($random == ord("o")) OR + (($random >= 91) AND ($random <= 96)) OR + ($random == $prec)) // Evite les doublons de caractères identiques (difficile à lire) + { + $i--; + continue; + } + $password .= chr($random); + $prec = $random; + } + return($password); +} + + +//************************************************************************************************************ +// Fonction : Vérification de la conformité d'un mot de passe (longueur, caractères utilisés, etc...) +// Reçoit : Le mot de passe à vérifier +// Retour : La liste des champs +//************************************************************************************************************ +function Check_mdp($mdp) +{ +global $message_erreur; + +// $pattern = "#(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{".MIN_TAILLE_MOTS_DE_PASSE.",".MAX_TAILLE_MOTS_DE_PASSE."}#"; + + // Nombre de caractères entre MIN et MAX, caractères minuscules ou majuscules ou chiffres ou '_' et '-' : +// $pattern = "#^[a-zA-Z0-9_-]{".MIN_TAILLE_MOTS_DE_PASSE.",".."}#"; + + $longueur = strlen($mdp); + if ($longueur < MIN_TAILLE_MOTS_DE_PASSE) return(0); + if ($longueur > MAX_TAILLE_MOTS_DE_PASSE) return(0); + + for ($i = 0; $i < $longueur; $i ++) + { + if (($mdp[$i] >= 'A') AND ($mdp[$i] <= 'Z')) continue; + if (($mdp[$i] >= 'a') AND ($mdp[$i] <= 'z')) continue; + if (($mdp[$i] >= '0') AND ($mdp[$i] <= '9')) continue; + if ($mdp[$i] == '_') continue; + if ($mdp[$i] == '-') continue; + if ($mdp[$i] == '!') continue; + if ($mdp[$i] == '*') continue; + if ($mdp[$i] == '=') continue; + if ($mdp[$i] == '.') continue; + + return(-3); + } + + return(1); + + // if (preg_match($pattern, $mdp)) return(true); + // else return(false); +} + + +//************************************************************************************************************ +// Fonction : Dump de base de données +// Reçoit : La BDD à dumper, la table concernée, le nom du fichier de sortie et le type de sortie attendu. Voir documentation de la fonction PHP 'mysqldump' pour détails). +// Retour : La liste des champs +//************************************************************************************************************ +function Dump_bdd($bdd, $table, $fichier_sortie, $type_sortie) +{ + + // Appel de la fonction de DUMP : + system('mysqldump --host='.BDD_HOST.' --user='.BDD_USER.' --password='.BDD_PASSWORD.' '.BDD_DATABASE.' --tables '.$table.' '.$type_sortie.' '.$fichier_sortie.' '); + +} + + +//================================================================================================================== +// Fonction : Création d'un fichier d'archive (compressé et encodé) à partir d'un répertoire +// Reçoit : Le chemin complet du répertoire à archiver et le nom du fichier de sortie. +// Retour : 0 si Ok, <0 si erreur +//================================================================================================================== +function creer_archive_chiffree(string $repertoire_a_chiffrer, string $fichier_sortie) +{ + if (!is_dir($repertoire_a_chiffrer)) return (-1); + + $tarFile = $fichier_sortie . '.tar'; + $gzFile = $tarFile . '.gz'; + $encFile = $gzFile . '.enc'; + + foreach ([$tarFile, $gzFile] as $f) { + if (file_exists($f)) { + unlink($f); + } + } + + // 1. Archivage + compression (tar.gz) + $phar = new PharData($tarFile); +// $phar->buildFromDirectory($repertoire_a_chiffrer); + $phar->buildFromDirectory("."); + $phar->compress(Phar::GZ); + unset($phar); + unlink($tarFile); + + // 2. Chiffrement AES-256-CBC avec clé dérivée par PBKDF2 + $contenu = file_get_contents($gzFile); + $salt = openssl_random_pseudo_bytes(16); + $iv = openssl_random_pseudo_bytes(16); + $iterations = 100000; + + $cle = openssl_pbkdf2(BDD_BATEAU_PASSWORD, $salt, 32, $iterations, 'sha256'); + + $chiffre = openssl_encrypt($contenu, 'aes-256-cbc', $cle, OPENSSL_RAW_DATA, $iv); + + if ($chiffre === false) return (-2); + + // Format du fichier : salt(16) + iv(16) + données chiffrées + file_put_contents($encFile, $salt . $iv . $chiffre); + + unlink($gzFile); + + return(0); +} + + + +//================================================================================================================== +// Fonction : +// Reçoit : Le chemin complet du répertoire à archiver et le nom du fichier de sortie. +// Retour : 0 si Ok, <0 si erreur +//================================================================================================================== +function dechiffrer_archive(string $fichierChiffre, string $dossierDestination, string $motDePasse) +{ + $contenu = file_get_contents($fichierChiffre); + $salt = substr($contenu, 0, 16); + $iv = substr($contenu, 16, 16); + $donnees = substr($contenu, 32); + + $iterations = 100000; + $cle = openssl_pbkdf2($motDePasse, $salt, 32, $iterations, 'sha256'); + + $dechiffre = openssl_decrypt($donnees, 'aes-256-cbc', $cle, OPENSSL_RAW_DATA, $iv); + + if ($dechiffre === false) return (-1); + + if (!is_dir($dossierDestination)) mkdir($dossierDestination, 0755, true); + + $tmpGz = tempnam(sys_get_temp_dir(), 'restore_') . '.tar.gz'; + file_put_contents($tmpGz, $dechiffre); + + $phar = new PharData($tmpGz); + $phar->extractTo($dossierDestination, null, true); + + unlink($tmpGz); + echo "Archive extraite dans : ".$dossierDestination."\n"; + return (0); +} + + diff --git a/config/fonctions_fichiers.php b/config/fonctions_fichiers.php new file mode 100644 index 0000000..824759b --- /dev/null +++ b/config/fonctions_fichiers.php @@ -0,0 +1,250 @@ +isFile()) + { + $filePath = $fileInfo->getPathname(); + $modificationTimestamp = $fileInfo->getMTime(); + $modificationDate = new DateTime('@' . $modificationTimestamp); + + if ($modificationDate < $date_max) + { + if (unlink($filePath)) + { + if ($verbose) echo "\tLe fichier [".$filePath."] a été supprimé.\n"; + } + else + { + if ($verbose) echo "\t/!\\ Le fichier [".$filePath."]. est antérieur a ".$nb_jours_anteriorite." jours mais n'a pas pu être supprimé...\n"; + $retour = -1; + } + } + } + } + return($retour); + + // Attention : non testé !! (Pierre 09/2024) : + // Get a list of all directories inside the root directory and delete the empty ones + // $subdirectories = array_filter(glob($repertoire . '*'), 'is_dir'); + + // foreach ($subdirectories as $subdirectory) { + // if (count(scandir($subdirectory)) === 2) { + // // if (rmdir($subdirectory)) { + // // if ($verbose) echo "Directory: {$subdirectory} removed.
"; + // // } else { + // // if ($verbose) echo "Error removing directory: {$subdirectory}.
"; + // // } + // echo "Directory: {$subdirectory} removed.
"; + // } + // } +} + + diff --git a/config/fonctions_ftp.php b/config/fonctions_ftp.php new file mode 100644 index 0000000..91ce608 --- /dev/null +++ b/config/fonctions_ftp.php @@ -0,0 +1,108 @@ +. +// Au passage, cette fonction étant la première appelée par chaque page (après l'ouverture +// de session obligatoire pour pouvoir accéder aux variables de session), on vérifie si +// l'environnement est correctement positionné. Si ce n'est pas le cas, par exemple avec +// l'accès à la BDD non établi ou aucune langue sélectionnée, elle renvoit immédiatement +// vers le fichier 'index.php' qui s'en chargera. +// Reçoit : Rien +// Retour : Rien +//************************************************************************************************************ +function Entete_page_html() +{ + // Vérification à chaque ouverture de page que les variables de session sont bien initialisées (le test se fait sur quelques "échantillons" supposés représentatifs...) : + if ((!isset($_SESSION['langue'])) OR + (!isset($_SESSION['display_menu']))) header('Location:index.php?origine='.basename($_SERVER['SCRIPT_FILENAME'])); + + // Entête HTML : + echo ''; + + echo ''; + + echo ''; + echo ''; + echo 'ShipHeart - Simplicity is true luxury'; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + + + echo ""; + echo ""; + echo ""; + + echo ""; + echo ""; + + // gestion des fichiers CSS (et de scripts spécifiques à certains fichiers) : + switch(basename($_SERVER['SCRIPT_FILENAME'])) + { + case "administration.php" : { echo ''; break; } + case "textes.php" : { echo ''; break; } + case "bateaux.php" : { echo ''; break; } + case "cartes.php" : { echo ''; break; } + case "mentions_legales.php" : { echo ''; break; } + case "shipmembers.php" : { echo ''; break; } + case "uploads.php" : { echo ''; break; } + case "versions.php" : { echo ''; break; } + } + + echo ''; // CSS de Bootstrap + echo ''; // CSS général, tous écrans. + echo ''; // CSS pour les petits écrans (doit être placé à la fin car il override les CSS globaux) + + // Chargement de srcipts JS généraux : + echo ''; // Pour Google Charts (graphiques) + echo ''; + + + + + echo ''; + + echo ''; +} + +//************************************************************************************************************ +// Fonction : Insertion de l'entête des pages avec l'affichage du bandeau de titre et les menus. +// Puis affichage des messages d'erreur et d'information en les marquant de façon différenciée +// selon que le menu est déployé ou non et/ou que le message d'erreur existe et/ou que le +// message d'information existe. +// Reçoit : Les message d'erreur et le message d'information (de plus, on retrouve le nom du fichier via les variables du serveur) +// Retour : Rien +//************************************************************************************************************ +function Entete_page($message_erreur, $message_information) +{ + + $nom_page = basename($_SERVER['SCRIPT_FILENAME']); + + // Détermination de la nouvelle langue par rapport à l'actuelle : + if ($_SESSION['langue'] == "FR") $new_langue = "EN"; + else $new_langue = "FR"; + + + echo '
'; + + //---------------------------------- + // Bandeau gauche : + echo ''; + +// echo ' '; +// echo ''; + + + //-------------------------------------------------------------------------------------------- + // Menu afficher / masquer -- Mobile + //-------------------------------------------------------------------------------------------- + echo ''; + + + //-------------------------------------------------------------------------------------------- + // Script d'affichage/masquage du menu : + //-------------------------------------------------------------------------------------------- + + + //-------------------------------------------------------------------------------------------- + // Affichage des messages d'erreur et d'info sous le menu : + //-------------------------------------------------------------------------------------------- + if (!PRODUCTION) $message_erreur .= "/!\ Base de données de test [".BDD_DATABASE."]
"; + // else $message_erreur .= "Base de données de production [".BDD_DATABASE."]
"; + + if ($message_erreur != "") echo '
'.$message_erreur.'
'; + if ($message_information != "") echo '
'.$message_information.'
'; + +} + + + + +//************************************************************************************************************ +// Fonction : Insertion du pied de page +// Reçoit : Rien (mais on retrouve le nom du fichier via les variables du serveur) +// Retour : Rien +//************************************************************************************************************ +function Pied_de_page() +{ + $nom_page = basename($_SERVER['SCRIPT_FILENAME']); + +// echo ""; + + echo ''; + + echo '
'; + echo '
'; + + + +//================================================================================== +// Script JS pour pieds de page : +?>'; + +echo ''; + +} // Fin de la fonction Pied_de_page() + + + diff --git a/config/fonctions_mail.php b/config/fonctions_mail.php new file mode 100644 index 0000000..f2f51a7 --- /dev/null +++ b/config/fonctions_mail.php @@ -0,0 +1,103 @@ + + + + + + + '.$texte_brut.' + + '; + + + $mail = new PHPMailer(); + + $mail->CharSet = 'UTF-8'; // Format d'encodage à utiliser pour les caractères + +// $mail->SMTPDebug = 4; // Valeur entre 0 (normal) et 4 (full debug). Attention : mettre cette valeur > 0 dévoule certains paramètres confidentiels ! + + $mail->isSMTP(); + $mail->Host = 'ssl0.ovh.net'; // Adresse IP ou DNS du serveur SMTP + $mail->Port = 587; // Port TCP du serveur SMTP (port SMTP chez OVH : 465=avec_SSL et 587=sans_SSL/avec_tls) + $mail->SMTPAuth = TRUE; // Utiliser l'authentification + + if($mail->SMTPAuth) + { + $mail->SMTPSecure = 'tls'; // Protocole de sécurisation des échanges avec le SMTP + $mail->Username = 'do_not_answer@koriolan.tech'; // Adresse email à utiliser pour le compte SMTP + $mail->Password = SMTP_PASSWORD; // Mot de passe de l'adresse email à utiliser + } + + if ($nom_expediteur == "") $mail->setFrom($adresse_expediteur); + else $mail->setFrom($adresse_expediteur, $nom_expediteur); // L'email et l'alias (facultatif) à afficher pour l'envoi + + if ($nom_destinataire == "") $mail->AddAddress($adresse_destinataire); + else $mail->AddAddress($adresse_destinataire, $nom_destinataire); // L'email du destinataire et son alias (facultatif) + + // $mail->addBCC('do_not_answer@koriolan.tech','ShipHeart by Koriolan'); // Destinataire BCC (idem AddAddress) + + $mail->Subject = $objet; // Le sujet du mail + + $mail->isHTML(TRUE); // Indique que le message dans Body sera en HTML + $mail->Body = $message_html; + $mail->AltBody = $texte_brut; // Texte brut alternatif + + + for ($i = 0; $i < 10; $i ++) // Pièces jointes (limité à un maxi de 10 !): + { + if (!isset($fichiers_joints[$i]['fichier']) OR ($fichiers_joints[$i]['fichier'] == "")) break; + else + { + if (isset($fichiers_joints[$i]['nom']) AND ($fichiers_joints[$i]['nom'] != "")) $mail->AddAttachment($fichiers_joints[$i]['fichier'], $fichiers_joints[$i]['nom']); + else $mail->AddAttachment($fichiers_joints[$i]['fichier']); + } + } + + + if(!$mail->Send()) // Envoi de l'email et test du résultat + { +// $message_information .= "Erreur lors de l'envoi de l'email. PHPMailer Error = [" . $mail->ErrorInfo."]"; + } + else + { +// $message_information .= "L'email a été envoyé correctement."; + } +} + diff --git a/config/fonctions_pdf.php b/config/fonctions_pdf.php new file mode 100644 index 0000000..5c87b33 --- /dev/null +++ b/config/fonctions_pdf.php @@ -0,0 +1,353 @@ +Image('images/logo_koriolan.png', 10, 10, 60, 0, 'PNG', 'https://koriolan.tech'); + } + + public function Footer() { + $this->SetFont('helvetica', '', 7); + $this->SetTextColor(150, 150, 150); + + // Partie gauche : + $this->SetXY(10, -23); + $this->Cell(90, 10, 'Koriolan', 0, false, 'L'); + $this->SetXY(10, -19); + $this->Cell(90, 10, 'SASU au capital social de 50 000€', 0, false, 'L'); + $this->SetXY(10, -15); + $this->Cell(90, 10, '6 rue Grange Bruyère - 69110 Sainte-Foy-Lès-Lyon - FRANCE', 0, false, 'L'); + + // Partie droite : + $this->SetXY(110, -23); + $this->Cell(90, 10, 'RCS Lyon 879 809 341', 0, false, 'R'); + $this->SetXY(110, -19); + $this->Cell(90, 10, 'SIRET 879 809 341 00016', 0, false, 'R'); + $this->SetXY(110, -15); + $this->Cell(90, 10, 'TVA Intraco. FR29 879 809 341', 0, false, 'R'); + } + + public function CreateTextBox($textval, $x = 0, $y = 0, $width = 0, $height = 10, $fontsize = 10, $fontstyle = '', $align = 'L', $border = 0) { + $this->SetXY($x, $y); + $this->SetFont('helvetica', $fontstyle, $fontsize); + $this->Cell($width, $height, $textval, 0, false, $align); + } +} + + +//******************************************************************************************************************************** +// Fonction : Génère le document PDF à partir des données reçues en paramètres +// Reçoit : une autre concernant la pièce ('Commande', 'Facture') et ses attributs, une variable concernant le client, +// et une autre contenant les lignes de la pièce. Le fichier généré est stocké dans 'documents/commandes' ou 'documents/factures'. +// Retour : 0 si Ok, -1 si erreur +//******************************************************************************************************************************** +function document_pdf($piece, $client, $lignes) +{ + + switch($piece['type']) + { + case "commande": + { + $nom_piece = $_SESSION['textes']['fonctions_pdf']['document']['piece']['type_commande']; + $rep = "commandes"; + break; + } + case "facture": + { + $nom_piece = $_SESSION['textes']['fonctions_pdf']['document']['piece']['type_facture']; + $rep = "factures"; + break; + } + default: return(-1); + } + + $pdf = new MYPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); + + // set document (meta) information : + $pdf->SetCreator(PDF_CREATOR); + $pdf->SetAuthor('Koriolan'); + $pdf->SetTitle($nom_piece.' '.$piece['no']); + $pdf->SetSubject('ShipHeart'); + $pdf->SetKeywords('ShipHeart by Koriolan'); + + $pdf->SetTextColor(0, 69, 99); + $pdf->SetFont('helvetica', '', 10); + + $pdf->AddPage(); + + // L'abscisse x varie de 10 à 200 (soit une marge de 10 à gauche et 10 à droite) + + // --------------------------------------------------------- + // Adresse du client : + $x = 120; // Doit rester < 200 qui est la marge droite ! + $y = 30; + $pdf->CreateTextBox($client['entreprise'], $x, $y, (200 - $x), 12, 12, 'B', 'L'); + $y += 6; + $pdf->CreateTextBox($client['nom_complet'], $x, $y, (200 - $x), 10, 10, '', 'L'); + $y += 5; + $pdf->CreateTextBox($client['rue'], $x, $y, (200 - $x), 10, 10, '', 'L'); + $y += 5; + $pdf->CreateTextBox($client['ville_complete'], $x, $y, (200 - $x), 10, 10, '', 'L'); + $y += 5; + $pdf->CreateTextBox($client['libelle_pays'], $x, $y, (200 - $x), 10, 10, '', 'L'); + + + // --------------------------------------------------------- + // N° de commande : + $x = 10; + $y += 10; + $pdf->CreateTextBox($nom_piece.' '.$piece['no'], $x, $y, (200 - $x), 20, 20, 'B', 'L'); + + // --------------------------------------------------------- + // Date : + $x = 120; + $y += 15; + + $pdf->CreateTextBox('Date : '.date(''.$_SESSION['textes']['all']['all']['date']['format_d_m_y'].''), $x, $y, (200 - $x), 10, 10, '', 'R'); + + // --------------------------------------------------------- + // Tableau + $x = 10; + $y += 15; + $pdf->Line($x, $y, (210 - $x), $y); // Ligne horizontale + + $x = 10; + // $y += 5; + $largeur_1 = 90; + $largeur_2 = 20; + $largeur_3 = 30; + $largeur_4 = 20; + $largeur_5 = 30; + $pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['designation_titre'], $x, $y, $largeur_1, 10, 10, 'B', 'L', 1); // Ligne d'entête + $x += $largeur_1; + $pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['quantite_titre'], $x, $y, $largeur_2, 10, 10, 'B', 'C', 1); + $x += $largeur_2; + $pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['pu_ht_titre'], $x, $y, $largeur_3, 10, 10, 'B', 'R', 1); + $x += $largeur_3; + $pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['taux_tva_titre'], $x, $y, $largeur_4, 10, 10, 'B', 'C', 1); + $x += $largeur_4; + $pdf->CreateTextBox($_SESSION['textes']['fonctions_pdf']['document']['piece']['pt_ttc_titre'], $x, $y, $largeur_5, 10, 10, 'B', 'R', 1); + + $x = 10; + $y += 10; + $pdf->Line($x, $y, (210 - $x), $y); // Ligne horizontale + + $x = 10; + // $y += 5; + for ($i = 0; $i < $piece['nb_lignes']; $i ++) + { + $pdf->CreateTextBox($lignes[$i]['designation'], + $x, $y, $largeur_1, 10, 10, '', 'L'); + $x += $largeur_1; + $pdf->CreateTextBox($lignes[$i]['qte'], + $x, $y, $largeur_2, 10, 10, '', 'C'); + $x += $largeur_2; + $pdf->CreateTextBox(number_format($lignes[$i]['pu_ht'], 2, ".", " ").' €', + $x, $y, $largeur_3, 10, 10, '', 'R'); + $x += $largeur_3; + $pdf->CreateTextBox(number_format($lignes[$i]['taux_tva'], 2, ".", " ").' %', + $x, $y, $largeur_4, 10, 10, '', 'C'); + $x += $largeur_4; + $pdf->CreateTextBox(number_format(($lignes[$i]['qte'] * $lignes[$i]['pu_ht'] * (1 + ($lignes[$i]['taux_tva']/100))), 2, ".", " ").' €', + $x, $y, $largeur_5, 10, 10, '', 'R'); + $x = 10; + $y += 5; + + if ($y > 260) // Détection d'un saut de page nécessaire + { + $y = 30; + $pdf->AddPage(); + } + } + + // Ligne horizontale : + $x = 10; + $y += 5; + $pdf->Line($x, $y, (210 - $x), $y); + + // --------------------------------------------------------- + // Vérification si un saut de page est nécessaire : + if ($y > 260) + { + $y = 30; + $pdf->AddPage(); + } + + // --------------------------------------------------------- + // Totaux : + $x = 10; + // $y += 5; + $pdf->CreateTextBox('TOTAL', $x, $y, $largeur_1, 10, 11, 'B', 'R'); + $x += $largeur_1; + $x += $largeur_2; + $pdf->CreateTextBox(number_format($piece['total_ht'], 2, ".", " ").' €', + $x, $y, $largeur_3, 10, 11, '', 'R'); + $x += $largeur_3; + $x += $largeur_4; + $pdf->CreateTextBox(number_format($piece['total_ttc'], 2, ".", " ").' €', + $x, $y, $largeur_5, 10, 11, 'B', 'R'); + + + // --------------------------------------------------------- + // Commentaire : + if ($piece['commentaire'] != "") + { + if ($y > 260) // Vérification si un saut de page est nécessaire + { + $y = 30; + $pdf->AddPage(); + } + + $x = 10; + $y += 30; + $pdf->SetFont('helvetica', '', 10); + $pdf->MultiCell((200 - $x), 10, $piece['commentaire'], + 'TRBL', 'J', 0, 1, $x, $y, true, 0, true, true); + } + + + // --------------------------------------------------------- + // Ajout des numéros de page : + // NB : les fonctions usuelles ('getAliasNumPage()' et 'getAliasNbPages()') dans le Header ou le Footer fonctionnent bien mais posent des soucis d'alignement... + $nb_pages = $pdf->getNumPages(); + + for($i = 1; $i < ($nb_pages + 1); $i ++) + { + $pdf->setPage($i); + $pdf->SetFont('helvetica', '', 10); + $pdf->SetTextColor(0, 69, 99); + $pdf->SetXY(150,10); + $pdf->Cell(50, 10, 'Page '.$i.'/'.$nb_pages, 0, false, 'R'); + } + + // --------------------------------------------------------- + // Fermeture de l'objet PDF et enreigistrement du fichier : + ob_clean(); // Semble nécessaire ; sinon erreur du 'output' suivant + $pdf_string = $pdf->Output('pseudo.pdf', 'S'); // export du flux dans une chaine (le nom du fichier est ignoré...) + + // Copie de cette chaine dans le fichier final (cette solution en 2 temps permet d'éviter de devoir utiliser un nom de fichier absolu (semble obligatoire avec Output et l'option 'F') + file_put_contents('../../documents/'.$rep.'/'.$piece['no'].'.pdf', $pdf_string); + + return(0); +} + + + +class MYPDF2 extends TCPDF { + public function Header() { + // $this->Image('images/logo_shipheart.png', 10, 10, 60, 0, 'PNG', 'https://shipheart.tech'); + } + + public function CreateTextBox($textval, $x = 0, $y = 0, $width = 0, $height = 10, $fontsize = 10, $fontstyle = '', $align = 'J', $border = 0) { + $this->SetXY($x, $y); + $this->SetFont('helvetica', $fontstyle, $fontsize); + $this->SetFillColor(255,255,255); + $this->MultiCell($width, $height, $textval, 0, $align, false); + } +} + + +//******************************************************************************************************************************** +// Fonction : Génère le document PDF à partir des données reçues en paramètres +// Reçoit : type du document (1er code généré pour le bateau, code généré par un autre utilisateur) +// client concerné a qui on envoie le pdf et le code d'accès pour générer le code QR. +// Retour : 0 si Ok, -1 si erreur +//******************************************************************************************************************************** +function code_acces_pdf($code, $no, $no_serie = "XX:XX:XX:XX:XX:XX", $client = "") +{ + $nom_piece = $no."_Code_acces_bateau_".$no_serie; + + + + $pdf = new MYPDF2('LANDSCAPE', 'px', 'A4', true, 'UTF-8', false); + + // set document (meta) information : + $pdf->SetCreator(PDF_CREATOR); + $pdf->SetAuthor('Koriolan'); + $pdf->SetTitle($nom_piece); + $pdf->SetSubject('ShipHeart'); + $pdf->SetKeywords('ShipHeart by Koriolan'); + + $pdf->SetTextColor(0, 69, 99); + $pdf->SetFont('helvetica', '', 10); + + $pdf->AddPage(); + $pdf->SetDrawColor(217,217,217); + $pdf->Line(421, 0, 421, 595); + + // First page + $pdf->Image('images/logo_shipheart.png', 506, 214, 252, 167, 'PNG', 'https://shipheart.tech'); + + // Firth page + $pdf->Image('images/logo_shipheart.png', 12, 12, 64, 45, 'PNG', 'https://shipheart.tech'); + + $pdf->CreateTextBox("Nous vous remercions pour votre confiance et sommes ravis de vous offrir un accès complet aux informations de votre bateau via notre platforme Ship2net. + + We thank you for your trust and are delighted to offer you full access to your boat information via our Ship2net platform.", 52, 166, 317, 195, 12); + + $pdf->CreateTextBox($no_serie, 0, 520, 421, 46, 12, '', 'C', 0); + + // $pdf->AddPage(); + $pdf->SetDrawColor(217,217,217); + $pdf->Line(421, 0, 421, 595); + + // Second page + $pdf->Image('images/logo_shipheart.png', 12, 12, 64, 45, 'PNG', 'https://shipheart.tech'); + + $pdf->Image('images/logo_shipheart.png', 766, 12, 64, 45, 'PNG', 'https://shipheart.tech'); + + $pdf->CreateTextBox("Pour activer votre accès au bateau merci de scanner le QR code ci-joint et de vous connecter à votre profil ShipMember existant ou d'en créer un. + + To activate your boat access please scan the attached QR code and log in to your existing ShipMember profile or create one.", 52, 218, 317, 160, 12); + + // Third page + $pdf->Image(generateCode($code), 546, 216, 164, 164, 'PNG', 'https://dev.shipheart.tech/shipmembers.php?code_acces='.$code); + + + // --------------------------------------------------------- + // Fermeture de l'objet PDF et enreigistrement du fichier : + ob_clean(); // Semble nécessaire ; sinon erreur du 'output' suivant + $pdf_string = $pdf->Output('pseudo.pdf', 'S'); // export du flux dans une chaine (le nom du fichier est ignoré...) + + // Copie de cette chaine dans le fichier final (cette solution en 2 temps permet d'éviter de devoir utiliser un nom de fichier absolu (semble obligatoire avec Output et l'option 'F') + file_put_contents('temp/PDF/'.$nom_piece.'.pdf', $pdf_string); + + $_SESSION['pdf']['src'] = 'temp/PDF/'.$nom_piece.'.pdf'; + + // Sauvegarder le pdf automatiquement + header("Cache-Control: public"); + header("Content-Description: File Transfer"); + header("Content-Disposition: attachment; filename=".$nom_piece.".pdf"); + header("Content-Type: application/zip"); + header("Content-Transfer-Encoding: binary"); + + // Read the file + readfile($_SESSION['pdf']['src']); + + // Suppression du pdf et codeqr du serveur + unlink('temp/CodeQR/'.$code.'.png'); + unlink($_SESSION['pdf']['src']); + return(0); +} + +function generateCode($code){ + $tempDir = "temp/CodeQR/"; + + $codeContents = 'https://shipheart.tech/shipmembers.php?code_acces='.$code; + + $fileName = $code.'.png'; + + $pngAbsoluteFilePath = $tempDir.$fileName; + $urlRelativeFilePath = $tempDir.$fileName; + + // generating + if (!file_exists($pngAbsoluteFilePath)) { + QRcode::png($codeContents, $pngAbsoluteFilePath); + } + return $urlRelativeFilePath; +} + + diff --git a/config/fonctions_traductions.php b/config/fonctions_traductions.php new file mode 100644 index 0000000..d877719 --- /dev/null +++ b/config/fonctions_traductions.php @@ -0,0 +1,123 @@ += NIVEAU_EDITEUR_ACCES_ADMINISTATEUR)){ + + if ($_SESSION['modifier_texte'] == 1) $texte = $texte.''; + } + + return $texte; +} + + +//************************************************************************************************************ +// Fonction : Récupération dans la base de données du lien du texte (spécial pour les NAVBAR) +// Reçoit : Nom du fichier, page, bloc et nom +// Retour : Lien sous la forme d'un '....." permettant l'accès à la modification du texte +// Navbar spécial ( class update_navbar pour bien afficher) +//************************************************************************************************************ +function Ajouter_lien_modif($fichier, $page, $bloc, $nom){ + $texte = ""; + if (($_SESSION['acces_valide']) && ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_EDITEUR_ACCES_ADMINISTATEUR)){ + + if ($_SESSION['modifier_texte'] == 1) $texte = ''; + } + + return $texte; +} + + +//************************************************************************************************************ +// Fonction : Récupération dans la base de données du lien du texte (pour les BUTTONS et les HREF) +// Reçoit : Nom du fichier, page, bloc et nom +// Retour : Lien sous la forme d'un '....." permettant l'accès à la modification du texte +// Le reste des buttons et href (suppression de la classe update_navbar) +//************************************************************************************************************ +function Ajouter_lien_modif_buttons($fichier, $page, $bloc, $nom){ + $texte = ""; + if (($_SESSION['acces_valide']) && ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_EDITEUR_ACCES_ADMINISTATEUR)){ + + if ($_SESSION['modifier_texte'] == 1) $texte = ''; + } + + return $texte; +} + + +//************************************************************************************************************ +// Fonction : Chargement d'une langue. Cela se traduit par charger dans une GROSSE variable de session tous les textes dans la langue choisie. +// Reçoit : Rien +// Retour : Rien (mais met à jour la variable de session contenant tous les textes) +// Attention : doit être rechargé à chaque fois qu'un texte est modifié dans la base +// Attention 2 : doit être rechargé à chaque fois qu'on change de langue +//******************************************************************************************************************************** +function chargement_langue() +{ + + Ouverture_bdd(); // Connexion à MySql + + $requete = "SELECT Fichier, Page, Bloc, Nom, (SELECT Texte FROM TB_Textes_traduction WHERE ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?) AND ID_TYPE = ".TYPE_UTILISATEUR_PROFESSIONNEL." AND TB_Textes_traduction.ID_TEXTES=TB_Textes_acces.ID_TEXTES) AS Libelle FROM TB_Textes_acces WHERE Validite='1'"; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['langue'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) // boucle sur tous les enregistrements de la table + { + $_SESSION['textes'][''.$donnees['Fichier'].''][''.$donnees['Page'].''][''.$donnees['Bloc'].''][''.$donnees['Nom'].''] = stripcslashes($donnees['Libelle']); + } + Liberation_jeu_de_resultat_bdd($reponse); + + Fermeture_bdd(); // Déconnexion de MySQL +} + + + + + + diff --git a/config/fonctions_utilitaires.php b/config/fonctions_utilitaires.php new file mode 100644 index 0000000..3f1b0c3 --- /dev/null +++ b/config/fonctions_utilitaires.php @@ -0,0 +1,585 @@ + +

'.Texte_jour_semaine(date("w")).'

+

'.date("d").' '.Texte_mois(date("n")-1).'

+

'.date("Y").'

+

'.date("H:i").'

+
'; +} + + +//************************************************************************************************************ +// Fonction : Affichage de la date en cours +// Reçoit : Rien +// Retour : Rien (le résultat est renvoyé directement sur la page par 'echo') +//************************************************************************************************************ +function Affichage_date() +{ + if (!isset($_SESSION['Prise_rendez_vous']['jour_en_cours'])) $_SESSION['Prise_rendez_vous']['jour_en_cours'] = date("Y-m-d"); + $current_date = $_SESSION['Prise_rendez_vous']['jour_en_cours']; + + // On regarde si le jour en cours est dans ce mois pour le marquer de façon particulière : + $month = substr($current_date, 5, 2); + $year = substr($current_date, 0, 4); + $day = substr($current_date, 8, 2); + $time = mktime(0,0,0, $month, $day, $year); + + echo '
+

'.Texte_jour_semaine(date("w", $time)).'

+

'.date("d", $time).' '.Texte_mois(date("n", $time)-1).'

+

'.date("Y", $time).'

+
'; +// echo '
+ // '.Texte_jour_semaine(date("w", $time)).'
' + // .date("j", $time).' '.Texte_mois(date("n", $time)-1).' '.date("Y", $time).'

+ //
'; +} + + +//******************************************************************************************************************************** +// Fonction : Vérifie la longueur d'un paramètre de formulaire en fonction de valeurs mini et maxi reçues et +// renvoie une chaine d'erreur dans la langue en cours +// Reçoit : Le titre du champ, la chaine du champs à vérifier, la longueur mini et la longueur maxi +// Retour : Une chaine d'erreur. Vide si aucune erreur ou message dans la langue en cours +//******************************************************************************************************************************** +function check_longueur_champ($titre_champ, $champ, $min, $max) +{ + $longueur = strlen($champ); + $retour = ""; + if (($longueur < $min) OR ($longueur > $max)) + { + $retour .= '['.$_SESSION['textes']['all']['all']['all'][''.$titre_champ.''].'] '; + $retour .= $_SESSION['textes']['all']['all']['erreurs']['longueur_champ_invalide']; + $retour .= ' (min = '.$min.' - max = '.$max.')'; + $retour .= '
'; + } + return($retour); +} + + +//************************************************************************************************************ +// Fonction : Affiche le comparatif des versions de ShipHeart qui est utilisé sur la Boutique et sur la page +// d'Accueil. +// Reçoit : Rien +// Retour : Rien (le résultat est renvoyé directement sur la page par 'echo') +//************************************************************************************************************ +function comparatif_shiphearts() +{ + + $nom_page = basename($_SERVER['SCRIPT_FILENAME']); + + // Variables spécifiques au fichier d'origine : + switch($nom_page) + { + case 'accueil.php' : + { + $image_coche = "selection_blanc.png"; + $type_fond = "fond_fonce"; + break; + } + case 'boutique.php' : + { + $image_coche = "selection.png"; + $type_fond = "fond_clair"; + break; + } + default : { $image_coche = "selection_hover.png"; break; } + } + + //========================================================================= + // Récupération des données : + Ouverture_bdd(); // Connexion à MySql + + // Variables spécifiques à la langue : + switch($_SESSION['langue']) + { + case "EN" : { $texte_coche = "Yes"; break; } + case "FR" : { $texte_coche = "Oui"; break; } + default : { $texte_coche = "langue_non_féfinie"; break; } // Ce texte ne sera jamais trouvé, donc jamais remplacé.... + } + + $nb_lignes_comparatif = 0; + $nb_renvois_comparatif = 0; +/* $requete = 'SELECT * FROM TB_Comparatif WHERE Validite=1 AND Visible_public=1 ORDER BY Priorite_affichage, Cle_primaire '; + // echo "Requete = ".$requete.'
'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); +*/ + $requete = 'SELECT ID, '; + $requete .= 'Renvoi, '; + $requete .= '(SELECT Texte FROM TB_Textes_traduction WHERE ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?) AND ID_TEXTES=ID_FONCTION) AS Texte, '; + $requete .= 'CONCAT(\'{\',GROUP_CONCAT(CONCAT(\'"\',ID_PRODUITS,\'":"\',(SELECT Texte FROM TB_Textes_traduction WHERE ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?) AND ID_TEXTES=ID_RESULTAT),\'"\') ORDER BY ID_PRODUITS ASC SEPARATOR ","),"}") AS Produits '; + $requete .= 'FROM TB_Galerie_comparatif LEFT JOIN TB_Comparatif ON TB_Galerie_comparatif.ID_COMPARATIF=TB_Comparatif.ID JOIN TB_Comparatif_produits ON TB_Comparatif.ID=TB_Comparatif_produits.ID_COMPARATIF '; + $requete .= 'WHERE TB_Galerie_comparatif.Priorite!=0 GROUP BY TB_Comparatif.ID ORDER BY TB_Galerie_comparatif.Priorite ASC'; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['langue']), + array('s', $_SESSION['langue'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $lignes_comparatif[$nb_lignes_comparatif]['id'] = $donnees['ID']; + $lignes_comparatif[$nb_lignes_comparatif]['fonction'] = $donnees['Texte']; + + // Traitement des renvois de bas de page : + if ($donnees['Renvoi'] > 0) + { + // Recherche si le même texte de renvoi a déjà été utilisé : + $renvoi_deja_utilise = 0; + for ($i=0; $i<$nb_renvois_comparatif; $i++) + { + if ($renvois_comparatif[$i]['id'] == $donnees['Renvoi']) + { + $renvoi_deja_utilise = $renvois_comparatif[$i]['no']; + break; + } + } + + if ($renvoi_deja_utilise != 0) $lignes_comparatif[$nb_lignes_comparatif]['fonction'] .= '['.$renvoi_deja_utilise.']'; + else + { + $renvois_comparatif[$nb_renvois_comparatif]['no'] = $nb_renvois_comparatif + 1; + $renvois_comparatif[$nb_renvois_comparatif]['id'] = $donnees['Renvoi']; + $renvois_comparatif[$nb_renvois_comparatif]['texte'] = nl2br($_SESSION['textes']['boutique']['accueil']['comparatif']['texte_renvoi_'.$donnees['Renvoi'].'']); + + $lignes_comparatif[$nb_lignes_comparatif]['fonction'] .= '['.($nb_renvois_comparatif + 1).']'; + + $nb_renvois_comparatif++; + } + } + + // Remplacement des textes "Oui"/"Yes" par l'image d'une case cochée + suppression de la langue dans la variable : + $lignes_comparatif[$nb_lignes_comparatif]['Produits'] = array(); + foreach(json_decode($donnees['Produits'], true) as $id_produit => $produit) + { + $lignes_comparatif[$nb_lignes_comparatif]['Produits'][$id_produit] = str_replace($texte_coche, "", $produit); + } + + // Demande de regroupement des lignes pour lesquelles les valeurs sont identiques : + $lignes_comparatif[$nb_lignes_comparatif]['type_ligne'] = count(array_unique($lignes_comparatif[$nb_lignes_comparatif]['Produits'])) <= 1 ? "unique" : "multiple"; + + $nb_lignes_comparatif ++; + } + Liberation_jeu_de_resultat_bdd($reponse); + + $requete = "SELECT CONCAT('{',GROUP_CONCAT(DISTINCT CONCAT('\"',ID_PRODUITS,'\":\"',(SELECT Texte FROM TB_Textes_traduction WHERE ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?) AND ID_TEXTES=(SELECT ID_NOM FROM TB_Produits WHERE ID=ID_PRODUITS)),'\"') ORDER BY ID_PRODUITS ASC SEPARATOR ','),'}') AS resultat FROM TB_Comparatif_produits"; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['langue'])), + __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + $title_comparatif = json_decode($donnees['resultat'], true); + Liberation_jeu_de_resultat_bdd($reponse); + + Fermeture_bdd(); // Déconnexion de MySQL + + + //========================================================================= + // Affichage : + echo '
'; + + //----------------------------------------------------------------- + // Bouton de sélection de l'affichage ou non de la table de comparaison : + echo ''; + + + echo '
'; + + //----------------------------------------------------------------- + // Table principale avec fonctions et valeur pour chaque version : + echo ''; + echo ' + '; +/* echo ''; + + foreach($title_comparatif as $id_produit => $produit) + { + echo ''; + } +*/ + echo ''; + echo ''; + echo ' + '; + +// $nb_lignes_comparatif = 0; + + echo ''; + for ($j = 0; $j < $nb_lignes_comparatif; $j ++) + { + echo ' + '; + + foreach($lignes_comparatif[$j]['Produits'] as $id_produit => $produit) + { + echo ''; + break; + } + /* if ($lignes_comparatif[$j]['type_ligne'] == "multiple") + { + foreach($lignes_comparatif[$j]['Produits'] as $id_produit => $produit) + { + echo ''; + } + } + else + { + foreach($lignes_comparatif[$j]['Produits'] as $id_produit => $produit) + { + echo ''; + break; + } + } + */ + echo ''; + } + echo ''; + + + echo '
'.$_SESSION['textes']['boutique']['accueil']['comparatif']['titre_1'].''.$produit.'
'.nl2br($lignes_comparatif[$j]['fonction']).''.nl2br($produit).''.nl2br($produit).''.nl2br($produit).'
'; + + //----------------------------------------------------------------- + // Table des renvois : + echo ' + '; + for ($j = 0; $j < $nb_renvois_comparatif; $j ++) + { + echo ' + + '; + } + + echo ' +
['.$renvois_comparatif[$j]['no'].'] '.nl2br($renvois_comparatif[$j]['texte']).'
'; + + echo '
'; + + echo ""; + + echo '
'; + +} + + +//************************************************************************************************************ +// Fonction : Convertit une valeur de latitude/longitude décimale en chaine de caratères comprenant Degrés, Minutes et Secondes +// Reçoit : L'indication "LAT" ou "LON" et la valeur décimale +// Retour : La chaine convertie +//************************************************************************************************************ +function Conversion_DECtoDMS($lat_lon, $valeur) +{ + if ($lat_lon == "LAT") $direction = $valeur < 0 ? 'S': 'N'; + elseif ($lat_lon == "LON") $direction = $valeur < 0 ? 'W': 'E'; + else $direction = ""; + + $signe = $valeur < 0 ? '-': ''; + + $degres = floor(abs($valeur ?? 0)); + + $decimale = (abs($valeur ?? 0)-$degres) * 3600; + + $min = floor($decimale / 60); + $sec = round($decimale - ($min * 60), 1); + + return (sprintf("%s%s°%02d'%04.1f\" %s", $signe, $degres, $min, $sec, $direction)); + +} + + +//************************************************************************************************************ +// Fonction : Enregistrement dans le fichier de log de l'évènement +// Reçoit : Le texte à afficher dans le log, le fichier d'origine et la ligne d'origine +// Retour : Rien +//************************************************************************************************************ +function Enregistrement_log($texte, $fichier, $ligne) +{ + $repertoire_logs = REPERTOIRE_LOGS."/www_shipheart"; + if (!file_exists($repertoire_logs) OR !is_dir($repertoire_logs)) // On vérifie d'abord que le répertoire existe, sinon on le créé. + { + mkdir($repertoire_logs); + $message_information .= "Le répertoire de logs [".$repertoire_logs."] n'existait pas. Il vient d'êtrer crééé
"; + } + + $fichier_log = $repertoire_logs.'/log_shipheart_'.date("Y-m-d").'.txt'; + $prefixe_ligne = date("d/m/Y H:i:s")." [".basename($fichier)." - ".$ligne."] \t: "; + $suffixe_ligne = "\r\n"; + + $log = fopen($fichier_log, "a+"); // Ouverture en lecture/écriture en mode append... + + fputs($log, $prefixe_ligne); // Entete de ligne + fputs($log, $texte); // Ecriture du texte de log + fputs($log, $suffixe_ligne); // Fin de ligne + + fclose($log); // Fermetue du fichier. + + if(SHOW_DEBUG) + { + echo $prefixe_ligne . $texte . $suffixe_ligne; + } +} + + +//************************************************************************************************************ +// Fonction : Conversion de format de dates +// Reçoit : Date à convertir +// Retour : la chaine mise en forme +//************************************************************************************************************ +function Formatage_date($date) +{ + if ($_SESSION['langue'] == "FR") + { + switch (substr($date, 5, 2)) + { + case 1: {$mois="janvier"; break;} + case 2: {$mois="février"; break;} + case 3: {$mois="mars"; break;} + case 4: {$mois="avril"; break;} + case 5: {$mois="mai"; break;} + case 6: {$mois="juin"; break;} + case 7: {$mois="juillet"; break;} + case 8: {$mois="août"; break;} + case 9: {$mois="septembre"; break;} + case 10: {$mois="octobre"; break;} + case 11: {$mois="novembre"; break;} + case 12: {$mois="décembre"; break;} + default: $mois = substr($date, 5, 2); + } + + $retour = substr($date, 8, 2).' '.$mois.' '.substr($date, 0, 4); + + $suffixe_heure = 'à'; + } + else + { + switch (substr($date, 5, 2)) + { + case 1: {$mois="January"; break;} + case 2: {$mois="February"; break;} + case 3: {$mois="March"; break;} + case 4: {$mois="April"; break;} + case 5: {$mois="May"; break;} + case 6: {$mois="June"; break;} + case 7: {$mois="July"; break;} + case 8: {$mois="August"; break;} + case 9: {$mois="September"; break;} + case 10: {$mois="October"; break;} + case 11: {$mois="November"; break;} + case 12: {$mois="December"; break;} + default: $mois = substr($date, 5, 2); + } + + $jour = ltrim(substr($date, 8, 2), "0"); // Suppression du zéro initial s'il y en a un... + switch($jour) + { + case 1: + case 21: + case 31: { $suffixe_jour = 'st'; break; } + case 2: + case 22: { $suffixe_jour = 'nd'; break; } + case 3: + case 23: { $suffixe_jour = 'rd'; break; } + default: { $suffixe_jour = 'th'; break; } + } + + $retour = $mois.' '.$jour.''.$suffixe_jour.', '.substr($date, 0, 4); + + $suffixe_heure = 'at'; + } + + if (strpos($date, ' ') !== false) $retour .= ' '.$suffixe_heure.' '.substr($date, 11); // Ajout de l'heure si la chaine d'entrée comprend un espace (entre date et heure) + + return($retour); +} + + +//******************************************************************************************************************************** +// Fonction : Recherche dans le BDD le prochain numéro de document, le formatte, et retourne le n° formatté du nouveau document. +// Reçoit : le type de document (cd dans definition.php) et l'année concernée +// Retour : Le numéro formatté du nouveau document, -1 si erreur de paramètres, -2 si dépassement de numérotation +// ATTENTION : l'accès à la BDD doit être ouvert AVANT d'accéder à cette fonction. +// NB : on pourrait l'ouvrir dedans mais on ne sait alors pas s'il faut la refermer... +//******************************************************************************************************************************** +function nouveau_numero_document($type, $annee) +{ + $nb_digits_numerotation = 4; + $erreur = 0; + + + // Contrôles et définition du préfixe au passage : + switch($type) + { + case NUM_TYPE_DEVIS : { $prefixe = "D"; $fonctionRequete = ""; break; } + case NUM_TYPE_COMMANDE : { $prefixe = "C"; $fonctionRequete = "porchainNoCommande"; break; } + case NUM_TYPE_FACTURE : { $prefixe = "F"; $fonctionRequete = "porchainNoFacture"; break; } + case NUM_TYPE_AVOIR : { $prefixe = "A"; $fonctionRequete = ""; break; } + default: return (-1); + } + + // Recherche d'une numérotation existante : + $dernier_no = -1; + $requete = "SELECT $fonctionRequete(?) AS No"; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $annee)), + __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + $dernier_no = $donnees['No']; + Liberation_jeu_de_resultat_bdd($reponse); + + // Formattage du n° de document : + if ($erreur != 0) return($erreur); + else return($prefixe.($annee-2000).str_pad($dernier_no, $nb_digits_numerotation, '0', STR_PAD_LEFT)); +} + + +//************************************************************************************************************ +// Fonction : Affichage du nom du jour de la semaine en français en version courte (3 lettres) +// Reçoit : Jour à convertir (entre 0: dimanche et 6: samedi voire 7:dimanche) +// Retour : Le texte court du jour en français +//************************************************************************************************************ +function Texte_court_jour_semaine($jour) +{ + + switch ($jour) + { + case 0: {$texte_jour_semaine="Dim"; break;} + case 1: {$texte_jour_semaine="Lun"; break;} + case 2: {$texte_jour_semaine="Mar"; break;} + case 3: {$texte_jour_semaine="Mer"; break;} + case 4: {$texte_jour_semaine="Jeu"; break;} + case 5: {$texte_jour_semaine="Ven"; break;} + case 6: {$texte_jour_semaine="Sam"; break;} + case 7: {$texte_jour_semaine="Dim"; break;} + default: $texte_jour_semaine = ""; + } + return($texte_jour_semaine); +} + + +//************************************************************************************************************ +// Fonction : Affichage du nom du jour de la semaine en français +// Reçoit : Jour à convertir (entre 0: dimanche et 6: samedi voire 7:dimanche) +// Retour : Le texte du jour en français +//************************************************************************************************************ +function Texte_jour_semaine($jour) +{ + + switch ($jour) + { + case 0: {$texte_jour_semaine="dimanche"; break;} + case 1: {$texte_jour_semaine="lundi"; break;} + case 2: {$texte_jour_semaine="mardi"; break;} + case 3: {$texte_jour_semaine="mercredi"; break;} + case 4: {$texte_jour_semaine="jeudi"; break;} + case 5: {$texte_jour_semaine="vendredi"; break;} + case 6: {$texte_jour_semaine="samedi"; break;} + case 7: {$texte_jour_semaine="dimanche"; break;} + default: $texte_jour_semaine = ""; + } + return($texte_jour_semaine); +} + + +//************************************************************************************************************ +// Fonction : Affichage du nom du mois en français +// Reçoit : Mois à convertir (entre 0: janvier et 11: décembre) +// Retour : Le texte du mois en français +//************************************************************************************************************ +function Texte_mois($mois) +{ + + switch ($mois) + { + case 0: {$texte_mois="janvier"; break;} + case 1: {$texte_mois="février"; break;} + case 2: {$texte_mois="mars"; break;} + case 3: {$texte_mois="avril"; break;} + case 4: {$texte_mois="mai"; break;} + case 5: {$texte_mois="juin"; break;} + case 6: {$texte_mois="juillet"; break;} + case 7: {$texte_mois="août"; break;} + case 8: {$texte_mois="septembre"; break;} + case 9: {$texte_mois="octobre"; break;} + case 10: {$texte_mois="novembre"; break;} + case 11: {$texte_mois="décembre"; break;} + default: $texte_mois = ""; + } + return($texte_mois); +} + + +//************************************************************************************************************ +// Fonction : Vérification d'un numero de téléphone + formatage +// Reçoit : Chaine représentant le numéro +// Retour : Le numéro formaté soud la forme "06 12 34 56 78 90" +//************************************************************************************************************ +function Verification_numero_telephone($chaine_numero) +{ + $numero_ok = true; + do + { + switch (strlen($chaine_numero)) + { + case 10 : // Aucun séparateur n'est présent dans la chaine reçue : + { + for ($i=0; $i<5; $i++) $numeros[$i] = substr($chaine_numero, ($i*2), 2); + $chaine_numero = $numeros[0]; + for ($i=1; $i<5; $i++) $chaine_numero .= ' '.$numeros[$i]; // Ajout des ' ' comme séparateur + break; + } + case 14 : // Un séparateur existe entre chaque groupe de deux chiffres : + { + for ($i=1; $i<5; $i++) $chaine_numero[($i*3)-1] = ' '; // Remplacement des séparateurs existants par des ' ' + break; + } + default : // Comibinaison de nombre de séparateurs ou de chiffres incohérent : + { + $numero_ok = false; + break; + } + } + if (! $numero_ok) break; // On sort de la boucle DO si une erreur a déjà été trouvée. + + // On décompose les 5 groupes : + $numeros = explode(" ", $chaine_numero); + if (count($numeros) != 5) {$numero_ok = false; break;} + foreach($numeros as $n) + { + if (strlen($n) != 2) {$numero_ok = false; break;} + if (($n < 0) OR ($n > 99)) {$numero_ok = false; break;} + } + if (($numeros[0] < 1) OR ($numeros[0] > 9)) {$numero_ok = false; break;} + } while (0); + + if ($numero_ok) return($chaine_numero); + else return ("Numéro non valide"); +} + diff --git a/config/lang/en.php b/config/lang/en.php new file mode 100644 index 0000000..e026469 --- /dev/null +++ b/config/lang/en.php @@ -0,0 +1,219 @@ + '[Email] is invalid!', + '[Email] est déjà utilisée par un ShipMember.
Si vous êtes le propriétaire de cette adresse, merci de vous connecter avec cette adresse.
Sinon, merci de choisir une autre adresse.' + => '[Email] is already in use by a ShipMember.
If you are the owner of this email address, please log in using it.
Otherwise, please choose a different email address.', + '

Félicitations !

+

Votre compte ShipMember est créé, vous y êtes presque.

+

Nom : [[Prenom]] [[Nom]]

+

Email : [[Email]]

+

Mot de passe provisoire : [[Password]]

+

Plus qu’un clic : Connectez-vous sur ShipHeart.tech pour valider votre compte ShipMember en modifiant votre mot de passe provisoire (*). C’est une garantie de sécurité à ne pas négliger.

+

Et ensuite, où que vous soyez et dès que votre ShipHeart est installé, accédez à votre bateau via votre accès privilégié ShipMember !

+

+

Bienvenue parmi nous !

+

L\'équipage ShipHeart

+

+

(*) L\'activation devra être faite avant le [[Date_maxi_activation]]. Mais pas d\'inquiétude ; si vous ne le faites pas avant, vous pourrez toujours demander un nouveau mot de passe provisoire.

' + => '

Congratulations!

+

Your ShipMember account has been created – you’re almost there.

+

Surname: [[First name]] [[Surname]]

+

Email: [[Email]]

+

Temporary password: [[Password]]

+

Just one more click: Log in to ShipHeart.tech to verify your ShipMember account by changing your temporary password (*). This is an important security measure that should not be overlooked.

+

And then, wherever you are and as soon as your ShipHeart is installed, access your boat via your exclusive ShipMember account!

+

+

Welcome on board!

+

The ShipHeart crew

+

+

(*) Activation must be completed by [[Date_maxi_activation]]. But don’t worry; if you don’t manage to do so by then, you can always request a new temporary password.

', + 'Votre accès ShipMember - Un dernier clic pour accéder à votre bateau !' + => 'Your ShipMember login – Just one more click to access your boat!', + 'Un email vient d\'être envoyé à [[Prenom]] [[Nom]] ([[Email]]) avec un mot de passe provisoire.' + => 'An email has just been sent to [[First name]] [[Surname]] ([[Email]]) containing a temporary password.', + 'Désolé, votre compte n\'a pas été activé dans le délai maximal.
Vous pouvez demander la génération d\'un nouveau mot de passe provisoire en cliquant sur le bouton ci-dessous. Il vous sera adressé immédiatement par email.' + => 'Sorry, your account has not been activated within the maximum time limit.
You can request a new temporary password by clicking the button below. It will be sent to you immediately by email.', + 'Bienvenue !' + => 'Welcome!', + 'Pour des raisons de sécurité, votre nouveau mot de passe ne peut pas être identique au mot de passe provisoire.' + => 'For safety reason, your new password can\'t be the same than the temporary password.', + 'Félicitations : votre compte est maintenant activé et vous êtes d\'ores et déjà connecté.e.' + => 'Congratulations: your account is now active and you\'re already logged in.', + 'Les deux mots de passe saisis doivent être identiques.' + => 'Both passwords shall be the same.', + 'Le mot de passe renseigné n\'est pas conforme. Pour la sécurité de vos données, il doit contenir entre 6 et 20 caractères, et être composé exclusivement de minuscules, de majuscules, de chiffres ou des caractères spéciaux suivants _-!*=.' + => 'The password you have entered not valid. To insure the security of your data, it must contain between 6 and 20 characters, and must consist exclusively of lower-case letters, upper-case letters, numbers or the following special characters _-!*=.', + '

Bonjour,

+

Le mot de passe de votre compte ShipMember vient d\'être réinitialisé à votre demande.

+

Nom : [[Prenom]] [[Nom]]

+

Email : [[Email]]

+

Mot de passe provisoire : [[Password]]

+

Plus qu’un clic : Connectez-vous sur Ship2net.fr pour activer votre compte ShipMember en modifiant votre mot de passe provisoire (*). C’est une garantie de sécurité à ne pas négliger...

+

Bienvenue à nouveau parmi nous !

+

L\'équipage ShipHeart

+

+

(*) L\'activation devra être faite avant le [[Date_maxi_activation]]. Mais pas d\'inquiétude ; si vous ne le faites pas avant, vous pourrez toujours demander un nouveau mot de passe provisoire.

' + => '

Hello,

+

The password for your ShipMember account has just been reset at your request.

+

Surname: [[First name]] [[Surname]]

+

Email: [[Email]]

+

Temporary password: [[Password]]

+

Just one more click: Log in to Ship2net.fr to activate your ShipMember account by changing your temporary password (*). This is an important security measure that should not be overlooked...

+

Welcome back!

+

The ShipHeart team

+

+

(*) Activation must be completed by [[Date_maxi_activation]]. But don’t worry; if you don’t manage to do so by then, you can always request a new temporary password.

', + 'Votre demande concernant votre accès ShipMember' + => 'Your enquiry regarding your ShipMember access', + 'Un email vient d\'être envoyé à [[Prenom]] [[Nom]] ([[Email]]) avec les informations relatives à votre inscription.' + => 'An email has just been sent to [[First name]] [[Surname]] ([[Email]]) containing details of your registration.', + '

Bonjour,

+

L\'adresse email associée à votre compte ShipMember vient d\'être modifiée à votre demande :

+

Ancienne adresse : [[Old_email]]

Nouvelle adresse : [[New_email]]

+

Si vous n\'êtes pas à l\'origine de ce changement d\'adresse, merci de contacter sans attendre l\'administrateur du site à : [[Adresse_email_alertes]].\'

+

L\'équipage ShipHeart

' + => '

Hello,

+

The email address associated with your ShipMember account has just been changed at your request:

+

Old address: [[Old_email]]

New address: [[New_email]]

+

If you did not request this change of address, please contact the site administrator immediately at: [[Alert_email_address]].\'

+

The ShipHeart team

', + 'Modifications de votre accès ShipMember' + => 'Changes to your ShipMember access', + 'Connectez-vous' + => 'Log in', + 'Déjà ShipMember ?' + => 'Already ShipMember?', + 'Merci de vous identifier :' + => 'Thank you for logging in:', + 'Email' + => 'Email', + 'Saisissez votre adresse email...' + => 'Enter your email address...', + 'Mot de passe' + => 'Password', + 'Saisissez votre mot de passe...' + => 'Enter your password...', + 'Valider' + => 'Confirm', + 'Générer un nouveau mot de passe' + => 'Generate a new password', + 'Pas encore ShipMember ?' + => 'Not a ShipMember yet?', + 'Merci de renseigner vos coordonnées ; votre espace ShipMember sera créé immédiatement :' + => 'Please fill in your details; your ShipMember account will be created immediately.', + 'Prénom' + => 'First name', + 'Nom' + => 'Last name', + 'Entreprise' + => 'Company', + 'Numéro et rue' + => 'Number and street', + 'Numéro et nom de voie, bâtiment, appartement, lotissement, ...' + => 'Number and name of lane, building, flat, housing estate,...', + 'Code postal' + => 'Postcode', + 'Ville' + => 'City', + 'Pays' + => 'Country', + 'Téléphone' + => 'Phone', + 'Mon espace ShipMember' + => 'My ShipMember account', + 'Activation de mon compte' + => 'Activation of my account', + 'Votre compte n\'a pas encore été activé. Pour cela, merci de changer votre mot de passe provisoire ci-dessous.' + => 'Your account has not yet been activated. Please change your temporary password below.', + 'Nouveau mot de passe' + => 'New password', + 'Entre 6 et 20 caractères, et être composé exclusivement de minuscules, majuscules, de chiffres ou des caractères spéciaux suivants _-!*=.' + => 'Between 6 and 20 characters, and must consist exclusively of lower-case letters, upper-case letters, numbers or the following special characters _-!*=.', + 'Nouveau mot de passe (2)' + => 'New password (2)', + 'Saisissez à nouveau votre nouveau mot de passe...' + => 'Re-enter your new password...', + 'Générer un nouveau mot de passe provisoire' + => 'Generate a new temporary password', + 'Renseignez votre adresse email puis confirmez votre demande.
Si votre adresse existe bien dans la liste des ShipMembers, un email vous sera adressé immédiatement avec un nouveau mot de passe provisoire.' + => 'Fill in your email address and confirm your request.
If your address exists in the ShipMembers list, an email will be sent to you immediately with a new temporary password.', + 'Attention : dès validation, seul ce nouveau mot de passe provisoire sera valide pour vous connecter. Si vous n\'avez pas reçu cet email dans les prochaines minutes, merci de vérifier s\'il ne se trouve pas dans vos courriers indésirables. ' + => 'Caution: as soon as you confirm, only this new temporary password will be valid to connect you. If you have not received this email within the next few minutes, please check your spam folder.', + 'Valider votre saisie...' + => 'Confirm your entry...', + 'Bienvenue dans votre espace ShipMember !' + => 'Welcome to your ShipMember area !', + 'Vous trouverez ici toutes les informations que nous conservons vous concernant. Notre objectif est de ne conserver que celles nécessaires au traitement de vos commandes et, surtout, vous permettant de profiter pleinement de toutes les fonctions de votre ShipHeart.' + => 'You\'ll find here all the information we keep about you. Our aim is to keep only the information necessary to process your orders and, above all, to allow you to take full advantage of all the functions of your ShipHeart.', + 'Enfin, nous vous rappelons que Koriolan ne diffuse et ne diffusera jamais la moindre de ces informations à d\'autres sociétés. Pour plus de précisions sur le traitement de vos données personnelles, n\'hésitez pas à consulter nos mentions légales accessibles en bas de cette page.' + => 'Finally, we would like to remind you that Koriolan does not and will never distribute any of this information to other companies. For more information on the processing of your personal data, please consult our legal notice at the bottom of this page.', + 'Voir les informations liées à votre compte ShipMember...' + => 'View your ShipMember account information...', + 'Mes informations' + => 'My information', + 'Accéder à mon bateau...' + => 'Getting to my boat...', + 'Mon bateau' + => 'My boat', + 'Fermer votre session...' + => 'Close your session...', + 'Déconnexion' + => 'Logout', + 'Numéro de ShipMember' + => 'ShipMember number', + 'Accéder au menu de modification de vos informations...' + => 'Go to the menu for changing your details...', + 'Modifier' + => 'Edit', + 'Retour à mon espace ShipMember...' + => 'Back to my ShipMember account...', + 'Retour' + => 'Back', + 'Modifier mes informations' + => 'Edit my details', + 'Si vous souhaitez modifier votre mot de passe, entrez votre nouveau mot de passe deux fois ci-dessous. Sinon, laissez ces deux champs vides.' + => 'If you wish to change your password, enter your new password twice below. Otherwise, leave these two fields blank.', + 'Saisissez votre nouveau mot de passe...' + => 'Enter your new password...', + 'Annuler la saisie...' + => 'Cancel your entry...', + 'Annuler' + => 'Cancel', + 'Accès à mes bateaux' + => 'Access to my boats', + 'Accès à mon bateau' + => 'Access to my boat', + 'Vous n\'avez pas encore de ShipHeart activé.' + => 'You do not yet have a ShipHeart activated.', + 'Mais dès que ce sera le cas, vous trouverez ici l\'accès à votre ou vos bateaux.' + => 'But as soon as that happens, you’ll find access to your boat or boats here.', + 'Pour chacun d\'eux, vous visualiserez l\'état de tous les circuits, leur consommation, le niveau des réservoirs et des batteries, mais aussi toutes les valeurs de vos capteurs : températures, pression atmosphérique, humidité, position géographique, etc...
Vous aurez également accès aux courbes historiques de toutes ces valeurs.' + => 'For each one, you will be able to view the status of all circuits, their power consumption, the levels of the tanks and batteries, as well as all the readings from your sensors: temperatures, atmospheric pressure, humidity, geographical position, etc...
You will also have access to historical trends for all these readings.', + 'C\'est également ici que vous pourrez créer des profils [Propriétaire], [Installateur] ou [Skipper] afin de donner accès de façon contrôlée à votre ou à vos bateaux. Sans aucune limite !' + => 'This is also where you can create [Owner], [Installer] or [Skipper] profiles to grant controlled access to your boat or boats. There are no limits!', + 'Revenir à mon espace ShipMember...' + => 'Back to my ShipMember dashboard...', + 'ShipHeart by Koriolan, la première centrale de vie à bord pour les bateaux de plaisance' + => 'ShipHeart by Koriolan, the first on-board life support system for pleasure craft', + 'Retour à l\'accueil' + => 'Back to home page...', + 'Switch to English...' + => 'Revenir en français...', + 'Accès validé pour ' + => 'Access granted to ', + 'ShipHeart ™ est une marque de Koriolan' + => 'ShipHeart™ is a brand of Koriolan', + 'Accéder à notre site Koriolan' + => 'Visit our Koriolan website', + 'Mentions légales' + => 'Legal notices', +]; + +/* +// OBSOLÈTES au 25/09/2026 à 16:53:47 - plus utilisées dans le code. +// À supprimer manuellement une fois confirmé qu'elles ne servent vraiment plus. +'Bienvenue à bord' => 'Welcome aboard', +*/ diff --git a/extraire_traductions.php b/extraire_traductions.php new file mode 100644 index 0000000..9637905 --- /dev/null +++ b/extraire_traductions.php @@ -0,0 +1,89 @@ +getFilename(), ".php")) continue; + if (str_contains($fichier->getPathname(), "/lang/")) continue; // ne pas s'auto-analyser + if ($fichier->getFilename() === basename(__FILE__)) continue; // idem, pour le script lui-même + $contenu = file_get_contents($fichier->getPathname()); + if (preg_match_all('/\bt\(\s*"((?:[^"\\\\]|\\\\.)*)"\s*\)/', $contenu, $matches)) { + foreach ($matches[1] as $chaine) { + $chaine = stripcslashes($chaine); + $chaines_trouvees[$chaine][] = $fichier->getPathname(); + } + } +} + +$traductions_en = file_exists($fichier_en) ? include $fichier_en : []; + +// --- Rapport console, comme avant --- +echo "=== Chaînes utilisées dans le code : " . count($chaines_trouvees) . " ===\n\n"; + +$manquantes = []; +foreach ($chaines_trouvees as $chaine => $fichiers) { + if (!array_key_exists($chaine, $traductions_en)) { + $manquantes[$chaine] = $fichiers[0]; + } +} +echo count($manquantes) . " nouvelle(s) chaîne(s) à traduire.\n"; + +$obsoletes = array_diff(array_keys($traductions_en), array_keys($chaines_trouvees)); +echo count($obsoletes) . " entrée(s) obsolète(s), déplacée(s) en commentaire.\n\n"; + +// --- Régénération de lang/en.php --- + +// Sauvegarde de précaution avant d'écraser : +if (file_exists($fichier_en)) { + copy($fichier_en, "$fichier_en.bak"); +} + +// Fusion : traductions existantes conservées pour les chaînes encore utilisées, +// nouvelles chaînes ajoutées avec une valeur vide : +$nouveau_tableau = []; +foreach ($chaines_trouvees as $chaine => $fichiers) { + $nouveau_tableau[$chaine] = $traductions_en[$chaine] ?? ""; +} + +$contenu = " $valeur) { + $contenu .= " " . var_export($cle, true) . " => " . var_export($valeur, true) . ",\n"; +} +$contenu .= "];\n"; + +if (!empty($obsoletes)) { + $contenu .= "\n/*\n"; + $contenu .= "// OBSOLÈTES au " . date("d/m/Y à H:i:s") . " - plus utilisées dans le code.\n"; + $contenu .= "// À supprimer manuellement une fois confirmé qu'elles ne servent vraiment plus.\n"; + foreach ($obsoletes as $chaine) { + $contenu .= var_export($chaine, true) . " => " . var_export($traductions_en[$chaine], true) . ",\n"; + } + $contenu .= "*/\n"; +} + +file_put_contents($fichier_en, $contenu); +echo "Fichier régénéré : $fichier_en\n"; +echo "(sauvegarde de l'ancienne version : $fichier_en.bak)\n"; diff --git a/html/.htaccess b/html/.htaccess new file mode 100644 index 0000000..2aafef8 --- /dev/null +++ b/html/.htaccess @@ -0,0 +1,2 @@ +# Activation du HSTS : +#Header set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" env=HTTPS diff --git a/html/administration.php b/html/administration.php new file mode 100644 index 0000000..0a4db70 --- /dev/null +++ b/html/administration.php @@ -0,0 +1,461 @@ +'.$bateaux[$i]['nb_elements'].' : ID = '.$donnees['ID'].'

'; + } + Liberation_jeu_de_resultat_bdd($reponse); + } + + //------------------------------------------------------------------- + // Boucle sur tous les bateaux pour traiter les entrées redondantes: + $nb_total_lignes_supprimees = 0; + for ($i = 0; $i < $nb_bateaux ; $i ++) + { + // Boucle sur tous les éléments : + for ($j = 0; $j < $bateaux[$i]['nb_elements']; $j ++) + { + $nb_redondants = 0; + $val_1 = -1; + $val_2 = 0; + $id_2 = 0; + $requete = 'SELECT Cle_primaire, Date, Valeur FROM '.$nom_table.' WHERE ID_Bateau=? AND ID=? ORDER BY Date '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateaux[$i]['ID_Bateau']), + array('i', $bateaux[$i][$j])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + // Recherche des conditions de redondance : + if (($val_1 == $val_2) AND ($val_2 == $donnees['Valeur'])) // Si la valeur actuelle est égale à la précédente et à celle encore avant : + { + $redondants[$nb_redondants ++] = $id_2; // ... on mémorise l'entrée intermédiaire (N-1) + $nb_total_lignes_supprimees ++; + if ($nb_total_lignes_supprimees >= $max_lignes_traitees) break; + } + + $val_1 = $val_2; + $val_2 = $donnees['Valeur']; + $id_2 = $donnees['Cle_primaire']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + + // Suppression des enregistrements redondants : + for ($k = 0; $k < $nb_redondants; $k ++) + { + // Création d'une chaine avec les différentes clés à supprimer afin de réduire le nombre de requêtes DELETE (impact sur temps de traitement d'environ / 50 avec la valeur de 100) : + $max_l = 100; + $chaine_cles_primaires = '(Cle_primaire='.$redondants[$k ++].' '; + if ($k < ($nb_redondants - 1)) + { + for ($l = 1; $l < $max_l; $l ++) + { + $chaine_cles_primaires .= 'OR Cle_primaire='.$redondants[$k].' '; + if (($k >= ($nb_redondants - 1)) OR ($l >= ($max_l - 1))) break; + $k ++; + } + } + $chaine_cles_primaires .= ')'; + + $requete = 'DELETE FROM '.$nom_table.' WHERE ID_Bateau='.$bateaux[$i]['ID_Bateau'].' AND '.$chaine_cles_primaires.' '; +// echo 'Requête = ['.$requete.']
'; + Requete_bdd($requete, __FILE__, __LINE__); // Pas de requête préparée pour accélérer le traitement... + } + if ($nb_total_lignes_supprimees >= $max_lignes_traitees) break; + } + if ($nb_total_lignes_supprimees >= $max_lignes_traitees) break; + } + + // Recherche de la taille de la table après traitement : + $requete = 'SELECT COUNT(*) AS Nb FROM '.$nom_table.' '; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $taille_table_apres_traitement = $donnees['Nb']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + // Calculate script execution time + $execution_time = number_format((microtime(true) - $start_time), 1, ".", " "); + + + + $tables[$x]['Taille_avant_traitement'] = $taille_table_avant_traitement; + $tables[$x]['Nb_total_lignes_supprimees'] = $nb_total_lignes_supprimees; + $tables[$x]['Execution_time'] = $execution_time; + $tables[$x]['Taille_apres_traitement'] = $taille_table_apres_traitement; + + + } + + + + break; + } + + //**************************************************************************************************************************** + case "Questionnaires": + { + switch($_SESSION['Administration']['questionnaire']) + { + default: + { + $message_erreur .= "Le questionnaire ".$_SESSION['Administration']['questionnaire']." est inconnu. Le questionnaire en cours est repassé à sa valeur par défaut."; + $_SESSION['Administration']['questionnaire'] = "Nautic2021"; + } + case "Nautic2021" : + { + $table_questionnaire = "TB_Nautic2021"; + + break; + } + } + + // Nombre de réponses : + $requete = 'SELECT COUNT(*) AS Nb FROM '.$table_questionnaire.' WHERE Validite=1'; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $reponses_questionnaire['Nb'] = $donnees['Nb']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + + // Dernier enregistrement : + $requete = 'SELECT DATE_FORMAT(Date_creation,"%d/%m/%Y à %H:%i:%s") as Date_creation FROM '.$table_questionnaire.' WHERE Validite=1 ORDER BY Date_creation DESC LIMIT 1'; +// echo 'Requête = '.$requete.'
'; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $reponses_questionnaire['Date_creation'] = $donnees['Date_creation']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + // Nombre d'enregistrements par jour : + $nb_jours = 0; + $requete = 'SELECT COUNT(*) as Nb_jours, DATE_FORMAT(Date_creation, "%d-%m-%Y") as Date_creations FROM '.$table_questionnaire.' WHERE Validite=1 GROUP BY DATE_FORMAT(Date_creation, "%Y-%m-%d")'; +// echo 'Requête = '.$requete.'
'; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $reponses_questionnaire['Creations_par_jour'][$nb_jours ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + + + break; + } + + + + } + + Fermeture_bdd(); // Déconnexion de MySQL + +//************************************************************************************************************************************ +// Affichage +//************************************************************************************************************************************ + + + //******************************************************************************************************************************** + // Affichage principal : + echo '
'; + + //========================================================================================= + // Entête : + Entete_page($message_erreur, $message_information); + + switch ($_SESSION['Administration']['page']) + { + //************************************************************************************************************************ + case "Accueil": + { + echo '
'; + + echo '

Administration

'; + + echo '

Accueil

'; + echo '

Attention : toute la partie Administration n\'est disponible qu\'en français.

'; + + echo '

ShipMembers et Bateaux

'; + echo '
'; + echo 'ShipMembers'; + echo 'Gestion des bateaux'; + echo '
'; + + echo '

Site web

'; + echo '
'; +// echo 'Commandes'; + echo 'Faq'; + echo 'Actualités'; + echo 'Produits'; + echo 'Galerie photos'; + echo 'Videos'; + echo 'Devis'; +// echo 'Questionnaires'; + echo 'Gestion des textes'; + echo '
'; + + echo '

Technique

'; + echo ''; + + echo '
'; + echo 'Retour au menu ShipMember'; + echo '
'; + + echo '
'; + + break; + } + + //************************************************************************************************************************ + case "Purge_bdd": + { + echo '
'; + + echo '

Administration

'; + + echo '

Purge de la base de données

'; + + for ($x = 0; $x < $nb_tables; $x ++) + { + echo '

'.$tables[$x]['Nom'].'

'; + echo '

Taille de la table AVANT traitement = '.number_format($tables[$x]['Taille_avant_traitement'], 0, ".", " ").' lignes

'; + echo '

Le nombre total de lignes supprimées est de '.number_format($tables[$x]['Nb_total_lignes_supprimees'], 0, ".", " ").' (maxi = '.number_format($max_lignes_traitees, 0, ".", " ").') en '.$tables[$x]['Execution_time'].' secondes

'; + echo '

Taille de la table APRES traitement = '.number_format($tables[$x]['Taille_apres_traitement'], 0, ".", " ").' lignes

'; + } + + echo '
'; + echo 'Retour à l\'accueil'; + echo 'Relancer la purge de la BDD'; + echo '
'; + + echo '
'; + + break; + } + + //**************************************************************************************************************************** + case "Questionnaires": + { + echo '
'; + + echo '

Administration

'; + + echo '

Questionnaire : '.$_SESSION['Administration']['questionnaire'].'

'; + + // Nb de fiche réponse : + echo '
+
Le nombre total de questionnaires enregistrés est :
+
'.$reponses_questionnaire['Nb'].'
+
'; + + // Date dernière réponse : + echo '
+
La date du dernier formulaire rempli est :
+
'.$reponses_questionnaire['Date_creation'].'
+
'; + + // Nb créations par jour : + echo '
'; + foreach($reponses_questionnaire['Creations_par_jour'] as $key => $creations) + { + echo '
Le nombre de formulaires saisis le '.$creations['Date_creations'].' est de :
+
'.$creations['Nb_jours'].'
'; + } + echo '
'; + + + + + + echo '
'; + echo 'Retour à l\'accueil'; + echo '
'; + + echo '
'; + + break; + } + + } + + echo '
'; + +Pied_de_page(); diff --git a/html/bateaux.php b/html/bateaux.php new file mode 100644 index 0000000..1f23cb3 --- /dev/null +++ b/html/bateaux.php @@ -0,0 +1,3684 @@ +'.$_SESSION['Bateaux']['bateau']['Nom'].' a été dévalidé dans la base de données.'; + + $_SESSION['Bateaux']['page'] = "Accueil"; + } + + break; + } + } + + if ($_SESSION['Bateaux']['ancre'] == "") header('Location:bateaux.php'); // Permet de "vider" la barre d'URL des champs GET et donc de doubler le traitement en cas de raffraichissement de page... + else header('Location:bateaux.php#'.$_SESSION['Bateaux']['ancre'].''); + } + + + // Variables POST : + if (isset($_POST['date_version'])){ + $_SESSION['Bateaux']['date_version'] = $_POST['date_version']; + } + + //--------------------------------------------------------------------------- + // Création/Modification Bateau : + if (isset($_POST['validation_creation_bateau']) OR isset($_POST['validation_modification_bateau'])) + { + // Vérification si un changement de carte a été demandé : + $flag_new_carte = false; + $new_id_carte = isset($_POST['ID_Carte']) ? addslashes ($_POST['ID_Carte']) : 0; + if ($_SESSION['Bateaux']['bateau']['ID_Carte'] != $new_id_carte) $flag_new_carte = true; + +//echo "Flag nouvelle carte = ".($flag_new_carte ? "Oui" : "Non")."
"; + + // Mémorisation des valeurs saisies pour éviter de les perdre en cas d'erreur rendant la création impossible : + $_SESSION['Bateaux']['bateau']['Nom'] = isset($_POST['Nom']) ? addslashes ($_POST['Nom']) : ""; + $_SESSION['Bateaux']['bateau']['ID_Flotte'] = isset($_POST['ID_Flotte']) ? addslashes ($_POST['ID_Flotte']) : 0; + $_SESSION['Bateaux']['bateau']['ID_Carte'] = isset($_POST['ID_Carte']) ? addslashes ($_POST['ID_Carte']) : 0; + $_SESSION['Bateaux']['bateau']['Date_mes'] = isset($_POST['Date_mes']) ? addslashes ($_POST['Date_mes']) : date("Y-m-d"); + $_SESSION['Bateaux']['bateau']['Date_carte'] = isset($_POST['Date_carte']) ? addslashes ($_POST['Date_carte']) : date("Y-m-d"); + $_SESSION['Bateaux']['bateau']['Commentaires'] = isset($_POST['Commentaires']) ? addslashes ($_POST['Commentaires']) : ""; + + if (isset($_POST['validation_creation_bateau'])) + { + // Création du bateau : + $requete = 'INSERT INTO TB_Bateaux (Nom, ID_Flotte, ID_Carte, Date_mes, Date_carte, Date_derniere_maj, Commentaires) VALUES (?, ?, ?, ?, ?, ?, ?)'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['Bateaux']['bateau']['Nom']), + array('i', $_SESSION['Bateaux']['bateau']['ID_Flotte']), + array('i', $_SESSION['Bateaux']['bateau']['ID_Carte']), + array('s', $_SESSION['Bateaux']['bateau']['Date_mes']), + array('s', $_SESSION['Bateaux']['bateau']['Date_carte']), + array('s', $_SESSION['Bateaux']['bateau']['Date_derniere_maj']), + array('s', $_SESSION['Bateaux']['bateau']['Commentaires'])), + __FILE__, __LINE__); + + // Récup de la clé primaire de l'enregistrement créé : + $_SESSION['Bateaux']['bateau']['Cle_primaire'] = Recuperation_id_cree_bdd(); + + // Retour à la liste si la création s'est bien passée : + $_SESSION['Bateaux']['page'] = "Accueil"; + } + else if (isset($_POST['validation_modification_bateau'])) + { + // Mise à jour du bateau : + $requete = 'UPDATE TB_Bateaux SET Nom=?, ID_Flotte=?, ID_Carte=?, Date_mes=?, Date_carte=?, Commentaires=? WHERE Cle_primaire=?'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['Bateaux']['bateau']['Nom']), + array('i', $_SESSION['Bateaux']['bateau']['ID_Flotte']), + array('i', $_SESSION['Bateaux']['bateau']['ID_Carte']), + array('s', $_SESSION['Bateaux']['bateau']['Date_mes']), + array('s', $_SESSION['Bateaux']['bateau']['Date_carte']), + array('s', $_SESSION['Bateaux']['bateau']['Commentaires']), + array('i', $_SESSION['Bateaux']['bateau']['Cle_primaire'])), + __FILE__, __LINE__); + + // Message d'information : + $message_information = 'Le bateau '.$_SESSION['Bateaux']['bateau']['Nom'].' vient d\'être modifié'; + + // Retour à la liste si la modification s'est bien passée : + $_SESSION['Bateaux']['page'] = "Accueil"; + } + + + // Recherche de l'adresse MAC de la carte ShipBase déclarée : + $requete = 'SELECT Adresse_mac FROM TB_Cartes WHERE Cle_primaire=?'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['Bateaux']['bateau']['ID_Carte'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $_SESSION['Bateaux']['bateau']['Adresse_mac'] = str_replace(":", "_", $donnees['Adresse_mac']); + } + + // Si changement de carte (ou nouveau bateau) : + if ($flag_new_carte) + { + // Vérification de l'existence du répertoire correspondant à cette adresse MAC sur le serveur, dans le répertoire "Bateaux" : + $flag_creation_repertoires = false; + if (repertoire_contient_repertoire(REPERTOIRE_BATEAUX, $_SESSION['Bateaux']['bateau']['Adresse_mac'])) // Le répertoire existe : + { + // Cas particulier du répertoire d'archives qui pouvait ne pas exister sur les premiers bateaux (permet de créer le fichier archive dans ce cas) : + if (!repertoire_contient_repertoire(REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'], 'archives')) mkdir(REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'/archives'); + + // Si le contenu des sous-répertoires est vide, on ne sauvegarde pas l'ancien bateau (cas standard) : + if (repertoire_est_vide(REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'/download') AND + repertoire_est_vide(REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'/upload') AND + repertoire_est_vide(REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'/archives')) + { + $message_information .= '
Le répertoire ['.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'] et ses trois sous-répertoires "download", "upload" et "archives" existaient déjà dans le répertoire "bateaux" et ils sont bien vides.'; + } + else // ... et son contenu n'est PAS vide : + { + $suffixe_repertoire_archive = '__SAUVEGARDE_'.date("Y-m-d_H-i-s"); + if (rename(REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'], REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'].$suffixe_repertoire_archive)) + { + $message_erreur .= 'Le répertoire ['.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'] n\'était pas vide ; il a donc été renommé en ['.REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'].$suffixe_repertoire_archive.']
'; + $flag_creation_repertoires = true; + } + else + { + $message_erreur .= 'Le répertoire ['.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'] dans "bateaux" existait et n\'était pas vide mais son renommage a échoué ! Il est conservé tel quel...
'; + } + } + } + else $flag_creation_repertoires = true; + + // Création du répertoire de communication pour cette adresse MAC : + if ($flag_creation_repertoires) + { + if (mkdir(REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'])) + { + mkdir(REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'/download'); + mkdir(REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'/upload'); + mkdir(REPERTOIRE_BATEAUX.'/'.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'/archives'); + $message_information .= '
Le répertoire ['.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'] et ses trois sous-répertoires "download", "upload" et "archives" viennent d\'être créés dans le répertoire "bateaux"'; + + } + else $message_erreur .= '!!! Le répertoire ['.$_SESSION['Bateaux']['bateau']['Adresse_mac'].'] n\'a pas pu être créé dans le répertoire "bateaux" !!!'; + } + } + } + + //--------------------------------------------------------------------------- + // Filtre du graphe : + if (isset($_POST['filtrer_graphe'])){ + $_SESSION['Bateaux']['graphe_date_debut'] = $_POST['date_debut']; + $_SESSION['Bateaux']['graphe_date_fin'] = $_POST['date_fin']; + } + + //--------------------------------------------------------------------------- + // Modifier la validité des droits + if (isset($_POST['validite_acces'])) { +// echo 'Validité = ON pour ID='.$_POST['ID'].'
'; + $requete = 'UPDATE TB_Lien_bateau_shipmember SET Validite_acces = 1 WHERE ID = '.$_POST['ID']; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + } + else if (!isset($_POST['validite_acces']) && isset($_POST['ID']) && !isset($_POST['supprimerAcces']) && !isset($_POST['modifierAcces'])){ +// echo 'Validité = OFF pour ID='.$_POST['ID'].'
'; + $requete = 'UPDATE TB_Lien_bateau_shipmember SET Validite_acces = 0 WHERE ID = '.$_POST['ID']; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + } + + //--------------------------------------------------------------------------- + // Supprimer l'accès + if (isset($_POST['supprimerAcces']) && isset($_POST['ID'])){ + $id = $_POST['ID']; + $requete = 'UPDATE TB_Lien_bateau_shipmember SET Validite = 0 WHERE ID = ? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $id)), + __FILE__, __LINE__); + } + + //--------------------------------------------------------------------------- + // Modifier l'accès + if (isset($_POST['modifierAcces']) && isset($_POST['ID'])){ + $id = $_POST['ID']; + $fin_validite = $_POST['fin_validite']." 23:59:59"; + $type_profil = $_POST['type_profil']; + $requete = 'UPDATE TB_Lien_bateau_shipmember SET Fin_validite = ? , ID_Type_acces_bateau_shipmember = ? WHERE ID = ? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $fin_validite), + array('i', $type_profil), + array('i', $id)), + __FILE__, __LINE__); + } + + + +//************************************************************************************************************************************ +// Traitement des données +//************************************************************************************************************************************ + + // Protection contre les accès directs... : + $flag_sortie = true; + do // Dummy loop : + { + if (!$_SESSION['acces_valide']) break; // Si on n'est pas identifié, on ne peut pas accéder quoi qu'il arrive... + + if ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_MINI_ACCES_ADMINISTATEUR) + { + $flag_sortie = false; // Si on est administrateur, on a toujours accès.... + break; + } + + // Recherche des droits d'accès à un bateau en particulier : + if ($_SESSION['Bateaux']['page'] == "Details_bateau") + { + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Validite_acces=1 AND ID_SHIPMEMBER=? AND ID_BATEAU=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['Cle_primaire']), + array('i', $_SESSION['Bateaux']['bateau']['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $flag_sortie = false; + break; + } + + Liberation_jeu_de_resultat_bdd($reponse); + } + if($flag_sortie && $_SESSION['Bateaux']['bateau']['Cle_primaire'] == 25){ + $flag_sortie = false; + } + } while (0); + + if ($flag_sortie) header('Location:shipmembers.php?action=navigation&destination=Login'); + + + switch ($_SESSION['Bateaux']['page']) + { + //**************************************************************************************************************************** + case "Accueil": + { + //-------------------------------------------------- + // Récupération des informations sur les bateaux : + $nb_bateaux = 0; + + switch($_SESSION['Bateaux']['tri_liste']) + { + case "Nom": { $tri_liste = " ORDER By Nom ".$_SESSION['Bateaux']['sens_tri_liste']; break; } + case "Flotte" : { $tri_liste = " ORDER By nom_flotte ".$_SESSION['Bateaux']['sens_tri_liste'].", Nom"; break; } + case "Carte": { $tri_liste = " ORDER By nom_carte ".$_SESSION['Bateaux']['sens_tri_liste']; break; } + case "Adresse_mac": { $tri_liste = " ORDER By adresse_carte ".$_SESSION['Bateaux']['sens_tri_liste']; break; } + case "Version": { $tri_liste = " ORDER By version ".$_SESSION['Bateaux']['sens_tri_liste'].", Nom"; break; } + case "Date_maj": { $tri_liste = " ORDER By Date_derniere_maj ".$_SESSION['Bateaux']['sens_tri_liste'].", Nom"; break; } + default : { $tri_liste = " ORDER By nom_flotte, Nom ".$_SESSION['Bateaux']['sens_tri_liste']; break; } + } + + $requete = 'SELECT TB_Bateaux.Cle_primaire AS Cle_primaire, '; + $requete .= ' TB_Bateaux.Nom AS Nom, '; + $requete .= ' (SELECT Nom FROM TB_Flottes WHERE Validite=1 AND Cle_primaire=TB_Bateaux.ID_Flotte) AS nom_flotte, '; + $requete .= ' (SELECT No_serie FROM TB_Cartes WHERE Validite=1 AND Cle_primaire=TB_Bateaux.ID_Carte) AS nom_carte, '; + $requete .= ' (SELECT Adresse_mac FROM TB_Cartes WHERE Validite=1 AND Cle_primaire=TB_Bateaux.ID_Carte) AS adresse_carte, '; + $requete .= ' (SELECT Valeur FROM TB_BATEAUX_Systeme WHERE Validite=1 AND ID_Bateau=TB_Bateaux.Cle_primaire AND Nom="Version_soft_no_package") AS version, '; + $requete .= ' TB_Bateaux.Date_derniere_maj AS Date_derniere_maj, '; + $requete .= ' TB_Bateaux.Commentaires AS Commentaires '; + $requete .= ' FROM `TB_Bateaux` '; + $requete .= ' WHERE Validite=1 '; + $requete .= $tri_liste; +// echo "Requête = [".$requete."]
"; + + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateaux[$nb_bateaux] = $donnees; + + // Mise en forme de certaines variables : + if ($bateaux[$nb_bateaux]['version'] == "") $bateaux[$nb_bateaux]['version'] = 'inconnue'; + if ($donnees['Date_derniere_maj'] < "2020-01-02") $bateaux[$nb_bateaux]['Date_derniere_maj'] = "Jamais"; + else $bateaux[$nb_bateaux]['Date_derniere_maj'] = Formatage_date($donnees['Date_derniere_maj']); + $bateaux[$nb_bateaux]['Commentaires'] = htmlspecialchars(stripcslashes($bateaux[$nb_bateaux]['Commentaires'])); + + $nb_bateaux ++; + } + Liberation_jeu_de_resultat_bdd($reponse); + + break; + } + + //**************************************************************************************************************************** + case "Details_bateau": + { + //-------------------------------------------------- + // Récupération des informations sur le bateau : + $nb_bateaux = 0; + + $requete = 'SELECT * FROM TB_Bateaux WHERE Cle_primaire=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['Bateaux']['bateau']['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateau = $donnees; + $sous_req = "SELECT Adresse_mac FROM TB_Cartes WHERE Validite = 1 AND Cle_primaire = ".$bateau['ID_Carte']; + $sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__); + $sous_don = Recherche_ligne_bdd($sous_rep); + + $bateau['Adresse_mac'] = $sous_don['Adresse_mac']; + Liberation_jeu_de_resultat_bdd($sous_rep); + + // Mise en forme de textes : + if ($donnees['Date_derniere_maj'] < "2020-01-02") $bateau['Date_derniere_maj'] = "".Recuperer_texte("bateau","details","derniere_connexion","jamais").""; + else { + $bateau['Date_derniere_maj'] = Formatage_date($donnees['Date_derniere_maj']); + $_SESSION['Bateaux']['derniere_maj'] = $donnees['Date_derniere_maj']; + } + $bateau['Commentaires'] = htmlspecialchars(stripcslashes($bateau['Commentaires'])); + } + Liberation_jeu_de_resultat_bdd($reponse); + + + // Recherche de la version en cours sur le bateau : + $bateau['version'] = "Version inconnue"; + $requete = 'SELECT Valeur FROM TB_BATEAUX_Systeme WHERE ID_Bateau=? AND Nom="Version_soft_no_package" AND Validite=1 '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['Bateaux']['bateau']['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateau['version'] = $donnees['Valeur']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + /* + for ($i = 0; $i < $_SESSION['acces']; $i++){ + if ($_SESSION['bateau_shipmember'][$i]['ID_Bateau'] == $bateau['Cle_primaire']){ + $acces = $_SESSION['bateau_shipmember'][$i]['Niveau_acces']; + break; + } + else $acces = 0; + } + if ($_SESSION['acces'] == 0) $acces = 0; + + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember_acces WHERE Validite=1 AND Niveau_acces='.$acces; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + $acces_profil = $donnees; + */ + + //--------------------------------------------- + // Recherche des droits d'accès au bateau : + //--------------------------------------------- + if ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_MINI_ACCES_ADMINISTATEUR) // Dans le cas des administrateurs, on accorde tous les droits, indépendamment des paramètres du bateau + { + $acces_profil['Creation_profils'] = 1; + $acces_profil['Devalidation_profils'] = 2; + $acces_profil['Consultation_donnees'] = 2; + $acces_profil['Modification_acces'] = 1; + } + else + { + // Valeurs par défaut : + $id_type_acces = 0; + $acces_profil['Creation_profils'] = 0; + $acces_profil['Devalidation_profils'] = 0; + $acces_profil['Consultation_donnees'] = 0; + $acces_profil['Modification_acces'] = 0; + + // Recherche de l'ID de l'accès le plus élevé pour ce bateau et ce shipmember : + $requete = 'SELECT ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Validite_acces=1 AND ID_Shipmember=? AND ID_Bateau=? AND Fin_validite>=? ORDER BY ID_Type_acces_bateau_shipmember DESC LIMIT 1'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['Cle_primaire']), + array('i', $_SESSION['Bateaux']['bateau']['Cle_primaire']), + array('s', date_format(date_create(), 'Y-m-d H:i:s'))), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $id_type_acces = $donnees['ID_Type_acces_bateau_shipmember']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + if ($_SESSION['Bateaux']['bateau']['Cle_primaire'] == 25 && $id_type_acces == 0){ + $id_type_acces = 4; + } + + // Recherche des caractérirtiques de l'accès le plus élevé trouvé : + if ($id_type_acces > 0) + { + $requete = 'SELECT * FROM TB_Types_acces_bateau_shipmember WHERE Validite=1 AND Cle_primaire=?'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $id_type_acces)), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $acces_profil = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + } + } + + + // Récupération des types d'accès possibles : + //$requete = 'SELECT Nom, Niveau_acces FROM TB_Lien_bateau_shipmember_acces WHERE Validite = 1 AND Niveau_acces < 99'; + $requete = 'SELECT * FROM TB_Types_acces_bateau_shipmember WHERE Validite=1 '; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $type_acces_nb = 0; + while($donnees = Recherche_ligne_bdd($reponse)){ + if ($_SESSION['langue'] == "EN") $donnees['Nom'] = $donnees['Nom_en']; + else $donnees['Nom'] = $donnees['Nom_fr']; + + $type_acces[$type_acces_nb++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + + // Génération d'un nouveau code d'acces : + if (isset($_POST['generer_code_acces'])){ + $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; + $charactersLength = strlen($characters); + $unique = false; + do { // Vérifier si le code n'est pas déjà utilisé + $code_acces = ''; + for ($i = 0; $i < 6; $i++) { + $code_acces .= $characters[random_int(0, $charactersLength - 1)]; + } + $req = 'SELECT Code FROM TB_Lien_bateau_shipmember WHERE Code="'.$code_acces.'"'; + $rep = Requete_bdd($req, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($rep); + if ($donnees == NULL) $unique = true; + } while($unique == false); + + if (isset($_POST['date_validite']) && (!empty($_POST['date_validite']))){ + $date = $_POST['date_validite']." 00:00:00"; + } + else $date = '9999-12-31 23:59:59'; + $requete = 'INSERT INTO TB_Lien_bateau_shipmember(ID_Bateau, Code, Fin_validite, Cree_par, ID_Type_acces_bateau_shipmember) VALUES (?,?,?,?,?)'; + $reponse = Requete_preparee_bdd($requete, array( + array('i', $bateau['Cle_primaire']), + array('s', $code_acces), + array('s', $date), + array('i', $_SESSION['shipmember']['Cle_primaire']), + array('i', $_POST['type_acces']) + ),__FILE__, __LINE__); + $no = Recuperation_id_cree_bdd(); + + if ( code_acces_pdf($code_acces, $no, $bateau['Adresse_mac'],"")== 0 ) Entete_page_html(); + + // Message d'information : + + // if (isset($_SESSION['pdf']['src']) && $_SESSION['pdf']['src'] != '') + // $message_information.= "Télécharger le code d'accès d' ici "; + // $_SESSION['pdf']['src'] =''; + + } + + + $nb_onglets = 0; + + //----------------------------------------------------------- + // Recherche des informations complémentaires sur le bateau : + switch($_SESSION['Bateaux']['type_details_bateau']) + { + //========================= + case "gerer_les_acces": + { + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND ID_Bateau='.$bateau['Cle_primaire'].' AND ID_Shipmember!=0 '; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $utilisateur_acces_nb = 0; + while ($donnees = Recherche_ligne_bdd($reponse)){ + // Récupérer le nom et le prénom du shipmember qui a accès : + $sous_req = ' SELECT Nom, Prenom, Email FROM TB_Shipmembers WHERE Validite=1 AND ID='.$donnees['ID_Shipmember'].''; + $sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__); + $sous_donnees = Recherche_ligne_bdd($sous_rep); + $donnees['sm_Nom'] = $sous_donnees['Nom']; + $donnees['sm_Prenom'] = $sous_donnees['Prenom']; + $donnees['sm_Email'] = $sous_donnees['Email']; + // Récupérer le nom et le prénom du shipmember qui a crée le lien : + $sous_req = ' SELECT Nom, Prenom FROM TB_Shipmembers WHERE Validite=1 AND ID='.$donnees['Cree_par'].''; + $sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__); + $sous_donnees = Recherche_ligne_bdd($sous_rep); + $donnees['cree_par_Nom'] = $sous_donnees['Nom']; + $donnees['cree_par_Prenom'] = $sous_donnees['Prenom']; + // Récupérer le niveau accès garantie à l'utilisateur : + //$sous_req = ' SELECT Nom FROM TB_Lien_bateau_shipmember_acces WHERE Validite=1 AND Niveau_acces='.$donnees['Niveau_acces'].''; + $sous_req = 'SELECT * FROM TB_Types_acces_bateau_shipmember WHERE Validite=1 AND Cle_primaire='.$donnees['ID_Type_acces_bateau_shipmember'].' '; + $sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__); + $sous_donnees = Recherche_ligne_bdd($sous_rep); + if ($_SESSION['langue'] == "EN") $donnees['Niveau_acces_nom'] = $sous_donnees['Nom_en']; + else $donnees['Niveau_acces_nom'] = $sous_donnees['Nom_fr']; + $utilisateur_acces[$utilisateur_acces_nb++] = $donnees; + } + + + break; + } + //========================= + case "TB_BATEAUX_Carte": + { + $timestamp_debut = hrtime(TRUE); // En ns + // Récupérer les positions du bateaux pour le maps (30 derniers jours) + $date = date_create(); + date_sub($date, date_interval_create_from_date_string(DATE_SEUIL_1.' days')); + + $date_debut_carte = date_format($date, 'Y-m-d H:00:00'); + + $data_map = []; + // $requete = 'SELECT DISTINCT Date FROM ( + // SELECT Date FROM TB_BATEAUX_Mesures_capteurs WHERE ID_Bateau = '.$_SESSION['Bateaux']['bateau']['Cle_primaire'].' AND ID = 7 AND ID_Variable = 64 AND Date > "'.$date_debut_carte.'" UNION ALL + // SELECT Date FROM TB_BATEAUX_Mesures_capteurs WHERE ID_Bateau = '.$_SESSION['Bateaux']['bateau']['Cle_primaire'].' AND ID = 8 AND ID_Variable = 64 AND Date > "'.$date_debut_carte.'" + // ) uni ORDER BY Date;'; + // echo "Requête = ".$requete."
"; // Temps de traitement = 1 470 ms pour 'Et Si... 2' + + // Recherche des coordonnées du début de carte : + // Latitude : + $requete = 'SELECT Date, Valeur FROM TB_BATEAUX_Mesures_capteurs WHERE ID_Bateau='.$_SESSION['Bateaux']['bateau']['Cle_primaire'].' AND ID=7 AND ID_Variable=64 AND Date<="'.$date_debut_carte.'" ORDER BY Date LIMIT 1'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + if ($donnees == NULL) // S'il n'y a aucune latitude AVANT le début de la carte, on cherche la première APRES la date de début : + { + $requete = 'SELECT Date, Valeur FROM TB_BATEAUX_Mesures_capteurs WHERE ID_Bateau='.$_SESSION['Bateaux']['bateau']['Cle_primaire'].' AND ID=7 AND ID_Variable=64 AND Date>"'.$date_debut_carte.'" ORDER BY Date LIMIT 1'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + } + else{ + + } + $data_map[0]['latitude'] = ($donnees != NULL) ? $donnees['Valeur'] : 45.735237; // NB : s'il n'y aucune valeur ni AVANT ni APRES, c'est qu'il n'y a pas de courbe à tracer... + + // Longitude : + $requete = 'SELECT Date, Valeur FROM TB_BATEAUX_Mesures_capteurs WHERE ID_Bateau='.$_SESSION['Bateaux']['bateau']['Cle_primaire'].' AND ID=8 AND ID_Variable=64 AND Date<="'.$date_debut_carte.'" ORDER BY Date LIMIT 1'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + if ($donnees == NULL) // S'il n'y a aucune longitude AVANT le début de la carte, on cherche la première APRES la date de début : + { + $requete = 'SELECT Date, Valeur FROM TB_BATEAUX_Mesures_capteurs WHERE ID_Bateau='.$_SESSION['Bateaux']['bateau']['Cle_primaire'].' AND ID=8 AND ID_Variable=64 AND Date>"'.$date_debut_carte.'" ORDER BY Date LIMIT 1'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + } + $data_map[0]['longitude'] = ($donnees != NULL) ? $donnees['Valeur'] : 4.804827; + $data_map[0]['date'] = $date_debut_carte; + $nb_data = 1; + + // Requête de tous les points sur la période : + $requete = 'SELECT Date, ID, Valeur FROM TB_BATEAUX_Mesures_capteurs WHERE ID_Bateau='.$_SESSION['Bateaux']['bateau']['Cle_primaire'].' AND (ID=7 OR ID=8) AND ID_Variable=64 AND Date>"'.$date_debut_carte.'" ORDER BY Date'; + // echo "Requête = ".$requete."
"; // Temps de traitement = 7.9ms pour Et Si... 2 + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + while($donnees = Recherche_ligne_bdd($reponse)) + { + $date_point = Formatage_date($donnees['Date']).' [UTC]'; + $date_point_sans_formatage = $donnees['Date']; + $jour = substr($donnees['Date'], 8, 2); + + if ($date_point == $data_map[$nb_data - 1]['date']) // Si on est sur la même date que la data précédente, on ne créée pas de nouveau point mais on ajoute juste la LAT ou LON sur le point précédent : + { + if ($donnees['ID'] == 7) + { + $data_map[$nb_data - 1]['latitude'] = $donnees['Valeur']; + $data_map[$nb_data - 1]['latitude_dms'] = Conversion_DECtoDMS("LAT", $donnees['Valeur']); + } + else + { + $data_map[$nb_data - 1]['longitude'] = $donnees['Valeur']; + $data_map[$nb_data - 1]['longitude_dms'] = Conversion_DECtoDMS("LON", $donnees['Valeur']); + } + } + else // Si on est sur une date différente de la dat précédente, on créée un nouveau point : + { + $data_map[$nb_data]['date'] = $date_point; + $data_map[$nb_data]['raw_date'] = $date_point_sans_formatage; + + // Couleur unie : + $data_map[$nb_data]['couleur'] = '#004563'; + $data_map[$nb_data]['opacite'] = 0.8; + + // Couleur de tracé alternée (bleu clair / bleu foncé) les jours pairs et impairs : + // if (($jour % 2) == 0) $data_map[$nb_data]['couleur'] = '#75B9DA'; //'#00FF00'; + // else $data_map[$nb_data]['couleur'] = '#004563'; //'#FF0000'; + + // Couleur de tracé avec 10 couleurs tournantes : + /* + switch($jour % 10) + { + default : + case 0 : { $data_map[$nb_data]['couleur'] = '#00FF99'; $data_map[$nb_data]['opacite'] = 1.0; break; } // Vert d'eau + case 1 : { $data_map[$nb_data]['couleur'] = '#FFC000'; $data_map[$nb_data]['opacite'] = 0.8; break; } // Orange + case 2 : { $data_map[$nb_data]['couleur'] = '#004563'; $data_map[$nb_data]['opacite'] = 0.8; break; } // Bleu Koriolan foncé + case 3 : { $data_map[$nb_data]['couleur'] = '#990099'; $data_map[$nb_data]['opacite'] = 0.8; break; } // Violet + case 4 : { $data_map[$nb_data]['couleur'] = '#00B050'; $data_map[$nb_data]['opacite'] = 0.6; break; } // Vert + case 5 : { $data_map[$nb_data]['couleur'] = '#FF0000'; $data_map[$nb_data]['opacite'] = 0.4; break; } // Rouge + case 6 : { $data_map[$nb_data]['couleur'] = '#FFFF00'; $data_map[$nb_data]['opacite'] = 0.8; break; } // Jaune + case 7 : { $data_map[$nb_data]['couleur'] = '#FF7DFF'; $data_map[$nb_data]['opacite'] = 0.9; break; } // Fushia + case 8 : { $data_map[$nb_data]['couleur'] = '#00B0F0'; $data_map[$nb_data]['opacite'] = 0.6; break; } // Bleu roi + case 9 : { $data_map[$nb_data]['couleur'] = '#996633'; $data_map[$nb_data]['opacite'] = 0.5; break; } // Marron + } + */ + + if ($donnees['ID'] == 7) + { + $data_map[$nb_data]['latitude'] = $donnees['Valeur']; + $data_map[$nb_data]['longitude'] = $data_map[$nb_data-1]['longitude']; // Dans le doute, on met à jour la LON avec la dernière valeur connue + } + else + { + $data_map[$nb_data]['longitude'] = $donnees['Valeur']; + $data_map[$nb_data]['latitude'] = $data_map[$nb_data-1]['latitude']; // Dans le doute, on met à jour la LAT avec la dernière valeur connue + } + + $data_map[$nb_data]['latitude_dms'] = Conversion_DECtoDMS("LAT", $data_map[$nb_data]['latitude']); + $data_map[$nb_data]['longitude_dms'] = Conversion_DECtoDMS("LON", $data_map[$nb_data]['longitude']); + + $nb_data ++; + } + } + + // Batteries du bateau + $requete = 'SELECT Nom, Tension_nominale, Soc FROM TB_BATEAUX_Batteries WHERE ID_Bateau=? AND Validite=1'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateau['Cle_primaire'])), + __FILE__, __LINE__); + $nb_batteries = 0; + while($donnees = Recherche_ligne_bdd($reponse)){ + $batteries[$nb_batteries++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + // Rservoirs du bateau + $nb_familles = 0; + // Recherche des onglets configurés sur le bateau : + $requete = 'SELECT Cle_primaire, Nom FROM TB_BATEAUX_Familles_reservoirs WHERE ID_Bateau=? AND Validite=1 ORDER BY Priorite_affichage ASC '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateau['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + // Recherche du nombre de réservoirs affectés à cette famille : + $sous_requete = 'SELECT COUNT(*) as Total FROM TB_BATEAUX_Reservoirs WHERE ID_Bateau=? AND Validite=1 AND ID_Famille_reservoirs=? '; + $sous_reponse = Requete_preparee_bdd($sous_requete, + array( + array('i', $bateau['Cle_primaire']), + array('i', $donnees['Cle_primaire'])), + __FILE__, __LINE__); + $sous_donnees = Recherche_ligne_bdd($sous_reponse); + + if ($sous_donnees['Total'] > 0) { + $bateau['familles'][$nb_familles] = $donnees; // Ajout de la famille au tableau des familles + + // Recherche des réservoirs appartenant à la famille en cours : + $reservoirs_requete = 'SELECT * FROM TB_BATEAUX_Reservoirs '; + $reservoirs_requete .= 'WHERE ID_Bateau=? AND Validite=1 AND ID_Famille_reservoirs=? ORDER BY ABS(Priorite_affichage_accueil) ASC'; + $reservoirs_reponse = Requete_preparee_bdd($reservoirs_requete, + array( + array('i', $bateau['Cle_primaire']), + array('i', $donnees['Cle_primaire'])), + __FILE__, __LINE__); + + while ($reservoir = Recherche_ligne_bdd($reservoirs_reponse)) { + $bateau['familles'][$nb_familles]['reservoirs'][] = $reservoir; // Ajout du réservoir au tableau de réservoirs de la famille + } + + Liberation_jeu_de_resultat_bdd($reservoirs_reponse); + + $nb_familles++; + } + } + Liberation_jeu_de_resultat_bdd($reponse); + + + + $nb_onglets = 0; + $timestamp_fin = hrtime(TRUE); // En ns + //echo "Temps exécution = ".number_format(($timestamp_fin - $timestamp_debut)/(1000 * 1000), 1, ".", " ")." ms et nb points = ".$nb_data."
"; + break; + } + //========================= + case "TB_BATEAUX_Systeme": + { + if (isset($_SESSION['Bateaux']['date_version']) && $_SESSION['Bateaux']['date_version'] != "") $date_ver = str_replace("T"," ",$_SESSION['Bateaux']['date_version']).":00"; + + if (isset($_SESSION['Bateaux']['date_version']) && $_SESSION['Bateaux']['date_version'] != "" && $_SESSION['Bateaux']['date_version'] != $_SESSION['Bateaux']['derniere_maj']){ + $requete = 'SELECT * FROM '.$_SESSION['Bateaux']['type_details_bateau'].'_archive WHERE ID_Bateau=? AND SUBSTR(date_maj, 1, 13) = (SELECT SUBSTR(date_maj, 1, 13) from '.$_SESSION['Bateaux']['type_details_bateau'].'_archive WHERE SUBSTR(date_maj, 1, 13) < SUBSTR("'.$date_ver.'", 1, 13) ORDER BY date_maj DESC limit 1) ORDER BY Nom ASC'; + } + + else { + $requete = 'SELECT * FROM '.$_SESSION['Bateaux']['type_details_bateau'].' WHERE ID_Bateau=? AND Validite=1 ORDER BY Nom ASC'; + } + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateau['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateau['details_bateau'][''.$donnees['Nom'].'']['Valeur'] = $donnees['Valeur']; + if (isset($donnees['Description'])) $bateau['details_bateau'][''.$donnees['Nom'].'']['Description'] = $donnees['Description']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + + // Mise en forme de certains champs et valeurs par défaut lorsqu'aucune donnée n'est encore disponible : + if(isset($bateau['details_bateau']['Version_soft_no_package']['Valeur'])) $bateau['version'] = $bateau['details_bateau']['Version_soft_no_package']['Valeur']; + elseif(isset($bateau['details_bateau']['Version_soft_package']['Valeur'])) $bateau['version'] = $bateau['details_bateau']['Version_soft_package']['Valeur']; + else $bateau['version'] = 'inconnue'; + + if (!isset($bateau['details_bateau']['Version_soft_modem']['Valeur'])) $bateau['details_bateau']['Version_soft_modem']['Valeur'] = 'inconnue'; + if (!isset($bateau['details_bateau']['No_iccid']['Valeur'])) $bateau['details_bateau']['No_iccid']['Valeur'] = 'inconnu'; + if (!isset($bateau['details_bateau']['No_imei']['Valeur'])) $bateau['details_bateau']['No_imei']['Valeur'] = 'inconnu'; + if (!isset($bateau['details_bateau']['No_imsi']['Valeur'])) $bateau['details_bateau']['No_imsi']['Valeur'] = 'inconnu'; + + + //------------------------------------- + // Recherche des cartes existantes à bord : + $nb_cartes = 0; + $requete=""; + //$requete = 'SELECT * FROM TB_BATEAUX_Cartes WHERE ID_Bateau=? AND Validite=1 AND Presence=1 ORDER BY Adresse_k_bus'; + if (isset($_SESSION['Bateaux']['date_version']) && $_SESSION['Bateaux']['date_version'] != ""){ + $requete = 'SELECT * FROM TB_BATEAUX_Cartes_archive WHERE ID_Bateau=? AND SUBSTR(date_maj, 1, 13) = (SELECT SUBSTR(date_maj, 1, 13) from TB_BATEAUX_Cartes_archive WHERE SUBSTR(date_maj, 1, 13) < substr("'.$date_ver.'",1 ,13) ORDER BY date_maj DESC limit 1) ORDER BY Adresse_k_bus'; + } + + else { + $requete = 'SELECT * FROM TB_BATEAUX_Cartes WHERE ID_Bateau=? AND Validite=1 ORDER BY Adresse_k_bus'; + } + //echo "Requête = [".$requete."]
"; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateau['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + // Mise en forme de certains champs : + switch($donnees['Type']) + { + //------------------------------- + case TYPE_CARTE_COMPAGNON: + { + $donnees['nom_type'] = "ShipBase"; + break; + } + + //------------------------------- + case TYPE_CARTE_SP812: + case TYPE_CARTE_SP8DC: + { + if ($donnees['Type'] == TYPE_CARTE_SP812) $donnees['nom_type'] = "ShipPower812"; + else $donnees['nom_type'] = "ShipPower8DC"; + + // Valeurs par défaut des circuits affectés à ce module : + for ($i = 0; $i < 8; $i++) $donnees['circuits'][$i]['Nom'] = "--- Non affecté ---"; + + // Recherche des circuits réellement affectés à ce module : + $sous_requete = 'SELECT * FROM TB_BATEAUX_Circuits WHERE ID_Bateau='.$bateau['Cle_primaire'].' AND No_carte='.$donnees['Adresse_k_bus'].' AND Validite=1 ORDER BY No_circuit_carte'; + //echo "Requête = [".$sous_requete."]
"; + $sous_reponse = Requete_bdd($sous_requete, __FILE__, __LINE__); + while ($sous_donnees = Recherche_ligne_bdd($sous_reponse)) + { + if ($sous_donnees['ID_Circuit_esclave'] >= 0) $donnees['circuits'][$sous_donnees['No_circuit_carte']]['Nom'] = ''.$sous_donnees['Nom'].''; + else $donnees['circuits'][$sous_donnees['No_circuit_carte']]['Nom'] = ''.$sous_donnees['Nom'].' [circuit renfort]'; + } + Liberation_jeu_de_resultat_bdd($sous_reponse); + + break; + } + + //------------------------------- + case TYPE_CARTE_SBS1224: + { + $donnees['nom_type'] = "ShipBS"; + break; + } + + //------------------------------- + case TYPE_CARTE_SP4AC: + { + $donnees['nom_type'] = "ShipPower4AC"; + + // Valeurs par défaut des circuits affectés à ce module : + for ($i = 0; $i < 4; $i++) $donnees['circuits'][$i]['Nom'] = "--- Non affecté ---"; + + // Recherche des circuits réellement affectés à ce module : + $sous_requete = 'SELECT * FROM TB_BATEAUX_Circuits WHERE ID_Bateau='.$bateau['Cle_primaire'].' AND No_carte='.$donnees['Adresse_k_bus'].' AND Validite=1 ORDER BY No_circuit_carte'; + //echo "Requête = [".$sous_requete."]
"; + $sous_reponse = Requete_bdd($sous_requete, __FILE__, __LINE__); + while ($sous_donnees = Recherche_ligne_bdd($sous_reponse)) + { + $donnees['circuits'][$sous_donnees['No_circuit_carte']]['Nom'] = ''.$sous_donnees['Nom'].''; + } + Liberation_jeu_de_resultat_bdd($sous_reponse); + break; + } + + //------------------------------- + default : { $donnees['nom_type'] = "Type inconnu..."; break; } + } + if ($donnees['Flag_resistance_terminaison'] == 1) $donnees['libelle_resistance_terminaison'] = "Oui"; + else $donnees['libelle_resistance_terminaison'] = "Non"; + + $cartes[$nb_cartes ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + break; + } + + //========================= + case "TB_BATEAUX_Capteurs": + { + if (isset($_SESSION['Bateaux']['date_version']) && $_SESSION['Bateaux']['date_version'] != "") $date_ver = str_replace("T"," ",$_SESSION['Bateaux']['date_version']).":00"; + + $nb_entrees = 0; + if (isset($_SESSION['Bateaux']['date_version']) && $_SESSION['Bateaux']['date_version'] != ""){ + $requete = 'SELECT * FROM '.$_SESSION['Bateaux']['type_details_bateau'].'_archive WHERE ID_Bateau=? AND SUBSTR(date_maj, 1, 13) = (SELECT SUBSTR(date_maj, 1, 13) from '.$_SESSION['Bateaux']['type_details_bateau'].'_archive WHERE SUBSTR(date_maj, 1, 13) < SUBSTR("'.$date_ver.'", 1, 13) ORDER BY date_maj DESC limit 1) ORDER BY Priorite_affichage_accueil ASC'; + } + else { + // Recherche des onglets configurés sur le bateau : + $requete = 'SELECT Cle_primaire, Nom FROM TB_BATEAUX_Familles_capteurs WHERE ID_Bateau=? AND Validite=1 ORDER BY Priorite_affichage ASC '; + + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateau['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + // Recherche du nombre de capteurs affectés à cette famille : + $sous_requete = 'SELECT COUNT(*) as Total FROM TB_BATEAUX_Capteurs WHERE ID_Bateau=? AND Validite=1 AND ID_Famille_capteurs=? '; + $sous_reponse = Requete_preparee_bdd($sous_requete, + array( + array('i', $bateau['Cle_primaire']), + array('i', $donnees['Cle_primaire'])), + __FILE__, __LINE__); + $sous_donnees = Recherche_ligne_bdd($sous_reponse); + + if ($sous_donnees['Total'] > 0) $bateau['onglets'][$nb_onglets ++] = $donnees; // On ne présente que les familles ayant au moins 1 capteur... + Liberation_jeu_de_resultat_bdd($sous_reponse); + } + Liberation_jeu_de_resultat_bdd($reponse); + // Affectation du premier onglet si aucun n'est sélectionné : + if ($nb_onglets > 0) + { + if ($_SESSION['Bateaux']['bateau']['ID_Famille'] == 0) $_SESSION['Bateaux']['bateau']['ID_Famille'] = $bateau['onglets'][0]['Cle_primaire']; + $filtre_famille = " ID_Famille_capteurs=".$_SESSION['Bateaux']['bateau']['ID_Famille']." "; + } + else $filtre_famille = " 1 "; + + // Recherche des éléments appartenant à l'onglet en cours : + $requete = 'SELECT * FROM TB_BATEAUX_Capteurs '; + $requete .= 'WHERE ID_Bateau=? AND Validite=1 AND '.$filtre_famille.' ORDER BY ABS(Priorite_affichage_accueil) ASC'; + } + + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateau['Cle_primaire'])), + __FILE__, __LINE__); + + // echo 'Requête = [ '.$requete.' ]
'; + + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateau['details_bateau'][$nb_entrees] = $donnees; + + // Recherche de l'unité du capteur : + $sous_requete = 'SELECT Unite FROM TB_BATEAUX_Variables WHERE ID_Bateau=? AND Validite=1 AND Cle_primaire=? '; + $sous_reponse = Requete_preparee_bdd($sous_requete, + array( + array('i', $bateau['Cle_primaire']), + array('i', $donnees['ID_Variable'])), + __FILE__, __LINE__); + $sous_donnees = Recherche_ligne_bdd($sous_reponse); + $bateau['details_bateau'][$nb_entrees]['Unite'] = $sous_donnees['Unite']; + Liberation_jeu_de_resultat_bdd($sous_reponse); + + $nb_entrees ++; + } + Liberation_jeu_de_resultat_bdd($reponse); + + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] != "Aucune") + { + // Préparation des paramètres spécifiques à chaque type (mais communs à tous les éléments de ce type) : + + $haxis_format = "'dd/MM'"; + $langue = "'".$_SESSION['langue']."'"; + $couleur_1 = "'rgb(117, 185, 218)'"; // Valeur par défaut (bleu Koriolan) + $couleur_2 = "'rgb(117, 185, 218)'"; // Valeur par défaut (bleu Koriolan) + $couleur_3 = "'rgb(117, 185, 218)'"; // Valeur par défaut (bleu Koriolan) + + + $titre_graphique = Recuperer_texte("bateau","details","capteurs","titre_graphe1"); + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Tous") $nom_table = "TB_BATEAUX_Mesures_capteurs"; + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese") $nom_table = "TB_BATEAUX_Archive_mesures_capteurs"; + $diviseur_unite = 1; + $variables = "SELECT Cle_primaire, Nom, Unite FROM TB_BATEAUX_Variables WHERE Type = ? AND ID_Bateau = ? ORDER BY Priorite_affichage"; + // $variables = "SELECT Cle_primaire, Nom, Unite FROM TB_BATEAUX_Variables WHERE Type = ? AND ID_Bateau = ? AND Priorite_affichage != 0 ORDER BY Priorite_affichage"; + $type_var = 3; + + + switch($_SESSION['Bateaux']['type_courbe_details_bateau']) + { + //=============== + case "Aucune": break; + + //=============== + default: $_SESSION['Bateaux']['type_courbe_details_bateau'] = "Synthese"; // Pas de break; + case "Synthese" : + { + $nb_jours_periode = 360; + $regroupement_donnees = 1; // * 60; // En secondes ATTENTION : Pas sûr car passé en ms dans la requête ci-desssous !!!! A Vérifier ! + + if ((isset($_SESSION['Bateaux']['graphe_date_debut']) && $_SESSION['Bateaux']['graphe_date_debut'] != '') || isset($_SESSION['Bateaux']['graphe_date_fin']) && $_SESSION['Bateaux']['graphe_date_fin'] != ''){ + if(isset($_SESSION['Bateaux']['graphe_date_debut']) && $_SESSION['Bateaux']['graphe_date_debut'] != '') $titre_graphique .= Recuperer_texte("bateau","details","all","titre_graphe5").str_replace("T"," ",$_SESSION['Bateaux']['graphe_date_debut']).":00"; + if(isset($_SESSION['Bateaux']['graphe_date_fin']) && $_SESSION['Bateaux']['graphe_date_fin'] != '') $titre_graphique .= Recuperer_texte("bateau","details","all","titre_graphe6").str_replace("T"," ",$_SESSION['Bateaux']['graphe_date_fin']).":00"; + $titre_graphique .= Recuperer_texte("bateau","details","all","titre_graphe"); + } + else $titre_graphique .= Recuperer_texte("bateau","details","capteurs","titre_graphe2").($nb_jours_periode).Recuperer_texte("bateau","details","capteurs","titre_graphe3"); + + $requete = ' SELECT (UNIX_TIMESTAMP(Date) * 1000) AS Date, '; // Le x1000 permet d'avoir directement un timestamp en ms (nécessaire pour la fonction Date de JS) + $requete .= ' Valeur_maxi AS Max, '; + $requete .= ' Valeur_mini AS Min, '; + $requete .= ' Valeur_moyenne AS Avg '; + $requete .= ' FROM '.$nom_table.' WHERE ID_Bateau=? AND ID=? AND ID_Variable=? AND Date>? AND Date<=? '; + $requete .= ' GROUP BY (Date DIV 1000000) ORDER BY Date '; // Le 'DIV 1000000' permet de passer de timestamp à des jours (https://dev.mysql.com/doc/refman/8.0/en/date-and-time-type-conversion.html ) + + $table = array(); + $table['cols'] = array( + array('label' => 'Date', 'type' => 'datetime'), + array('label' => 'Max', 'type' => 'number'), // Nb : le nom de chaque champs (comme 'Max') est visible à l'écran quand on balade la crosshair. + array('label' => 'Min', 'type' => 'number'), // ... Il vaut donc mieux leur donner un nom explicite, notamment sur ce graphique avec plusieurs courbes. + array('label' => 'Avg', 'type' => 'number') // ... A noter que la question de la traduction peut se poser... + ); + + $nom_val_max = "Max"; // Nom de la variable sur laquelle la valeur max de la courbe sera calculée + $nom_val_min = "Min"; // Nom de la variable sur laquelle la valeur min de la courbe sera calculée + + $couleur_1 = "'rgb(0, 69, 99)'"; + $couleur_2 = "'rgb(117,185,218)'"; + $couleur_3 = "'rgb(171, 215, 237)'"; + + break; + } + //=============== + case "Tous" : + { + $nb_jours_periode = DATE_SEUIL_1; + $regroupement_donnees = 1; // * 60; // En secondes ATTENTION : Pas sûr car passé en ms dans la requête ci-desssous !!!! A Vérifier ! + + $titre_graphique .= Recuperer_texte("bateau","details","capteurs","titre_graphe2").($nb_jours_periode).Recuperer_texte("bateau","details","capteurs","titre_graphe4"); + + $requete = ' SELECT (UNIX_TIMESTAMP(Date) * 1000) AS Date, '; // Le x1000 permet d'avoir directement un timestamp en ms (nécessaire pour la fonction Date de JS) + $requete .= ' Valeur AS Val '; + $requete .= ' FROM '.$nom_table.' WHERE ID_Bateau=? AND ID=? AND ID_Variable=? AND Date>? AND Date<=?'; + $requete .= ' GROUP BY (Date DIV '.$regroupement_donnees.') ORDER BY Date '; + + $table = array(); + $table['cols'] = array( + array('label' => 'Date', 'type' => 'datetime'), + array('label' => 'Val', 'type' => 'number'), + array('label' => 'Valeur_2', 'type' => 'number'), + array('label' => 'Valeur_3', 'type' => 'number') + ); + + $nom_val_max = "Val"; // Nom de la variable sur laquelle la valeur max de la courbe sera calculée + $nom_val_min = "Val"; // Nom de la variable sur laquelle la valeur min de la courbe sera calculée + + $couleur_1 = "'rgb(0, 69, 99)'"; + $couleur_2 = "'rgb(117,185,218)'"; + $couleur_3 = "'rgb(171, 215, 237)'"; + break; + } + } + // Préparation du tableau de valeurs : + $min = 999999; + $max = -999999; + $rows = array(); + + + + // Calcul des dates de début de filtrage des données du graphique : + $date = date_create(); + $date_fin = date_format($date, 'Y-m-d H:i:s'); + date_sub($date, date_interval_create_from_date_string(''.$nb_jours_periode.' days')); + $date_debut = date_format($date, 'Y-m-d H:i:s'); + + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese"){ + if(isset($_SESSION['Bateaux']['graphe_date_debut']) && $_SESSION['Bateaux']['graphe_date_debut'] != '') $date_debut = str_replace("T"," ",$_SESSION['Bateaux']['graphe_date_debut']).":00"; + if(isset($_SESSION['Bateaux']['graphe_date_fin']) && $_SESSION['Bateaux']['graphe_date_fin'] != '') $date_fin = str_replace("T"," ",$_SESSION['Bateaux']['graphe_date_fin']).":00"; + } + + // Récupération des datas : + + + // if ($_SESSION['Bateaux']['id_variable_details_bateau'] == 0){ + // $_SESSION['Bateaux']['id_variable_details_bateau'] = $variables[0]['Cle_primaire']; // Variable par default pour ne pas avoir un graphe vide + // } + + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateau['Cle_primaire']), + array('i', $_SESSION['Bateaux']['id_entree_details_bateau']), + array('i', $_SESSION['Bateaux']['id_variable_details_bateau']), + array('s', $date_debut), + array('s', $date_fin)), + __FILE__, __LINE__); + + while ($donnees = Recherche_ligne_bdd($reponse)) + { + // Préparation de la chaine de date selon format "Date(Year, Month, Day, Hours, Minutes, Seconds, Milliseconds)" : + $chaine_date = 'Date('.$donnees['Date'].')'; // On créée la chaine qui appellera la fonction Date avec le timestamp (soit une chaine du genre 'Date(124524415214225)') + $temp = array(); + $temp[] = array('v' => $chaine_date); + switch($_SESSION['Bateaux']['type_courbe_details_bateau']) + { + case "Synthese" : + { + $temp[] = array('v' => $donnees['Max']); + $temp[] = array('v' => $donnees['Min']); + $temp[] = array('v' => $donnees['Avg']); + break; + } + case "Tous" : + { + $temp[] = array('v' => $donnees['Val']); + + break; + } + } + $rows[] = array('c' => $temp); + + if ($donnees[''.$nom_val_max.''] != '' && $donnees[''.$nom_val_max.''] > $max) $max = $donnees[''.$nom_val_max.'']; + if ($donnees[''.$nom_val_min.''] != '' && $donnees[''.$nom_val_min.''] < $min) $min = $donnees[''.$nom_val_min.'']; + + } + + Liberation_jeu_de_resultat_bdd($reponse); + // Préparation des données : + // Création des faux points 0.1ms avant chaque nouveau enregistrement pour bien affiché les graphes + switch($_SESSION['Bateaux']['type_courbe_details_bateau']) + { + case "Synthese" : + { + $size = sizeof($rows); + for ($i = 1; $i < $size; $i++){ + $date = str_replace(')','',str_replace('Date(','',$rows[$i]['c']['0']['v']))-100; + $date = 'Date('.$date.')'; + + $temp_faux = array(); + $temp_faux[] = array('v' => $date); + $temp_faux[] = array('v' => $rows[$i-1]['c']['1']['v']); + $temp_faux[] = array('v' => $rows[$i-1]['c']['2']['v']); + $temp_faux[] = array('v' => $rows[$i-1]['c']['3']['v']); + $rows[] = array('c' => $temp_faux); + } + // if (sizeof($rows) > 0){ + // $temp_faux = array(); + // $temp_faux[] = array('v' => "Date(".time()."000)"); + // $temp_faux[] = array('v' => $rows[$i-1]['c']['1']['v']); + // $temp_faux[] = array('v' => $rows[$i-1]['c']['2']['v']); + // $temp_faux[] = array('v' => $rows[$i-1]['c']['3']['v']); + // $rows[] = array('c' => $temp_faux); + // } + + break; + } + case "Tous" : + { + $size = sizeof($rows); + for ($i = 1; $i < $size; $i++){ + $date = str_replace(')','',str_replace('Date(','',$rows[$i]['c']['0']['v']))-100; + $date = 'Date('.$date.')'; + + $temp_faux = array(); + $temp_faux[] = array('v' => $date); + $temp_faux[] = array('v' => $rows[$i-1]['c']['1']['v']); + + $rows[] = array('c' => $temp_faux); + } + // if (sizeof($rows) > 0){ + // $temp_faux = array(); + // $temp_faux[] = array('v' => "Date(".time()."000)"); + // $temp_faux[] = array('v' => $rows[$i-1]['c']['1']['v']); + + // $rows[] = array('c' => $temp_faux); + // } + break; + } + } + // Trier le tableau du data + function sortByDate_rows($a, $b) { + return str_replace(')','',str_replace('Date(','',$a['c']['0']['v'])) - str_replace(')','',str_replace('Date(','',$b['c']['0']['v'])); + } + usort($rows, 'sortByDate_rows'); + $table['rows'] = $rows; // Stockage de toutes les rows créées dans 'table' + $jsonTable = json_encode($table); // Mise au format JSON pour être lu par la fonction JS + + $nomgraphique = "'graphique_".$_SESSION['Bateaux']['id_entree_details_bateau']."'"; // Permet de passer à la fonction JS le nom du graphique (différent pour chaque capteur...) + + //=============================================================================================================================================== + // GRAPHIQUES : + //=============================================================================================================================================== + // Appels JavaScript pour générer le graphique : + ?> + + + 0) $bateau['onglets'][$nb_onglets ++] = $donnees; // On ne présente que les familles ayant au moins 1 circuit... + } + Liberation_jeu_de_resultat_bdd($reponse); + + // Affectation du premier onglet si aucun n'est sélectionné : + if ($nb_onglets > 0) + { + if ($_SESSION['Bateaux']['bateau']['ID_Famille'] == 0) $_SESSION['Bateaux']['bateau']['ID_Famille'] = $bateau['onglets'][0]['Cle_primaire']; + $filtre_famille = " ID_Famille_circuits=".$_SESSION['Bateaux']['bateau']['ID_Famille']." "; + } + else $filtre_famille = " 1 "; + + // Recherche des éléments appartenant à l'onglet en cours : + $requete = 'SELECT * FROM TB_BATEAUX_Circuits '; + $requete .= 'WHERE ID_Bateau=? AND Validite=1 AND '.$filtre_famille.' ORDER BY ABS(Priorite_affichage_accueil) ASC'; + + + break; + } + + //---------------------------------------- + case "TB_BATEAUX_Reservoirs": + { + // Recherche des onglets configurés sur le bateau : + $requete = 'SELECT Cle_primaire, Nom FROM TB_BATEAUX_Familles_reservoirs WHERE ID_Bateau=? AND Validite=1 ORDER BY Priorite_affichage ASC '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateau['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + // Recherche du nombre de réservoirs affectés à cette famille : + $sous_requete = 'SELECT COUNT(*) as Total FROM TB_BATEAUX_Reservoirs WHERE ID_Bateau=? AND Validite=1 AND ID_Famille_reservoirs=? '; + $sous_reponse = Requete_preparee_bdd($sous_requete, + array( + array('i', $bateau['Cle_primaire']), + array('i', $donnees['Cle_primaire'])), + __FILE__, __LINE__); + $sous_donnees = Recherche_ligne_bdd($sous_reponse); + + if ($sous_donnees['Total'] > 0) $bateau['onglets'][$nb_onglets ++] = $donnees; // On ne présente que les familles ayant au moins 1 réservoir... + } + Liberation_jeu_de_resultat_bdd($reponse); + // Affectation du premier onglet si aucun n'est sélectionné : + if ($nb_onglets > 0) + { + if ($_SESSION['Bateaux']['bateau']['ID_Famille'] == 0) $_SESSION['Bateaux']['bateau']['ID_Famille'] = $bateau['onglets'][0]['Cle_primaire']; + $filtre_famille = " ID_Famille_reservoirs=".$_SESSION['Bateaux']['bateau']['ID_Famille']." "; + } + else $filtre_famille = " 1 "; + + // Recherche des éléments appartenant à l'onglet en cours : + $requete = 'SELECT * FROM TB_BATEAUX_Reservoirs '; + $requete .= 'WHERE ID_Bateau=? AND Validite=1 AND '.$filtre_famille.' ORDER BY ABS(Priorite_affichage_accueil) ASC'; + + break; + } + + //---------------------------------------- + default : + { + $requete = 'SELECT * FROM '.$_SESSION['Bateaux']['type_details_bateau'].' WHERE ID_Bateau=? AND Validite=1 ORDER BY Priorite_affichage_accueil ASC'; + break; + } + } + // echo 'Requête = [ '.$requete.' ]
'; + + } + + // Exécution de la requête et récupération des résultats : + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateau['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateau['details_bateau'][$nb_entrees] = $donnees; + + switch($_SESSION['Bateaux']['type_details_bateau']) + { + //---------------------------------------- + case "TB_BATEAUX_Batteries": + { + // Capacité 1 : + if ($bateau['details_bateau'][$nb_entrees]['Capacite_1'] != "") + { + $capa = explode("/", $bateau['details_bateau'][$nb_entrees]['Capacite_1']); + $bateau['details_bateau'][$nb_entrees]['capacite_1'] = number_format($capa[0], 0, ".", " ")." Ah [C".number_format($capa[1], 0, ".", " ")."]"; + } + else $bateau['details_bateau'][$nb_entrees]['capacite_1'] = "".Recuperer_texte("bateau","details","batteries","capacite_1_non_renseignee").""; // Ce cas ne devrait jamais se produire ! + + // Capacité 2 : + if ($bateau['details_bateau'][$nb_entrees]['Capacite_2'] != "") + { + $capa = explode("/", $bateau['details_bateau'][$nb_entrees]['Capacite_2']); + $bateau['details_bateau'][$nb_entrees]['capacite_2'] = number_format($capa[0], 0, ".", " ")." Ah [C".number_format($capa[1], 0, ".", " ")."]"; + } + else $bateau['details_bateau'][$nb_entrees]['capacite_2'] = "".Recuperer_texte("bateau","details","batteries","capacite_2_non_renseignee").""; + + // Type : + switch($bateau['details_bateau'][$nb_entrees]['Type']) + { + case 0 : { $bateau['details_bateau'][$nb_entrees]['type'] = "".Recuperer_texte("bateau","details","batteries","non_defini").""; break; } + case 1 : { $bateau['details_bateau'][$nb_entrees]['type'] = Recuperer_texte("bateau","details","batteries","type_pb_acide_liquide"); break; } + case 2 : { $bateau['details_bateau'][$nb_entrees]['type'] = Recuperer_texte("bateau","details","batteries","type_pb_agm"); break; } + case 3 : { $bateau['details_bateau'][$nb_entrees]['type'] = Recuperer_texte("bateau","details","batteries","type_pb_gel"); break; } + case 4 : { $bateau['details_bateau'][$nb_entrees]['type'] = Recuperer_texte("bateau","details","batteries","type_pb_carbone"); break; } + case 10 : { $bateau['details_bateau'][$nb_entrees]['type'] = Recuperer_texte("bateau","details","batteries","type_lithium"); break; } + default : { $bateau['details_bateau'][$nb_entrees]['type'] = "".Recuperer_texte("bateau","details","batteries","type_inconnu").""; break; } + } + + break; + } + + //---------------------------------------- + case "TB_BATEAUX_Circuits": + case "TB_BATEAUX_Reservoirs": + default : + { + break; + } + } + + $nb_entrees ++; + + } + Liberation_jeu_de_resultat_bdd($reponse); + + + // Calculs des éléments de la courbe si une courbe est demandée : + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] != "Aucune") + { + // $start_time = microtime(true); + + // Préparation des paramètres spécifiques à chaque type (mais communs à tous les éléments de ce type) : + + $haxis_format = "'dd/MM/yy'"; + $langue = "'".$_SESSION['langue']."'"; + $couleur_1 = "'rgb(117, 185, 218)'"; // Valeur par défaut (bleu Koriolan) + $couleur_2 = "'rgb(117, 185, 218)'"; // Valeur par défaut (bleu Koriolan) + $couleur_3 = "'rgb(117, 185, 218)'"; // Valeur par défaut (bleu Koriolan) + + $regroupement_donnees = 1; // Valeur par défaut (en secondes) + + switch($_SESSION['Bateaux']['type_details_bateau']) + { + case "TB_BATEAUX_Batteries": + { + $titre_graphique = ""; + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Tous") $nom_table = "TB_BATEAUX_Mesures_batteries"; + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese") $nom_table = "TB_BATEAUX_Archive_mesures_batteries"; + $diviseur_unite = 1; + if ((version_compare($bateau['version'], '2.1.8') < 0) && ($bateau['Cle_primaire'] != 25)) + { + $variables = "SELECT Cle_primaire, Nom, Unite FROM TB_BATEAUX_Variables WHERE Type = ? AND ID_Bateau = ? ORDER BY Priorite_affichage"; + } + else $variables = "SELECT Cle_primaire, Nom, Unite FROM TB_BATEAUX_Variables WHERE Type=? AND ID_Bateau=? AND Priorite_affichage!=0 ORDER BY Priorite_affichage"; + + $type_var = 4; + break; + } + case "TB_BATEAUX_Circuits": + { + $titre_graphique = ""; + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Tous") $nom_table = "TB_BATEAUX_Mesures_circuits"; + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese") $nom_table = "TB_BATEAUX_Archive_mesures_circuits"; + $diviseur_unite = 1; + $variables = "SELECT Cle_primaire, Nom, Unite FROM TB_BATEAUX_Variables WHERE Type = ? AND ID_Bateau = ? ORDER BY Priorite_affichage"; + // $variables = "SELECT Cle_primaire, Nom, Unite FROM TB_BATEAUX_Variables WHERE Type = ? AND ID_Bateau = ? AND Priorite_affichage != 0 ORDER BY Priorite_affichage"; + $type_var = 1; + break; + } + case "TB_BATEAUX_Reservoirs": + { + // limite du nombre de valeurs affichées qui atteignait 82 000 sur 30 jours.... ! + $regroupement_donnees = 120; // En secondes + $titre_graphique = ""; + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Tous") $nom_table = "TB_BATEAUX_Mesures_reservoirs"; + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese") $nom_table = "TB_BATEAUX_Archive_mesures_reservoirs"; + $diviseur_unite = 1; + $variables = "SELECT Cle_primaire, Nom, Unite FROM TB_BATEAUX_Variables WHERE Type = ? AND ID_Bateau = ? ORDER BY Priorite_affichage"; + // $variables = "SELECT Cle_primaire, Nom, Unite FROM TB_BATEAUX_Variables WHERE Type = ? AND ID_Bateau = ? AND Priorite_affichage != 0 ORDER BY Priorite_affichage"; + $type_var = 3; + break; + } + } + + switch($_SESSION['Bateaux']['type_courbe_details_bateau']) + { + //=============== + case "Aucune": break; + + //=============== + default: $_SESSION['Bateaux']['type_courbe_details_bateau'] = "Synthese"; // Pas de break; + case "Synthese" : + { + $nb_jours_periode = 360; + + // $titre_graphique .= Recuperer_texte("bateau","details","rest","titre_graphe2").($nb_jours_periode).Recuperer_texte("bateau","details","rest","titre_graphe3"); + + if ((isset($_SESSION['Bateaux']['graphe_date_debut']) && $_SESSION['Bateaux']['graphe_date_debut'] != '') || isset($_SESSION['Bateaux']['graphe_date_fin']) && $_SESSION['Bateaux']['graphe_date_fin'] != ''){ + if(isset($_SESSION['Bateaux']['graphe_date_debut']) && $_SESSION['Bateaux']['graphe_date_debut'] != '') $titre_graphique .= Recuperer_texte("bateau","details","all","titre_graphe5").str_replace("T"," ",$_SESSION['Bateaux']['graphe_date_debut']).":00"; + if(isset($_SESSION['Bateaux']['graphe_date_fin']) && $_SESSION['Bateaux']['graphe_date_fin'] != '') $titre_graphique .= Recuperer_texte("bateau","details","all","titre_graphe6").str_replace("T"," ",$_SESSION['Bateaux']['graphe_date_fin']).":00"; + $titre_graphique .= Recuperer_texte("bateau","details","all","titre_graphe"); + } + else $titre_graphique .= Recuperer_texte("bateau","details","rest","titre_graphe2").($nb_jours_periode).Recuperer_texte("bateau","details","rest","titre_graphe3"); + + + $requete = ' SELECT (UNIX_TIMESTAMP(Date) * 1000) AS Date, '; // Le x1000 permet d'avoir directement un timestamp en ms (nécessaire pour la fonction Date de JS) + $requete .= ' Valeur_maxi AS Max, '; + $requete .= ' Valeur_mini AS Min, '; + $requete .= ' Valeur_moyenne AS Avg '; + $requete .= ' FROM '.$nom_table.' WHERE ID_Bateau=? AND ID=? AND ID_Variable=? AND Date>? AND Date<=? '; + $requete .= ' GROUP BY (Date DIV 1000000) ORDER BY Date '; // Le 'DIV 1000000' permet de passer de timestamp à des jours (https://dev.mysql.com/doc/refman/8.0/en/date-and-time-type-conversion.html ) + + $table = array(); + $table['cols'] = array( + array('label' => 'Date', 'type' => 'datetime'), + array('label' => 'Max', 'type' => 'number'), // Nb : le nom de chaque champs (comme 'Max') est visible à l'écran quand on balade la crosshair. + array('label' => 'Min', 'type' => 'number'), // ... Il vaut donc mieux leur donner un nom explicite, notamment sur ce graphique avec plusieurs courbes. + array('label' => 'Avg', 'type' => 'number') // ... A noter que la question de la traduction peut se poser... + ); + + $nom_val_max = "Max"; // Nom de la variable sur laquelle la valeur max de la courbe sera calculée + $nom_val_min = "Min"; // Nom de la variable sur laquelle la valeur min de la courbe sera calculée + + $couleur_1 = "'rgb(0, 69, 99)'"; + $couleur_2 = "'rgb(117,185,218)'"; + $couleur_3 = "'rgb(171, 215, 237)'"; + + break; + } + + //=============== + case "Tous" : + { + $nb_jours_periode = DATE_SEUIL_1; + + $titre_graphique .= Recuperer_texte("bateau","details","rest","titre_graphe2").($nb_jours_periode).Recuperer_texte("bateau","details","rest","titre_graphe4"); + + $requete = ' SELECT (UNIX_TIMESTAMP(Date) * 1000) AS Date, '; + $requete .= ' Valeur AS Val '; // Le x1000 permet d'avoir directement un timestamp en ms (nécessaire pour la fonction Date de JS) + $requete .= ' FROM '.$nom_table.' WHERE ID_Bateau=? AND ID=? AND ID_Variable=? AND Date>? AND Date<=?'; + $requete .= ' GROUP BY (Date DIV '.$regroupement_donnees.') ORDER BY Date '; + + $table = array(); + $table['cols'] = array( + array('label' => 'Date', 'type' => 'datetime'), + array('label' => 'Val', 'type' => 'number'), + array('label' => 'Valeur_2', 'type' => 'number'), + array('label' => 'Valeur_3', 'type' => 'number') + ); + + $nom_val_max = "Val"; // Nom de la variable sur laquelle la valeur max de la courbe sera calculée + $nom_val_min = "Val"; // Nom de la variable sur laquelle la valeur min de la courbe sera calculée + + $couleur_1 = "'rgb(0, 69, 99)'"; + $couleur_2 = "'rgb(117,185,218)'"; + $couleur_3 = "'rgb(171, 215, 237)'"; + break; + } + } + + + // Préparation du tableau de valeurs : + $min = 999999; + $max = -999999; + $rows = array(); + + + + // Calcul des dates de début de filtrage des données du graphique : + $date = date_create(); + $date_fin = date_format($date, 'Y-m-d H:i:s'); + date_sub($date, date_interval_create_from_date_string(''.$nb_jours_periode.' days')); + $date_debut = date_format($date, 'Y-m-d H:i:s'); + + if ($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese"){ + if(isset($_SESSION['Bateaux']['graphe_date_debut']) && $_SESSION['Bateaux']['graphe_date_debut'] != '') $date_debut = str_replace("T"," ",$_SESSION['Bateaux']['graphe_date_debut']).":00"; + if(isset($_SESSION['Bateaux']['graphe_date_fin']) && $_SESSION['Bateaux']['graphe_date_fin'] != '') $date_fin = str_replace("T"," ",$_SESSION['Bateaux']['graphe_date_fin']).":00"; + } + + // Récupération des noms de variables + $var_reponse = Requete_preparee_bdd($variables, + array( + array('i', $type_var), + array('i', $bateau['Cle_primaire']) + ), + __FILE__, __LINE__); + +//echo 'Requête : '.$variables.', type_var='.$type_var.' et clé_primaire du bateau = '.$bateau['Cle_primaire'].'
'; + $nb_var = 0; + $variables = NULL; + while ($donnees = Recherche_ligne_bdd($var_reponse)) + { +// echo $nb_var.' : '.$donnees['Nom'].'
'; + $variables[$nb_var ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($var_reponse); + + + // Récupération des datas : + if ($_SESSION['Bateaux']['id_variable_details_bateau'] == 0){ + $_SESSION['Bateaux']['id_variable_details_bateau'] = $variables[0]['Cle_primaire']; // Variable par default pour ne pas avoir un graphe vide + } + + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateau['Cle_primaire']), + array('i', $_SESSION['Bateaux']['id_entree_details_bateau']), + array('i', $_SESSION['Bateaux']['id_variable_details_bateau']), + array('s', $date_debut), + array('s', $date_fin)), + __FILE__, __LINE__); + $nb_val = 0; + while ($donnees = Recherche_ligne_bdd($reponse)) + { + // Préparation de la chaine de date selon format "Date(Year, Month, Day, Hours, Minutes, Seconds, Milliseconds)" : + $chaine_date = 'Date('.$donnees['Date'].')'; // On créée la chaine qui appellera la fonction Date avec le timestamp (soit une chaine du genre 'Date(124524415214225)') + $temp = array(); + $temp[] = array('v' => $chaine_date); + switch($_SESSION['Bateaux']['type_courbe_details_bateau']) + { + case "Synthese" : + { + $temp[] = array('v' => $donnees['Max']); + $temp[] = array('v' => $donnees['Min']); + $temp[] = array('v' => $donnees['Avg']); + break; + } + case "Tous" : + { + $temp[] = array('v' => $donnees['Val']); + break; + } + } + $rows[] = array('c' => $temp); + + if ($donnees[''.$nom_val_max.''] != '' && $donnees[''.$nom_val_max.''] > $max) $max = $donnees[''.$nom_val_max.'']; + if ($donnees[''.$nom_val_min.''] != '' && $donnees[''.$nom_val_min.''] < $min) $min = $donnees[''.$nom_val_min.'']; + $nb_val ++; + } + Liberation_jeu_de_resultat_bdd($reponse); + //$titre_graphique .= "
Nb de valeurs = ".$nb_val."
"; + // Préparation des données : + // Création des faux points 0.1ms avant chaque nouveau enregistrement pour bien affiché les graphes + switch($_SESSION['Bateaux']['type_courbe_details_bateau']) + { + case "Synthese" : + { + $size = sizeof($rows); + for ($i = 1; $i < $size; $i++){ + $date = str_replace(')','',str_replace('Date(','',$rows[$i]['c']['0']['v']))-100; + $date = 'Date('.$date.')'; + + $temp_faux = array(); + $temp_faux[] = array('v' => $date); + $temp_faux[] = array('v' => $rows[$i-1]['c']['1']['v']); + $temp_faux[] = array('v' => $rows[$i-1]['c']['2']['v']); + $temp_faux[] = array('v' => $rows[$i-1]['c']['3']['v']); + $rows[] = array('c' => $temp_faux); + } + // if (sizeof($rows) > 0){ + // $temp_faux = array(); + // $temp_faux[] = array('v' => "Date(".time()."000)"); + // $temp_faux[] = array('v' => $rows[$i-1]['c']['1']['v']); + // $temp_faux[] = array('v' => $rows[$i-1]['c']['2']['v']); + // $temp_faux[] = array('v' => $rows[$i-1]['c']['3']['v']); + // $rows[] = array('c' => $temp_faux); + // } + + break; + } + case "Tous" : + { + $size = sizeof($rows); + for ($i = 1; $i < $size; $i++){ + $date = str_replace(')','',str_replace('Date(','',$rows[$i]['c']['0']['v']))-100; + $date = 'Date('.$date.')'; + + $temp_faux = array(); + $temp_faux[] = array('v' => $date); + $temp_faux[] = array('v' => $rows[$i-1]['c']['1']['v']); + + $rows[] = array('c' => $temp_faux); + } + // if (sizeof($rows) > 0){ + // $temp_faux = array(); + // $temp_faux[] = array('v' => "Date(".time()."000)"); + // $temp_faux[] = array('v' => $rows[$i-1]['c']['1']['v']); + + // $rows[] = array('c' => $temp_faux); + // } + break; + } + } + + // Trier le tableau du data + function sortByDate_rows($a, $b) { + return str_replace(')','',str_replace('Date(','',$a['c']['0']['v'])) - str_replace(')','',str_replace('Date(','',$b['c']['0']['v'])); + } + usort($rows, 'sortByDate_rows'); + + $table['rows'] = $rows; // Stockage de toutes les rows créées dans 'table' + $jsonTable = json_encode($table); // Mise au format JSON pour être lu par la fonction JS + + $nomgraphique = "'graphique_".$_SESSION['Bateaux']['id_entree_details_bateau']."'"; // Permet de passer à la fonction JS le nom du graphique (différent pour chaque capteur...) + + /*$nb_intervalles = 5; + $maille = 100; + $max = ceil($max / $maille) * $maille; + $intervalle = floor(($max - $min) / $nb_intervalles); + echo 'Min = '.$min.', Max = '.$max.' et intervalle = '.$intervalle.'
'; + */ + + //=============================================================================================================================================== + // GRAPHIQUES : + //=============================================================================================================================================== + // Appels JavaScript pour générer le graphique : + ?> + + '; + } + + break; + } + + //========================= + default: break; + + } // Fin du switch 'type_details_bateau' + + $requete_date_maj = "SELECT substr(date_maj,1,10) as date from TB_BATEAUX_Systeme_archive WHERE ID_Bateau = ? GROUP BY substr(date_maj,1,10) UNION + SELECT substr(date_maj,1,10) as date from TB_BATEAUX_Batteries_archive WHERE ID_Bateau = ? GROUP BY substr(date_maj,1,10) UNION + SELECT substr(date_maj,1,10) as date from TB_BATEAUX_Cartes_archive WHERE ID_Bateau = ? GROUP BY substr(date_maj,1,10) UNION + SELECT substr(date_maj,1,10) as date from TB_BATEAUX_Circuits_archive WHERE ID_Bateau = ? GROUP BY substr(date_maj,1,10) UNION + SELECT substr(date_maj,1,10) as date from TB_BATEAUX_Systeme_archive WHERE ID_Bateau = ? GROUP BY substr(date_maj,1,10) "; + $reponse_date_maj = Requete_preparee_bdd($requete_date_maj, + array( + array('i', $bateau['Cle_primaire']), + array('i', $bateau['Cle_primaire']), + array('i', $bateau['Cle_primaire']), + array('i', $bateau['Cle_primaire']), + array('i', $bateau['Cle_primaire']) + ), + __FILE__, __LINE__); + $nb_dates_maj = 0; + while ($donnees = Recherche_ligne_bdd($reponse_date_maj)) + { + $dates_maj[$nb_dates_maj ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse_date_maj); + + function sortByDate($a, $b) { + return str_replace('-','',preg_replace('/[T_-_ _:]/', '', $b['date'])) - str_replace('-','',preg_replace('/[T_-_ _:]/', '', $a['date'])); + } + if ($nb_dates_maj != 0) usort($dates_maj, 'sortByDate'); + + + + break; + } + + //**************************************************************************************************************************** + case "Creation_bateau": + case "Modification_bateau": + { + //-------------------------------------------------- + // Préparation des variables du bateau : + if ($_SESSION['Bateaux']['page'] == "Creation_bateau") + { + $_SESSION['Bateaux']['bateau']['Cle_primaire'] = 0; + $_SESSION['Bateaux']['bateau']['Nom'] = ""; + $_SESSION['Bateaux']['bateau']['ID_Flotte'] = 0; + $_SESSION['Bateaux']['bateau']['ID_Carte'] = 0; + $_SESSION['Bateaux']['bateau']['Date_mes'] = date("Y-m-d"); + $_SESSION['Bateaux']['bateau']['Date_carte'] = date("Y-m-d"); + $_SESSION['Bateaux']['bateau']['Date_derniere_maj'] = "2020-01-01 00:00:00"; + $_SESSION['Bateaux']['bateau']['Commentaires'] = ""; + } + else // Modification : + { + $requete = 'SELECT * FROM TB_Bateaux WHERE Cle_primaire=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['Bateaux']['bateau']['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $_SESSION['Bateaux']['bateau'] = $donnees; + + // Mise en forme de textes : + $_SESSION['Bateaux']['bateau']['Commentaires'] = htmlspecialchars(stripcslashes($_SESSION['Bateaux']['bateau']['Commentaires'])); + } + Liberation_jeu_de_resultat_bdd($reponse); + } + + //-------------------------------------------------- + // Recherche des flottes existantes : + $nb_flottes = 0; + + $flottes[$nb_flottes]['Cle_primaire'] = 0; + $flottes[$nb_flottes]['Nom'] = '--- Affecté à aucune flotte ---'; + $nb_flottes ++; + + $requete = 'SELECT * FROM TB_Flottes WHERE Validite=1 ORDER BY Nom ASC'; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $flottes[$nb_flottes ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + //-------------------------------------------------------------------------------------- + // Recherche des cartes existantes et disponibles (+ la carte actuellement installée) : + $nb_cartes = 0; + + $cartes[$nb_cartes]['Cle_primaire'] = 0; + $cartes[$nb_cartes]['No_serie'] = '--- Aucune carte ShipBase installée ---'; + $cartes[$nb_cartes]['Adresse_mac'] = ""; + $cartes[$nb_cartes]['Affectee'] = false; + $nb_cartes ++; + + // $requete = 'SELECT * FROM TB_Cartes WHERE Validite=1 AND Type=1 AND (NOT EXISTS (SELECT ID_Carte FROM TB_Bateaux WHERE TB_Cartes.Cle_primaire=TB_Bateaux.ID_Carte) OR '.$ajout_requete.') ORDER BY No_serie ASC'; + $requete = 'SELECT *, EXISTS(SELECT ID_Carte FROM TB_Bateaux WHERE TB_Bateaux.Validite=1 AND TB_Cartes.Cle_primaire=TB_Bateaux.ID_Carte) AS Affectee FROM TB_Cartes WHERE Validite=1 AND Type=0 AND Etat!='.ETAT_CARTE_REBUT.' ORDER BY No_serie ASC'; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $cartes[$nb_cartes] = $donnees; + if ($_SESSION['Bateaux']['bateau']['ID_Carte'] == $donnees['Cle_primaire']) $cartes[$nb_cartes]['Affectee'] = false; // Permet de resélectionner la carte existante carte... + $nb_cartes ++; + } + Liberation_jeu_de_resultat_bdd($reponse); + + + break; + } + + //**************************************************************************************************************************** + case "Confirmation_suppression_bateau": + { + break; + } + + //**************************************************************************************************************************** + default: + { + $_SESSION['Bateaux']['page'] = "Accueil"; + break; + } + } + + Fermeture_bdd(); // Déconnexion de MySQL + + + //************************************************************************************************************************************ + // Affichage + //************************************************************************************************************************************ + + + //******************************************************************************************************************************** + // Affichage principal : + echo '
'; + + //========================================================================================= + // Entête : + Entete_page($message_erreur, $message_information); + + switch ($_SESSION['Bateaux']['page']) + { + //************************************************************************************************************************ + case "Accueil": + { + echo '
'; + echo '

Bateaux

'; + echo '
'; + echo ' + + '; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + // echo ''; + echo ' + + '; + for ($i = 0; $i < $nb_bateaux; $i ++) + { + echo ' + '; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + // echo ''; + echo ''; + } + echo ' +
NomFlotteShipBaseAdresse MACVersionDernière mise à jour [UTC]Commentaires
+ + '.$bateaux[$i]['Nom'].' + + '.$bateaux[$i]['nom_flotte'].''.$bateaux[$i]['nom_carte'].''.$bateaux[$i]['adresse_carte'].''.$bateaux[$i]['version'].''.$bateaux[$i]['Date_derniere_maj'].''.$bateaux[$i]['Commentaires'].'
'; + echo '
'; + + echo ''; + + echo '
'; + + break; + } + + + //**************************************************************************************************************************** + case "Details_bateau": + { + echo '
'; + + echo '

Bateau '.$bateau['Nom'].'

'; + + echo '
'; + if ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_MINI_ACCES_ADMINISTATEUR || $acces_profil['Consultation_donnees'] == 2) + { + echo '
'; + echo Ajouter_lien_modif_buttons("bateau","details","boutons","acces"); + echo ' + '.$_SESSION['textes']['bateau']['details']['boutons']['acces'] .' + '; + echo '
'; + } + + echo '
'.Recuperer_texte("bateau","details","derniere_connexion","libelle").' : '.$bateau['Date_derniere_maj'].' [UTC]
'; + echo '
'; + + // if ($nb_dates_maj != 0){ + // echo '
Consulter une configuration précédente :'; + // echo '
+ + // + // + //
'; + + // echo '
'; + // } + // echo '
Version date précise:'; + // echo '
+ // + + // + //
'; + + // echo '
'; + + + // if ($nb_data > 0){ + // echo '
+ + //
'; + // } + //-------------------------------- + // Boutons de haut de page : + echo '
'; + if ( ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_MINI_ACCES_ADMINISTATEUR) || + (($acces_profil['Consultation_donnees'] == 1) || + ($acces_profil['Consultation_donnees'] == 2)) ) + { + + echo '
'; + echo Ajouter_lien_modif_buttons("bateau","details","boutons","carte"); + echo ' + '.$_SESSION['textes']['bateau']['details']['boutons']['carte'] .' + '; + echo '
'; + echo '
'; + echo Ajouter_lien_modif_buttons("bateau","details","boutons","batteries"); + echo ' + '.$_SESSION['textes']['bateau']['details']['boutons']['batteries'] .' + '; + echo '
'; + echo '
'; + echo Ajouter_lien_modif_buttons("bateau","details","boutons","circuits"); + echo ' + '.$_SESSION['textes']['bateau']['details']['boutons']['circuits'] .' + '; + echo '
'; + echo '
'; + echo Ajouter_lien_modif_buttons("bateau","details","boutons","reservoirs"); + echo ' + '.$_SESSION['textes']['bateau']['details']['boutons']['reservoirs'] .' + '; + echo '
'; + echo '
'; + echo Ajouter_lien_modif_buttons("bateau","details","boutons","capteurs"); + echo ' + '.$_SESSION['textes']['bateau']['details']['boutons']['capteurs'] .' + '; + echo '
'; + echo '
'; + echo Ajouter_lien_modif_buttons("bateau","details","boutons","par_sys"); + echo '' + .$_SESSION['textes']['bateau']['details']['boutons']['par_sys']. + ''; + echo '
'; + } + + + echo '
'; + + // Affichage des onglets lorsqu'il y en a : + if ($nb_onglets > 0) + { + echo '
'; + for ($i = 0; $i < $nb_onglets; $i ++) + { + echo '' + .$bateau['onglets'][$i]['Nom']. + ''; + } + echo '
'; + } + + echo '
'; + switch($_SESSION['Bateaux']['type_details_bateau']) + { + case "TB_BATEAUX_Carte": + { + if ($nb_data > 0){ + echo '
'; + + echo '
'; + + // echo '
+ //
+ // + // + // + // + // '; + // for ($i = 0; $i < $nb_batteries; $i ++) + // { + // echo ' + // + // + // + // + // + // + // '; + // } + // elseif ($i==1) { + // echo + // '[en dur]Maximale : + // + // '; + // } + // if ($i==2) { + // echo + // '[en dur]Minimale: + // + // '; + // } + // echo + // ''; + // } + // echo' + //
Etat de charge : Consommation électrique :
'.$batteries[$i]['Nom'].' : '.$batteries[$i]['Tension_nominale'].' V '.$batteries[$i]['Soc'].' % '; + // if ($i==0) { + // echo + // '[en dur]Moyenne: [en dur]3.2A [en dur]Sur 24h [en dur]8.2A [en dur]2h30 au total [en dur]0.13 [en dur]13h21
+ //


+ // + // + // + // + // + // + // + // + // + // + // + // + // + // '; + + + // for ($i = 0; $i < $nb_familles; $i ++){ + // echo + // ' + // + // + // + // + // + // ' + // ; + // for($j = 0; $j < sizeof($bateau['familles'][$i]['reservoirs']); $j++){ + // echo + // ' + // + // + // + // + // + // + // + // + // ' + // ; + // } + // } + + // echo + + // ' + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + // + //
Date début de la croisière : Date fin de la croisière : Nom de la croisière :
Nom
'.$bateau['familles'][$i]['Nom'].' : Consommation moyenne : Consommation depuis le début de la croisière : Nbre de pleins :
'.$bateau['familles'][$i]['reservoirs'][$j]['Nom'].' : '.$bateau['familles'][$i]['reservoirs'][$j]['Capacite'].' l '.$bateau['familles'][$i]['reservoirs'][$j]['Niveau'].' % [en dur] x/24h [en dur] x l [en dur] x
Distance parcourue : Vitesse moyenne : Vitesse max :
Dernières 24h : Depuis le début de la croisière : Dernières 24h : Depuis le début de la croisière : Depuis le début de la croisière :
+ + echo '
'; + } + break; + } + //=========================================================== + case "TB_BATEAUX_Batteries": + { + for ($i = 0; $i < $nb_entrees; $i ++) + { + echo '
'; // L'utilisation d'une div dédiée permet de donner une "hauteur" à l'ancre et ainsi dégager de dessous le bandeau de menu... + + echo '
+

+ + '.$bateau['details_bateau'][$i]['Nom'].' + +

+ +
+

'.Recuperer_texte("bateau","details","batterie","tension").' : '.number_format($bateau['details_bateau'][$i]['Tension'], 2, ".", " ").' V

+

'.Recuperer_texte("bateau","details","batterie","soc").' : + $bateau['details_bateau'][$i]['Soc_seuil_haut']) echo " green"; + else echo " orange"; + echo '">'.number_format($bateau['details_bateau'][$i]['Soc'], 2, ".", " ").' % +

+
+ + +
'; + + // Graphique : + if (($bateau['details_bateau'][$i]['Cle_primaire'] == $_SESSION['Bateaux']['id_entree_details_bateau']) AND + ($_SESSION['Bateaux']['type_courbe_details_bateau'] != "Aucune")) + { + echo '
'; + echo '
'; + for($j = 0; $j < $nb_var; $j++){ + if ($_SESSION['Bateaux']['id_variable_details_bateau'] == $variables[$j]['Cle_primaire']){ + $titre_graphique = $variables[$j]['Nom'].' (en '.$variables[$j]['Unite'].')'.$titre_graphique; + } + } + echo $titre_graphique; + echo '
'; + if($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese" ){ + echo ' +
+ + + +
'; + } + echo '
'; + if($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Tous" || $_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese"){ + echo '
'; + + for($j = 0; $j < $nb_var; $j++){ + echo ''; + } + echo' +
'; + } + echo'
+
'; + echo '
+ +
'; + $_SESSION['Bateaux']['graphe_date_debut'] = ''; + $_SESSION['Bateaux']['graphe_date_fin'] = ''; + echo '
'; + echo ''.$_SESSION['textes']['bateau']['details']['graph']['display_all'].Ajouter_lien_modif_buttons("bateau","details","graph","display_all").''; + else echo ' >'.$_SESSION['textes']['bateau']['details']['graph']['display_daily'] .Ajouter_lien_modif_buttons("bateau","details","graph","display_daily").''; + echo '
'; + // Capacité 1 : + echo '
+
'.Recuperer_texte("bateau","details","batterie","cap").' 1
+
'.$bateau['details_bateau'][$i]['capacite_1'].'
+
'; + + // Capacité 2 : + echo '
+
'.Recuperer_texte("bateau","details","batterie","cap").' 2
+
'.$bateau['details_bateau'][$i]['capacite_2'].'
+
'; + + // Type : + echo '
'; + //echo '
'.Recuperer_texte("bateau","details","batterie","cap").' 2
+ echo '
Type de batterie
+
'.$bateau['details_bateau'][$i]['type'].'
+
'; + + // Seuil soc haut : + echo '
+
'.Recuperer_texte("bateau","details","batterie","seuil_haut").'
+
'.number_format($bateau['details_bateau'][$i]['Soc_seuil_haut'], 0, ".", " ").' %
+
'; + + // Seuil soc bas : + echo '
+
'.Recuperer_texte("bateau","details","batterie","seuil_bas").'
+
'.number_format($bateau['details_bateau'][$i]['Soc_seuil_bas'], 0, ".", " ").' %
+
'; + + } + + + } + + break; + } + + //=========================================================== + case "TB_BATEAUX_Circuits": + { + for ($i = 0; $i < $nb_entrees; $i ++) + { + echo '
'; // L'utilisation d'une div dédiée permet de donner une "hauteur" à l'ancre et ainsi dégager de dessous le bandeau de menu... + + echo '
+

+ + '.$bateau['details_bateau'][$i]['Nom'].' + +

+ +
+

Off'; + elseif ($bateau['details_bateau'][$i]['Etat_commande_carte'] == 2) echo 'A DEFINIR en fonction de la valeur de Mode_test de la carte de commande'; + elseif ($bateau['details_bateau'][$i]['Consigne'] == 0) echo 'capteur_off "> Off'; + else + { + echo 'capteur_on "> On'; + echo '

'.number_format($bateau['details_bateau'][$i]['Intensite'], 2, ".", " ").' A

'; + if (($bateau['details_bateau'][$i]['Consigne'] > 0) AND + ($bateau['details_bateau'][$i]['Consigne'] < 100)) echo '['.$bateau['details_bateau'][$i]['Consigne'].' %]'; + } + echo '

+ + +

+ + +
'; + + + // Graphique : + if (($bateau['details_bateau'][$i]['Cle_primaire'] == $_SESSION['Bateaux']['id_entree_details_bateau']) AND + ($_SESSION['Bateaux']['type_courbe_details_bateau'] != "Aucune")) + { + echo '
'; + echo '
'; + for($j = 0; $j < $nb_var; $j++){ + if ($_SESSION['Bateaux']['id_variable_details_bateau'] == $variables[$j]['Cle_primaire']){ + $titre_graphique = $variables[$j]['Nom'].' (en '.$variables[$j]['Unite'].')'.$titre_graphique; + } + } + echo $titre_graphique; + echo '
'; + if($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese" ){ + echo ' +
+ + + +
'; + } + echo '
'; + if($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Tous" || $_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese"){ + echo '
'; + + for($j = 0; $j < $nb_var; $j++){ + echo ''; + } + echo' +
'; + } + echo'
+
'; + echo '
+ +
'; + $_SESSION['Bateaux']['graphe_date_debut'] = ''; + $_SESSION['Bateaux']['graphe_date_fin'] = ''; + echo '
'; + echo ''.$_SESSION['textes']['bateau']['details']['graph']['display_all'].Ajouter_lien_modif_buttons("bateau","details","graph","display_all").''; + else echo ' >'.$_SESSION['textes']['bateau']['details']['graph']['display_daily'] .Ajouter_lien_modif_buttons("bateau","details","graph","display_daily").''; + echo '
'; + + // Etat : + echo '
+
'.Recuperer_texte("bateau","details","circuits","etat").'
+
'; + if ($bateau['details_bateau'][$i]['Etat_commande_carte'] == 1) { echo Recuperer_texte("bateau","details","circuits","tension_faible"); } + elseif ($bateau['details_bateau'][$i]['Etat_commande_carte'] == 2) { echo Recuperer_texte("bateau","details","circuits","cmd_man"); } + else + { + switch($bateau['details_bateau'][$i]['Etat']) + { + case 1 : { echo Recuperer_texte("bateau","details","circuits","limitation"); break; } + case 2 : { echo Recuperer_texte("bateau","details","circuits","protection"); break; } + case 3 : { echo Recuperer_texte("bateau","details","circuits","disjonction"); break; } + case 4 : { echo Recuperer_texte("bateau","details","circuits","court_circuit_batterie"); break; } + case 5 : { echo Recuperer_texte("bateau","details","circuits","delestage"); break; } + default: { echo Recuperer_texte("bateau","details","circuits","ok"); break; } + } + } + echo '
+
'; + + // Consigne : + echo '
+
'.Recuperer_texte("bateau","details","circuits","etat").'
+
'; + if ($bateau['details_bateau'][$i]['Etat_commande_carte'] == 1) echo 'Off'; + elseif ($bateau['details_bateau'][$i]['Etat_commande_carte'] == 2) echo 'A DEFINIR en fonction de la valeur de Mode_test de la carte de commande'; + elseif ($bateau['details_bateau'][$i]['Consigne'] == 0) echo 'Off'; + else + { + echo 'On'; + if (($bateau['details_bateau'][$i]['Consigne'] > 0) AND + ($bateau['details_bateau'][$i]['Consigne'] < 100)) echo '['.$bateau['details_bateau'][$i]['Consigne'].' %]'; + } + echo '
+
'; + + // Seuil de disjonction : + echo '
+
'.Recuperer_texte("bateau","details","circuits","seuil_disjonction").'
+
'.number_format($bateau['details_bateau'][$i]['Intensite_seuil_haut'], 0, ".", " ").' A
+
'; + + // Temporisation de disjonction : + echo '
+
'.Recuperer_texte("bateau","details","circuits","temp_disjonction").'
+
'.number_format($bateau['details_bateau'][$i]['Intensite_seuil_haut_tempo']/1000, 1, ".", " ").' '.Recuperer_texte("bateau","details","circuits","sec").'
+
'; + + } + + } + + break; + } + + //=========================================================== + case "TB_BATEAUX_Reservoirs": + { + for ($i = 0; $i < $nb_entrees; $i ++) + { + echo '
'; // L'utilisation d'une div dédiée permet de donner une "hauteur" à l'ancre et ainsi dégager de dessous le bandeau de menu... + + echo '
+

+ + '.$bateau['details_bateau'][$i]['Nom'].' + +

+ +
+

'.Recuperer_texte("bateau","details","reservoirs","niveau").' : + $bateau['details_bateau'][$i]['Niveau_seuil_haut']) echo " green"; + else echo " orange"; + echo '">'.number_format(($bateau['details_bateau'][$i]['Capacite'] * $bateau['details_bateau'][$i]['Niveau'])/100, 0, ".", " ").' '.Recuperer_texte("bateau","details","reservoirs","litres").' + soit '.number_format($bateau['details_bateau'][$i]['Niveau'], 1, ".", " ").' % + +

+

'.Recuperer_texte("bateau","details","reservoirs","capacite_totale").' : '.$bateau['details_bateau'][$i]['Capacite'].' litres +

+
+ + +
'; + + // Graphique : + if (($bateau['details_bateau'][$i]['Cle_primaire'] == $_SESSION['Bateaux']['id_entree_details_bateau']) AND + ($_SESSION['Bateaux']['type_courbe_details_bateau'] != "Aucune")) + { + echo '
'; + echo '
'; + for($j = 0; $j < $nb_var; $j++){ + if ($_SESSION['Bateaux']['id_variable_details_bateau'] == $variables[$j]['Cle_primaire']){ + $titre_graphique = $variables[$j]['Nom'].' (en '.$variables[$j]['Unite'].')'.$titre_graphique; + } + } + echo $titre_graphique; + echo '
'; + if($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese" ){ + echo ' +
+ + + +
'; + } + echo '
'; + if($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Tous" || $_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese"){ + echo ''; + } + echo'
+
'; + echo '
+ +
'; + $_SESSION['Bateaux']['graphe_date_debut'] = ''; + $_SESSION['Bateaux']['graphe_date_fin'] = ''; + echo '
'; + echo ''.$_SESSION['textes']['bateau']['details']['graph']['display_all'].Ajouter_lien_modif_buttons("bateau","details","graph","display_all").''; + else echo ' >'.$_SESSION['textes']['bateau']['details']['graph']['display_daily'] .Ajouter_lien_modif_buttons("bateau","details","graph","display_daily").''; + echo '
'; + + // // Seuil niveau haut : + echo '
+
'.Recuperer_texte("bateau","details","reservoirs","seuil_haut").'
+
'.number_format($bateau['details_bateau'][$i]['Niveau_seuil_haut'], 0, ".", " ").' %
+
'; + + // Seuil niveau bas : + echo '
+
'.Recuperer_texte("bateau","details","reservoirs","seuil_bas").'
+
'.number_format($bateau['details_bateau'][$i]['Niveau_seuil_bas'], 0, ".", " ").' %
+
'; + } + } + + break; + } + + //=========================================================== + case "TB_BATEAUX_Capteurs": + { + for ($i = 0; $i < $nb_entrees; $i ++) + { + echo '
'; // L'utilisation d'une div dédiée permet de donner une "hauteur" à l'ancre et ainsi dégager de dessous le bandeau de menu... + + echo '
+

+ + '.$bateau['details_bateau'][$i]['Nom'].' + +

+ +
+

'.Recuperer_texte("bateau","details","capteurs","valeur").' : + '.number_format($bateau['details_bateau'][$i]['Valeur'], $bateau['details_bateau'][$i]['Precision_affichage_accueil'], ".", " ").' '.$bateau['details_bateau'][$i]['Unite'].' +

+
+ + +
'; + + + + // Graphique : + if (($bateau['details_bateau'][$i]['Cle_primaire'] == $_SESSION['Bateaux']['id_entree_details_bateau']) AND + ($_SESSION['Bateaux']['type_courbe_details_bateau'] != "Aucune")) + { + echo '
'; + echo '
'; + echo $titre_graphique; + echo '
'; + + if($_SESSION['Bateaux']['type_courbe_details_bateau'] == "Synthese"){ + echo '
+ + + + +
'; + } + echo '
'; + echo'
+
'; + echo '
+ +
'; + $_SESSION['Bateaux']['graphe_date_debut'] = ''; + $_SESSION['Bateaux']['graphe_date_fin'] = ''; + echo '
'; + echo ''.$_SESSION['textes']['bateau']['details']['graph']['display_all'].Ajouter_lien_modif_buttons("bateau","details","graph","display_all").''; + else echo ' >'.$_SESSION['textes']['bateau']['details']['graph']['display_daily'] .Ajouter_lien_modif_buttons("bateau","details","graph","display_daily").''; + echo '
'; + + // Valeur seuil haut : + echo '
+
'.Recuperer_texte("bateau","details","capteurs","valeur_seuil_haut").'
+
'.number_format($bateau['details_bateau'][$i]['Valeur_seuil_haut'], $bateau['details_bateau'][$i]['Precision_affichage_accueil'], ".", " ").' '.$bateau['details_bateau'][$i]['Unite'].'
+
'; + + // Valeur seuil bas : + echo '
+
'.Recuperer_texte("bienvenue","details","capteurs","valeur_seuil_bas").'
+
'.number_format($bateau['details_bateau'][$i]['Valeur_seuil_bas'], $bateau['details_bateau'][$i]['Precision_affichage_accueil'], ".", " ").' '.$bateau['details_bateau'][$i]['Unite'].'
+
'; + + // Etat : + echo '
+
'.Recuperer_texte("bateau","details","capteurs","etat").'
+
'; + if ($bateau['details_bateau'][$i]['Etat'] == 0) { echo Recuperer_texte("bateau","details","capteurs","ok"); } + elseif ($bateau['details_bateau'][$i]['Etat'] == 1) { echo Recuperer_texte("bateau","details","capteurs","alerte"); } + elseif ($bateau['details_bateau'][$i]['Etat'] == 2) { echo Recuperer_texte("bateau","details","capteurs","alarme"); } + + echo '
+
'; + } + + + + // // Boutons graphique : + // echo '
'; + // echo ''.$_SESSION['textes']['bateau']['details']['graph']['hide'].''; + // else echo ' >'.$_SESSION['textes']['bateau']['details']['graph']['display_daily'] .Ajouter_lien_modif_buttons("bateau","details","graph","display_daily").''; + // echo ''.$_SESSION['textes']['bateau']['details']['graph']['hide'].''; + // else echo ' >'.$_SESSION['textes']['bateau']['details']['graph']['display_all'] .''; + // echo '
'; + } + + break; + } + + //=========================================================== + case "TB_BATEAUX_Systeme": + { + // Informations provenant de TB_Systeme : + // Version : + echo '
+
'.Recuperer_texte("bateau","details","parsys","ver").'
+
'.$bateau['version'].'
+
'; + + // Version modem : + echo '
+
'.Recuperer_texte("bateau","details","parsys","verm").'
+
'.$bateau['details_bateau']['Version_soft_modem']['Valeur'].'
+
'; + + // N° d'ICCID : + echo '
+
'.Recuperer_texte("bateau","details","parsys","iccid").'
+
'.$bateau['details_bateau']['No_iccid']['Valeur'].'
+
'; + + // N° d'IMEI : + echo '
+
'.Recuperer_texte("bateau","details","parsys","imei").'
+
'.$bateau['details_bateau']['No_imei']['Valeur'].'
+
'; + + // N° d'IMSI : + echo '
+
'.Recuperer_texte("bateau","details","parsys","imsi").'
+
'.$bateau['details_bateau']['No_imsi']['Valeur'].'
+
'; + + // Informations sur les cartes présentes à bord (TB_Cartes) : + for ($i = 0; $i < $nb_cartes; $i ++) + { + + echo '
'; // L'utilisation d'une div dédiée permet de donner une "hauteur" à l'ancre et ainsi dégager de dessous le bandeau de menu... + + echo '
+

'; + echo ''; + if (($cartes[$i]['Adresse_k_bus']) != 0 ) echo $cartes[$i]['Adresse_k_bus']." - "; + echo $cartes[$i]['nom_type']; + echo ''; + echo '

+ +
+

'.Recuperer_texte("bateau","details","parsys","mac").' : '.$cartes[$i]['Adresse_mac'].'

+

'.Recuperer_texte("bateau","details","parsys","ver_logicielle").' : '.$cartes[$i]['Software_version'].'

'; + echo '
+ + +
'; + + if ($cartes[$i]['Cle_primaire'] == $_SESSION['Bateaux']['id_entree_details_bateau']){ + echo '
'; + // Résistance de terminaison : + echo '
+
'.Recuperer_texte("bateau","details","parsys","resistance").'
+
'.$cartes[$i]['libelle_resistance_terminaison'].'
+
'; + + // Version matérielle : + echo '
+
'.Recuperer_texte("bateau","details","parsys","ver_materielle").'
+
'.$cartes[$i]['Hardware_version'].'
+
'; + + // Données spécifiques en fonction du type de carte : + echo '
'; + switch($cartes[$i]['Type']) + { + //--------------------------- + case TYPE_CARTE_SP812: + case TYPE_CARTE_SP8DC: + { + // Circuits affectés à ce module : + for ($j = 0; $j < 8; $j++) + { + echo '
+
Circuit n° '.($j + 1).'
+
'.$cartes[$i]['circuits'][$j]['Nom'].'
+
'; + } + + break; + } + + //--------------------------- + case TYPE_CARTE_SP4AC: + { + // Circuits affectés à ce module : + for ($j = 0; $j < 4; $j++) + { + echo '
+
Circuit n° '.($j + 1).'
+
'.$cartes[$i]['circuits'][$j]['Nom'].'
+
'; + } + break; + } + + //--------------------------- + case TYPE_CARTE_COMPAGNON: + case TYPE_CARTE_SBS1224: + default : break; + } + echo '
'; + } + } + + /* // Version complète de tous les champs de TB_Systeme : + foreach($bateau['details_bateau'] as $key => $value) + { + echo '
+
+ '.$key.' +
+
+ '.$value['Valeur'].' +
'; + if (isset($value['Description'])) + { + echo '
+ '.$value['Description'].' +
'; + } + echo '
'; + } + */ + break; + } + + + //=========================================================== + case "gerer_les_acces": + { + echo '
'; + echo '
+
'; + echo ' '; + echo ' '; + echo ' '; + echo '
+
'; + echo '
'; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + if ($utilisateur_acces_nb == 0) echo ''; + else { + for($i = 0; $i < $utilisateur_acces_nb; $i++){ + + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + echo ' '; + if ($acces_profil['Modification_acces'] == 1){ + echo ' '; + } + echo ' '; + echo ' '; + } + + + } + echo '
'.Recuperer_texte("bateau","details","acces","validite").' '.Recuperer_texte("bateau","details","acces","shipmember").' '.Recuperer_texte("bateau","details","acces","cree_par").' '.Recuperer_texte("bateau","details","acces","type_profil").' '.Recuperer_texte("bateau","details","acces","fin_validite").'
0 shipmember / acces
'.$utilisateur_acces[$i]['sm_Prenom'].' '.$utilisateur_acces[$i]['sm_Nom'].' ['.$utilisateur_acces[$i]['sm_Email'].'] '.$utilisateur_acces[$i]['cree_par_Prenom'].' '.$utilisateur_acces[$i]['cree_par_Nom'].''.$utilisateur_acces[$i]['Niveau_acces_nom'].' '; + echo (substr($utilisateur_acces[$i]['Fin_validite'],0,-9) == "9999-12-31") ? Recuperer_texte("bateau","details","acces","aucune_fin") : substr($utilisateur_acces[$i]['Fin_validite'],0,-9) ; + echo '
'; + echo '
'; + + echo '
'; + + echo ''; + + break; + } + + //=========================================================== + default: + { + echo '

'.Recuperer_texte("bateau","details","autres","autre").'

'; + break; + } + } + echo '
'; // Fin de class="corps_details_bateau" + + + + //-------------------------------- + echo '
'; + if ($_SESSION['Bateaux']['origine'] == "shipmember") echo 'Retour au menu ShipMember'; + else + { + echo 'Retour au menu Administration'; + echo 'Revenir à la liste des bateaux'; + echo 'Modifier'; + } + echo '
'; + + + //------------------------------- + // Help + echo ''; + echo '
'; + echo '
'; + + + echo '
'; + + break; + } + + + //************************************************************************************************************************ + case "Creation_bateau": + case "Modification_bateau": + { + echo '
'; + + echo '

Bateaux

'; + + echo '
'; + + + + if ($_SESSION['Bateaux']['page'] == "Creation_bateau") echo '

Nouveau bateau

'; + else echo '

Modification du bateau '.$_SESSION['Bateaux']['bateau']['Nom'].'

'; + + //---------------------------------------- + // Nom : + echo '
+
+ Nom +
+
+ +
+
'; + + //---------------------------------------- + // Date de mise en service : + echo '
+
+ Date de mise en service +
+
+ +
+
'; + + //---------------------------------------- + // Flotte : + echo '
+
+ Flotte à laquelle le bateau appartient +
+
+ +
+
'; + + //---------------------------------------- + // Carte : + echo '
+
+ Carte ShipBase installée à bord +
+
+ +
+
'; + + //---------------------------------------- + // Date d'installation de la carte ShipBase à bord : + echo '
+
+ Date d\'installation de la carte ShipBase à bord +
+
+ +
+
'; + + //---------------------------------------- + // Commentaires : + echo '
+
+ Commentaires +
+
+ +
+
'; + + //---------------------------------------- + // Boutons de bas de page : + echo '
'; + if ($_SESSION['Bateaux']['page'] == "Creation_bateau") // Création : + { + echo 'Annuler'; + echo ''; + } + else // Modification : + { + echo 'Annuler'; + echo ''; + echo 'Supprimer la bateau'; + } + echo '
'; + + echo '
'; + + echo '
'; + + break; + } + + + //**************************************************************************************************************************** + case "Confirmation_suppression_bateau": + { + echo '
'; + + echo '

Bateaux

'; + + echo '
'; + + echo '

+ Confirmez-vous la suppression du bateau + '; + echo $_SESSION['Bateaux']['bateau']['Nom']; + echo ' ? +

'; + echo '

Si oui, son entrée dans la base de données sera dévalidée de la base de données.

'; + + echo '
'; + + echo '
'; + echo 'Annuler'; + echo 'Confirmer la suppression'; + echo '
'; + + echo '
'; + + break; + } + + + + } + + echo '
'; + +Pied_de_page(); +?> + + + \ No newline at end of file diff --git a/html/cartes.php b/html/cartes.php new file mode 100644 index 0000000..d9cdb73 --- /dev/null +++ b/html/cartes.php @@ -0,0 +1,712 @@ +'; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $cartes[$nb_cartes ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); +*/ + if ($nb_cartes == 0) $_SESSION['Cartes']['page'] = "Confirmation_suppression_carte"; // Si aucune carte de ShipHeart ne l'utilise, on passe à l'étape de confitmation finale. + else // Sinon, on indique une erreur et on affiche les cartes l'utilisant (limitée à N lignes...) + { + $flag_redirection = true; // Evite que le message d'erreur soit supprimé par la redirection de purge d'URL + $message_erreur = "Vous ne pouvez pas supprimer cette carte qui est utilisée dans les cartes de ShipHeart suivantes :"; + /* for ($i = 0; $i < $nb_cartes; $i ++) + { + if ($i < 10) $message_erreur .= "
".$cartes[$i]['Nom']." "; + else + { + $message_erreur .= "
[...]"; + break; + } + } + */ + } + } + + break; + } + + //=================================== + case "confirmation_suppression_carte": + { + if (isset($_GET['id_carte'])) + { + $_SESSION['Cartes']['carte']['Cle_primaire'] = $_GET['id_carte']; + + // Suppression de la carte : + $requete = 'UPDATE TB_Cartes SET Validite=0 WHERE Cle_primaire=?'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['Cartes']['carte']['Cle_primaire'])), + __FILE__, __LINE__); + + $flag_redirection = true; // Evite que le message d'erreur soit supprimé par la redirection de purge d'URL + + $message_information = "La carte ".$types_carte[$_SESSION['Cartes']['carte']['Type']]." n° ".$_SESSION['Cartes']['carte']['No_serie']." a été supprimée de la base de données."; + + $_SESSION['Cartes']['page'] = "Liste_cartes"; + } + + break; + } + } + + if (!$flag_redirection) header('Location:cartes.php'.$_SESSION['Cartes']['ancre'].''); + } + + + // Variables POST : + + //--------------------------------------------------------------------------- + // Création Version : + if (isset($_POST['validation_creation_carte']) OR + isset($_POST['validation_modification_carte'])) + { + // Mémorisation des valeurs saisies pour éviter de les perdre en cas d'erreur rendant la création impossible : + $_SESSION['Cartes']['carte']['No_serie'] = isset($_POST['No_serie']) ? addslashes ($_POST['No_serie']) : ""; + $nb_cartes_a_creer = isset($_POST['nb_cartes_a_creer']) ? $_POST['nb_cartes_a_creer'] : 1; + $_SESSION['Cartes']['carte']['Version'] = isset($_POST['Version']) ? addslashes ($_POST['Version']) : ""; + $_SESSION['Cartes']['carte']['Revision'] = isset($_POST['Revision']) ? addslashes ($_POST['Revision']) : ""; + $_SESSION['Cartes']['carte']['Adresse_mac'] = isset($_POST['Adresse_mac']) ? addslashes ($_POST['Adresse_mac']) : ""; + $_SESSION['Cartes']['carte']['Date_reception'] = isset($_POST['Date_reception']) ? addslashes ($_POST['Date_reception']) : date("Y-m-d"); + $_SESSION['Cartes']['carte']['Modifications'] = isset($_POST['Modifications']) ? addslashes ($_POST['Modifications']) : ""; + $_SESSION['Cartes']['carte']['Tests'] = isset($_POST['Tests']) ? addslashes ($_POST['Tests']) : ""; + $_SESSION['Cartes']['carte']['Etat'] = isset($_POST['Etat']) ? addslashes ($_POST['Etat']) : 0; + $_SESSION['Cartes']['carte']['Destination'] = isset($_POST['Destination']) ? addslashes ($_POST['Destination']) : ""; + $_SESSION['Cartes']['carte']['Commentaires'] = isset($_POST['Commentaires']) ? addslashes ($_POST['Commentaires']) : ""; + + if (isset($_POST['validation_creation_carte'])) + { + for ($i = 0; $i < $nb_cartes_a_creer; $i ++) + { + // Création de la carte : + $requete = 'INSERT INTO TB_Cartes (Type, No_serie, Version, Revision, Adresse_mac, Date_reception, Modifications, Tests, Etat, Destination, Commentaires) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['Cartes']['carte']['Type']), + array('s', $_SESSION['Cartes']['carte']['No_serie']), + array('s', $_SESSION['Cartes']['carte']['Version']), + array('s', $_SESSION['Cartes']['carte']['Revision']), + array('s', $_SESSION['Cartes']['carte']['Adresse_mac']), + array('s', $_SESSION['Cartes']['carte']['Date_reception']), + array('s', $_SESSION['Cartes']['carte']['Modifications']), + array('s', $_SESSION['Cartes']['carte']['Tests']), + array('i', $_SESSION['Cartes']['carte']['Etat']), + array('s', $_SESSION['Cartes']['carte']['Destination']), + array('s', $_SESSION['Cartes']['carte']['Commentaires'])), + __FILE__, __LINE__); + + // Récup de la clé primaire de l'enregistrement créé : + $_SESSION['Cartes']['carte']['Cle_primaire'] = Recuperation_id_cree_bdd(); + + // Préparation des champs pour les cartes suivantes : + if ($nb_cartes_a_creer > 1) + { + $cartes_a_creer[$i]['No_serie'] = $_SESSION['Cartes']['carte']['No_serie']; + list($annee, $no) = explode("-", $_SESSION['Cartes']['carte']['No_serie']); + $lg_no = strlen($no); + $_SESSION['Cartes']['carte']['No_serie'] = $annee.'-'.str_pad(($no+1), $lg_no, '0', STR_PAD_LEFT); + + $_SESSION['Cartes']['carte']['Adresse_mac'] = ""; // Seule la première carte aura l'adresse MAC enregistrée + } + } + + // Message d'information : + if ($nb_cartes_a_creer <= 1) $message_information = "La carte ".$types_carte[$_SESSION['Cartes']['carte']['Type']]." n° ".$_SESSION['Cartes']['carte']['No_serie']." vient d'être créée"; + else $message_information = $nb_cartes_a_creer." cartes ".$types_carte[$_SESSION['Cartes']['carte']['Type']].", du n° [".$cartes_a_creer[0]['No_serie']."] au n° [".$cartes_a_creer[$nb_cartes_a_creer-1]['No_serie']."], viennent d'être créées"; + + // Retour à la liste si la création s'est bien passée : + $_SESSION['Cartes']['page'] = "Liste_cartes"; + + } + else if (isset($_POST['validation_modification_carte'])) + { + // Mise à jour de la carte : + $requete = 'UPDATE TB_Cartes SET Type=?, No_serie=?, Version=?, Revision=?, Adresse_mac=?, Date_reception=?, Modifications=?, Tests=?, Etat=?, Destination=?, Commentaires=? WHERE Cle_primaire=?'; + Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['Cartes']['carte']['Type']), + array('s', $_SESSION['Cartes']['carte']['No_serie']), + array('s', $_SESSION['Cartes']['carte']['Version']), + array('s', $_SESSION['Cartes']['carte']['Revision']), + array('s', $_SESSION['Cartes']['carte']['Adresse_mac']), + array('s', $_SESSION['Cartes']['carte']['Date_reception']), + array('s', $_SESSION['Cartes']['carte']['Modifications']), + array('s', $_SESSION['Cartes']['carte']['Tests']), + array('i', $_SESSION['Cartes']['carte']['Etat']), + array('s', $_SESSION['Cartes']['carte']['Destination']), + array('s', $_SESSION['Cartes']['carte']['Commentaires']), + array('i', $_SESSION['Cartes']['carte']['Cle_primaire'])), + __FILE__, __LINE__); + + // Message d'information : + $message_information = "La carte ".$types_carte[$_SESSION['Cartes']['carte']['Type']]." n° ".$_SESSION['Cartes']['carte']['No_serie']." vient d'être modifiée"; + + // Retour à la liste si la modification s'est bien passée : + $_SESSION['Cartes']['page'] = "Liste_cartes"; + } + } + + + + + + +//************************************************************************************************************************************ +// Traitement des données +//************************************************************************************************************************************ + + // Protection contre les accès directs : + if ((!$_SESSION['acces_valide']) OR ($_SESSION['shipmember']['Niveau_acces'] < NIVEAU_MINI_ACCES_ADMINISTATEUR)) header('Location:shipmembers.php?action=navigation&destination=Login'); + + switch ($_SESSION['Cartes']['page']) + { + //**************************************************************************************************************************** + case "Accueil": + { + + break; + } + + //**************************************************************************************************************************** + case "Liste_cartes": + { + // Récupération des informations sur les cartes : + $nb_cartes = 0; + + $requete = 'SELECT * FROM TB_Cartes WHERE Validite=1 AND Type=? ORDER BY Version ASC, No_serie ASC'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['Cartes']['carte']['Type'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $cartes[$nb_cartes] = $donnees; + + // Mise en forme de textes : + $cartes[$nb_cartes]['Modifications'] = htmlspecialchars(stripcslashes($cartes[$nb_cartes]['Modifications'])); + $cartes[$nb_cartes]['Tests'] = htmlspecialchars(stripcslashes($cartes[$nb_cartes]['Tests'])); + $cartes[$nb_cartes]['Destination'] = htmlspecialchars(stripcslashes($cartes[$nb_cartes]['Destination'])); + $cartes[$nb_cartes]['Commentaires'] = htmlspecialchars(stripcslashes($cartes[$nb_cartes]['Commentaires'])); + + $nb_cartes ++; + } + Liberation_jeu_de_resultat_bdd($reponse); + + break; + } + + //**************************************************************************************************************************** + case "Creation_carte": + case "Modification_carte": + { + if ($_SESSION['Cartes']['page'] == "Creation_carte") + { + $_SESSION['Cartes']['carte']['Cle_primaire'] = 0; + // $_SESSION['Cartes']['carte']['Type'] = 0; + $_SESSION['Cartes']['carte']['No_serie'] = ""; + $_SESSION['Cartes']['carte']['Version'] = ""; + $_SESSION['Cartes']['carte']['Revision'] = ""; + $_SESSION['Cartes']['carte']['Adresse_mac'] = ""; + $_SESSION['Cartes']['carte']['Date_reception'] = date("Y-m-d"); + $_SESSION['Cartes']['carte']['Modifications'] = ""; + $_SESSION['Cartes']['carte']['Tests'] = ""; + $_SESSION['Cartes']['carte']['Etat'] = 0; + $_SESSION['Cartes']['carte']['Destination'] = ""; + $_SESSION['Cartes']['carte']['Commentaires'] = ""; + } + else // Modification : + { + $requete = 'SELECT * FROM TB_Cartes WHERE Cle_primaire=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['Cartes']['carte']['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $_SESSION['Cartes']['carte'] = $donnees; + + // Mise en forme de textes : + $_SESSION['Cartes']['carte']['Modifications'] = htmlspecialchars(stripcslashes($_SESSION['Cartes']['carte']['Modifications'])); + $_SESSION['Cartes']['carte']['Tests'] = htmlspecialchars(stripcslashes($_SESSION['Cartes']['carte']['Tests'])); + $_SESSION['Cartes']['carte']['Destination'] = htmlspecialchars(stripcslashes($_SESSION['Cartes']['carte']['Destination'])); + $_SESSION['Cartes']['carte']['Commentaires'] = htmlspecialchars(stripcslashes($_SESSION['Cartes']['carte']['Commentaires'])); + } + Liberation_jeu_de_resultat_bdd($reponse); + } + + break; + } + + //**************************************************************************************************************************** + case "Confirmation_suppression_carte": + { + + + break; + } + + //**************************************************************************************************************************** + default: + { + $_SESSION['Cartes']['page'] = "Accueil"; + break; + } + } + + Fermeture_bdd(); // Déconnexion de MySQL + +//************************************************************************************************************************************ +// Affichage +//************************************************************************************************************************************ + + + //******************************************************************************************************************************** + // Affichage principal : + echo '
'; + + //========================================================================================= + // Entête : + Entete_page($message_erreur, $message_information); + + switch ($_SESSION['Cartes']['page']) + { + //************************************************************************************************************************ + case "Accueil": + { + echo '
'; + + echo '

Cartes

'; + + echo '

Type de cartes

'; + + echo '
'; + for ($i=0; $types_carte[$i] != ""; $i ++) + { + echo ''.$types_carte[$i].''; + } + echo '
'; + + echo '
'; + echo 'Retour au menu Administration'; + echo '
'; + + echo '
'; + + break; + } + + //************************************************************************************************************************ + case "Liste_cartes": + { + echo '
'; + + echo '

Cartes

'; + + echo '

Liste des cartes '.$types_carte[$_SESSION['Cartes']['carte']['Type']].'

'; + + echo ' + + + + + + + + + + + '; + for ($i = 0; $i < $nb_cartes; $i ++) + { + switch($cartes[$i]['Etat']) + { + default: + case ETAT_CARTE_INCONNU: { echo ''; break; } + case ETAT_CARTE_OK: { echo ''; break; } + case ETAT_CARTE_EN_PANNE: { echo ''; break; } + case ETAT_CARTE_REBUT: { echo ''; break; } + } + echo ' + + + + + + '; + } + echo ' +
N° de sérieVersionRév.Adresse MACDate réceptionDestination
+ + '.$cartes[$i]['No_serie'].' + + '.$cartes[$i]['Version'].''.$cartes[$i]['Revision'].''.$cartes[$i]['Adresse_mac'].''.$cartes[$i]['Date_reception'].''.$cartes[$i]['Destination'].'
'; + + echo ''; + + + echo '
'; + + break; + } + + //************************************************************************************************************************ + case "Creation_carte": + case "Modification_carte": + { + echo '
'; + + echo '

Cartes

'; + + echo '
'; + + + + if ($_SESSION['Cartes']['page'] == "Creation_carte") echo '

Nouvelle carte '.$types_carte[$_SESSION['Cartes']['carte']['Type']].'

'; + else echo '

Modification de la carte '.$types_carte[$_SESSION['Cartes']['carte']['Type']].' n° '.$_SESSION['Cartes']['carte']['No_serie'].'

'; + + //---------------------------------------- + // N° de série : + echo '
+
+ N° de série +
+
+ +
+
'; + + //---------------------------------------- + // Nombre de cartes à créer : + if ($_SESSION['Cartes']['page'] == "Creation_carte") + { + echo '
+
+ Nombre de cartes à créer +
+
+ +
+
+ Si cette valeur est > 1, plusieurs cartes seront créées avec un numéro de série incrémenté de 1 et avec les mêmes champs (sauf adresse MAC) +
+
'; + } + + //---------------------------------------- + // Version : + echo '
+
+ Version +
+
+ +
+
'; + + //---------------------------------------- + // Révision : + echo '
+
+ Révision +
+
+ +
+
'; + + //---------------------------------------- + // Adresse MAC : + echo '
+
+ Adresse MAC +
+
+ +
+
'; + + //---------------------------------------- + // Date de réception : + echo '
+
+ Date de réception +
+
+ +
+
'; + + //---------------------------------------- + // Modifications : + echo '
+
+ Modificationss +
+
+ +
+
'; + + //---------------------------------------- + // Tests : + echo '
+
+ Tests +
+
+ +
+
'; + + //---------------------------------------- + // Etat : + echo '
+
Etat
+
+ +
+
'; + + //---------------------------------------- + // Destination : + echo '
+
+ Destination +
+
+ +
+
'; + + //---------------------------------------- + // Commentaires : + echo '
+
+ Commentaires +
+
+ +
+
'; + + //---------------------------------------- + // Boutons de bas de page : + echo '
'; + if ($_SESSION['Cartes']['page'] == "Creation_carte") /// Création : + { + echo 'Annuler'; + echo ''; + } + else // Modification : + { + echo 'Retour à la liste des cartes'; + echo ''; + echo 'Supprimer la carte'; + } + echo '
'; + + + + + echo '
'; + + echo '
'; + + break; + } + + + //**************************************************************************************************************************** + case "Confirmation_suppression_carte": + { + echo '
'; + + echo '

Cartes

'; + + echo '
'; + + echo '

+ Confirmez-vous la suppression de la carte + '.$types_carte[$_SESSION['Cartes']['carte']['Type']].' + n° + '.$_SESSION['Cartes']['carte']['No_serie'].' ? +

'; + + echo '
'; + + echo '
'; + echo 'Annuler'; + echo 'Confirmer la suppression'; + echo '
'; + + echo '
'; + + break; + } + + + + } + + echo '
'; + +Pied_de_page(); diff --git a/html/data_archive_treatment.php b/html/data_archive_treatment.php new file mode 100644 index 0000000..73e709a --- /dev/null +++ b/html/data_archive_treatment.php @@ -0,0 +1,2 @@ + inclus */ +} +#Accueil #bandeau_accueil p { + font-size:1.8em; +} + +#Accueil #notre_actualite p { + margin-bottom: 2em; +} +#Accueil #notre_actualite a { + width: 90%; + border-radius: 1em; + padding: 30px 0px; +} +#Accueil #qu_est_ce_que_shipheart .corps { + padding:50px 0px 50px 0px; + border-bottom:10px solid var(--bleu_koriolan_transparent); + font-weight: 300; + font-size: 1em; +} +#Accueil #qu_est_ce_que_shipheart .corps p { + margin-top: 10px; + margin-bottom: 10px; +} +#Accueil #qu_est_ce_que_shipheart .corps .made_in_france { + margin:20px 5% 50px 5%; +} +#Accueil #qu_est_ce_que_shipheart .corps .made_in_france img { + width: 99%; +} + +#Accueil #marguerite { + padding:0.5em 0px; +} +#Accueil #marguerite .corps { + grid-template-columns: 1fr; + row-gap:60px; +} +#Accueil #marguerite .corps .rubrique { + border: none; + border-bottom:10px solid var(--bleu_koriolan_transparent); + padding:10px 10px; +} +#Accueil #boutique .corps a { + margin: 20px auto 20px auto; + padding: 30px 0px; + width: 96%; + /* font-size: 2.0em; */ +} + + +#Accueil #faq .corps .rubriques { + grid-template-columns: 1fr; + row-gap: 50px; +} + + + +#Accueil #qui_sommes_nous img { + /* width:100%; */ +} +#Accueil #qui_sommes_nous .image_bandeau { + height:200px; +} +#Accueil #qui_sommes_nous .corps { + /* padding:50px 0px; */ +} +#Accueil #qui_sommes_nous .carte_de_visite { + grid-template-columns: 1% 1fr 2fr; +} +#Accueil #qui_sommes_nous .carte_de_visite .texte p { + font-size: 0.8em; +} + +#Accueil #qui_sommes_nous .contact { + /* grid-template-columns: 20px 1fr 20px; */ + padding-top: 50px; + /* font-size: 1.8em; */ +} +#Accueil #qui_sommes_nous .contact a { + width: 95%; + margin: 60px auto; + padding: 30px 0px; +} + + +/*********************************************************************************************************************** +Fichier actualites.php +***********************************************************************************************************************/ +/*----------------------------------------*/ +#Actualites #accueil .photos { + grid-template-columns: 1fr; +} + + + + + +/*********************************************************************************************************************** +Fichier boutique.php +***********************************************************************************************************************/ +#Boutique .info_mobile { + display: inline-block; +} +#Boutique .boutons_bas_de_page { + grid-template-columns: 1fr; + grid-template-areas: + " suivant " + " retour "; + margin-top: 20px; +} +#Boutique .boutons_bas_de_page a { + margin: 30px 0px; +} + +/*--------------------------------------------------*/ +#Boutique #bandeau_avancement { + grid-template-columns: repeat(7, auto); + font-size:0.6em; +} +#Boutique #bandeau_avancement .etape:first-child { + border-radius: 0px; +} +#Boutique #bandeau_avancement .etape:last-child { + border-radius: 0px; +} + + +/*--------------------------------------------------*/ +#Boutique #accueil .famille { + grid-template-columns: 1fr; +} +#Boutique #accueil .famille .produit { + /* border-top:10px solid var(--bleu_koriolan_fonce); */ + grid-template-rows: auto; + row-gap:20px; +} +#Boutique #accueil .famille .produit .image img { + height: auto; + width: min(80%, 350px); + margin-top: 20px; +} +#Boutique #accueil .famille .produit .boutons a { + width: calc(96% - 20px); + /* padding: 40px 10px; */ + margin-bottom: 20px; +} +#Boutique #accueil .famille .produit .boutons a:hover { +} + +/*--------------------------------------------------*/ +#Boutique #panier .liste_produits { + grid-row-gap: 10px; +} +#Boutique #panier .liste_produits .titre { + display:none; +} + +#Boutique #panier .liste_produits .produit { + border: 3px solid var(--bleu_koriolan_fonce); + grid-template-columns: 1fr 1fr; + grid-template-rows: auto; + row-gap: 10px; + grid-template-areas: + " image image " + " nom nom " + " descriptif descriptif " + " delai delai " + " boutons quantite " + " prix_ht prix_ht " + " prix_ttc prix_ttc "; + + align-items: center; + justify-items: center; + + margin: 10px 0px 50px 0px; + padding: 20px 10px; + + /* font-size: 0.8em; */ +} +#Boutique #panier .liste_produits .produit .image { + text-align: center; +} +#Boutique #panier .liste_produits .produit .image img { + height: auto; + width: min(80%, 350px); +} +#Boutique #panier .liste_produits .produit .descriptif { + font-style: normal; +} +#Boutique #panier .liste_produits .produit .quantite { + /* font-size:1.5em; */ +} +#Boutique #panier .liste_produits .produit .quantite .info_mobile { + font-size:0.8em; +} +#Boutique #panier .liste_produits .produit .boutons { + grid-template-columns: 1fr 1fr; + grid-template-areas: + " moins plus "; + grid-column-gap: 20px; + align-items: center; +} +#Boutique #panier .liste_produits .produit .boutons a { + height: 100%; + width: 100%; +} +#Boutique #panier .liste_produits .produit .boutons a img { + width: 100%; +} +#Boutique #panier .liste_produits .produit .delai { + line-height: normal; +} +#Boutique #panier .liste_produits .produit .prix_ht { + line-height: normal; +} +#Boutique #panier .liste_produits .produit .prix_ttc { + line-height: normal; + font-size:1.2em; +} +#Boutique #panier .liste_produits .synthese { + grid-template-columns: 2fr 2fr 2fr; +} +#Boutique #panier .liste_produits .synthese.titres.info_mobile { + display: block; +} + + +/*--------------------------------------------------*/ +#Boutique #identification form { + grid-template-columns: 1fr; + grid-template-areas: + " shipmember " + " new_shipmember "; + + row-gap:10px; +} + + +/*--------------------------------------------------*/ +#Boutique #validation .liste_produits .titre { + display:none; +} + +#Boutique #validation .liste_produits .produit { + border: 3px solid var(--bleu_koriolan_fonce); + grid-template-columns: 1fr 1fr; + grid-template-rows: auto; + row-gap: 20px; + grid-template-areas: + " image image " + " nom nom " + " descriptif descriptif " + " delai delai " + " prix_ht prix_ht " + " prix_ttc prix_ttc " + " boutons quantite "; + + align-items: center; + justify-items: center; + + margin: 10px 0px 10px 0px; + padding: 20px 10px; + + /* font-size: 0.8em; */ +} +#Boutique #validation .liste_produits .produit .image { + text-align: center; +} +#Boutique #validation .liste_produits .produit .image img { + height: auto; + width: min(80%, 350px); +} +#Boutique #validation .liste_produits .produit .descriptif { + font-style: normale; +} +#Boutique #validation .liste_produits .produit .quantite { + font-size:1.5em; + line-height: 1.5em; +} +#Boutique #validation .liste_produits .produit .quantite .info_mobile { + font-size:0.8em; +} +#Boutique #validation .liste_produits .produit .boutons { + grid-template-columns: 1fr 1fr; + grid-template-areas: + " moins plus "; + grid-column-gap: 20px; + align-items: center; +} +#Boutique #validation .liste_produits .produit .boutons a { + height: 200px; + width: 200px; + line-height: 200px; +} +#Boutique #validation .liste_produits .produit .boutons a img { + width: 100px; +} +#Boutique #validation .liste_produits .produit .delai { + line-height: normal; +} +#Boutique #validation .liste_produits .produit .prix_ht { + line-height: normal; +} +#Boutique #validation .liste_produits .produit .prix_ttc { + line-height: normal; + font-size:1.2em; +} + +#Boutique #validation .liste_produits .synthese { + grid-template-columns: 2fr 2fr 2fr; +} +#Boutique #validation .liste_produits .synthese.titres.info_mobile { + display: inline; +} + + +#Boutique #validation .message_validation_cgv input { + width: 40px; +} +#Boutique #validation .message_validation_cgv label { + line-height: 20px; +} +#Boutique #validation .message_validation_cgv a { + padding: 0px 30px; + /* background-color: var(--bleu_koriolan_fonce); */ +} + + + + +/*--------------------------------------------------*/ +#Boutique #paiement .saisie_paiement form { + /* padding: 20px 0px 100px 0px; */ +} + +#Boutique #paiement .saisie_paiement #card-element { + width: 90%; + margin-bottom: 50px; + + /* margin: 50px 0px 150px 0px; */ + /* background: var(--bleu_koriolan_transparent); */ +} + + + + +/*--------------------------------------------------*/ +#Boutique #cloture h2 { + margin-top: 50px; +} + + + + + + + + + + +/*********************************************************************************************************************** +Fichier faq.php +***********************************************************************************************************************/ + +/*----------------------------------------*/ +#Faq #accueil h2 { + border-bottom: none; +} +#Faq #accueil .famille a { + padding-bottom:10px; + border: 2px solid var(--bleu_koriolan); + margin: 5px 0px; +} +#Faq #accueil .famille .reponse { + margin:0px 10px 30px 10px; +} +#Faq #accueil .famille .reponse .photos { + grid-template-columns: 1fr; +} + + + + +/*********************************************************************************************************************** +Fichier galerie.php +***********************************************************************************************************************/ + +#Galerie #accueil #photos { + grid-template-columns: 1fr; +} +#Galerie #accueil #photos .photo .legende { + /* font-size:1.6em; */ +} +#Galerie #accueil #photos .photo { + grid-template-rows: 1fr auto; +} + + +/*********************************************************************************************************************** +Fichier mentions_legales.php +***********************************************************************************************************************/ +#Mentions_legales #accueil { +} +#Mentions_legales #accueil a { + padding:0px 5px 1px 5px; +} +#Mentions_legales #accueil p { + /* text-align: justify; */ + /* margin: 0px; */ +} + +#Mentions_legales #accueil .adresse { + /* padding-left:10%; */ +} + +/*********************************************************************************************************************** +Fichier nautic2021.php +***********************************************************************************************************************/ +#Nautic2021 .logo_sh { + height:80px; +} +#Nautic2021 .logo_nautic { + height:80px; +} +#Nautic2021 .champs .champs_valeur { + min-height: 50px; + line-height: 50px; + vertical-align: middle; +} +#Nautic2021 .champs .champs_valeur input[type="checkbox"] { + margin-left: 30px; +} +#Nautic2021 .champs .champs_valeur label { + width: 70%; + min-height: 50px; +} + + +/*********************************************************************************************************************** +Fichier produits.php +***********************************************************************************************************************/ + + +#Produits .boutons_bas_de_page { + grid-template-columns: 1fr; + grid-template-areas: + "retour" + "suivant"; +} + +/*----------------------------------------*/ +#Produits #accueil .produit { + grid-template-columns: 1fr; + grid-template-rows: auto; + grid-template-areas: + "photo_principale" + "nom" + "descriptif" + "photos"; +} + + + +/*********************************************************************************************************************** +Fichier shipmembers.php +***********************************************************************************************************************/ +/*--------------------------------------------------*/ +#Shipmember { + /* font-size: 1.5em; */ +} +#Shipmember .message { + /* font-size: 0.9em; */ +} + +#Shipmember .boutons_bas_de_page a { + margin: 50px 0px 30px 0px; + padding: 30px 10px; +} +#Shipmember .boutons_bas_de_page button { + display:block; + margin: 50px 0px 30px 0px; + padding: 30px 10px; + /* font-size: 1.2em; */ +} + + +/*--------------------------------------------------*/ +#Shipmember #login form { + grid-template-columns: 1fr; +} +#Shipmember #login form table td:nth-child(1) { + width: 30%; +} + + +/*--------------------------------------------------*/ +#Shipmember #profil .profil { + row-gap:50px; +} +#Shipmember #profil .profil .champs { + display: grid; + grid-template-columns: 1fr; + row-gap: 20px; +} + + + + + + + + + + + + diff --git a/html/format_administration.css b/html/format_administration.css new file mode 100644 index 0000000..3cfc893 --- /dev/null +++ b/html/format_administration.css @@ -0,0 +1,51 @@ +/*********************************************************************************************************************** +Fichier administration.php +***********************************************************************************************************************/ + +#Administration #accueil p { + text-align: justify; +} + +#Administration .boutons_bas_de_page { + text-align: center; + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-areas: + "retour suivant"; + grid-column-gap: 20px; + grid-row-gap: 20px; + align-items: center; + margin-top: 50px; +} +#Administration .boutons_bas_de_page a { + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); +} +#Administration .boutons_bas_de_page .retour { + grid-area: retour; +} +#Administration .boutons_bas_de_page .suivant { + grid-area: suivant; +} +#Administration .boutons_bas_de_page a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} + + +#Administration #questionnaires .indicateur { +margin: 20px 0px 30px 0px; +} +#Administration #questionnaires .libelle_indicateur { + /* display: inline-block; */ + width: 100%; + text-align: center; +} +#Administration #questionnaires .valeur_indicateur { + /* display: inline-block; */ + width: 100%; + text-align: center; + font-weight: bold; + font-size: 2em; +} + diff --git a/html/format_bateaux.css b/html/format_bateaux.css new file mode 100644 index 0000000..3e7145c --- /dev/null +++ b/html/format_bateaux.css @@ -0,0 +1,604 @@ + + + +/*********************************************************************************************************************** +Fichier bateaux.php +***********************************************************************************************************************/ + +#Bateaux .entete_bateau { + border-bottom: 2px solid var(--bleu_koriolan_fonce); + height: 60px; +} +#Bateaux .entete_bateau .derniere_maj { + width: 60%; + padding: 10px 0px; +} +#Bateaux .entete_bateau .bouton_gestion_acces { + text-align: right; + float: right +} +#Bateaux .entete_bateau .bouton_gestion_acces a { + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); + width: 100%; + padding: 5px 20px; + display: block; +} +#Bateaux .entete_bateau .bouton_gestion_acces a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} +#Bateaux .entete_bateau .bouton_gestion_acces a.actif { + background-color: var(--bleu_koriolan); + color: var(--bleu_koriolan_fonce); +} + + +#Bateaux .boutons_haut_de_page { + text-align: center; + display: grid; + grid-template-columns: repeat(6, 1fr); + grid-column-gap: 20px; + grid-row-gap: 20px; + align-items: center; + margin: 20px 0px 30px 0px; +} +#Bateaux .boutons_haut_de_page a { + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); + width: 100%; + display: block; +} +#Bateaux .boutons_haut_de_page a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} +#Bateaux .boutons_haut_de_page a.actif { + background-color: var(--bleu_koriolan); + color: var(--bleu_koriolan_fonce); +} + + + + +#Bateaux #details_bateau .graphique .top_part_graph .vars .var{ + cursor: pointer; +} +#Bateaux #details_bateau .graphique .top_part_graph .vars .var.actif { + border-radius: 5px; + background-color: var(--bleu_koriolan_transparent); + color: var(--bleu_koriolan_fonce); + font-weight: 600; +} +.page_principale { + width: 80% !important; + max-width: unset !important; +} + +.table_wrapper { + overflow-x: auto; +} + +#Bateaux #accueil table { + width: 100%; + margin-top: 20px; + text-align: center; +} +#Bateaux #accueil table th { + text-align: center; + padding: 3px 10px; +} +#Bateaux #accueil table td { + border-top: 1px solid var(--gris_tres_tres_pale); + text-align: center; + padding: 3px 10px; + font-size: 0.9em; +} +#Bateaux #accueil table td:nth-child(7) { + text-align: left; +} +#Bateaux #accueil table td a { + margin: 0px; + padding: 0px; +} + +#Bateaux #details_bateau .onglets a { + background-color: var(--bleu_koriolan_fonce); + border-radius: 1em 1em 0 0; + color: var(--blanc); + display: inline-block; + padding: 3px 20px; + margin: 1px 1px 0px 1px; +} +#Bateaux #details_bateau .onglets a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} +#Bateaux #details_bateau .onglets a.actif { + background-color: var(--bleu_koriolan); + color: var(--bleu_koriolan_fonce); +} + +#Bateaux #details_bateau .corps_details_bateau { + background-color: var(--blanc_casse); +} +#Bateaux #details_bateau .corps_details_bateau h2:nth-child(2) { + margin: 0px; +/* border-top: 0px;*/ +} + +#Bateaux #details_bateau .corps_details_bateau .champs { + display: grid; + grid-template-columns: 1fr 1fr; + margin-top: 5px; +} +#Bateaux #details_bateau .corps_details_bateau .champs .champs_titre { + text-align: left; + font-weight: bold; + padding-left: 20px; + /* background-color: var(--blanc_casse); */ +} +#Bateaux #details_bateau .corps_details_bateau .champs .champs_valeur { + text-align: left; + /* background-color: var(--blanc_casse); */ +} +.red { + color: red; +} +.orange { + color: #ffa600; +} +.green { + color: #02a602; +} +.capteur_state{ + display: block; + padding: 0px; + height: 60px; + line-height: 60px; + width: 80px; + text-align: center !important; + font-size: 1.5em; + border-radius: 5px; +} +.capteur_off{ + background-color: rgba(255, 30, 0, 0.2); + color: rgb(255,30,0); +} +.consommation_instantanee { + font-size: 1em; + padding: 6px; + background-image: url(images/icone_consommation_electrique.png); + background-size: contain; + background-position: center; + background-repeat: no-repeat; + margin-right: 5px; +} +.capteur_on{ + background-color: rgba(177, 251, 23, 0.3); + color: rgb(177, 251, 23); +} +#Bateaux #details_bateau .corps_details_bateau .champs .champs_description { + grid-column: 1 / span 2; + text-align: justify; + font-size:0.8em; +} +#Bateaux #details_bateau .boutons_graphique { + text-align: center; + display: grid; + grid-template-columns: 1fr ; + grid-column-gap: 20px; + align-items: center; + margin: 20px 0px 20px 0px; +} +#Bateaux #details_bateau .boutons_graphique a { + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); + width: 300px; + margin: auto; +} +#Bateaux #details_bateau .boutons_graphique a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} +#Bateaux #details_bateau .boutons_graphique a.actif { + background-color: var(--bleu_koriolan); + color: var(--bleu_koriolan_fonce); +} +#Bateaux #details_bateau .corps_details_bateau .titre_composant { + display: grid; + grid-template-columns: 2fr 3fr 60px; + /* height: 70px; */ + padding: 15px 0px 15px 0px; + margin: 2em 0px 0.2em 0px; + border-top: 1px solid var(--bleu_koriolan_fonce); + border-bottom: 1px solid var(--bleu_koriolan_fonce); +} +#Bateaux #details_bateau .corps_details_bateau .titre_composant p{ + margin: unset; + text-align : unset; +} +#Bateaux #details_bateau .corps_details_bateau .titre_composant .titre_text{ + font-size: 1.8em; + font-weight: 500; +} +#Bateaux #details_bateau .corps_details_bateau .titre_composant .titre_desc{ + /* font-size: 1.8em; */ +} +#Bateaux #details_bateau .corps_details_bateau .titre_composant .titre_capt{ + display: flex; +} +#Bateaux #details_bateau .corps_details_bateau .titre_composant .titre_icon { + background-size: contain; + background-repeat: no-repeat; + cursor: pointer; + background-position: center; + margin-right: 10px; +} +#Bateaux #details_bateau .corps_details_bateau .titre_composant .more { + background-image: url("images/show_more.png"); +} +#Bateaux #details_bateau .corps_details_bateau .titre_composant .less { + background-image: url("images/show_less.png"); +} +#Bateaux #creation_bateau .champs { + display: grid; + grid-template-columns: 1fr; +} +#Bateaux #creation_bateau .champs .champs_titre { + text-align: left; + margin-top: 20px; +} +#Bateaux #creation_bateau .champs .champs_valeur { + text-align: left; +} +#Bateaux #creation_bateau .champs .champs_valeur select option.selection_actuelle { + color: var(--bleu_koriolan_fonce); + font-weight: bold; +} +#Bateaux #creation_bateau .champs .champs_valeur select option[disabled] { + color: var(--gris_tres_pale); + background-color: var(--gris_tres_tres_pale); +} +#Bateaux #creation_bateau .champs .champs_valeur input { + text-align: left; +} +#Bateaux #creation_bateau .champs .champs_valeur textarea { + border:1px solid var(--bleu_koriolan); + border-radius: 10px; + text-align: left; +} +#Bateaux #creation_bateau .champs .champs_valeur a img { + width: 60%; +} +#Bateaux #creation_bateau .champs .champs_nb { + font-size: 0.8em; + font-style: italic; +} + +#Bateaux #confirmation_suppression_bateau .message_confirmation { + border-radius: 10px; + padding: 20px; + background-color: var(--rouge); + color: var(--jaune_post_it); +} + +#Bateaux .boutons_bas_de_page { + text-align: center; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-column-gap: 20px; + grid-row-gap: 20px; + align-items: center; + margin-top: 50px; +} +#Bateaux .boutons_bas_de_page a { + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); +} +#Bateaux .boutons_bas_de_page a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} +.graphique { + display: flex; + flex-direction: column; + height: unset !important; + margin: 20px 0px 20px 0px !important; +} +.graphique .graph { + width: 100%; + height: 100%; + position: relative; +} +.graphique .titre{ + margin-bottom: 20px; +} +.top_part_graph { + display: flex; + height: 100%; +} +.var { + /* display: flex; */ + flex-direction: row; +} +.var input{ + width: unset !important; + margin-right: 10px !important; +} +.var label{ + display: unset !important; +} +.date_pick form{ + display: flex; + flex-direction: column; +} + +.date_pick input { + width: 100%; + position: relative; + margin: auto; +} + +.date_pick label { + display: grid; + grid-template-columns: 2fr 3fr; +} + +.date_pick span { + position: relative; + margin: auto; +} + +.date_maj_version{ + display: flex; +} + +.date_maj_version input,.date_maj_version select{ + width: 200px !important; + margin-left: 30px !important; + margin-right: 30px !important; +} + +.gestion_acces{ + /* height: 100; */ + /* display: flex; */ +} + +.gestion_acces .users{ + margin-bottom: 50px; + overflow-x: auto; +} + +.gestion_acces .users table { + text-align: center; +} + +.gestion_acces .users table tr { + height: 35px; +} + +.gestion_acces .users table td { + border-top: 1px solid var(--gris_tres_tres_pale); + padding: 3px 10px; + font-size: 0.9em; +} + +.gestion_acces .users table td#modifier_acces { + background-image: url(images/stylo.png); + background-repeat: no-repeat; + background-size: 80%; + background-position: center; + cursor: pointer; +} +.gestion_acces .generer_code form{ + display: grid; + grid-template-columns: 2fr 2fr 1fr; + margin-bottom: 30px; + margin-top: 30px; +} + +.download{ + font-weight: 800; + padding: 0; + color: red; +} +.download:hover { + background: red; + color: var(--blanc_casse); +} +#type_acces { + height: unset; +} + +form.variables { + display: grid; + padding-left: 100px; + grid-template-columns: 2fr 2fr 100px; + padding-right: 100px; +} + +form.variables input{ + padding: 5px 10px; +} +.variables button{ + height: 40px; + padding: 0; + top: 20; + position: relative; +} +.help { + position: fixed; + height: 50px; + width: 50px; + background-size: contain; + background-repeat: no-repeat; + cursor: pointer; + bottom: 20px; + right: 20px; + z-index: 100; +} +.help_open { + background-image: url("images/question.png"); +} +.help_close{ + background-image: url("images/fermer_aide.png"); +} +.help:hover{ + animation: heart_pulse 2s ease-in 0s infinite; +} +.help_note{ + width: 300px; + background-color: var(--blanc_casse); + min-height: 40px; + max-height: 600px; + position: fixed; + bottom: 26px; + right: 26px; + border-radius: 5px; + border: var(--bleu_koriolan) 1px solid; + padding-bottom: 20px; + z-index: 50; +} +#maCarte { + height: 600px; + z-index: 1; +} + +/* --------------------- POP UP EDIT ACCESS----------------------*/ +#popUpAcces{ + display: block; + width: 100vw; + height: 100vh; + position: fixed; + background: rgba(255, 255, 255, 0.8); + backdrop-filter: blur(3px); + left: 0; + top: 0; + z-index: 9999; +} +#popUpAccesModal{ + width: 50%; + background: white; + height: 45%; + border-radius: 10px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + position: fixed; + box-shadow: 0px 0px 7px 2px var(--bleu_koriolan); + overflow-y: auto; +} +#popUpAccesModal #top_part{ + display: grid; + grid-template-columns: auto 50px; +} +#popUpAccesModal #top_part p{ + margin: unset; + text-align: left; + margin-left: 30px; + margin-top: 20px; + margin-bottom: 20px; + color: var(--bleu_koriolan_fonce); + font-weight: 600; + font-size: 25px; +} +#popUpAccesModal #top_part p#close{ + background-image: url(images/croix_carre.png); + background-repeat: no-repeat; + background-size: contain; + cursor: pointer; + width: 30px; + height: 30px; + margin: 10px; +} +#popUpAccesModal form{ + display: grid; + grid-template-columns: 1fr 1fr; + padding: 20px; + column-gap: 30px; + row-gap: 50px; +} +#popUpAccesModal form label{ + position: relative; +} +#popUpAccesModal form label input, #popUpAccesModal form label select{ + width: 100%; +} +#popUpAccesModal form label span { + position: absolute; + top: 0; + left: 10px; + transform: translateY(-18px); + font-size: 18px; + transition-duration: 300ms; + padding-left: 10px; + padding-right: 10px; + color: var(--bleu_koriolan_fonce); + font-weight: 600; + background-color: white; +} +#popUpAccesModal form .buttons_acces{ + display: grid; +} + +/* ------------------ Autres ---------------- */ +#dateSlider{ + margin-bottom: 50px !important; + margin-top: 50px !important; +} + +#dateSlider .noUi-connect{ + background-color: var(--bleu_koriolan); +} +@media only screen and (max-width: 580px) { + #Bateaux .boutons_haut_de_page { + grid-template-columns: minmax(50px, auto); + } + form.variables { + display: flex; + margin-bottom: 50px; + flex-direction: column; + padding : 0; + } + .vars { + display: grid !important; + grid-template-columns: 1fr !important; + } + #popUpAccesModal{ + width: 95% !important; + height: 60% !important; + } + #popUpAccesModal form { + grid-template-columns: 1fr; + row-gap: 30px; + } +} + +@media only screen and (max-width: 850px) { + .top_part_graph { + flex-direction: column-reverse; + } + .vars { + display: grid !important; + grid-template-columns: 1fr 1fr; + } + .page_principale { + width: 96% !important; + } + .gestion_acces{ + flex-direction: column-reverse; + } + form.variables { + + padding : 0; + } + #popUpAccesModal{ + width: 80%; + height: 40%; + } + #dateSlider{ + margin: auto; + width: 80%; + } +} diff --git a/html/format_cartes.css b/html/format_cartes.css new file mode 100644 index 0000000..bd47bbf --- /dev/null +++ b/html/format_cartes.css @@ -0,0 +1,106 @@ +/*********************************************************************************************************************** +Fichier cartes.php +***********************************************************************************************************************/ + +#Cartes #accueil .choix_type_carte { + display: grid; + grid-template-columns: 1fr 1fr; + grid-row-gap: 10px; + grid-column-gap: 10px; + margin:50px 0px; +} +#Cartes #accueil .choix_type_carte a { + background-color: var(--bleu_koriolan); + color: var(--bleu_koriolan_fonce); +} +#Cartes #accueil .choix_type_carte a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} + + +#Cartes #liste_cartes table { + width: 100%; + margin-top: 20px; +} +#Cartes #liste_cartes table th { + text-align: center; + padding: 3px 10px; +} +#Cartes #liste_cartes table td { + border-top: 1px solid var(--gris_tres_tres_pale); + text-align: center; + padding: 3px 10px; + font-size: 0.9em; +} +#Cartes #liste_cartes table td:nth-child(6) { + text-align: left; +} +#Cartes #liste_cartes table tr.carte_etat_inconnu td { + background-color: var(--blanc_casse); +} +#Cartes #liste_cartes table tr.carte_en_panne td { + background-color: var(--rouge_transparent); +} +#Cartes #liste_cartes table tr.carte_rebut td { + background-color: var(--gris_moyen); +} +#Cartes #liste_cartes table td a { + margin: 0px; + padding: 0px; +} + + +#Cartes #creation_carte .champs { + display: grid; + grid-template-columns: 1fr; +} +#Cartes #creation_carte .champs .champs_titre { + text-align: left; + margin-top: 20px; +} +#Cartes #creation_carte .champs .champs_valeur { + text-align: left; +} +#Cartes #creation_carte .champs .champs_valeur input { + text-align: left; +} +#Cartes #creation_carte .champs .champs_valeur textarea { + border:1px solid var(--bleu_koriolan); + border-radius: 10px; + text-align: left; +} +#Cartes #creation_carte .champs .champs_valeur a img { + width: 60%; +} +#Cartes #creation_carte .champs .champs_nb { + font-size: 0.8em; + font-style: italic; +} + +#Cartes #confirmation_suppression_carte .message_confirmation { + border-radius: 10px; + padding: 20px; + background-color: var(--rouge); + color: var(--jaune_post_it); +} + +#Cartes .boutons_bas_de_page { + text-align: center; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-column-gap: 20px; + grid-row-gap: 20px; + align-items: center; + margin-top: 20px; +} +#Cartes .boutons_bas_de_page a { + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); +} +#Cartes .boutons_bas_de_page a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} + + diff --git a/html/format_contact.css b/html/format_contact.css new file mode 100644 index 0000000..57b81f8 --- /dev/null +++ b/html/format_contact.css @@ -0,0 +1,152 @@ +#Contact{ + height: 60vh; + width: 100%; + position: relative; + margin: auto; + display: flex; + flex-direction: column; +} +.text_contact{ + height: 50%; + padding-left: 20%; + padding-right: 20%; + align-items: center; + display: flex; +} +.text_contact p{ + font-size: 25px; + font-style: unset; + position: relative; + margin: auto; +} +.content_contact{ + height: 50%; + padding-left: 5%; + padding-right: 5%; + display: flex; +} +.linkedin{ + width: 33%; + height: 100%; + /* padding: 5%; */ + display: flex; +} +.linkedin img{ + height: 50px; + position: relative; + object-fit: contain; + margin: auto; +} +.linkedin a { + margin: auto; +} +.mail{ + width: 43%; + height: 100%; + display: flex; +} +.mail p{ + position: relative; + margin: auto; + padding: 20px; + padding-left: 40px; + padding-right: 40px; + background-color: var(--bleu_koriolan); + border-radius: 10px; + color: white; + font-size: 20px; +} +.phone{ + width: 33%; + height: 100%; + /* padding: 5%; */ + display: flex; +} +.phone p{ + position: relative; + margin: auto; + padding: 20px; + padding-left: 40px; + padding-right: 40px; + background-color: var(--bleu_koriolan); + border-radius: 10px; + color: white; + font-size: 20px; + white-space: nowrap; +} +a:hover { + color: white !important; +} +@media only screen and (max-width: 850px) { + .content_contact{ + display: flex; + flex-direction: column; + margin-top: -10px; + padding-left: 10%; + padding-right: 10%; + } + .linkedin{ + width: 80vw; + height: 33%; + padding: 5%; + } + .mail{ + width: 80vw; + height: 33%; + padding: 5%; + } + .phone{ + width: 80vw; + height: 33%; + padding: 5%; + } + .text_contact{ + height: 50%; + padding-left: 5%; + padding-right: 5%; + align-items: center; + display: flex; + } + .text_contact p{ + font-size: 18px; + background-color: var(--bleu_koriolan_transparent); + padding: 22px; + border: 3px solid var(--bleu_koriolan_transparent); + border-radius: 15px; + } + .linkedin img{ + height: 50px; + position: relative; + object-fit: contain; + margin: auto; + border-radius: 14px; + } + .mail p{ + position: relative; + margin: auto; + margin-top: -10px; + width: 80vw; + padding: 20px; + padding-left: 30px; + padding-right: 30px; + background-color: var(--bleu_koriolan); + border-radius: 10px; + color: white; + font-size: 18px; + max-height: 67px; + } + .phone p{ + position: relative; + width: 80vw; + margin: auto; + margin-top: -10px; + padding: 20px; + padding-left: 30px; + padding-right: 30px; + background-color: var(--bleu_koriolan); + border-radius: 10px; + color: white; + font-size: 18px; + max-height: 67px; + } +} diff --git a/html/format_mentions_legales.css b/html/format_mentions_legales.css new file mode 100644 index 0000000..5f65f1b --- /dev/null +++ b/html/format_mentions_legales.css @@ -0,0 +1,23 @@ +/*********************************************************************************************************************** +Fichier mentions_legales.php +***********************************************************************************************************************/ +#Mentions_legales { + display: grid; + grid-template-columns: 1fr; +} +#Mentions_legales #accueil a { + padding:0px 5px 1px 5px; + background-color: var(--bleu_koriolan); +} +#Mentions_legales #accueil a:hover { + padding:0px 5px 1px 5px; + background-color: var(--blanc); +} +#Mentions_legales #accueil p { + text-align: justify; + margin: 0px; +} + +#Mentions_legales #accueil .adresse { + padding-left:10%; +} diff --git a/html/format_shipmembers.css b/html/format_shipmembers.css new file mode 100644 index 0000000..2f0c915 --- /dev/null +++ b/html/format_shipmembers.css @@ -0,0 +1,306 @@ +/*********************************************************************************************************************** +Fichier shipmembers.php +***********************************************************************************************************************/ +#Shipmembers h2 { + margin-bottom: 30px; +} +#Shipmembers .message p { + text-align: justify; +} + + +#Shipmembers .boutons_bas_de_page a { + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); + text-align: center; + margin: 10px 0px 30px 0px; + display:block; +} +#Shipmembers .boutons_bas_de_page a:hover { + color: var(--bleu_koriolan); +} +#Shipmembers .boutons_bas_de_page button { + display:block; + margin: 10px 0px 30px 0px; + width: 100%; +} + + +/*--------------------------------------------------*/ +#Shipmembers #login form { + display: grid; + grid-template-columns: 1fr 1fr; + column-gap:40px; + row-gap:80px; + align-items: start; +} + + +#Shipmembers #login .login { + display: grid; + grid-template-columns: 1fr; + row-gap:20px; +} +#Shipmembers #login .login .message_login { + text-align: justify; +} +#Shipmembers #login .login .champs { + + display: grid; + grid-template-columns: 1fr; +} +#Shipmembers #login .login .champs .champs_titre { + text-align: left; +} +#Shipmembers #login .login .champs .champs_valeur { + text-align: left; +} +#Shipmembers #login .login .champs .champs_valeur input { + text-align: left; +} +#Shipmembers #login .login .champs .champs_valeur textarea { + border:1px solid var(--bleu_koriolan); + border-radius: 10px; + text-align: left; +} + +/*--------------------------------------------------*/ +#Shipmembers #activation form { + display: grid; + grid-template-columns: 1fr; + row-gap:80px; + align-items: start; +} +#Shipmembers #activation .shipmember { + display: grid; + grid-template-columns: 1fr; + row-gap:10px; +} + +#Shipmembers #activation .shipmember .lignes { + display: grid; + grid-template-columns: 1fr; + row-gap:10px; +} +#Shipmembers #activation .shipmember .ligne { + display: grid; + grid-template-columns: 1fr 3fr; +} +#Shipmembers #activation .shipmember .ligne .titre_ligne { + border-bottom: 1px solid var(--bleu_koriolan); +} + + + +/*--------------------------------------------------*/ +#Shipmembers #generation_mdp form { + display: grid; + grid-template-columns: 1fr; + row-gap:80px; + align-items: start; +} +#Shipmembers #generation_mdp .shipmember { + display: grid; + grid-template-columns: 1fr; + row-gap:10px; +} + +#Shipmembers #generation_mdp .shipmember .lignes { + display: grid; + grid-template-columns: 1fr; + row-gap:10px; +} +#Shipmembers #generation_mdp .shipmember .ligne { + display: grid; + grid-template-columns: 1fr 3fr; +} +#Shipmembers #generation_mdp .shipmember .ligne .titre_ligne { + border-bottom: 1px solid var(--bleu_koriolan); +} + + +/*--------------------------------------------------*/ +#Shipmembers #accueil { + display: grid; + grid-template-columns: 1fr; + column-gap:40px; + row-gap:80px; + align-items: start; +} +#Shipmembers #accueil .message { + text-align: justify; +} + +/*--------------------------------------------------*/ +#Shipmembers #administration table { + width: 100%; + margin: 20px 0px 50px 0px; +} +#Shipmembers #administration table th { + text-align: center; + padding: 3px 10px; +} +#Shipmembers #administration table td { + border-top: 1px solid var(--gris_tres_tres_pale); + text-align: left; + padding: 3px 10px; + font-size: 0.9em; +} +#Shipmembers #administration table td:nth-child(3) { + text-align: center; +} +#Shipmembers #administration table td a { + margin: 0px; + padding: 0px; +} + + +/*--------------------------------------------------*/ +#Shipmembers #details table { + width: 100%; + margin: 20px 0px 50px 0px; +} +#Shipmembers #details table td { + border-top: 1px solid var(--gris_tres_tres_pale); + text-align: left; + padding: 3px 10px; + font-size: 0.9em; +} + + + +/*--------------------------------------------------*/ +#Shipmembers #profil form { + display: grid; + grid-template-columns: 1fr; + column-gap:40px; + row-gap:80px; + align-items: start; +} + + +#Shipmembers #profil .profil { + display: grid; + grid-template-columns: 1fr; + row-gap:10px; +} + +#Shipmembers #profil .profil .champs { + + display: grid; + grid-template-columns: 1fr 3fr; +} +#Shipmembers #profil .profil .champs .champs_titre { + text-align: left; + padding-left:20px; + line-height: 30px; + background-color: var(--bleu_koriolan_transparent); + border-bottom: 1px solid var(--bleu_koriolan); + border-radius: 5px 0px 0px 5px; +} +#Shipmembers #profil .profil .champs .champs_valeur { + text-align: left; + padding-left:20px; + line-height: 30px; + border-bottom: 1px solid var(--bleu_koriolan); + border-radius: 0px 5px 5px 0px; +} + + + + + + +/*--------------------------------------------------*/ +#Shipmembers #modifier_profil form { + display: grid; + grid-template-columns: 1fr; + column-gap:40px; + row-gap:80px; + align-items: start; +} +#Shipmembers #modifier_profil .profil { + display: grid; + grid-template-columns: 1fr; + row-gap:10px; +} +#Shipmembers #modifier_profil .profil .message { + margin-top: 20px; +} + + + +/*--------------------------------------------------*/ +#Shipmembers #historique form { + display: grid; + grid-template-columns: 1fr; + column-gap:40px; + row-gap:80px; +} + + +#Shipmembers #historique .liste_commandes { + display: grid; + grid-template-columns: 1fr; + text-align: center; +} +#Shipmembers #historique .liste_commandes .titre { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); + line-height:40px; +} +#Shipmembers #historique .liste_commandes .commande { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; + line-height:30px; +} +#Shipmembers #historique .liste_commandes .commande:nth-child(even) { + background-color: var(--bleu_koriolan_transparent); +} + +#Shipmembers #historique .liste_commandes .commande .prix_ttc { + text-align: right; +} +#Shipmembers #historique .liste_commandes .commande .download a { + line-height:30px; +} +#Shipmembers #historique .liste_commandes .commande .download img { + width: 30px; + vertical-align: middle; +} + + + +/*--------------------------------------------------*/ +#Shipmembers #bateau form { + display: grid; + grid-template-columns: 1fr; + column-gap:40px; + row-gap:80px; + /* align-items: start; */ +} +#Shipmembers #bateau form a { + display: grid; + grid-template-columns: 1fr; + column-gap:40px; + row-gap:80px; + /* align-items: start; */ +} +#Shipmembers #bateau .acces_bateau a { + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); + text-align: left; + padding-left: 20px; + margin: 10px 30px 30px 30px; + display:block; +} +#Shipmembers #bateau .acces_bateau a:hover { + color: var(--bleu_koriolan); +} +#Shipmembers #bateau .acces_bateau button { + display:block; + margin: 10px 0px 30px 0px; + width: 100%; +} diff --git a/html/format_textes.css b/html/format_textes.css new file mode 100644 index 0000000..4bf6f85 --- /dev/null +++ b/html/format_textes.css @@ -0,0 +1,90 @@ +.page_principale { + max-width: 80vw !important; +} + +.create_text{ + max-width: var(--largeur_maxi); + position: relative; + margin: auto; +} + +.boutons_bas_de_page { + text-align: center; + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-areas: + "retour suivant"; + grid-column-gap: 20px; + grid-row-gap: 20px; + align-items: center; + margin-top: 50px; +} + +.top_part { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + margin-bottom: 50px; + margin-top: 50px; + position: relative; + margin-left: auto; + margin-right: auto; + width: 100%; +} + +.textes { + display: grid; + margin-bottom: 50px; + grid-template-columns: 1fr 1fr; + row-gap: 30px; +} + +label{ + width: 90%; + position: relative; + margin-left: auto; + margin-right: auto; +} + +label select, label input , label textarea { + width: 100%; +} + +label span{ + position:absolute; + top:0; + left:10px; + transform: translateY(-20px); + font-size:20px; + transition-duration:300ms; + padding-left : 10px; + padding-right : 10px; + color : var(--bleu_koriolan_fonce); + font-weight: 600; + background-color: white; +} + +#label_chemin_acces{ + margin-top: 10px; +} + +#chemin_acces{ + height: 120px; +} +.create_text form{ + display: grid; + grid-template-columns: 1fr; +} + +@media only screen and (max-width: 850px) { + .top_part, .textes{ + grid-template-columns: 1fr; + margin-bottom: 10px; + } + label select, label input , label textarea { + margin-bottom: 20px; + } + label span { + transform: translateY(-15px); + font-size: 15px; + } +} \ No newline at end of file diff --git a/html/format_uploads.css b/html/format_uploads.css new file mode 100644 index 0000000..7825248 --- /dev/null +++ b/html/format_uploads.css @@ -0,0 +1,38 @@ +/*********************************************************************************************************************** +Fichier uploads.php +***********************************************************************************************************************/ + +#Uploads #accueil p { + text-align: justify; +} +#Uploads #accueil th:nth-child(2) { + text-align: center; +} +#Uploads #accueil td:nth-child(2) { + text-align: center; +} +#Uploads #accueil td.erreur_fichier { + color: var(--rouge); + font-weight: bold; +} + + +#Uploads .boutons_bas_de_page { + text-align: center; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-column-gap: 20px; + grid-row-gap: 20px; + align-items: center; + margin-top: 20px; +} +#Uploads .boutons_bas_de_page a { + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); +} +#Uploads .boutons_bas_de_page a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} + + diff --git a/html/format_versions.css b/html/format_versions.css new file mode 100644 index 0000000..02ca785 --- /dev/null +++ b/html/format_versions.css @@ -0,0 +1,138 @@ +/*********************************************************************************************************************** +Fichier versions.php +***********************************************************************************************************************/ + +#Versions #accueil .choix_type_version { + display: grid; + grid-template-columns: 1fr 1fr; + grid-row-gap: 10px; + grid-column-gap: 10px; + margin:50px 0px; +} +#Versions #accueil .choix_type_version a { + background-color: var(--bleu_koriolan); + color: var(--bleu_koriolan_fonce); +} +#Versions #accueil .choix_type_version a.package { + grid-column: 1 / 3; + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); +} + +#Versions #accueil .choix_type_version a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} + + +#Versions #liste_versions table { + width: 100%; + margin-top: 20px; +} +#Versions #liste_versions table th { + text-align: left; + padding: 3px 10px; +} +#Versions #liste_versions table td { + border-top: 1px solid var(--gris_tres_tres_pale); + text-align: left; + padding: 3px 10px; + font-size: 0.9em; +} +#Versions #liste_versions table td a { + margin: 0px; + padding: 0px; +} +#Versions #liste_versions table.package th:nth-child(1) { + width: 8%; +} +#Versions #liste_versions table.package th:nth-child(2) { + width: 12%; +} +#Versions #liste_versions table.package td:nth-child(1) { + font-weight: bold; + text-align: center; +} +#Versions #liste_versions table.version th:nth-child(2) { + width: 80%; +} + + + +#Versions #creation_version .champs { + display: grid; + grid-template-columns: 1fr; +} +#Versions #creation_version .champs .champs_titre { + text-align: left; + margin-top: 20px; +} +#Versions #creation_version .champs .champs_valeur { + text-align: left; +} +#Versions #creation_version .champs .champs_valeur input { + text-align: left; +} +#Versions #creation_version .champs .champs_valeur textarea { + border:1px solid var(--bleu_koriolan); + border-radius: 10px; + text-align: left; +} +#Versions #creation_version .champs .champs_valeur a img { + width: 60%; +} + +#Versions #confirmation_suppression_carte .message_confirmation { + border-radius: 10px; + padding: 20px; + background-color: var(--rouge); + color: var(--jaune_post_it); +} + +#Versions #generation_archive .champs { + display: grid; + grid-template-columns: 1fr; +} +#Versions #generation_archive .champs .champs_titre { + text-align: left; + margin-top: 20px; +} +#Versions #generation_archive .champs .champs_valeur { + text-align: left; +} + + + +#Versions .boutons_haut_bas_de_page { + text-align: center; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-column-gap: 20px; + grid-row-gap: 20px; + align-items: center; + margin-top: 20px; +} +#Versions #liste_versions .boutons_haut_bas_de_page { + grid-template-columns: 1fr 1fr; +} +#Versions #creation_version .boutons_haut_bas_de_page { + grid-template-columns: 1fr 1fr; +} +#Versions #creation_version .boutons_haut_bas_de_page.modification { + grid-template-columns: 1fr 1fr 1fr; +} +#Versions #generation_archive .boutons_haut_bas_de_page { + grid-template-columns: 1fr 1fr; +} + +#Versions .boutons_haut_bas_de_page a { + background-color: var(--bleu_koriolan_fonce); + color: var(--blanc); +} +#Versions .boutons_haut_bas_de_page a:hover { + color: var(--bleu_koriolan); + background-color: var(--bleu_koriolan_fonce); +} + + + diff --git a/html/images/Facebook_signature.png b/html/images/Facebook_signature.png new file mode 100644 index 0000000000000000000000000000000000000000..69e55de55d69467be547c0cee2302b3ed01a7aa6 GIT binary patch literal 1661 zcmbVNe{2&~9KS7uY$StZQCW;Lmz$Y$c)cIJ^~ZCCY;9qMwbZR+6E*I7_u8KA{n*`Y z?P}Bne`UcbLZaYi2r(KUhVTbQGm_B>8%7f`VEhA62}q1Avbc~imu2%^*EV3LL@s&v z-n;jCpYQMQ4TVEns@6Qb2E(wbK%1`v%@0_kVl{dX57kzosZwiu#=x*uA#0Si?%ub6 z7B{6xkJ%G!2ZAcwcu|c)TSnFp8pE15Wi(z$LKBa|xTJW9nUkjoToOG*cTD+ z%QnbbiB>TRenK9jGQ37HHrlc&4-|zGPV3iGdEuf!!4#CCVj2j`l(1StHB}>_{tI>K z_$~p+x4~dZ#)`Vga!G_?`Uj911&6GNHX?%>q&lFX_Ui)l456df)!RM5{1vweS2V;Hl2Wo z^gqJA3^UZ2ndWua5=Y*;XF5?xdCIE8Wjm;UnwUSkqh^b6)CjC)sRf};sfj@abuJyX zs4u7&4r5qZQ^3~}aSea+!zs%9bj{SC+o$K>3%B^jDyl0_PUPCoyf~e^a`yF!U#_k@ zUejK^EnYn`*}&|G9zPTq;c9Nm*`H2icb>boamM}I$nDYFqx&v3estPB5dQw)jfQL7 z*51co-t}Q)@4Ct6cNQzRCF@#`o%K62tyQO8KZ2v#$9`T4V~5|AFUMv_dIDEBkH7WJ zcNcTw?xAwN>pAf#$Z_w_myHj-`{|Jl?Vpd-j9vdLGCIBLfsd^P$-f8tPwp z@Y^$_xjo&J nOV2*l#V$_HOrOuyt$h_+e~H?AfcyP5>jx3=hkVCcdw2Z}OQ1aj literal 0 HcmV?d00001 diff --git a/html/images/Instagram_signature.png b/html/images/Instagram_signature.png new file mode 100644 index 0000000000000000000000000000000000000000..ef7f5f9c9e9a3739ec2c1d9723aa08ece4f751cb GIT binary patch literal 2292 zcmbVO2~-nj9uK4_(q_dfD;{jefN~~tB!*;cpqRiCH6j!Qr7DxjghY}|n3)hrrBtdF zDx_3Fxw$vS=T@{VNb430f~`;5dX>vc;VG^=;mB+Ex!bp$_r96$oB92Z z-~W13xN7BJd0un9I2;a76{}2OpR=6Ha|(MeF7)HEk7<_JH8h9AUE*AB+dn@f;c%Ym zGbE-kDe4s{PMU<6medf!Y?FmWb2u+XW?L{kgJ1v+k!~={`TY%_@d1NY&QD&fhSU}X zp*O_ZDdJ`O%0%3rfy=b~$Oz!YY?M`CA{Y$FHW|${nl0y#=|$PS^EJo^#vn|FoFC;h z2&AZ20Sb~L0GSXH;1C1>;W8l{4&z9;E(|~*1OXu_2ulR86on8}ECMDjK5LHB>d*vb z%!D!aBF!!DMl%HPaJuVj~7-V-^q=LQYO&KrQaVS*(+^36u(4IET{fQTi^=3NK{L@=ERBhPJQYnR=2!?YfuKn%g%i

Ki6m*9%+#t$mjOg9gn*!AgIP=3=-^)o5K4?82Fliq7GtpA1#59sM^Yw?C2TNZ=>%vor}F_< z7*PdjBq`P~>z!!K3$+?mnP~1j0h-z-z_dsl&*QczTnSg_0vN1@p~&uHzwZ*IlMZd0pR6#&&pj8 zC5Z=)7q%R%eCwT0f~~r~Gf(P1A2om=cXeM_&jYn}bdwCPgG zo`Cf;kG3IT&DP=hy^{0E#hSX+$n$fW|KU#r-M;9tdN!V?__VtGImfZxo4g(z=#~Wd z*{5SGrfxc$P`UQ&4&w$BRrU&=uBvTXTos!1Wk~YT-a5a^pI&>fa${Rey-HW`Zc|Ng!YEzuC3hO6DPgqUyn7u2U5(f6{GrRY`~q4gyEb1aUc2y)g;_seeq#~J8ysCyloXN=Qkg%{xoU*irLNI zWQkf&+`G^nb881vd-CwEus}!FkEIQkgFd!3p8ee8EqyD`$cj1^44*mG{P^m&mP0q@ zdfn~dy}HYfS~9R-;l6w3*<~X*m-OrF^!*cao-g1@xErL0xL2D#RPS5Z7+H0&Xw^ralL+OWgCN@L#FCHU91}b+WMU?jB%nM5JSR ztYU8EPx)Qt9_^<~y+`J3audHv*R5@jx0VCa`m~bo+>LXxzG?a4LgB{&Vcu=rI=6mr zQ%&-nKu%R_X=3A&YmXOQzTvfW?HfNdx($Tz2Ty;Zn|fIio?ArE|B73&sJ3L}>PG`b z6|1hja?m4IQxo#~e9Y6B_H{a)zx&b7!HtodFJ@N91Z=PW?0Q<=--C7fO}B{qLPI z>s41WA5H1_9tzG3Nln&7tNIfiWf*xWx9$US3R1VYr)=2)NODSv#wU!vbMtZx&m%4{ zv*p{8O*`jJUHan-3umflboq2z7Y=pCiahIKE)b=c-BGGju$s($#Y$&c^Bh-udm~&eXjZ1zPi0IO>{rUR;ymx7c_XMq_f6% zr`b;4_8f>Q@7~*WX_}ix^3Z>ORNB>0x!z}a;gU(+bL20# ixS>Ouq|eXJ8+~?5XVay^IPTbwi7I-f^5dmx`TqtWBV^G4 literal 0 HcmV?d00001 diff --git a/html/images/Linkedin_signature.png b/html/images/Linkedin_signature.png new file mode 100644 index 0000000000000000000000000000000000000000..5fdc66111f73541b7e7cc2d9c24c29c40f451723 GIT binary patch literal 1730 zcmbVNe{2&~9Pc7d85Ym{I&g#NlF0WC#Hgh?==g(FCGm%rIb#IEjgW$cQAHGKTNEwgEFGa>={* z-o4NJe1Cthud(52ZAM;(Mx)U>>m1E+&QZss>F^!v%h$qbsaV%0Ycxv^sUxl17#M!JQ5D zD~d>ASU4QkhYfl`@?nJ4YQ=C8BS{@Z=;SV5p(8q8E=n>ufXqmosBi+0sEo8n=um7Z zRCU3IkeH(7<%FN0$FK-3VuT)7ZHfa~CWR9_q+nb)%U~b~LV#Cfh$T{3(Jv^1>=*up zI(2-H0O(tnDRAW+Qgf!}Ln0=};q^ zywCp6`&%RqmKGg+U>>#L)Rds=I2i`3D^U?Gpgpk)a!5Q2D4J2T+lDe~SOJSBK64N3 zfd$&IA3)Oo2=@X^7Q9NBmOzycdh5RFghAyowGJ2T!2W4s{OqopO~PR#P?xC|1UIQB z26))HB-o;!HC-;zXwsriN0r+W8~M(*C8sGT{U@LA(vp>V>vOdy@I5c}4ehR*D4c%b zo7T*%!PvQ;$#a8^jZLkyO;yz);Idc8mNr$N{Gj{H`D34d^76s;W&S+4!zt;&(t$I{*i%zf5l(uDc>w~MO?o{vLZ$6%}v;R`&(c*de>K~P!ylnHTxtM9)ly+ds;*IVpjr4|R zd$Q|)*49b~UioXA-T!AnK{008oV`Dr&$!Y%TzjHuE*d+vp>5ri=jh(txlgZDjJc10 zJ9QQH9`FC~%;D*^?fGBMTP5p{%T6B}YaYKd5I8-sqp)E8jfu}H58ontwho=NHV7NP z@3@ivTgiOa?emk<&kXnIPQ5m}NwU6*9(?z}?5(pc6Ps`DCHn0@j6FBRe|=>7eX;CX zByXgsK68BdiDmg8uVUZ)!c1SdJimH$%}Dmy&T&(3|M1$8-s_Ruk7T~xGE(S#FH8N) NIBOal$EtVq{0(Z;Q^x=R literal 0 HcmV?d00001 diff --git a/html/images/Pascal_rond.png b/html/images/Pascal_rond.png new file mode 100644 index 0000000000000000000000000000000000000000..374cfb52281bb019209af0d5441b50072f8868a3 GIT binary patch literal 9277 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

'; + echo ''; + echo ''; + } + else header('Refresh: 0; URL=shipmembers.php'); // Une fois que les variables de version sont chargées + // else header('Refresh: 0; URL=accueil.php'); // Une fois que les variables de version sont chargées + diff --git a/html/mentions_legales.php b/html/mentions_legales.php new file mode 100644 index 0000000..2d5f3eb --- /dev/null +++ b/html/mentions_legales.php @@ -0,0 +1,127 @@ +'; + + Entete_page(isset($message_erreur) ? $message_erreur : "", isset($message_information) ? $message_information : ""); + + echo '
+ +

'.Recuperer_texte('mentions_legales','accueil','h1','texte').'

+ +

'.Recuperer_texte('mentions_legales','accueil','societe','titre').'

+

'.Recuperer_texte('mentions_legales','accueil','societe','texte_1').'

+ + +

'.Recuperer_texte('mentions_legales','accueil','droits_auteur','titre').'

+

'.Recuperer_texte('mentions_legales','accueil','droits_auteur','texte_1').'

+

'.Recuperer_texte('mentions_legales','accueil','droits_auteur','texte_2').'

+

'.Recuperer_texte('mentions_legales','accueil','droits_auteur','texte_3').'

+

'.Recuperer_texte('mentions_legales','accueil','droits_auteur','texte_4').'

+

'.Recuperer_texte('mentions_legales','accueil','droits_auteur','texte_5').'

+ + + +

'.Recuperer_texte('mentions_legales','accueil','donnees_personnelles','titre').'

+

'.Recuperer_texte('mentions_legales','accueil','donnees_personnelles','texte_1').'

+

'.Recuperer_texte('mentions_legales','accueil','donnees_personnelles','texte_2').'

+
    '.Recuperer_texte('mentions_legales','accueil','donnees_personnelles','ul_li').'
+ + +

'.Recuperer_texte('mentions_legales','accueil','contact','titre').'

+

+ '.Recuperer_texte('mentions_legales','accueil','contact','texte_1').' + '.$_SESSION['Config__Adresse_email_contact'].' +

+

+ '.Recuperer_texte('mentions_legales','accueil','contact','texte_2').' + '.$_SESSION['Config__Adresse_email_alertes'].' +

+

+ '.Recuperer_texte('mentions_legales','accueil','contact','texte_3').' + gdpr@koriolan.tech +

+

+ '.Recuperer_texte('mentions_legales','accueil','contact','texte_4').' +

+

+ '.nl2br($_SESSION['Config__Adresse_postale_hebergement']).' +

+ +
'; + + echo '
'; + + + //******************************************************************************************************************************** + // Menu de pieds de page : +Pied_de_page(); diff --git a/html/shipmembers.php b/html/shipmembers.php new file mode 100644 index 0000000..aa4e36b --- /dev/null +++ b/html/shipmembers.php @@ -0,0 +1,1933 @@ +Si vous êtes le propriétaire de cette adresse, merci de vous connecter avec cette adresse.
Sinon, merci de choisir une autre adresse."); + } + } + Liberation_jeu_de_resultat_bdd($reponse); + } + + if ($message_erreur == "") // Si les contrôles ne sont pas invalides, on créé le nouvel utilisateur : + { + // Génération d'un MDP aléatoire : + $password = Mdp_aleatoire(6); // Si l'adresse email est vide, il est inutile de préparer un mdp... + + + // Création du ShipMember : + $requete = 'INSERT INTO TB_Shipmembers(Nom, Prenom, Entreprise, Rue, Code_postal, Ville, ID_PAYS, Telephone, Email, ID_LANGUAGES, ID_Stripe, Mdp, Date_creation_compte) VALUES (?,?,?,?,?,?,?,?,?,(SELECT ID FROM TB_Langues WHERE Prefix=?),?,?,?)'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['shipmember']['Nom']), + array('s', $_SESSION['shipmember']['Prenom']), + array('s', $_SESSION['shipmember']['Entreprise']), + array('s', $_SESSION['shipmember']['Rue']), + array('s', $_SESSION['shipmember']['Code_postal']), + array('s', $_SESSION['shipmember']['Ville']), + array('i', $_SESSION['shipmember']['ID_Pays']), + array('s', $_SESSION['shipmember']['Telephone']), + array('s', $_SESSION['shipmember']['Email']), + array('s', $_SESSION['langue']), + array('s', ""), + array('s', password_hash($password, PASSWORD_DEFAULT)), + array('s', date("Y-m-d H:i:s"))), + __FILE__, __LINE__); + + $_SESSION['shipmember']['Cle_primaire'] = Recuperation_id_cree_bdd(); + + $requete = 'INSERT INTO TB_Activation(ID_SHIPMEMBERS, Date_creation_mdp) VALUES (?, ?)'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['shipmember']['Cle_primaire']), + array('s', date("Y-m-d H:i:s"))), + __FILE__, __LINE__); + + // Mise à jour du libellé du pays : + $requete = 'SELECT Texte AS Libelle_pays FROM TB_Textes_traduction WHERE ID_TEXTES=(SELECT ID_NOM FROM TB_Pays WHERE ID=?) AND ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?)'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['ID_Pays']), + array('s', $_SESSION['langue'])), + __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + $_SESSION['shipmember']['libelle_pays'] = $donnees['Libelle_pays']; + Liberation_jeu_de_resultat_bdd($reponse); + + // Calcul de la date limite d'activation du compte : + $date = date_create("now"); // Date courante + date_add($date, date_interval_create_from_date_string(''.$_SESSION['Config__Time_out_activation_compte'].' days')); // Date courante + Nb jour configurés + $date_maxi_activation = date_format($date, "d/m/Y à H:i"); + + //......................................................................... + // Préparation et envoi de l'email de confirmation de création de compte : + $texte_email = t("

Félicitations !

+

Votre compte ShipMember est créé, vous y êtes presque.

+

Nom : [[Prenom]] [[Nom]]

+

Email : [[Email]]

+

Mot de passe provisoire : [[Password]]

+

Plus qu’un clic : Connectez-vous sur ShipHeart.tech pour valider votre compte ShipMember en modifiant votre mot de passe provisoire (*). C’est une garantie de sécurité à ne pas négliger.

+

Et ensuite, où que vous soyez et dès que votre ShipHeart est installé, accédez à votre bateau via votre accès privilégié ShipMember !

+

+

Bienvenue parmi nous !

+

L'équipage ShipHeart

+

+

(*) L'activation devra être faite avant le [[Date_maxi_activation]]. Mais pas d'inquiétude ; si vous ne le faites pas avant, vous pourrez toujours demander un nouveau mot de passe provisoire.

"); + + // Mise à jour des parametres du texte : + $texte_email = str_replace("[[Prenom]]", $_SESSION['shipmember']['Prenom'], $texte_email); + $texte_email = str_replace("[[Nom]]", $_SESSION['shipmember']['Nom'], $texte_email); + $texte_email = str_replace("[[Email]]", $_SESSION['shipmember']['Email'], $texte_email); + $texte_email = str_replace("[[Password]]", $password, $texte_email); + $texte_email = str_replace("[[Date_maxi_activation]]", $date_maxi_activation, $texte_email); + + Envoi_email('', $_SESSION['shipmember']['Email'], + t("Votre accès ShipMember - Un dernier clic pour accéder à votre bateau !"), + $texte_email, + "ShipHeart by Koriolan", $_SESSION['Config__Adresse_email_shipmember'], ''); + //Fin......................................................................... + + //............................................................................ + // Message d'information : + $message = t("Un email vient d'être envoyé à [[Prenom]] [[Nom]] ([[Email]]) avec un mot de passe provisoire."); + + $message = str_replace("[[Prenom]]", $_SESSION['shipmember']['Prenom'], $message); + $message = str_replace("[[Nom]]", $_SESSION['shipmember']['Nom'], $message); + $message = str_replace("[[Email]]", $_SESSION['shipmember']['Email'], $message); + + $message_information .= $message; + //Fin......................................................................... + + // Créer le lien bateau shipmember, affecter l'enregitrement a cet utilisateur : + if (isset($_SESSION['code_acces']) && $_SESSION['code_acces']!=''){ + $code = $_SESSION['code_acces']; + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Code="'.$code.'" AND ID_Shipmember=0'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + Liberation_jeu_de_resultat_bdd($reponse); + if ($donnees == NULL) $message_erreur .= "Code invalide ou déjà utilisé \n"; + else + { + $sous_req = 'UPDATE TB_Lien_bateau_shipmember SET ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' WHERE Validite=1 AND Code="'.$code.'" AND ID_Shipmember=0'; + $sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__); + } + $_SESSION['code_acces'] = ''; + } + + // Récupération des liaisons shipmember - bateau + + $current_timestamp = date_format(date_create(), 'Y-m-d H:i:s'); + $requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $nb_acces = 0; + // $bateau_shipmember = [] + while ($donnees = Recherche_ligne_bdd($reponse)) { + $_SESSION['bateau_shipmember'][$nb_acces++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + $_SESSION['acces'] = $nb_acces; + $_SESSION['acces_valide'] = true; + $_SESSION['Shipmembers']['page'] = "Accueil"; + } + } + + + //--------------------------------------------------------------------------- + // Lecture de l'email et du mot de passe et filtrage contre les injections SQL : + if (isset($_POST['validation_login_shipmember']) AND isset($_POST['email_validation']) AND isset($_POST['mdp_validation'])) + { + // if (preg_match("#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#", $_POST['email_validation']) != 1) $message_information .= "Erreur de PERG MATCH
"; + + if (($_POST['email_validation'] != NULL) AND + ($_POST['mdp_validation'] != NULL) AND + (preg_match("#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#", $_POST['email_validation']) == 1)) // Ce Preg-Match semble bien plus efficace que le "filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)"... + { + $email = Protection_mysql(strtolower($_POST['email_validation'])); // On ajoute les caractères d'échappement sur l'email qui sera envoyé dans la requête + $mdp = $_POST['mdp_validation']; // Le MDP n'est pas envoyé... + + $requete = 'SELECT ID AS Cle_primaire, Validite, Nom, Prenom, Entreprise, Rue, Code_postal, Ville, Telephone, Email, ID_Stripe, Mdp, Date_creation_compte, Niveau_acces, ID_PAYS AS ID_Pays, ID_LANGUAGES, (SELECT 1 FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Compte_a_activer, (SELECT Date_creation_mdp FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Date_creation_mdp FROM TB_Shipmembers WHERE Email=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $email)), + __FILE__, __LINE__); + + while ($donnees = Recherche_ligne_bdd($reponse)) + { + if (password_verify($mdp, $donnees['Mdp'])) + { + + $_SESSION['shipmember'] = $donnees; // Sauvegarde des informations du ShipMember + + if ($donnees['Compte_a_activer'] != 0) + { + $date = date_create("now"); // Date courante + date_sub($date, date_interval_create_from_date_string(''.$_SESSION['Config__Time_out_activation_compte'].' days')); // Date courante - Nb jour configurés + $date_creation = date_create_from_format('Y-m-d H:i:s', $donnees['Date_creation_mdp']); + + if ($date < $date_creation) // Si le Mdp provisoire est toujours valable : + { + $_SESSION['Shipmembers']['page'] = "Activation"; + } + else // Si le Mdp provisoireest expiré : + { + $message_erreur .= t("Désolé, votre compte n'a pas été activé dans le délai maximal.
Vous pouvez demander la génération d'un nouveau mot de passe provisoire en cliquant sur le bouton ci-dessous. Il vous sera adressé immédiatement par email."); + } + } + else + { + // Mémorisation dans l'historique de la connexion : + $requete = 'INSERT INTO TB_Historique(Type, Sous_type, ID_ELEMENT, Valeur, Description) VALUES (?, ?, ?, ?, ?)'; + Requete_preparee_bdd($requete, + array( + array('i', SYSTEME), + array('i', SYSTEME_CONNEXION_USER), + array('i', $_SESSION['shipmember']['Cle_primaire']), + array('i', 0), + array('s', 'Connexion de '.$donnees['Prenom'].' '.$donnees['Nom'].' [N° '.$_SESSION['shipmember']['Cle_primaire'].']')), + __FILE__, __LINE__); + + // Recherche des informations du ShipMember : + $requete = 'SELECT ID AS Cle_primaire, Validite, Nom, Prenom, Entreprise, Rue, Code_postal, Ville, Telephone, Email, ID_Stripe, Mdp, Date_creation_compte, Niveau_acces, ID_PAYS AS ID_Pays, ID_LANGUAGES, (SELECT 1 FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Compte_a_activer, (SELECT Date_creation_mdp FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Date_creation_mdp FROM TB_Shipmembers WHERE ID=?'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) $_SESSION['shipmember'] = $donnees; + Liberation_jeu_de_resultat_bdd($reponse); + + // Mise à jour du libellé du pays : + $requete = 'SELECT Texte AS Libelle_pays FROM TB_Textes_traduction WHERE ID_TEXTES=(SELECT ID_NOM FROM TB_Pays WHERE ID=?) AND ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?)'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['ID_Pays']), + array('s', $_SESSION['langue'])), + __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + $_SESSION['shipmember']['libelle_pays'] = $donnees['Libelle_pays']; + Liberation_jeu_de_resultat_bdd($reponse); + + // Message de bienvenue : + $message_information .= t("Bienvenue !"); + + $_SESSION['acces_valide'] = true; + + // Créer le lien bateau shipmember, affecter l'enregitrement a cet utilisateur + if (isset($_SESSION['code_acces']) && $_SESSION['code_acces']!=''){ + $code = $_SESSION['code_acces']; + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Code="'.$code.'" AND ID_Shipmember=0'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + // Vérifier si le code est tjrs valable + if ($donnees == NULL){ + $message_erreur .= "Code invalide ou déjà utilisé \n"; + $_SESSION['code_acces'] = ''; + } + else { + $sous_req = 'UPDATE TB_Lien_bateau_shipmember SET ID_Shipmember = '.$_SESSION['shipmember']['Cle_primaire'].' WHERE Validite=1 AND Code="'.$code.'" AND ID_Shipmember=0'; + $sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__); + $_SESSION['code_acces'] = ''; + // $_SESSION['droits_acces'] = $donnees['Niveau_acces']; + } + } + + // Récupération des liaisons shipmember - bateau + + $current_timestamp = date_format(date_create(), 'Y-m-d H:i:s'); + $requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $nb_acces = 0; + // $bateau_shipmember = [] + while ($donnees = Recherche_ligne_bdd($reponse)) { + $_SESSION['bateau_shipmember'][$nb_acces++] = $donnees; + } + $_SESSION['acces'] = $nb_acces; + $_SESSION['Shipmembers']['page'] = "Accueil"; + } + + break; // Dans le cas où il y aurait plus d'une entrée avec le bon email ET le bon mdp, on ne traite que le premier... + } + // else $message_information .= "MDP ne matchent pas. "; + } + Liberation_jeu_de_resultat_bdd($reponse); + + } + // else $message_information .= "Email ou MDP non valides : [".$_POST['email_validation']."] et [".$_POST['mdp_validation']."]."; + else $message_erreur .= "Email ou MDP non valides"; + } + + + //--------------------------------------------------------------------------- + // Activation Shipmember : + if (isset($_POST['validation_activation_shipmember']) AND + isset($_POST['Mot_de_passe_1']) AND + isset($_POST['Mot_de_passe_2'])) + { + if (($_POST['Mot_de_passe_1'] == $_POST['Mot_de_passe_2']) AND (Check_mdp($_POST['Mot_de_passe_1']) == 1)) + { + $new_mdp = $_POST['Mot_de_passe_1']; + + // Recherche du MDP existant de l'adhérent : + $requete = 'SELECT ID AS Cle_primaire, Validite, Nom, Prenom, Entreprise, Rue, Code_postal, Ville, Telephone, Email, ID_Stripe, Mdp, Date_creation_compte, Niveau_acces, ID_PAYS AS ID_Pays, ID_LANGUAGES, (SELECT 1 FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Compte_a_activer, (SELECT Date_creation_mdp FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Date_creation_mdp FROM TB_Shipmembers WHERE ID=?'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) $shipmember = $donnees; + Liberation_jeu_de_resultat_bdd($reponse); + + // Vérification que le mot de passe est changé : +// if (Hash_Mdp($new_mdp) == $shipmember['Mdp']) $message_erreur .= nl2br(Recuperation_texte('all','all','erreurs','pwd_egal_temporaire')); + if (password_verify($new_mdp, $shipmember['Mdp'])) $message_erreur .= nl2br(t("Pour des raisons de sécurité, votre nouveau mot de passe ne peut pas être identique au mot de passe provisoire.")); + else + { + // Mise à jour du nouveau mot de passe : + $mdp_filtre = Protection_mysql($new_mdp); + $requete = 'UPDATE TB_Shipmembers SET Mdp=? WHERE ID=?'; + Requete_preparee_bdd($requete, + array( + array('s', password_hash($mdp_filtre, PASSWORD_DEFAULT)), + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + + $requete = 'DELETE FROM TB_Activation WHERE ID_SHIPMEMBERS=?'; + Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + + $_SESSION['acces_valide'] = true; + + // Récupération des liaisons shipmember - bateau + + $current_timestamp = date_format(date_create(), 'Y-m-d H:i:s'); + $requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $nb_acces = 0; + // $bateau_shipmember = [] + while ($donnees = Recherche_ligne_bdd($reponse)) { + $_SESSION['bateau_shipmember'][$nb_acces++] = $donnees; + } + $_SESSION['acces'] = $nb_acces; + // $_SESSION['acces_valide'] = true; + $_SESSION['Shipmembers']['page'] = "Accueil"; + + + $_SESSION['Shipmembers']['page'] = "Accueil"; + $message_information .= t("Félicitations : votre compte est maintenant activé et vous êtes d'ores et déjà connecté.e.").' !'; + } + } + else + { + if ($_POST['Mot_de_passe_1'] != $_POST['Mot_de_passe_2']) $message_erreur .= t("Les deux mots de passe saisis doivent être identiques."); + else $message_erreur .= nl2br(t("Le mot de passe renseigné n'est pas conforme. Pour la sécurité de vos données, il doit contenir entre 6 et 20 caractères, et être composé exclusivement de minuscules, de majuscules, de chiffres ou des caractères spéciaux suivants _-!*=.")); + } + } + + //--------------------------------------------------------------------------- + // Regenération du mot de passe : + if (isset($_POST['regenerer_mdp_shipmember']) AND isset($_POST['Email'])) + { + $_SESSION['shipmember']['Email'] = strtolower(trim($_POST['Email'])); + + // Vérifications : + if (preg_match("#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#", $_SESSION['shipmember']['Email']) != 1) // Ce Preg-Match semble bien plus efficace que le "filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)"... + { + $message_erreur .= t("[Email] est invalide !"); + } + + // Vérification si l'email existe bien dans la base : + if ($message_erreur == "") + { + $nb_emails_valides = 0; + + $requete = 'SELECT ID AS Cle_primaire, Validite, Nom, Prenom, Entreprise, Rue, Code_postal, Ville, Telephone, Email, ID_Stripe, Mdp, Date_creation_compte, Niveau_acces, ID_PAYS AS ID_Pays, ID_LANGUAGES, (SELECT 1 FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Compte_a_activer, (SELECT Date_creation_mdp FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Date_creation_mdp FROM TB_Shipmembers WHERE Validite=1 AND Email=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['shipmember']['Email'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $_SESSION['shipmember']['Cle_primaire'] = $donnees['Cle_primaire']; + $_SESSION['shipmember']['Prenom'] = $donnees['Prenom']; + $_SESSION['shipmember']['Nom'] = $donnees['Nom']; + $nb_emails_valides ++; + } + Liberation_jeu_de_resultat_bdd($reponse); + + if ($nb_emails_valides > 0) + { + // Génération d'un MDP aléatoire : + $password = Mdp_aleatoire(6); // Si l'adresse email est vide, il est inutile de préparer un mdp... + + // Mise à jour du nouveau mot de passe : + $requete = 'DELETE FROM TB_Activation WHERE ID_SHIPMEMBERS=?'; + Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + + $requete = 'UPDATE TB_Shipmembers SET Mdp=? WHERE ID=?'; + Requete_preparee_bdd($requete, + array( + array('s', password_hash($password, PASSWORD_DEFAULT)), + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + + $requete = 'INSERT INTO TB_Activation(ID_SHIPMEMBERS) VALUES (?)'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + + // Mémorisation dans l'historique de la connexion : + $requete = 'INSERT INTO TB_Historique(Type, Sous_type, ID_ELEMENT, Valeur, Description) VALUES (?, ?, ?, ?, ?)'; + Requete_preparee_bdd($requete, + array( + array('i', SYSTEME), + array('i', SYSTEME_REINIT_MDP_USER), + array('i', $_SESSION['shipmember']['Cle_primaire']), + array('i', 0), + array('s', 'Réinitialisation du mot de passe de '.$_SESSION['shipmember']['Prenom'].' '.$_SESSION['shipmember']['Prenom'].' [N° '.$_SESSION['shipmember']['Cle_primaire'].']')), + __FILE__, __LINE__); + + + // Calcul de la date limite d'activation du compte : + $date = date_create("now"); // Date courante + date_add($date, date_interval_create_from_date_string(''.$_SESSION['Config__Time_out_activation_compte'].' days')); // Date courante + Nb jour configurés + $date_maxi_activation = date_format($date, "d/m/Y à H:i"); + + //......................................................................... + // Préparation et envoi de l'email de regénération de mot de passe : + $texte_email = t("

Bonjour,

+

Le mot de passe de votre compte ShipMember vient d'être réinitialisé à votre demande.

+

Nom : [[Prenom]] [[Nom]]

+

Email : [[Email]]

+

Mot de passe provisoire : [[Password]]

+

Plus qu’un clic : Connectez-vous sur ShipHeart.tech pour activer votre compte ShipMember en modifiant votre mot de passe provisoire (*). C’est une garantie de sécurité à ne pas négliger...

+

Bienvenue à nouveau parmi nous !

+

L'équipage ShipHeart

+

+

(*) L'activation devra être faite avant le [[Date_maxi_activation]]. Mais pas d'inquiétude ; si vous ne le faites pas avant, vous pourrez toujours demander un nouveau mot de passe provisoire.

"); + + // Mise à jour des parametres du texte : + $texte_email = str_replace("[[Prenom]]", $_SESSION['shipmember']['Prenom'], $texte_email); + $texte_email = str_replace("[[Nom]]", $_SESSION['shipmember']['Nom'], $texte_email); + $texte_email = str_replace("[[Email]]", $_SESSION['shipmember']['Email'], $texte_email); + $texte_email = str_replace("[[Password]]", $password, $texte_email); + $texte_email = str_replace("[[Date_maxi_activation]]", $date_maxi_activation, $texte_email); + + Envoi_email('', $_SESSION['shipmember']['Email'], + t("Votre demande concernant votre accès ShipMember"), + $texte_email, + "ShipHeart by Koriolan", $_SESSION['Config__Adresse_email_shipmember'], ''); + //Fin......................................................................... + + //............................................................................ + // Message d'information : + $message = t("Un email vient d'être envoyé à [[Prenom]] [[Nom]] ([[Email]]) avec les informations relatives à votre inscription.")."
"; + + $message = str_replace("[[Prenom]]", $_SESSION['shipmember']['Prenom'], $message); + $message = str_replace("[[Nom]]", $_SESSION['shipmember']['Nom'], $message); + $message = str_replace("[[Email]]", $_SESSION['shipmember']['Email'], $message); + + $message_information .= $message; + //Fin......................................................................... + // Récupération des liaisons shipmember - bateau + + $current_timestamp = date_format(date_create(), 'Y-m-d H:i:s'); + $requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $nb_acces = 0; + // $bateau_shipmember = [] + while ($donnees = Recherche_ligne_bdd($reponse)) { + $_SESSION['bateau_shipmember'][$nb_acces++] = $donnees; + } + $_SESSION['acces'] = $nb_acces; + + $_SESSION['acces_valide'] = true; + $_SESSION['Shipmembers']['page'] = "Accueil"; + } + + $_SESSION['Shipmembers']['page'] = "Login"; + } + } + + //--------------------------------------------------------------------------- + // Modifications ShipMember : + if (isset($_POST['validation_modification_shipmember']) AND + isset($_POST['Prenom']) AND + isset($_POST['Nom']) AND + isset($_POST['Entreprise']) AND + isset($_POST['Rue']) AND + isset($_POST['Code_postal']) AND + isset($_POST['Ville']) AND + isset($_POST['ID_Pays']) AND + isset($_POST['Email']) AND + isset($_POST['Telephone']) AND + isset($_POST['Mot_de_passe_1']) AND + isset($_POST['Mot_de_passe_2'])) + { + // Mémorisation des valeurs saisies pour éviter de les perdre en cas d'erreur rendant la création impossible : + $old_email = $_SESSION['shipmember']['Email']; + $_SESSION['shipmember']['Prenom'] = trim($_POST['Prenom']); + $_SESSION['shipmember']['Nom'] = trim($_POST['Nom']); + $_SESSION['shipmember']['Entreprise'] = trim($_POST['Entreprise']); + $_SESSION['shipmember']['Rue'] = trim($_POST['Rue']); + $_SESSION['shipmember']['Code_postal'] = trim($_POST['Code_postal']); + $_SESSION['shipmember']['Ville'] = trim($_POST['Ville']); + $_SESSION['shipmember']['ID_Pays'] = $_POST['ID_Pays']; + $_SESSION['shipmember']['Telephone'] = trim($_POST['Telephone']); + $_SESSION['shipmember']['Email'] = strtolower(trim($_POST['Email'])); + + if ($old_email != $_SESSION['shipmember']['Email']) $flag_new_email = true; + else $flag_new_email = false; + + + // Vérifications : + $message_erreur .= check_longueur_champ('prenom_titre', $_SESSION['shipmember']['Prenom'], MIN_LONGUEUR_PRENOM, MAX_LONGUEUR_PRENOM); + $message_erreur .= check_longueur_champ('nom_titre', $_SESSION['shipmember']['Nom'], MIN_LONGUEUR_NOM, MAX_LONGUEUR_NOM); + $message_erreur .= check_longueur_champ('rue_titre', $_SESSION['shipmember']['Rue'], MIN_LONGUEUR_RUE, MAX_LONGUEUR_RUE); + $message_erreur .= check_longueur_champ('code_postal_titre', $_SESSION['shipmember']['Code_postal'], MIN_LONGUEUR_CODE_POSTAL, MAX_LONGUEUR_CODE_POSTAL); + $message_erreur .= check_longueur_champ('ville_titre', $_SESSION['shipmember']['Ville'], MIN_LONGUEUR_VILLE, MAX_LONGUEUR_VILLE); + $message_erreur .= check_longueur_champ('telephone_titre', $_SESSION['shipmember']['Telephone'], MIN_LONGUEUR_TELEPHONE, MAX_LONGUEUR_TELEPHONE); + + if (preg_match("#^[a-z0-9._-]+@[a-z0-9._-]{2,}\.[a-z]{2,4}$#", $_SESSION['shipmember']['Email']) != 1) // Ce Preg-Match semble bien plus efficace que le "filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)"... + { + $message_erreur .= t("[Email] est invalide !"); + } + + // Vérification si l'email n'existe pas déjà : + if (($message_erreur == "") AND ($flag_new_email)) + { + $requete = 'SELECT count(ID) AS Nb_shipmembers FROM TB_Shipmembers WHERE Validite=1 AND Email=?'; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['shipmember']['Email'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + if ($donnees['Nb_shipmembers'] != 0) + { + $message_erreur .= t("[Email] est déjà utilisée par un ShipMember.
Si vous êtes le propriétaire de cette adresse, merci de vous connecter avec cette adresse.
Sinon, merci de choisir une autre adresse."); + } + } + Liberation_jeu_de_resultat_bdd($reponse); + } + + // Vérification des nouveaux mots de passe : + $flag_new_pwd = false; + if (strlen($_POST['Mot_de_passe_1']) != 0) // Si le premier mot de passe est vide, on considère qu'aucune mise à jour de MDP n'est demandée. + { + if ($_POST['Mot_de_passe_1'] != $_POST['Mot_de_passe_2']) $message_erreur .= t("Les deux mots de passe saisis doivent être identiques."); + elseif (Check_mdp($_POST['Mot_de_passe_1']) != 1) $message_erreur .= t("Le mot de passe renseigné n'est pas conforme. Pour la sécurité de vos données, il doit contenir entre 6 et 20 caractères, et être composé exclusivement de minuscules, de majuscules, de chiffres ou des caractères spéciaux suivants _-!*=."); + else $flag_new_pwd = true; + } + + + + // Si les contrôles ne sont pas invalides, on met à jour le ShipMember : + if ($message_erreur == "") + { + $requete = 'UPDATE TB_Shipmembers SET Prenom=?, Nom=?, Entreprise=?, Rue=?, Code_postal=?, Ville=?, ID_Pays=?, Telephone=?, Email=? WHERE ID=?'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['shipmember']['Prenom']), + array('s', $_SESSION['shipmember']['Nom']), + array('s', $_SESSION['shipmember']['Entreprise']), + array('s', $_SESSION['shipmember']['Rue']), + array('s', $_SESSION['shipmember']['Code_postal']), + array('s', $_SESSION['shipmember']['Ville']), + array('i', $_SESSION['shipmember']['ID_Pays']), + array('s', $_SESSION['shipmember']['Telephone']), + array('s', Protection_mysql($_SESSION['shipmember']['Email'])), // On protège l'Email contre les injections car c'est lui qui va servir aux requetes tant qu'on n'a pas la Clé_primaire. + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + + // Mise à jour du nouveau mot de passe : + if ($flag_new_pwd) + { + $requete = 'UPDATE TB_Shipmembers SET Mdp=? WHERE ID=?'; + Requete_preparee_bdd($requete, + array( + array('s', password_hash(Protection_mysql($_POST['Mot_de_passe_1']), PASSWORD_DEFAULT)), + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + + $requete = 'DELETE FROM TB_Activation WHERE ID_SHIPMEMBERS=?'; + Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + // NB : on met à 0 le flag 'compte_a_activer' car il se peut qu'on soit là juste après la création (en accès temporaire). Dans ce cas, si on a mis à jour les mots de passe, + // il est inutile de demander ensuite une activation. + } + + // Mise à jour du libellé du pays : + $requete = 'SELECT Texte AS Libelle_pays FROM TB_Textes_traduction WHERE ID_TEXTES=(SELECT ID_NOM FROM TB_Pays WHERE ID=?) AND ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?)'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['ID_Pays']), + array('s', $_SESSION['langue'])), + __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + $_SESSION['shipmember']['libelle_pays'] = $donnees['Libelle_pays']; + Liberation_jeu_de_resultat_bdd($reponse); + + // Mise à jour de l'email : + if ($flag_new_email) + { + //......................................................................... + // Préparation et envoi de l'email de modification d'adresse email : + $texte_email = t("

Bonjour,

+

L'adresse email associée à votre compte ShipMember vient d'être modifiée à votre demande :

+

Ancienne adresse : [[Old_email]]

Nouvelle adresse : [[New_email]]

+

Si vous n'êtes pas à l'origine de ce changement d'adresse, merci de contacter sans attendre l'administrateur du site à : [[Adresse_email_alertes]].'

+

L'équipage ShipHeart

"); + + // Mise à jour des parametres du texte : + $texte_email = str_replace("[[Old_email]]", $old_email, $texte_email); + $texte_email = str_replace("[[New_email]]", $_SESSION['shipmember']['Email'], $texte_email); + $texte_email = str_replace("[[Adresse_email_alertes]]", $_SESSION['Config__Adresse_email_alertes'], $texte_email); + + Envoi_email('', $_SESSION['shipmember']['Email'], + t("Modifications de votre accès ShipMember"), + $texte_email, + "ShipHeart by Koriolan", $_SESSION['Config__Adresse_email_shipmember'], ''); + //Fin......................................................................... + + } + + $_SESSION['Shipmembers']['page'] = "Profil"; + } + + } + + + + +//************************************************************************************************************************************ +// Traitement des données +//************************************************************************************************************************************ + + // Protection contre les accès directs... : + if (($_SESSION['Shipmembers']['page'] != "Login") AND + ($_SESSION['Shipmembers']['page'] != "Activation") AND + ($_SESSION['Shipmembers']['page'] != "Generation_mdp") AND + (!$_SESSION['acces_valide'])) header('Location:shipmembers.php?action=navigation&destination=Login'); + + // $_SESSION['code_acces'] = $_GET['code_acces']; + // if (isset($_GET['code_acces']) && !isset($_SESSION['code_acces'])) $_SESSION['code_acces'] = $_GET['code_acces']; + + switch ($_SESSION['Shipmembers']['page']) + { + //**************************************************************************************************************************** + case "Login": + { + //--------------------------------------------------------------------- + // Saut à l'accueil sans login si on est déjà identifié : + if ($_SESSION['acces_valide'] && (!isset($_SESSION['code_acces']) || $_SESSION['code_acces'] == '') ) header('Location:shipmembers.php?action=navigation&destination=Accueil'); + else if ($_SESSION['acces_valide'] && (isset($_SESSION['code_acces']) && $_SESSION['code_acces'] != '') ) header('Location:shipmembers.php?action=navigation&destination=Accueil&code_acces='.$_SESSION['code_acces']); + //--------------------------------------------------------------------- + // Récupération des informations sur les pays : + $nb_pays = 0; + $requete = 'SELECT ID, ID AS Cle_primaire, Code_alpha2, Code_alpha3, (SELECT Texte AS Libelle_pays FROM TB_Textes_traduction WHERE ID_TEXTES=ID_NOM AND ID_TYPE = 1 AND ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?)) AS Nom FROM TB_Pays ORDER BY Nom ASC'; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['langue'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $pays[$nb_pays ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + break; + } + + //**************************************************************************************************************************** + case "Activation": + { + //--------------------------------------------------------------------- + // Saut à l'accueil sans login si on est déjà identifié : + if ($_SESSION['acces_valide']) header('Location:shipmembers.php?action=navigation&destination=Accueil'); + + break; + } + + //**************************************************************************************************************************** + case "Generation_mdp": + { + //--------------------------------------------------------------------- + // Saut à l'accueil sans login si on est déjà identifié : + if ($_SESSION['acces_valide']) header('Location:shipmembers.php?action=navigation&destination=Accueil'); + + break; + } + + //**************************************************************************************************************************** + case "Accueil": + { + // Mise à jour des données du ShipMember (au cas où) : + $requete = 'SELECT ID AS Cle_primaire, Validite, Nom, Prenom, Entreprise, Rue, Code_postal, Ville, Telephone, Email, ID_Stripe, Mdp, Date_creation_compte, Niveau_acces, ID_PAYS AS ID_Pays, ID_LANGUAGES, (SELECT 1 FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Compte_a_activer, (SELECT Date_creation_mdp FROM TB_Activation WHERE ID_SHIPMEMBERS=ID) AS Date_creation_mdp FROM TB_Shipmembers WHERE ID=?'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $_SESSION['shipmember'] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + + // Créer le lien bateau shipmember, affecter l'enregitrement a cet utilisateur + if (isset($_SESSION['code_acces']) && $_SESSION['code_acces']!=''){ + $code = $_SESSION['code_acces']; + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Code="'.$code.'" AND ID_Shipmember=0'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + // Vérifier si le code est tjrs valable + if ($donnees == NULL){ + $message_erreur .= "Code invalide ou déjà utilisé \n"; + $_SESSION['code_acces'] = ''; + } + else { + $sous_req = 'UPDATE TB_Lien_bateau_shipmember SET ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' WHERE Validite=1 AND Code="'.$code.'" AND ID_Shipmember=0'; + $sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__); + $_SESSION['code_acces'] = ''; + // $_SESSION['droits_acces'] = $donnees['Niveau_acces']; + } + } + + // Récupération des liaisons shipmember - bateau + + $current_timestamp = date_format(date_create(), 'Y-m-d H:i:s'); + $requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $nb_acces = 0; + // $bateau_shipmember = [] + while ($donnees = Recherche_ligne_bdd($reponse)) { + $_SESSION['bateau_shipmember'][$nb_acces++] = $donnees; + } + $_SESSION['acces'] = $nb_acces; + // $_SESSION['acces_valide'] = true; + + + break; + } + + //**************************************************************************************************************************** + case "Administration": + { + // Protection contre les accès directs : + if ((!$_SESSION['acces_valide']) OR ($_SESSION['shipmember']['Niveau_acces'] < NIVEAU_MINI_ACCES_ADMINISTATEUR)) header('Location:shipmembers.php?action=navigation&destination=Login'); + + // Récupération des informations sur les ShipMembers : + $nb_shipmembers = 0; + + $requete = 'SELECT * FROM TB_Shipmembers WHERE Validite=1 ORDER BY ID ASC'; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $shipmembers[$nb_shipmembers ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + break; + } + + //**************************************************************************************************************************** + case "Details": + { + // Modifier les droits d'accès d'un utilisateur + if (isset($_POST['acces'])){ + $requete = 'UPDATE TB_Shipmembers SET Niveau_acces=? WHERE ID=?'; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_POST['acces']), + array('i', $_SESSION['Shipmembers']['ID'])), + __FILE__, __LINE__); + + } + + // Récupération des informations sur le ShipMember : + $requete = 'SELECT *, (SELECT Texte FROM TB_Textes_traduction WHERE ID_TYPE = 1 AND ID_TEXTES=(SELECT ID_NOM FROM TB_Pays WHERE ID=TB_Shipmembers.ID_PAYS) AND ID_LANGUAGES=1) AS Libelle_pays FROM TB_Shipmembers WHERE ID='.$_SESSION['Shipmembers']['ID'].' '; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $shipmember = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + $requete = ''; + + // Récupération des informations sur le ou les bateaux accessibles à ce ShipMember : + $nb_bateaux = 0; + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE ID_SHIPMEMBER=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['Shipmembers']['ID'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateaux[$nb_bateaux ++]['Cle_primaire'] = $donnees['ID_Bateau']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + // Récupération des informations relatives à chacun des bateaux accessibles : + for ($i=0; $i<$nb_bateaux; $i ++) + { + $requete = 'SELECT * FROM TB_Bateaux WHERE Cle_primaire=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateaux[$i]['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateaux[$i] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + } + // Créer le lien bateau shipmember, affecter l'enregitrement a cet utilisateur + if (isset($_SESSION['code_acces']) && $_SESSION['code_acces']!=''){ + $code = $_SESSION['code_acces']; + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Code="'.$code.'" AND ID_Shipmember=0'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + // Vérifier si le code est tjrs valable + if ($donnees == NULL){ + $message_erreur .= "Code invalide ou déjà utilisé \n"; + $_SESSION['code_acces'] = ''; + } + else { + $sous_req = 'UPDATE TB_Lien_bateau_shipmember SET ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' WHERE Validite=1 AND Code="'.$code.'" AND ID_Shipmember=0'; + $sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__); + $_SESSION['code_acces'] = ''; + // $_SESSION['droits_acces'] = $donnees['Niveau_acces']; + } + } + + // Récupération des liaisons shipmember - bateau + + $current_timestamp = date_format(date_create(), 'Y-m-d H:i:s'); + $requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $nb_acces = 0; + // $bateau_shipmember = [] + while ($donnees = Recherche_ligne_bdd($reponse)) { + $_SESSION['bateau_shipmember'][$nb_acces++] = $donnees; + } + $_SESSION['acces'] = $nb_acces; + // $_SESSION['acces_valide'] = true; + + break; + } + + //**************************************************************************************************************************** + case "Profil": + { + //--------------------------------------------------------------------- + // Récupération des informations sur les pays : + $nb_pays = 0; + $requete = 'SELECT ID, Code_alpha2, Code_alpha3, (SELECT Texte FROM TB_Textes_traduction WHERE ID_TEXTES=ID_NOM AND ID_TYPE = 1 AND ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?)) AS Nom FROM TB_Pays WHERE ID=?'; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['langue']), + array('i', $_SESSION['shipmember']['ID_Pays'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $pays = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + break; + } + + //**************************************************************************************************************************** + case "Modifier_profil": + { + + //--------------------------------------------------------------------- + // Récupération des informations sur les pays : + $nb_pays = 0; + $requete = 'SELECT ID, ID AS Cle_primaire, Code_alpha2, Code_alpha3, (SELECT Texte AS Libelle_pays FROM TB_Textes_traduction WHERE ID_TEXTES=ID_NOM AND ID_TYPE = 1 AND ID_LANGUAGES=(SELECT ID FROM TB_Langues WHERE Prefix=?)) AS Nom FROM TB_Pays ORDER BY Nom ASC'; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['langue'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $pays[$nb_pays ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + break; + } + + + //**************************************************************************************************************************** + case "Bateau": + { + // Récupération des informations sur le ou les bateaux accessibles à ce ShipMember : + $nb_bateaux = 0; + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Validite_acces=1 AND ID_SHIPMEMBER=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $_SESSION['shipmember']['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateaux[$nb_bateaux ++]['Cle_primaire'] = $donnees['ID_Bateau']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + // Bateau demonstration pour les SM affectés à aucun bateau + + if ($nb_bateaux == 0){ + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Validite_acces=1 AND ID_SHIPMEMBER=? AND Code=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', 0), + array('s', "0000")), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateaux[$nb_bateaux ++]['Cle_primaire'] = $donnees['ID_Bateau']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + } + // Récupération des informations relatives à chacun des bateaux accessibles : + for ($i=0; $i<$nb_bateaux; $i ++) + { + $requete = 'SELECT * FROM TB_Bateaux WHERE Cle_primaire=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('i', $bateaux[$i]['Cle_primaire'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $bateaux[$i] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + } + + // Créer le lien bateau shipmember, affecter l'enregitrement a cet utilisateur + if (isset($_SESSION['code_acces']) && $_SESSION['code_acces']!=''){ + $code = $_SESSION['code_acces']; + $requete = 'SELECT * FROM TB_Lien_bateau_shipmember WHERE Validite=1 AND Code="'.$code.'" AND ID_Shipmember=0'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $donnees = Recherche_ligne_bdd($reponse); + // Vérifier si le code est tjrs valable + if ($donnees == NULL){ + $message_erreur .= "Code invalide ou déjà utilisé \n"; + $_SESSION['code_acces'] = ''; + } + else { + $sous_req = 'UPDATE TB_Lien_bateau_shipmember SET ID_Shipmember = '.$_SESSION['shipmember']['Cle_primaire'].' WHERE Validite=1 AND Code="'.$code.'" AND ID_Shipmember=0'; + $sous_rep = Requete_bdd($sous_req, __FILE__, __LINE__); + $_SESSION['code_acces'] = ''; + // $_SESSION['droits_acces'] = $donnees['Niveau_acces']; + } + } + + // Récupération des liaisons shipmember - bateau + + $current_timestamp = date_format(date_create(), 'Y-m-d H:i:s'); + $requete = 'SELECT ID_Bateau, ID_Type_acces_bateau_shipmember FROM TB_Lien_bateau_shipmember WHERE ID_Shipmember='.$_SESSION['shipmember']['Cle_primaire'].' AND Validite=1 AND Validite_acces=1 AND Fin_validite>="'.$current_timestamp.'"'; + $reponse = Requete_bdd($requete, __FILE__, __LINE__); + $nb_acces = 0; + // $bateau_shipmember = [] + while ($donnees = Recherche_ligne_bdd($reponse)) { + $_SESSION['bateau_shipmember'][$nb_acces++] = $donnees; + } + $_SESSION['acces'] = $nb_acces; + // $_SESSION['acces_valide'] = true; + + break; + } + + //**************************************************************************************************************************** + default: + { + $_SESSION['Shipmembers']['page'] = "Accueil"; + break; + } + } + + Fermeture_bdd(); // Déconnexion de MySQL + + +//************************************************************************************************************************************ +// Affichage +//************************************************************************************************************************************ + + Entete_page_html(); + + //******************************************************************************************************************************** + // Affichage principal : + echo '
'; + + echo '
'; // Permet de remonter au début de page par défaut + + //========================================================================================= + // Entête : + Entete_page($message_erreur, $message_information); + // if (isset($_SESSION['code_acces'])) echo $_SESSION['code_acces']; + switch ($_SESSION['Shipmembers']['page']) + { + //************************************************************************************************************************ + case "Login": + { + echo '
'; + + echo '

'.t("Connectez-vous").'

'; + + echo '
'; + + //--------------------------------------------------------------------------- + // Déjà ShipMember : + echo ''; + + + //--------------------------------------------------------------------------- + // Nouveau ShipMember : + echo ''; + + echo '
'; + + break; + } + + + //************************************************************************************************************************ + case "Activation": + { + echo '
'; + + echo '

'.t("Mon espace ShipMember").'

'; + + echo '
'; + + echo '
'; + + echo '

'.t("Activation de mon compte").'

'; + + echo '
+

'.t("Votre compte n'a pas encore été activé. Pour cela, merci de changer votre mot de passe provisoire ci-dessous.").'

+
'; + + echo '
'; + + echo '
+
'.t("Prénom").'
+
'.$_SESSION['shipmember']['Prenom'].'
+
'; + + echo '
+
'.t("Nom").'
+
'.$_SESSION['shipmember']['Nom'].'
+
'; + + echo '
+
'.t("Email").'
+
'.$_SESSION['shipmember']['Email'].'
+
'; + + echo '
+
'.t("Nouveau mot de passe").'
+
+ +
+
'; + + echo '
+
'.t("Nouveau mot de passe (2)").'
+
+ +
+
'; + + echo '
'; + + echo '
+ +
'; + + echo '
'; + + echo '
'; + + echo '
'; + + break; + } + + //************************************************************************************************************************ + case "Generation_mdp": + { + echo '
'; + + echo '

'.t("Mon espace ShipMember").'

'; + + echo '
'; + + echo '
'; + + echo '

'.t("Générer un nouveau mot de passe provisoire").'

'; + + echo '
+

'.t("Renseignez votre adresse email puis confirmez votre demande.
Si votre adresse existe bien dans la liste des ShipMembers, un email vous sera adressé immédiatement avec un nouveau mot de passe provisoire.").'

+

'.t("Attention : dès validation, seul ce nouveau mot de passe provisoire sera valide pour vous connecter. Si vous n'avez pas reçu cet email dans les prochaines minutes, merci de vérifier s'il ne se trouve pas dans vos courriers indésirables. ").'

+
'; + + echo '
'; + + echo '
+
+ '.t("Email").'* +
+
+ +
+
'; + + echo '
'; + + echo '
+ +
'; + + echo '
'; + + echo '
'; + + echo '
'; + + break; + } + + + //************************************************************************************************************************ + case "Accueil": + { + echo '
'; + + echo '

'.t("Mon espace ShipMember").'

'; + + echo '
'; + + echo '
+

'.t("Bienvenue dans votre espace ShipMember !").'

+

'.t("Vous trouverez ici toutes les informations que nous conservons vous concernant. Notre objectif est de ne conserver que celles nécessaires au traitement de vos commandes et, surtout, vous permettant de profiter pleinement de toutes les fonctions de votre ShipHeart.").'

+

'.t("Enfin, nous vous rappelons que Koriolan ne diffuse et ne diffusera jamais la moindre de ces informations à d'autres sociétés. Pour plus de précisions sur le traitement de vos données personnelles, n'hésitez pas à consulter nos mentions légales accessibles en bas de cette page.").'

+
'; + + echo '
'; + + echo '
'; +// echo Ajouter_lien_modif_buttons('shipmember','accueil','espace_shipmember','menu_1_a_texte'); + echo ' + '.t("Mes informations").' + '; + + echo ' + '.t("Mon bateau").' + '; + + echo ' + '.t("Déconnexion").' + '; + + // Accès au menu d'administration : + // if (isset($_SESSION['shipmember']['Niveau_administration']) && $_SESSION['shipmember']['Niveau_administration'] != '') + if ($_SESSION['shipmember']['Niveau_acces'] >= NIVEAU_MINI_ACCES_ADMINISTATEUR) + { + echo ' + Administration + '; + } + + echo '
'; + + echo ''; + + break; + } + + //************************************************************************************************************************ + case "Administration": + { + echo '
'; + + echo '

Administration

'; + + echo '

ShipMembers

'; + + echo ' + + + + + + + + + '; + for ($i = 0; $i < $nb_shipmembers; $i ++) + { + echo ' + + + + + '; + } + echo ' +
NomEntrepriseTelephoneEmail
+ + '.$shipmembers[$i]['Prenom'].' '.$shipmembers[$i]['Nom'].' + + '.$shipmembers[$i]['Entreprise'].''.$shipmembers[$i]['Telephone'].''.$shipmembers[$i]['Email'].'
'; + + echo '
'; + echo 'Retour au menu Administration'; + echo '
'; + + echo '
'; + + break; + } + + //************************************************************************************************************************ + case "Details": + { + echo '
'; + + echo '

Administration

'; + + echo '

ShipMember n° '.$shipmember['ID'].'

'; + + echo ' + '; + echo ' + + + '; + + echo ' + + + '; + + echo ' + + + '; + + echo ' + + + '; + + echo ' + + + '; + + echo ' + + + '; + + echo ' + + + '; + + + echo ' + + + '; + + + + echo ' +
Nom complet'.$shipmember['Prenom'].' '.$shipmember['Nom'].'
Entreprise'.$shipmember['Entreprise'].'
Adresse'.$shipmember['Rue'].' - '.$shipmember['Code_postal'].' '.$shipmember['Ville'].' - '.$shipmember['Libelle_pays'].'
Téléphone'.$shipmember['Telephone'].'
Email'.$shipmember['Email'].'
Date création du compte'.Formatage_date($shipmember['Date_creation_compte']).'
Niveau d\'accès
+ + +
+
Bateaux accessibles'; + if ($nb_bateaux == 0) echo 'Aucun...'; + else + { + for ($i=0; $i<$nb_bateaux; $i ++) + { + echo $bateaux[$i]['Nom'].'
'; + } + } + echo '
'; + + echo ''; + + echo '
'; + + break; + } + + //************************************************************************************************************************ + case "Profil": + { + echo '
'; + + echo '

'.t("Mon espace ShipMember").'

'; + + echo '
'; + + //--------------------------------------------------------------------------- + // Profil ShipMember : + echo '
'; + + echo '

'.t("Mes informations").'

'; + + /* echo '
+
+ '.t("Numéro de ShipMember").' +
+
+ '.$_SESSION['shipmember']['Cle_primaire'].' +
+
'; */ + + echo '
+
+ '.t("Prénom").' +
+
+ '.$_SESSION['shipmember']['Prenom'].' +
+
'; + + echo '
+
+ '.t("Nom").' +
+
+ '.$_SESSION['shipmember']['Nom'].' +
+
'; + + echo '
+
+ '.t("Entreprise").' +
+
+ '.$_SESSION['shipmember']['Entreprise'].' +
+
'; + + echo '
+
+ '.t("Numéro et rue").' +
+
+ '.$_SESSION['shipmember']['Rue'].' +
+
'; + + echo '
+
+ '.t("Code postal").' +
+
+ '.$_SESSION['shipmember']['Code_postal'].' +
+
'; + + echo '
+
+ '.t("Ville").' +
+
+ '.$_SESSION['shipmember']['Ville'].' +
+
'; + + echo '
+
+ '.t("Pays").' +
+
+ '.$pays['Nom'].' +
+
'; + + echo '
+
+ '.t("Téléphone").' +
+
+ '.$_SESSION['shipmember']['Telephone'].' +
+
'; + + echo '
+
+ '.t("Email").' +
+
+ '.$_SESSION['shipmember']['Email'].' +
+
'; + + echo '
'; + + + echo '
'; + echo Ajouter_lien_modif_buttons('shipmember','profil','bas_de_page','modifier_a_texte'); + echo ' + '.t("Modifier").' + '; + + echo Ajouter_lien_modif_buttons('shipmember','profil','bas_de_page','retour_a_texte'); + echo ' + '.t("Retour").' + '; + echo '
'; + + echo '
'; + + break; + } + + //************************************************************************************************************************ + case "Modifier_profil": + { + echo '
'; + + echo '

'.t("Modifier mes informations").'

'; + + echo '
'; + + //--------------------------------------------------------------------------- + // Profil ShipMember : + echo '
'; + + echo '

'.t("Modifier mes informations").'

'; + + echo '
+
+ '.t("Prénom").'* +
+
+ +
+
'; + + echo '
+
+ '.t("Nom").'* +
+
+ +
+
'; + + echo '
+
+ '.t("Entreprise").' +
+
+ +
+
'; + + echo '
+
+ '.t("Numéro et rue").' +
+
+ +
+
'; + + echo '
+
+ '.t("Code postal").' +
+
+ +
+
'; + + echo '
+
+ '.t("Ville").' +
+
+ +
+
'; + + echo '
+
+ '.t("Pays").' +
+
+ +
+
'; + + echo '
+
+ '.t("Téléphone").' +
+
+ +
+
'; + + echo '
+
+ '.t("Email").'* +
+
+ +
+
'; + + + // Modification MDP : + echo '
+

'.t("Si vous souhaitez modifier votre mot de passe, entrez votre nouveau mot de passe deux fois ci-dessous. Sinon, laissez ces deux champs vides.").'

+
'; + + echo '
+
'.t("Nouveau mot de passe").'
+
+ +
+
'; + + echo '
+
'.t("Nouveau mot de passe (2)").'
+
+ +
+
'; + + + echo '
'; + + echo '
'; + echo ''; + + echo ' + '.t("Annuler").' + '; + echo '
'; + + echo '
'; + + break; + } + + + //************************************************************************************************************************ + case "Bateau": + { + echo '
'; + + echo '

'.t("Mon espace ShipMember").'

'; + + echo '
'; + + echo '
'; + + if ($nb_bateaux > 1) echo '

'.t("Accès à mes bateaux").'

'; + else echo '

'.t("Accès à mon bateau").'

'; + + if ($nb_bateaux == 0) // Si aucun bateau n'est configuré pour ce ShipMember : + { + echo '
+

'.t("Vous n'avez pas encore de ShipHeart activé.").'

+

'.t("Mais dès que ce sera le cas, vous trouverez ici l'accès à votre ou vos bateaux.").'

+

'.t("Pour chacun d'eux, vous visualiserez l'état de tous les circuits, leur consommation, le niveau des réservoirs et des batteries, mais aussi toutes les valeurs de vos capteurs : températures, pression atmosphérique, humidité, position géographique, etc...
Vous aurez également accès aux courbes historiques de toutes ces valeurs.").'

+

'.t("C'est également ici que vous pourrez créer des profils [Propriétaire], [Installateur] ou [Skipper] afin de donner accès de façon contrôlée à votre ou à vos bateaux. Sans aucune limite !").'

+
'; + } + else // Si au moins un bateau est configuré pour ce ShipMember + { + for ($i=0; $i<$nb_bateaux; $i ++) + { + + echo ' + '.$bateaux[$i]['Nom'].' + '; + + } + } + + echo '
'; + + echo '
'; + echo ' + '.t("Retour").' + '; + echo '
'; + + echo '
'; + + break; + } + + + } + + + echo '
'; + + echo '
'; + + + //******************************************************************************************************************************** + // Menu de pieds de page : +Pied_de_page(); diff --git a/html/textes.php b/html/textes.php new file mode 100644 index 0000000..427df41 --- /dev/null +++ b/html/textes.php @@ -0,0 +1,497 @@ +'; + + //========================================================================================= + // Entête : + Entete_page($message_erreur, $message_information); + + switch ($_SESSION['Textes']['page']) + { + //************************************************************************************************************************ + case "Accueil": + { + + echo '
'; + + if ($_SESSION['texte_fichier'] == ""){ + echo '

Ajouter un texte

'; + echo '
+
+
+ + + + + + + + +
+
+ + + + + + + +
+ + + +
+ + +
+ + + +
+ + +
'; + } + + if ($_SESSION['texte_fichier'] != ""){ + echo '

Modifier le texte

'; + echo '
+
+
+ + + + + + + + +
+
+ + + + + + + +
+ + + +
+ + +
+ + + +
+ + +
'; + } + + echo '
'; + + + break; + } + + + + + } + + echo '
'; + +Pied_de_page(); +?> + + \ No newline at end of file diff --git a/html/uploads.php b/html/uploads.php new file mode 100644 index 0000000..c1f264f --- /dev/null +++ b/html/uploads.php @@ -0,0 +1,198 @@ +'; + + //========================================================================================= + // Entête : + Entete_page($message_erreur, $message_information); + + switch ($_SESSION['Uploads']['page']) + { + //************************************************************************************************************************ + case "Accueil": + { + echo '
'; + + echo '

Uploads

'; + + echo '

Nb total de fichiers traités = '.$nb_total_fichiers.' (maxi = '.$max_nb_total_fichiers.') en '.$execution_time.' secondes

'; + + for ($i = 0; $i < $nb_repertoires_bateaux; $i ++) + { + if ($repertoires_bateaux[$i]['nb_fichiers'] == 0) continue; + + echo '

Fichiers traités pour le bateau '.$repertoires_bateaux[$i]['nom_bateau'].'

'; + + echo '

Nb de fichiers traités pour ce bateau = '.$repertoires_bateaux[$i]['nb_fichiers'].'

'; + + echo ' + + + + + + + '; + for ($j = 0; $j < $repertoires_bateaux[$i]['nb_fichiers']; $j ++) + { + echo ' + '; + if ($repertoires_bateaux[$i]['resultats'][$j] == "Ok") echo ''; + } + echo ' +
FichierRésultat
'.($j+1).' - '.$repertoires_bateaux[$i]['fichiers'][$j].''; + else echo ''; + + echo $repertoires_bateaux[$i]['resultats'][$j].'
'; + } + + echo '
'; + echo 'Retour au menu Administration'; + echo '
'; + + echo '
'; + + break; + } + + //************************************************************************************************************************ + default: + { + break; + } + } + + echo '
'; + + + + +Pied_de_page(); diff --git a/html/versions.php b/html/versions.php new file mode 100644 index 0000000..3484649 --- /dev/null +++ b/html/versions.php @@ -0,0 +1,1531 @@ +'; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $versions[$nb_versions ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + if ($nb_versions == 0) $_SESSION['Versions']['page'] = "Confirmation_suppression_version"; // Si aucune version de ShipHeart ne l'utilise, on passe à l'étape de confitmation finale. + else // Sinon, on indique une erreur et on affiche les versions l'utilisant (limitée à N lignes...) + { + $flag_redirection = true; // Evite que le message d'erreur soit supprimé par la redirection de purge d'URL + $message_erreur = "Vous ne pouvez pas supprimer cette version qui est utilisée dans les versions de ShipHeart suivantes :"; + for ($i = 0; $i < $nb_versions; $i ++) + { + if ($i < 10) $message_erreur .= "
".$versions[$i]['Nom']."
"; + else + { + $message_erreur .= "
[...]"; + break; + } + } + } + } + } + + break; + } + + //=================================== + case "confirmation_suppression_version": + { + if ((isset($_GET['type_version'])) && (isset($_GET['id_version']))) + { + $_SESSION['Versions']['type_version'] = $_GET['type_version']; + $_SESSION['Versions']['version']['Cle_primaire'] = $_GET['id_version']; + + // Suppression de la version (ou du package) : +// $requete = 'UPDATE '.$types_version[$_SESSION['Versions']['type_version']][1].' SET Validite=0 WHERE Cle_primaire=?'; + $requete = 'DELETE FROM '.$types_version[$_SESSION['Versions']['type_version']][1].' WHERE Cle_primaire=?'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['Versions']['version']['Cle_primaire'])), + __FILE__, __LINE__); + + $flag_redirection = true; // Evite que le message d'erreur soit supprimé par la redirection de purge d'URL + + if ($types_version[$_SESSION['Versions']['type_version']][3] != "package") + { + if ($types_version[$_SESSION['Versions']['type_version']][2] == "Fichier") + { + // Détermination du nom complet du fichier : + $dossier = REPERTOIRE_VERSIONS_SHIPHEART.$types_version[$_SESSION['Versions']['type_version']][5]; // Dossier de stockage des fichiers + $fichier = $dossier.'/'.$_SESSION['Versions']['version']['Fichier']; + + // Suppression du fichier sur le serveur : + if (unlink($fichier)) $message_information = "La version ".$_SESSION['Versions']['version']['Fichier']." a été supprimée de la base de données et le fichier correspondant a été supprimé du serveur."; + else $message_erreur = "La version ".$_SESSION['Versions']['version']['Fichier']." a bien été supprimée de la base de données mais le fichier correspondant n'a pas pu être supprimé du serveur."; + } + // RAZ des variables de session de la version qui vient d'être supprimée : + $_SESSION['Versions']['version']['Cle_primaire'] = 0; + $_SESSION['Versions']['version']['Fichier'] = ""; + $_SESSION['Versions']['version']['Description'] = ""; + } + else $message_information = "Le package ".$_SESSION['Versions']['version']['Nom']." a été supprimée de la base de données."; + + $_SESSION['Versions']['page'] = "Liste_versions"; + } + + break; + } + + //=================================== + case "demande_generation_archive": + { + if ((isset($_GET['type_version'])) && (isset($_GET['id_version']))) + { + $_SESSION['Versions']['type_version'] = $_GET['type_version']; + $_SESSION['Versions']['version']['Cle_primaire'] = $_GET['id_version']; + $_SESSION['Versions']['page'] = "Generation_archive"; + } + + break; + } + } + + if (!$flag_redirection) header('Location:versions.php'.$_SESSION['Versions']['ancre'].''); + } + + + // Variables POST : + + //--------------------------------------------------------------------------- + // Création Package : + if ( (isset($_POST['validation_creation_package']) OR + isset($_POST['validation_modification_package'])) AND + isset($_POST['Nom']) AND + isset($_POST['ID_Version_appli']) AND + isset($_POST['ID_Version_qt']) AND + isset($_POST['ID_Version_compagnon_v1']) AND + isset($_POST['ID_Version_compagnon_v2']) AND + isset($_POST['ID_Version_sp812']) AND + isset($_POST['ID_Version_sp4ac']) AND + isset($_POST['ID_Version_sp8dc']) AND + isset($_POST['ID_Version_sbs']) AND + isset($_POST['ID_Version_sql']) AND + isset($_POST['ID_Version_www']) AND + isset($_POST['ID_Version_updater']) AND + isset($_POST['Description_interne']) AND + isset($_POST['Description_externe'])) + { + // Mémorisation des valeurs saisies pour éviter de les perdre en cas d'erreur rendant la création impossible : + $_SESSION['Versions']['version']['Nom'] = trim($_POST['Nom']); + $_SESSION['Versions']['version']['Date'] = trim($_POST['Date']); + $_SESSION['Versions']['version']['ID_Version_appli'] = trim($_POST['ID_Version_appli']); + $_SESSION['Versions']['version']['ID_Version_qt'] = trim($_POST['ID_Version_qt']); + $_SESSION['Versions']['version']['ID_Version_compagnon_v1'] = trim($_POST['ID_Version_compagnon_v1']); + $_SESSION['Versions']['version']['ID_Version_compagnon_v2'] = trim($_POST['ID_Version_compagnon_v2']); + $_SESSION['Versions']['version']['ID_Version_sp812'] = trim($_POST['ID_Version_sp812']); + $_SESSION['Versions']['version']['ID_Version_sp4ac'] = trim($_POST['ID_Version_sp4ac']); + $_SESSION['Versions']['version']['ID_Version_sp8dc'] = trim($_POST['ID_Version_sp8dc']); + $_SESSION['Versions']['version']['ID_Version_sbs'] = trim($_POST['ID_Version_sbs']); + $_SESSION['Versions']['version']['ID_Version_sql'] = $_POST['ID_Version_sql']; + $_SESSION['Versions']['version']['ID_Version_www'] = $_POST['ID_Version_www']; + $_SESSION['Versions']['version']['ID_Version_updater'] = trim($_POST['ID_Version_updater']); + $_SESSION['Versions']['version']['Description_interne'] = trim($_POST['Description_interne']); + $_SESSION['Versions']['version']['Description_externe'] = trim($_POST['Description_externe']); + + // Vérifications : + + // Vérification que le nom n'est pas vide : + if ($_SESSION['Versions']['version']['Nom'] == "") $message_erreur .= "Le nom du package ne peut pas être vide..."; + + // Si les contrôles ne sont pas invalides, on créé le nouveau package : + if ($message_erreur == "") + { + if (isset($_POST['validation_creation_package'])) + { + // Recherche des versions de ShipHeart qui auraient le même nom : + $nb_versions = 0; + $requete = 'SELECT * FROM TB_Versions WHERE Validite=1 AND Nom=? '; + $reponse = Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['Versions']['version']['Nom'])), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $nb_versions ++; + } + Liberation_jeu_de_resultat_bdd($reponse); + if ($nb_versions > 0) $message_erreur .= "Le nom du package [".$_SESSION['Versions']['version']['Nom']."] est déjà utilisé. Vous ne pouvez pas l'utiliser à nouveau..."; + + if ($message_erreur == "") + { + // Création de la version : + $requete = 'INSERT INTO TB_Versions (Nom, Date, ID_Version_appli, ID_Version_qt, ID_Version_compagnon_v1, ID_Version_compagnon_v2, ID_Version_sp812, ID_Version_sp4ac, ID_Version_sp8dc, ID_Version_sbs, ID_Version_sql, ID_Version_www, ID_Version_updater, Description_interne, Description_externe) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['Versions']['version']['Nom']), + array('s', $_SESSION['Versions']['version']['Date']), + array('i', $_SESSION['Versions']['version']['ID_Version_appli']), + array('i', $_SESSION['Versions']['version']['ID_Version_qt']), + array('i', $_SESSION['Versions']['version']['ID_Version_compagnon_v1']), + array('i', $_SESSION['Versions']['version']['ID_Version_compagnon_v2']), + array('i', $_SESSION['Versions']['version']['ID_Version_sp812']), + array('i', $_SESSION['Versions']['version']['ID_Version_sp4ac']), + array('i', $_SESSION['Versions']['version']['ID_Version_sp8dc']), + array('i', $_SESSION['Versions']['version']['ID_Version_sbs']), + array('i', $_SESSION['Versions']['version']['ID_Version_sql']), + array('i', $_SESSION['Versions']['version']['ID_Version_www']), + array('i', $_SESSION['Versions']['version']['ID_Version_updater']), + array('s', $_SESSION['Versions']['version']['Description_interne']), + array('s', $_SESSION['Versions']['version']['Description_externe'])), + __FILE__, __LINE__); + + // Récup de la clé primaire de l'enregistrement créé : + $_SESSION['Versions']['version']['Cle_primaire'] = Recuperation_id_cree_bdd(); + + // Message d'information : + $message_information = "La version ".$_SESSION['Versions']['version']['Nom']." vient d'être créée"; + } + } + else if (isset($_POST['validation_modification_package'])) + { + // Mise à jour de la version : + $requete = 'UPDATE TB_Versions SET Nom=?, Date=?, ID_Version_appli=?, ID_Version_qt=?, ID_Version_compagnon_v1=?, ID_Version_compagnon_v2=?, ID_Version_sp812=?, ID_Version_sp4ac=?, ID_Version_sp8dc=?, ID_Version_sbs=?, ID_Version_sql=?, ID_Version_www=?, ID_Version_updater=?, Description_interne=?, Description_externe=? WHERE Cle_primaire=?'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['Versions']['version']['Nom']), + array('s', $_SESSION['Versions']['version']['Date']), + array('i', $_SESSION['Versions']['version']['ID_Version_appli']), + array('i', $_SESSION['Versions']['version']['ID_Version_qt']), + array('i', $_SESSION['Versions']['version']['ID_Version_compagnon_v1']), + array('i', $_SESSION['Versions']['version']['ID_Version_compagnon_v2']), + array('i', $_SESSION['Versions']['version']['ID_Version_sp812']), + array('i', $_SESSION['Versions']['version']['ID_Version_sp4ac']), + array('i', $_SESSION['Versions']['version']['ID_Version_sp8dc']), + array('i', $_SESSION['Versions']['version']['ID_Version_sbs']), + array('i', $_SESSION['Versions']['version']['ID_Version_sql']), + array('i', $_SESSION['Versions']['version']['ID_Version_www']), + array('i', $_SESSION['Versions']['version']['ID_Version_updater']), + array('s', $_SESSION['Versions']['version']['Description_interne']), + array('s', $_SESSION['Versions']['version']['Description_externe']), + array('s', $_SESSION['Versions']['version']['Cle_primaire'])), + __FILE__, __LINE__); + + // Message d'information : + $message_information = "La version ".$_SESSION['Versions']['version']['Nom']." vient d'être modifiée"; + } + $_SESSION['Versions']['page'] = "Liste_versions"; + } + } + + //--------------------------------------------------------------------------- + // Création Version : + if ((isset($_POST['validation_creation_version']) OR + isset($_POST['validation_modification_version'])) AND + isset($_POST['Description'])) + { + // Mémorisation des valeurs saisies pour éviter de les perdre en cas d'erreur rendant la création impossible : + $_SESSION['Versions']['version']['Description'] = trim($_POST['Description']); + if (isset($_POST['Repertoire'])) $_SESSION['Versions']['version']['Repertoire'] = trim($_POST['Repertoire']); + + if (isset($_POST['validation_creation_version'])) + { + do // Dummy loop pour gérer les sorties sur erreur... + { + + + if($types_version[$_SESSION['Versions']['type_version']][2] == "Fichier") + { + + // Traitement des erreurs HTML : + if ($_FILES['new_file']['error']) + { + switch ($_FILES['new_file']['error']) + { + case 1: // UPLOAD_ERR_INI_SIZE (limite de PHP.INI) + { + $message_erreur = 'La taille du fichier est trop importante (taille maxi = '.number_format(MAX_TAILLE_FICHIER_VERSION, 0, ".", " ").' octets) [erreur #1]'; + break; + } + case 2: // UPLOAD_ERR_FORM_SIZE (limite du formulaire HTML) + { + $message_erreur = 'La taille du fichier est trop importante (taille maxi = '.number_format(MAX_TAILLE_FICHIER_VERSION, 0, ".", " ").' octets) [erreur #2]'; + break; + } + case 3: // UPLOAD_ERR_PARTIAL (interruption pendant le téléchargement) + { + $message_erreur = "Le téléchargement du fichier a été interrompu pendant le transfert... [erreur #3]"; + break; + } + case 4: // UPLOAD_ERR_NO_FILE (tentative de téléchargement d'un fichier vide) + { + $message_erreur = "Le fichier que vous avez essayé de télécharger a une taille nulle... [erreur #4]"; + break; + } + } + break; + } + if ($message_erreur != "") break; // Sortie de la dummy loop + + /* // Vérifications de l'extension du fichier : + $extension = strrchr($_FILES['new_file']['name'], '.'); // Extension du fichier téléchargé + + switch ($extension) + { + case ".pdf": + case ".PDF": + { + $extension = ".pdf"; + break; + } + default : + { + $message_erreur = 'Vous ne pouvez télécharger une photo qu\'au format PDF (donc avec une extension \'.pdf\' ou \'.PDF\') [erreur #5]'; + break; + } + } + if ($message_erreur != "") break; // Sortie de la dummy loop + */ + + // Répertoire de stockage de la version : + $dossier = REPERTOIRE_VERSIONS_SHIPHEART.$types_version[$_SESSION['Versions']['type_version']][5]; // Dossier de stockage des fichiers + if (!file_exists($dossier) OR !is_dir($dossier)) mkdir($dossier); // On vérifie d'abord que le répertoire existe. Sinon on le créé + + // Création du nom de fichier complet : + $_SESSION['Versions']['version']['Fichier'] = $_FILES['new_file']['name']; + $destination = $dossier.'/'.$_SESSION['Versions']['version']['Fichier']; + + // Stockage du fichier : + if(!move_uploaded_file($_FILES['new_file']['tmp_name'], $destination)) + { + $message_erreur = 'Erreur de téléchargement... [erreur #7]'; + break; // Sortie de la dummy loop + } + } + else // Cas d'un répertoire : + { + + } + + // Création de la version : + $requete = 'INSERT INTO '.$types_version[$_SESSION['Versions']['type_version']][1].' ('.$types_version[$_SESSION['Versions']['type_version']][2].', Description) VALUES (?, ?)'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['Versions']['version'][''.$types_version[$_SESSION['Versions']['type_version']][2].'']), + array('s', $_SESSION['Versions']['version']['Description'])), + __FILE__, __LINE__); + + // Récup de la clé primaire de l'enregistrement créé : + $_SESSION['Versions']['version']['Cle_primaire'] = Recuperation_id_cree_bdd(); + + // Message d'information : + $message_information = "La version ".$_SESSION['Versions']['version']['Fichier']." vient d'être créée"; + + // Retour à la liste si la création s'est bien passée : + $_SESSION['Versions']['page'] = "Liste_versions"; + + } while (0); + } + else if (isset($_POST['validation_modification_version'])) + { + // Mise à jour de la version : + $requete = 'UPDATE '.$types_version[$_SESSION['Versions']['type_version']][1].' SET '.$types_version[$_SESSION['Versions']['type_version']][2].'=?, Description=? WHERE Cle_primaire=?'; + Requete_preparee_bdd($requete, + array( + array('s', $_SESSION['Versions']['version'][''.$types_version[$_SESSION['Versions']['type_version']][2].'']), + array('s', $_SESSION['Versions']['version']['Description']), + array('i', $_SESSION['Versions']['version']['Cle_primaire'])), + __FILE__, __LINE__); + + // Message d'information : + $message_information = "La version ".$_SESSION['Versions']['version'][''.$types_version[$_SESSION['Versions']['type_version']][2].'']." vient d'être modifiée"; + + // Retour à la liste si la modification s'est bien passée : + $_SESSION['Versions']['page'] = "Liste_versions"; + } + } + + + //--------------------------------------------------------------------------- + // Génération archive : + if (isset($_POST['validation_generation_archive'])) + { + do // Fake loop + { + if ($types_version[$_SESSION['Versions']['type_version']][3] != "package") break; // On ne traite une telle demande que s'il s'agit bien d'un package.... + + //-------------------------------------------------------------------------------------------------- + // Vidage du répertoire temporaire : + //-------------------------------------------------------------------------------------------------- + $repertoire_temp = REPERTOIRE_VERSIONS_SHIPHEART.$types_version[$_SESSION['Versions']['type_version']][5].'/temp'; + +// Sécurité en dur pour s'assurer qu'on ne pointe pas sur un autre répertoire qu'on va supprimer : +if (strpos($repertoire_temp, "/home/ciuqsga/versions/shipheart/packages/temp") === false) +{ + $message_erreur .= "L'adresse du répertoire TEMP a été modifiée (répertoire = ".$repertoire_temp.").
Afin d'éviter toute catastrophe (ce répertoire et ses sous-répertoires vont être supprimés !), merci de mettre à jour ce test de vérification...
"; + break; +} + + // Suppression du répertoire (permet de le vider simplement, yc ses sous-répertoires) : + // ATTENTION : la commande est récursive. Il ne faut PAS se tromper de répertoire !!!! + if (file_exists($repertoire_temp) AND is_dir($repertoire_temp)) + { + // Vidage mas pas suppression (l'intérêt de cette commande vs 'rm -r' est qu'il ne déclenche pas d'erreur si le répertoire est vide...) : + // NB : le répertoire n'est PAS supprimé par cette commande (juste vidé) + exec("find ".$repertoire_temp."/* -delete"); + } + + if (!file_exists($repertoire_temp) OR !is_dir($repertoire_temp)) mkdir($repertoire_temp); // Si le répertoire n'existe pas, on le créé. + + if (count(glob($repertoire_temp."/*")) != 0) // Compte le nb de fichiers... + { + $message_erreur .= "La préparation du répertoire de nouvelle version [".$repertoire_temp."] a échoué. La génération de l'archive est abandonnée...
"; + break; + } + + //-------------------------------------------------------------------------------------------------- + // Recherche des infos sur le package : + //-------------------------------------------------------------------------------------------------- + $requete = 'SELECT * FROM '.$types_version[$_SESSION['Versions']['type_version']][1].' WHERE Cle_primaire="'.$_SESSION['Versions']['version']['Cle_primaire'].'" '; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $_SESSION['Versions']['version'] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + + //-------------------------------------------------------------------------------------------------- + // Création du fichier JSON (début) : + //-------------------------------------------------------------------------------------------------- + $donnees_json['NoVersion'] = $_SESSION['Versions']['version']['Nom']; + + //-------------------------------------------------------------------------------------------------- + // Copie des fichiers de sous-version vers le dossier 'temp' : + //-------------------------------------------------------------------------------------------------- + for ($i = 0; (($i < $max_nb_types_version) && ($types_version[$i][0] != "")); $i ++) + { + if ($types_version[$i][4] == "") continue; // On ne traite pas le cas du PACKAGE qui n'a pas de fichier à récupérer.... + + // Recherche du nom de fichier ou de répertoire qui doit être inclus dans l'archive : + $nom = ""; // Par défaut (utile si un nouveau type de module a été créé mais n'existait pas sur cette version) + $requete = 'SELECT * FROM '.$types_version[$i][1].' WHERE Cle_primaire='.$_SESSION['Versions']['version'][''.$types_version[$i][4].''].' '; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $nom = $donnees[''.$types_version[$i][2].'']; + } + Liberation_jeu_de_resultat_bdd($reponse); + + if ($nom == "") continue; // Si le type de module en cours n'existait pas pour cette version, on ne met rien dans le fichier JSON à ce sujet... + + // Copie du fichier ou du répertoire dans le répertoire temporaire : + if ($types_version[$i][2] == "Fichier") // Cas d'un fichier simple : + { + $fichier_source = REPERTOIRE_VERSIONS_SHIPHEART.$types_version[$i][5].'/'.$nom; + $fichier_destination = $repertoire_temp.'/'.$nom; + + if (!copy($fichier_source, $fichier_destination)) + { + $message_erreur .= "La copie du fichier [".$fichier_source."] de son répertoire d'archive vers le répertoire temporaire a échoué. La génération de l'archive est abandonnée...
"; + break; + } +// else $message_information .= "La copie du fichier [".$fichier_source."] de son répertoire d'archive vers le répertoire temporaire a été effectué avec succès. La génération de l'archive se poursuit.
"; + } + else // Cas d'un répertoire : + { + $repertoire_source = REPERTOIRE_VERSIONS_SHIPHEART.$types_version[$i][5].'/'.$nom; + $repertoire_destination = $repertoire_temp.'/'.$nom; + if ((!file_exists($repertoire_source)) && (!is_dir($repertoire_source))) + { + $message_erreur .= "
/!\\
Le répertioire [".$repertoire_source."] n'existe pas !
La génération est arrêtée...

"; + break; + } + + if (copie_repertoire($repertoire_source, $repertoire_destination) == -1) + { + $message_erreur .= "
Erreur lors de la copîe du répertoire [".$repertoire_source."] vers le répertoire [".$repertoire_destination."]
La génération est arrêtée...

"; + break; + } + } + $donnees_json[''.$types_version[$i][0].''] = $nom; // Ajout du type de firmware/dossier + nom du firmware/dossier dans JSON + } + + if ($message_erreur != "") break; + + //-------------------------------------------------------------------------------------------------- + // Copie du répertoire SYSTEME vers le dossier 'temp' : + //-------------------------------------------------------------------------------------------------- + $repertoire_source = REPERTOIRE_VERSIONS_SHIPHEART."/ressources/systeme"; + $repertoire_destination = $repertoire_temp.'/systeme'; + + if (copie_repertoire($repertoire_source, $repertoire_destination) == -1) + { + $message_erreur .= "
Erreur lors de la copîe du répertoire [".$repertoire_source."] vers le répertoire [".$repertoire_destination."]
La génération est arrêtée...

"; + break; + } + + //-------------------------------------------------------------------------------------------------- + // Copie du répertoire UTILS vers le dossier 'temp' : + //-------------------------------------------------------------------------------------------------- + $repertoire_source = REPERTOIRE_VERSIONS_SHIPHEART."/ressources/utils"; + $repertoire_destination = $repertoire_temp.'/utils'; + + if (copie_repertoire($repertoire_source, $repertoire_destination) == -1) + { + $message_erreur .= "
Erreur lors de la copîe du répertoire [".$repertoire_source."] vers le répertoire [".$repertoire_destination."]
La génération est arrêtée...

"; + break; + } + + //-------------------------------------------------------------------------------------------------- + // Copie du répertoire CONFIG vers le dossier 'temp' : + //-------------------------------------------------------------------------------------------------- + $repertoire_source = REPERTOIRE_VERSIONS_SHIPHEART."/ressources/config"; + $repertoire_destination = $repertoire_temp.'/config'; + + if (copie_repertoire($repertoire_source, $repertoire_destination) == -1) + { + $message_erreur .= "
Erreur lors de la copîe du répertoire [".$repertoire_source."] vers le répertoire [".$repertoire_destination."]
La génération est arrêtée...

"; + break; + } + + //-------------------------------------------------------------------------------------------------- + // Création du fichier JSON (fin): + //-------------------------------------------------------------------------------------------------- + $type = "update"; + $chaines_a_echapper = array("\"", "\r", "\n"); // Utiliser pour ne pas véroler le fichier JSON dans la partie Description. Mettre ici les chaines interdites.... + $chaines_echappement = array("\\\"", " ", ""); // ... et ici leur remplaçante. + $donnees_json['Repertoire_data'] = ""; // Vide dans le cas d'un NEW ou d'un UPDATE (utilisé plus tard dans le cas d'un RESTORE) + $donnees_json['SQL_data'] = ""; // Vide dans le cas d'un NEW ou d'un UPDATE (utilisé plus tard dans le cas d'un RESTORE) + $donnees_json['Type'] = $type; + $donnees_json['Description'] = str_replace($chaines_a_echapper, $chaines_echappement, $_SESSION['Versions']['version']['Description_externe']); + + // Génération du nom de fichier JSON de la forme 'v_1_2_14_update.json' où le dernier groupe représente le type de mise à jour ('new' ou 'update' - 'restore' ne peut pas être généré ici) : + $base_nom_archive = 'v_'.str_replace(".", "_", $_SESSION['Versions']['version']['Nom']); + $nom_fichier_json = $base_nom_archive.'_'.$type.'.json'; + file_put_contents($repertoire_temp.'/'.$nom_fichier_json, json_encode($donnees_json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); // Le 'file_put_contents' crée le fichier + + + //-------------------------------------------------------------------------------------------------- + // Déplacement vers le répertoire temporaire : + // NB : le déplacement sur le répertoire est impératif. Si on utilise les chemins absolu, cela fonctionne... MAIS + // l'archive contient les chemins absolu de chaque fichier. Le décodage n'est ensuite plus possible ! + //-------------------------------------------------------------------------------------------------- + if (!chdir($repertoire_temp)) + { + $message_erreur .= "Le déplacement vers [".$repertoire_temp."] n'a pas été possible. La génération de l'archive est abandonnée...
"; + break; + } + +/* ANCIENNE VERSION : Début (< V4) + //-------------------------------------------------------------------------------------------------- + // Création du fichier archive UPDATE TAR.GZ : + //-------------------------------------------------------------------------------------------------- + $output = null; + $retval = null; + $nom_fichier_tar_gz = 'ShipHeart_'.$base_nom_archive.'_'.$type.'.tar.gz'; + $cde = "tar -cvzf ".$nom_fichier_tar_gz." *"; // NB : ne PAS utiliser SUDO qui n'est pas autorisé sur le serveur OVH... +// echo 'Commande = ['.$cde.']
'; + exec($cde, $output, $retval); + + if ($retval != 0) + { + $message_erreur .= "La génération du fichier [".$nom_fichier_tar_gz."] a échoué. La génération de l'archive est abandonnée...
"; + break; + } + + //-------------------------------------------------------------------------------------------------- + // Création du fichier encodé UPDATE TAR.GZ.ENC : + //-------------------------------------------------------------------------------------------------- + $output = null; + $retval = null; + + $nom_fichier_tar_gz_enc = $nom_fichier_tar_gz.".enc"; + $cde = "openssl enc -aes-256-cbc -pbkdf2 -iter 10000 -md sha256 -in ".$nom_fichier_tar_gz." -out ".$nom_fichier_tar_gz_enc." -pass pass:".BDD_BATEAU_PASSWORD." "; +// echo 'Commande = ['.$cde.']
'; + exec($cde, $output, $retval); // NB : ne PAS utiliser SUDO qui n'est pas autorisé sur le serveur OVH... + + if ($retval != 0) + { + $message_erreur .= "L'encryptage du fichier [".$nom_fichier_tar_gz_enc."] a échoué. La génération de l'archive est abandonnée...
"; + break; + } + + // Suppression du fichier TAR.GZ qui, sinon, reste là : + exec("rm ".$nom_fichier_tar_gz); // NB : ne PAS utiliser SUDO qui n'est pas autorisé sur le serveur OVH... +ANCIENNE VERSION : Fin */ + + //-------------------------------------------------------------------------------------------------- + // Création du fichier archive TAR.GZ.ENC : + //-------------------------------------------------------------------------------------------------- + $nom_fichier = "ShipHeart_".$base_nom_archive.'_'.$type; + $nom_fichier_tar_gz_enc = $nom_fichier.".tar.gz.enc"; + + if (creer_archive_chiffree($repertoire_temp, $nom_fichier) != 0) + { + $message_erreur .= "\t/!\\ L'encryptage du fichier [".$nom_fichier."] a échoué. La génération de l'archive est abandonnée...\n"; + break; + } + + //-------------------------------------------------------------------------------------------------- + // Création du répertoire d'archive de la version : + //-------------------------------------------------------------------------------------------------- + $repertoire_archive_version = REPERTOIRE_VERSIONS_SHIPHEART.$types_version[$_SESSION['Versions']['type_version']][5].'/v_'.str_replace(".", "_", $_SESSION['Versions']['version']['Nom']); + if (!file_exists($repertoire_archive_version) OR !is_dir($repertoire_archive_version)) mkdir($repertoire_archive_version); // On vérifie d'abord que le répertoire existe. Sinon on le créé + + $repertoire_archive_version_ressources = $repertoire_archive_version."/ressources"; + if (!file_exists($repertoire_archive_version_ressources) OR !is_dir($repertoire_archive_version_ressources)) mkdir($repertoire_archive_version_ressources); // On vérifie d'abord que le répertoire existe. Sinon on le créé + + //-------------------------------------------------------------------------------------------------- + // Copie du fichier archive UPDATE dans le répertoire de sa version : + //-------------------------------------------------------------------------------------------------- + if (!rename($repertoire_temp."/".$nom_fichier_tar_gz_enc, $repertoire_archive_version.'/'.$nom_fichier_tar_gz_enc)) + { + $message_erreur .= "\t/!\\ Le déplacement du fichier [".$nom_fichier_tar_gz_enc."] du répertoire temporaire vers le répertoire de version a échoué. La génération de l'archive est abandonnée...\n"; + break; + } + + //-------------------------------------------------------------------------------------------------- + // Relecture du fichier JSON et transformation en version 'new' : + //-------------------------------------------------------------------------------------------------- + + // Lecture du contenu du fichier JSON puis archivage du fichier : + $contenu = file_get_contents($repertoire_temp.'/'.$base_nom_archive.'_'.$type.'.json'); // Lecture du fichier + $donnees_json = json_decode($contenu, true); // Décodage du fichier JSON (true = tableau associatif) + rename($repertoire_temp.'/'.$base_nom_archive.'_'.$type.'.json', $repertoire_archive_version_ressources.'/'.$base_nom_archive.'_'.$type.'.json'); // Déplacement du JSON d'origine dans le répertoire Ressources + + $type = "new"; + // Création du nouveau fichier JSON (nouveau nom et contenu mis à jour) : + $nom_fichier_json = $base_nom_archive.'_'.$type.'.json'; + $donnees_json['Type'] = $type; //Mise à jour (ou ajout si inexistant) du champ Type + file_put_contents($repertoire_temp.'/'.$nom_fichier_json, json_encode($donnees_json, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); // Le 'file_put_contents' crée le fichier + + +/* ANCIENNE VERSION : Début (< V4) + //-------------------------------------------------------------------------------------------------- + // Création du fichier archive NEW TAR.GZ : + //-------------------------------------------------------------------------------------------------- + $output = null; + $retval = null; + $nom_fichier_tar_gz = "ShipHeart_".$base_nom_archive.'_'.$type.".tar.gz"; + $cde = "tar -cvzf ".$nom_fichier_tar_gz." *"; // NB : ne PAS utiliser SUDO qui n'est pas autorisé sur le serveur OVH... +// echo 'Commande = ['.$cde.']
'; + exec($cde, $output, $retval); + + if ($retval != 0) + { + $message_erreur .= "La génération du fichier [".$nom_fichier_tar_gz."] a échoué. La génération de l'archive est abandonnée...
"; + break; + } + + //-------------------------------------------------------------------------------------------------- + // Création du fichier encodé NEW TAR.GZ.ENC : + //-------------------------------------------------------------------------------------------------- + $output = null; + $retval = null; + + $nom_fichier_tar_gz_enc = $nom_fichier_tar_gz.".enc"; + $cde = "openssl enc -aes-256-cbc -pbkdf2 -iter 10000 -md sha256 -in ".$nom_fichier_tar_gz." -out ".$nom_fichier_tar_gz_enc." -pass pass:".BDD_BATEAU_PASSWORD." "; +// echo 'Commande = ['.$cde.']
'; + exec($cde, $output, $retval); // NB : ne PAS utiliser SUDO qui n'est pas autorisé sur le serveur OVH... + + if ($retval != 0) + { + $message_erreur .= "L'encryptage du fichier [".$nom_fichier_tar_gz_enc."] a échoué. La génération de l'archive est abandonnée...
"; + break; + } + + // Suppression du fichier TAR.GZ qui, sinon, reste là : + exec("rm ".$nom_fichier_tar_gz); // NB : ne PAS utiliser SUDO qui n'est pas autorisé sur le serveur OVH... +ANCIENNE VERSION : Fin */ + + //-------------------------------------------------------------------------------------------------- + // Création du fichier archive TAR.GZ.ENC : + //-------------------------------------------------------------------------------------------------- + $nom_fichier = "ShipHeart_".$base_nom_archive.'_'.$type; + $nom_fichier_tar_gz_enc = $nom_fichier.".tar.gz.enc"; + + if (creer_archive_chiffree($repertoire_temp, $nom_fichier) != 0) + { + $message_erreur .= "\t/!\\ L'encryptage du fichier [".$nom_fichier."] a échoué. La génération de l'archive est abandonnée...\n"; + break; + } + + //-------------------------------------------------------------------------------------------------- + // Copie du fichier archive NEW dans le répertoire de sa version : + //-------------------------------------------------------------------------------------------------- + if (!rename($repertoire_temp."/".$nom_fichier_tar_gz_enc, $repertoire_archive_version.'/'.$nom_fichier_tar_gz_enc)) + { + $message_erreur .= "\t/!\\ Le déplacement du fichier [".$nom_fichier_tar_gz_enc."] du répertoire temporaire vers le répertoire de version a échoué. La génération de l'archive est abandonnée...\n"; + break; + } + + $message_information .= "Les fichiers archives [".$base_nom_archive."] viennent d'être créés dans le répertoire [".$repertoire_archive_version."]"; + + //-------------------------------------------------------------------------------------------------- + // Copie de tous les fichiers utilisés dans le sous-répertoire Ressources du répertoire de version : + // NB : seul le fichier JSON de en version 'update' y est déjà (on va ici déplacer celui de la version 'new') + // NB 2 : les fichiers encryptés ne sont pas stockés dans Ressources mais à la racine du répertoire + //-------------------------------------------------------------------------------------------------- + copie_repertoire($repertoire_temp , $repertoire_archive_version_ressources); + + //-------------------------------------------------------------------------------------------------- + // Suppression du répeertoire temporaire : + // Nb : on ne teste pas le résultat car pas de soucis en cas d'erreur... + //-------------------------------------------------------------------------------------------------- + exec("find ".$repertoire_temp."/* -delete"); // NB : ne PAS utiliser SUDO qui n'est pas autorisé sur le serveur OVH... + rmdir($repertoire_temp); + + //-------------------------------------------------------------------------------------------------- + // RAZ des paramètres : + //-------------------------------------------------------------------------------------------------- + $_SESSION['Versions']['page'] = "Modification_version"; + + } while (0); + +$flag_redirection = true; // Evite que le message d'erreur soit supprimé par la redirection de purge d'URL + } + + + +//************************************************************************************************************************************ +// Traitement des données +//************************************************************************************************************************************ + + // Protection contre les accès directs : + if ((!$_SESSION['acces_valide']) OR ($_SESSION['shipmember']['Niveau_acces'] < NIVEAU_MINI_ACCES_ADMINISTATEUR)) header('Location:shipmembers.php?action=navigation&destination=Login'); + + switch ($_SESSION['Versions']['page']) + { + //**************************************************************************************************************************** + case "Accueil": + { + // Récupération des informations sur les versions : +/* $nb_versions = 0; + $requete = 'SELECT * FROM TB_Versions WHERE Validite=1 ORDER BY Nom DESC'; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $versions[$nb_versions ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); +*/ + break; + } + + //**************************************************************************************************************************** + case "Liste_versions": + { + // Récupération des informations sur les versions : + + $nb_versions = 0; + + switch($types_version[$_SESSION['Versions']['type_version']][3]) + { + //--------------------------------------------------------------------------- + case "package" : // Uniquement pour les versions principales : + { + $tri = 'INET_ATON('.$types_version[$_SESSION['Versions']['type_version']][2].') DESC'; + break; + } + //--------------------------------------------------------------------------- + default : // Pour toutes les versions secondaires : + { + $tri = ' '.$types_version[$_SESSION['Versions']['type_version']][2].' DESC'; + break; + } + } + + $requete = 'SELECT * FROM '.$types_version[$_SESSION['Versions']['type_version']][1].' WHERE Validite=1 ORDER BY '.$tri.' '; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $versions[$nb_versions ++] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + break; + } + + + //**************************************************************************************************************************** + case "Liste_evolutions": + { + // Récupération des informations sur les versions : + + $nb_versions = 0; + + $requete = 'SELECT Cle_primaire, Nom, Date, Description_externe FROM TB_Versions WHERE Validite=1 ORDER BY INET_ATON(Nom) DESC'; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $versions[$nb_versions] = $donnees; + if ($versions[$nb_versions]['Description_externe'] == "") $versions[$nb_versions]['Description_externe'] = "Pas de modification fonctionnelle significative"; + $nb_versions ++; + } + Liberation_jeu_de_resultat_bdd($reponse); + + break; + } + + //**************************************************************************************************************************** + case "Creation_version": + case "Modification_version": + { + if ($_SESSION['Versions']['page'] == "Creation_version") + { + switch($types_version[$_SESSION['Versions']['type_version']][3]) + { + //--------------------------------------------------------------------------- + case "package" : // Uniquement pour les versions principales : + { + $_SESSION['Versions']['version']['Cle_primaire'] = 0; + $_SESSION['Versions']['version']['Nom'] = ""; + $_SESSION['Versions']['version']['Date'] = date("Y-m-d"); + $_SESSION['Versions']['version']['ID_Version_appli'] = 0; + $_SESSION['Versions']['version']['ID_Version_qt'] = 0; + $_SESSION['Versions']['version']['ID_Version_compagnon_v1'] = 0; + $_SESSION['Versions']['version']['ID_Version_compagnon_v2'] = 0; + $_SESSION['Versions']['version']['ID_Version_sp812'] = 0; + $_SESSION['Versions']['version']['ID_Version_sp4ac'] = 0; + $_SESSION['Versions']['version']['ID_Version_sp8dc'] = 0; + $_SESSION['Versions']['version']['ID_Version_sbs'] = 0; + $_SESSION['Versions']['version']['ID_Version_sql'] = 0; + $_SESSION['Versions']['version']['ID_Version_www'] = 0; + $_SESSION['Versions']['version']['ID_Version_updater'] = 0; + $_SESSION['Versions']['version']['Description_interne'] = ""; + $_SESSION['Versions']['version']['Description_externe'] = ""; + + break; + } + //--------------------------------------------------------------------------- + default : // Pour toutes les versions secondaires : + { + $_SESSION['Versions']['version']['Cle_primaire'] = 0; + $_SESSION['Versions']['version']['Fichier'] = ""; + $_SESSION['Versions']['version']['Repertoire'] = ""; + $_SESSION['Versions']['version']['Description'] = ""; + + if ($types_version[$_SESSION['Versions']['type_version']][2] == "Repertoire") $message_information .= "
/!\\
Pensez à copier le répertoire de la version créée sur le serveur, dans 'versions/shipheart/www' par exemple

"; + + break; + } + } + } + else // Modification : + { + $requete = 'SELECT * FROM '.$types_version[$_SESSION['Versions']['type_version']][1].' WHERE Cle_primaire="'.$_SESSION['Versions']['version']['Cle_primaire'].'" '; + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $_SESSION['Versions']['version'] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + } + + + switch($types_version[$_SESSION['Versions']['type_version']][3]) + { + //--------------------------------------------------------------------------- + case "package" : // Uniquement pour les versions principales : + { + $nb_versions_secondaires = 0; + + for ($i = 0; (($i < $max_nb_types_version) && ($types_version[$i][0] != "")); $i ++) + { + $versions_secondaires[$nb_versions_secondaires]['nb_versions'] = 0; + + $requete = 'SELECT * FROM '.$types_version[$i][1].' WHERE Validite=1 ORDER BY '.$types_version[$i][2].' DESC'; + + $reponse = Requete_preparee_bdd($requete, + array(), + __FILE__, __LINE__); + while ($donnees = Recherche_ligne_bdd($reponse)) + { + $versions_secondaires[$nb_versions_secondaires][$versions_secondaires[$nb_versions_secondaires]['nb_versions'] ++]['version'] = $donnees; + } + Liberation_jeu_de_resultat_bdd($reponse); + + // Ajout d'une valeur "Aucune" dans la liste des versions secondaire pour la cas où on affiche un package avec un type de version secondaire qui n'existait pas (ID = 0) : + // L'ajout à la fin permet de n'avoir ce choix qu'en tout dernier puisque le tri est DESC dans la requête (la valeur par défaut est la dernière version) + // On n'ajoute ce choix qu'en modification (en création, ça perturebe la valeur par défaut et on ne devrait pas en avoir besoin...). + if ($_SESSION['Versions']['page'] == "Modification_version") + { + $versions_secondaires[$nb_versions_secondaires][$versions_secondaires[$nb_versions_secondaires]['nb_versions']]['version']['Cle_primaire'] = 0; + $versions_secondaires[$nb_versions_secondaires][$versions_secondaires[$nb_versions_secondaires]['nb_versions']]['version'][''.$types_version[$i][2].''] = "--- Aucune ---"; + $versions_secondaires[$nb_versions_secondaires]['nb_versions'] ++; + } + + $nb_versions_secondaires ++; + } + + break; + } + //--------------------------------------------------------------------------- + default : // Pour toutes les versions secondaires : + { + break; + } + } + + break; + } + + //**************************************************************************************************************************** + case "Confirmation_suppression_version": + { + + + break; + } + + //**************************************************************************************************************************** + case "Generation_archive": + { + + + break; + } + + //**************************************************************************************************************************** + default: + { + $_SESSION['Versions']['page'] = "Accueil"; + break; + } + + } + + Fermeture_bdd(); // Déconnexion de MySQL + +//************************************************************************************************************************************ +// Affichage +//************************************************************************************************************************************ + + + //******************************************************************************************************************************** + // Affichage principal : + echo '
'; + + //========================================================================================= + // Entête : + Entete_page($message_erreur, $message_information); + + switch ($_SESSION['Versions']['page']) + { + //************************************************************************************************************************ + case "Accueil": + { + echo '
'; + + echo '

Versions

'; + + echo '

Type de versions

'; + + echo '
'; + for ($i=0; ($i < $max_nb_types_version) && ($types_version[$i][0] != ""); $i ++) + { + switch($types_version[$i][3]) + { + case "package" : + { + echo 'Packages '.$types_version[$i][0].''; + break; + } + default : // Pour toutes les versions secondaires : + { + echo 'Versions de '.$types_version[$i][0].''; + break; + } + } + } + echo '
'; + + echo ''; + + echo '
'; + + break; + } + + //************************************************************************************************************************ + case "Liste_versions": + { + echo '
'; + + echo '

Versions

'; + + + + switch($types_version[$_SESSION['Versions']['type_version']][3]) + { + //--------------------------------------------------------------------------- + case "package" : // Uniquement pour les versions principales : + { + echo ''; + + echo '

Liste des packages '.$types_version[$_SESSION['Versions']['type_version']][0].'

'; + + echo ' + + + + + + + + '; + for ($i = 0; $i < $nb_versions; $i ++) + { + echo ' + + + + '; + } + echo ' +
NomDateDescription interne
+ + '.$versions[$i]['Nom'].' + + '.$versions[$i]['Date'].''.nl2br($versions[$i]['Description_interne']).'
'; + + echo ''; + + break; + } + + //--------------------------------------------------------------------------- + default : // Pour toutes les versions secondaires : + { + echo ''; + + echo '

Liste des versions de '.$types_version[$_SESSION['Versions']['type_version']][0].'

'; + + echo ' + + + + + + + '; + for ($i = 0; $i < $nb_versions; $i ++) + { + $nom_champ = $types_version[$_SESSION['Versions']['type_version']][2]; + echo ' + + + '; + } + echo ' +
'.$types_version[$_SESSION['Versions']['type_version']][2].'Description
+ + '.$versions[$i][''.$nom_champ.''].' + + '.nl2br($versions[$i]['Description']).'
'; + + echo ''; + + break; + } + } + + echo '
'; + + break; + } + + //************************************************************************************************************************ + case "Liste_evolutions": + { + echo '
'; + + echo '

Evolutions entre les versions

'; + + echo '
'; + echo 'Retour aux types de versions'; + echo '
'; + + echo ' + + + + + + + + '; + for ($i = 0; $i < $nb_versions; $i ++) + { + echo ' + + + + '; + } + echo ' +
NomDateDescription publique
+ + '.$versions[$i]['Nom'].' + + '.$versions[$i]['Date'].''.nl2br($versions[$i]['Description_externe']).'
'; + + echo '
'; + echo 'Retour aux types de versions'; + echo '
'; + + echo '
'; + + break; + } + + //************************************************************************************************************************ + case "Creation_version": + case "Modification_version": + { + echo '
'; + + echo '

Versions

'; + +// echo '
'; +echo ''; + + + switch($types_version[$_SESSION['Versions']['type_version']][3]) + { + //--------------------------------------------------------------------------------------------------------- + case "package" : + { + if ($_SESSION['Versions']['page'] == "Creation_version") echo '

Nouvelle version de '.$types_version[$_SESSION['Versions']['type_version']][0].'

'; + else echo '

Modification de la version '.$_SESSION['Versions']['version']['Nom'].'

'; + + + echo '
+
+ Nom de la version +
+
+ +
+
'; + + echo '
+
+ Date de la version +
+
+ +
+
'; + + + for ($i = 0; $i < $nb_versions_secondaires; $i ++) + { + if ($types_version[$i][3] == "package") continue; + + echo '
+
+ Version de '.$types_version[$i][0].' +
+
+ +
+
'; + } + + echo '
+
+ Description interne +
+
+ +
+
'; + + echo '
+
+ Description publique +
+
+ +
+
'; + + + echo '
'; + if ($_SESSION['Versions']['page'] == "Creation_version") /// Création : + { + echo 'Annuler'; + echo ''; + } + else // Modification : + { + echo 'Retour à la liste des packages'; + echo ''; + echo 'Supprimer le package'; + echo 'Générer une archive'; + } + echo '
'; + + break; + } + + //--------------------------------------------------------------------------------------------------------- + default: + { + if ($_SESSION['Versions']['page'] == "Creation_version") echo '

Nouvelle version de '.$types_version[$_SESSION['Versions']['type_version']][0].'

'; + else echo '

Modification de la version '.$_SESSION['Versions']['version'][''.$types_version[$_SESSION['Versions']['type_version']][2].''].'

'; + + if ($_SESSION['Versions']['page'] == "Creation_version") // On ne donne la possibilité de charger un fichier que lors de la création (pour modifier un fichier, il faut supprimer la version et la recréer (puisque le nom de la version est le nom du fichier...) + { + echo '
'; + + if ($types_version[$_SESSION['Versions']['type_version']][2] == "Repertoire") + { + echo '
+ Répertoire +
+
+ '; +// echo ' +// '; + echo '
'; + } + else + { + echo '
+ Fichier +
+
+ +
'; + } + + echo '
'; + } + + echo '
+
+ Description +
+
+ +
+
'; + + + if ($_SESSION['Versions']['page'] == "Creation_version") /// Création : + { + echo '
'; + echo 'Annuler'; + echo ''; + echo '
'; + } + else // Modification : + { + echo '
'; + echo 'Retour à la liste des versions'; + echo ''; + echo 'Supprimer la version'; + echo '
'; + } + + + break; + } + } + + echo '
'; + + echo '
'; + + break; + } + + + //**************************************************************************************************************************** + case "Confirmation_suppression_version": + { + echo '
'; + + echo '

Versions

'; + + echo '
'; + switch($types_version[$_SESSION['Versions']['type_version']][3]) + { + //--------------------------------------------------------------------------------------------------------- + case "package" : + { + echo '

+ Confirmez-vous la suppression de la version + '; + echo $_SESSION['Versions']['version']['Nom']; + echo ' ? +

'; + echo '

Si oui, son entrée dans la base de données sera supprimée du serveur !

'; + + break; + } + //--------------------------------------------------------------------------------------------------------- + default: + { + echo '

+ Confirmez-vous la suppression de la version + '; + echo $_SESSION['Versions']['version'][''.$types_version[$_SESSION['Versions']['type_version']][2].'']; + echo ' ? +

'; + echo '

Si oui, le fichier correspondant et son entrée dans la base de données seront supprimés du serveur !

'; + + break; + } + } + echo '
'; + + echo '
'; + echo 'Annuler'; + echo 'Confirmer la suppression'; + echo '
'; + + echo '
'; + + break; + } + + + + //************************************************************************************************************************ + case "Generation_archive": + { + echo '
'; + + echo '

Versions

'; + + echo '
'; + + echo '

Génération d\'un fichier archive pour la version '.$_SESSION['Versions']['version']['Nom'].'

'; + + echo '
'; + echo 'Retour aux détails de la version'; + echo ''; + echo '
'; + + echo '
'; + + echo '
'; + + break; + } + + + + } + + echo '
'; + +Pied_de_page(); diff --git a/vendor/phpqrcode/CHANGELOG b/vendor/phpqrcode/CHANGELOG new file mode 100644 index 0000000..1088530 --- /dev/null +++ b/vendor/phpqrcode/CHANGELOG @@ -0,0 +1,38 @@ +* 1.0.0 build 2010031920 + + - first public release + - help in readme, install + - cleanup ans separation of QRtools and QRspec + - now TCPDF binding requires minimal changes in TCPDF, having most of job + done in QRtools tcpdfBarcodeArray + - nicer QRtools::timeBenchmark output + - license and copyright notices in files + - indent cleanup - from tab to 4spc, keep it that way please :) + - sf project, repository, wiki + - simple code generator in index.php + +* 1.1.0 build 2010032113 + + - added merge tool wich generate merged version of code + located in phpqrcode.php + - splited qrconst.php from qrlib.php + +* 1.1.1 build 2010032405 + + - patch by Rick Seymour allowing saving PNG and displaying it at the same time + - added version info in VERSION file + - modified merge tool to include version info into generated file + - fixed e-mail in almost all head comments + +* 1.1.2 build 2010032722 + + - full integration with TCPDF thanks to Nicola Asuni, it's author + - fixed bug with alphanumeric encoding detection + +* 1.1.3 build 2010081807 + + - short opening tags replaced with standard ones + +* 1.1.4 build 2010100721 + + - added missing static keyword QRinput::check (found by Luke Brookhart, Onjax LLC) diff --git a/vendor/phpqrcode/INSTALL b/vendor/phpqrcode/INSTALL new file mode 100644 index 0000000..eac6b07 --- /dev/null +++ b/vendor/phpqrcode/INSTALL @@ -0,0 +1,67 @@ +== REQUIREMENTS == + + * PHP5 + * PHP GD2 extension with JPEG and PNG support + +== INSTALLATION == + +If you want to recreate cache by yourself make sure cache directory is +writable and you have permisions to write into it. Also make sure you are +able to read files in it if you have cache option enabled + +== CONFIGURATION == + +Feel free to modify config constants in qrconfig.php file. Read about it in +provided comments and project wiki page (links in README file) + +== QUICK START == + +Notice: probably you should'nt use all of this in same script :) + +encode('PHP QR Code :)'); +QRspec::debug($tab, true); + +== TCPDF INTEGRATION == + +Inside bindings/tcpdf you will find slightly modified 2dbarcodes.php. +Instal phpqrcode liblaty inside tcpdf folder, then overwrite (or merge) +2dbarcodes.php + +Then use similar as example #50 from TCPDF examples: + + true, + 'padding' => 4, + 'fgcolor' => array(0,0,0), + 'bgcolor' => false, //array(255,255,255) +); + +//code name: QR, specify error correction level after semicolon (L,M,Q,H) +$pdf->write2DBarcode('PHP QR Code :)', 'QR,L', '', '', 30, 30, $style, 'N'); diff --git a/vendor/phpqrcode/LICENSE b/vendor/phpqrcode/LICENSE new file mode 100644 index 0000000..1883303 --- /dev/null +++ b/vendor/phpqrcode/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + 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 that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU 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 as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/vendor/phpqrcode/README b/vendor/phpqrcode/README new file mode 100644 index 0000000..a022fb5 --- /dev/null +++ b/vendor/phpqrcode/README @@ -0,0 +1,45 @@ +This is PHP implementation of QR Code 2-D barcode generator. It is pure-php +LGPL-licensed implementation based on C libqrencode by Kentaro Fukuchi. + +== LICENSING == + +Copyright (C) 2010 by Dominik Dzienia + +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 3 of the License, or 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 (LICENSE file) +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., 51 +Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +== INSTALATION AND USAGE == + + * INSTALL file + * http://sourceforge.net/apps/mediawiki/phpqrcode/index.php?title=Main_Page + +== CONTACT == + +Fell free to contact me via e-mail (deltalab at poczta dot fm) or using +folowing project pages: + + * http://sourceforge.net/projects/phpqrcode/ + * http://phpqrcode.sourceforge.net/ + +== ACKNOWLEDGMENTS == + +Based on C libqrencode library (ver. 3.1.1) +Copyright (C) 2006-2010 by Kentaro Fukuchi +http://megaui.net/fukuchi/works/qrencode/index.en.html + +QR Code is registered trademarks of DENSO WAVE INCORPORATED in JAPAN and other +countries. + +Reed-Solomon code encoder is written by Phil Karn, KA9Q. +Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + \ No newline at end of file diff --git a/vendor/phpqrcode/VERSION b/vendor/phpqrcode/VERSION new file mode 100644 index 0000000..9f99279 --- /dev/null +++ b/vendor/phpqrcode/VERSION @@ -0,0 +1,2 @@ +1.1.4 +2010100721 \ No newline at end of file diff --git a/vendor/phpqrcode/bindings/tcpdf/qrcode.php b/vendor/phpqrcode/bindings/tcpdf/qrcode.php new file mode 100644 index 0000000..0a222ce --- /dev/null +++ b/vendor/phpqrcode/bindings/tcpdf/qrcode.php @@ -0,0 +1,2874 @@ + +// http://phpqrcode.sourceforge.net/ +// https://sourceforge.net/projects/phpqrcode/ +// +// The "PHP QR Code encoder" is based on +// "C libqrencode library" (ver. 3.1.1) +// License: GNU-LGPL 2.1 +// Copyright (C) 2006-2010 by Kentaro Fukuchi +// http://megaui.net/fukuchi/works/qrencode/index.en.html +// +// Reed-Solomon code encoder is written by Phil Karn, KA9Q. +// Copyright (C) 2002-2006 Phil Karn, KA9Q +// +// QR Code is registered trademark of DENSO WAVE INCORPORATED +// http://www.denso-wave.com/qrcode/index-e.html +// --------------------------------------------------------- +// +// Author: Nicola Asuni +// +// (c) Copyright 2010: +// Nicola Asuni +// Tecnick.com S.r.l. +// Via della Pace, 11 +// 09044 Quartucciu (CA) +// ITALY +// www.tecnick.com +// info@tecnick.com +//============================================================+ + +/** + * Class to create QR-code arrays for TCPDF class. + * QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD. + * The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness. + * This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004. + * Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode. + * + * This class is derived from "PHP QR Code encoder" by Dominik Dzienia (http://phpqrcode.sourceforge.net/) based on "libqrencode C library 3.1.1." by Kentaro Fukuchi (http://megaui.net/fukuchi/works/qrencode/index.en.html), contains Reed-Solomon code written by Phil Karn, KA9Q. QR Code is registered trademark of DENSO WAVE INCORPORATED (http://www.denso-wave.com/qrcode/index-e.html). + * Please read comments on this class source file for full copyright and license information. + * + * @package com.tecnick.tcpdf + * @abstract Class for generating QR-code array for TCPDF. + * @author Nicola Asuni + * @copyright 2010 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com + * @link http://www.tcpdf.org + * @license http://www.gnu.org/copyleft/lesser.html LGPL + * @version 1.0.002 + */ + +// definitions +if (!defined('QRCODEDEFS')) { + + /** + * Indicate that definitions for this class are set + */ + define('QRCODEDEFS', true); + + // ----------------------------------------------------- + + // Encoding modes (characters which can be encoded in QRcode) + + /** + * Encoding mode + */ + define('QR_MODE_NL', -1); + + /** + * Encoding mode numeric (0-9). 3 characters are encoded to 10bit length. In theory, 7089 characters or less can be stored in a QRcode. + */ + define('QR_MODE_NM', 0); + + /** + * Encoding mode alphanumeric (0-9A-Z $%*+-./:) 45characters. 2 characters are encoded to 11bit length. In theory, 4296 characters or less can be stored in a QRcode. + */ + define('QR_MODE_AN', 1); + + /** + * Encoding mode 8bit byte data. In theory, 2953 characters or less can be stored in a QRcode. + */ + define('QR_MODE_8B', 2); + + /** + * Encoding mode KANJI. A KANJI character (multibyte character) is encoded to 13bit length. In theory, 1817 characters or less can be stored in a QRcode. + */ + define('QR_MODE_KJ', 3); + + /** + * Encoding mode STRUCTURED (currently unsupported) + */ + define('QR_MODE_ST', 4); + + // ----------------------------------------------------- + + // Levels of error correction. + // QRcode has a function of an error correcting for miss reading that white is black. + // Error correcting is defined in 4 level as below. + + /** + * Error correction level L : About 7% or less errors can be corrected. + */ + define('QR_ECLEVEL_L', 0); + + /** + * Error correction level M : About 15% or less errors can be corrected. + */ + define('QR_ECLEVEL_M', 1); + + /** + * Error correction level Q : About 25% or less errors can be corrected. + */ + define('QR_ECLEVEL_Q', 2); + + /** + * Error correction level H : About 30% or less errors can be corrected. + */ + define('QR_ECLEVEL_H', 3); + + // ----------------------------------------------------- + + // Version. Size of QRcode is defined as version. + // Version is from 1 to 40. + // Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. + // So version 40 is 177*177 matrix. + + /** + * Maximum QR Code version. + */ + define('QRSPEC_VERSION_MAX', 40); + + /** + * Maximum matrix size for maximum version (version 40 is 177*177 matrix). + */ + define('QRSPEC_WIDTH_MAX', 177); + + // ----------------------------------------------------- + + /** + * Matrix index to get width from $capacity array. + */ + define('QRCAP_WIDTH', 0); + + /** + * Matrix index to get number of words from $capacity array. + */ + define('QRCAP_WORDS', 1); + + /** + * Matrix index to get remainder from $capacity array. + */ + define('QRCAP_REMINDER', 2); + + /** + * Matrix index to get error correction level from $capacity array. + */ + define('QRCAP_EC', 3); + + // ----------------------------------------------------- + + // Structure (currently usupported) + + /** + * Number of header bits for structured mode + */ + define('STRUCTURE_HEADER_BITS', 20); + + /** + * Max number of symbols for structured mode + */ + define('MAX_STRUCTURED_SYMBOLS', 16); + + // ----------------------------------------------------- + + // Masks + + /** + * Down point base value for case 1 mask pattern (concatenation of same color in a line or a column) + */ + define('N1', 3); + + /** + * Down point base value for case 2 mask pattern (module block of same color) + */ + define('N2', 3); + + /** + * Down point base value for case 3 mask pattern (1:1:3:1:1(dark:bright:dark:bright:dark)pattern in a line or a column) + */ + define('N3', 40); + + /** + * Down point base value for case 4 mask pattern (ration of dark modules in whole) + */ + define('N4', 10); + + // ----------------------------------------------------- + + // Optimization settings + + /** + * if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code + */ + define('QR_FIND_BEST_MASK', true); + + /** + * if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly + */ + define('QR_FIND_FROM_RANDOM', 2); + + /** + * when QR_FIND_BEST_MASK === false + */ + define('QR_DEFAULT_MASK', 2); + + // ----------------------------------------------------- + +} // end of definitions + +// #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# + +if (!class_exists('QRcode', false)) { + + // for compaibility with PHP4 + if (!function_exists('str_split')) { + /** + * Convert a string to an array (needed for PHP4 compatibility) + * @param string $string The input string. + * @param int $split_length Maximum length of the chunk. + * @return If the optional split_length parameter is specified, the returned array will be broken down into chunks with each being split_length in length, otherwise each chunk will be one character in length. FALSE is returned if split_length is less than 1. If the split_length length exceeds the length of string , the entire string is returned as the first (and only) array element. + */ + function str_split($string, $split_length=1) { + if ((strlen($string) > $split_length) OR (!$split_length)) { + do { + $c = strlen($string); + $parts[] = substr($string, 0, $split_length); + $string = substr($string, $split_length); + } while ($string !== false); + } else { + $parts = array($string); + } + return $parts; + } + } + + // ##################################################### + + /** + * Class to create QR-code arrays for TCPDF class. + * QR Code symbol is a 2D barcode that can be scanned by handy terminals such as a mobile phone with CCD. + * The capacity of QR Code is up to 7000 digits or 4000 characters, and has high robustness. + * This class supports QR Code model 2, described in JIS (Japanese Industrial Standards) X0510:2004 or ISO/IEC 18004. + * Currently the following features are not supported: ECI and FNC1 mode, Micro QR Code, QR Code model 1, Structured mode. + * + * This class is derived from "PHP QR Code encoder" by Dominik Dzienia (http://phpqrcode.sourceforge.net/) based on "libqrencode C library 3.1.1." by Kentaro Fukuchi (http://megaui.net/fukuchi/works/qrencode/index.en.html), contains Reed-Solomon code written by Phil Karn, KA9Q. QR Code is registered trademark of DENSO WAVE INCORPORATED (http://www.denso-wave.com/qrcode/index-e.html). + * Please read comments on this class source file for full copyright and license information. + * + * @name QRcode + * @package com.tecnick.tcpdf + * @abstract Class for generating QR-code array for TCPDF. + * @author Nicola Asuni + * @copyright 2010 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com + * @link http://www.tcpdf.org + * @license http://www.gnu.org/copyleft/lesser.html LGPL + * @version 1.0.002 + */ + class QRcode { + + /** + * @var barcode array to be returned which is readable by TCPDF + * @access protected + */ + protected $barcode_array = array(); + + /** + * @var QR code version. Size of QRcode is defined as version. Version is from 1 to 40. Version 1 is 21*21 matrix. And 4 modules increases whenever 1 version increases. So version 40 is 177*177 matrix. + * @access protected + */ + protected $version = 0; + + /** + * @var Levels of error correction. See definitions for possible values. + * @access protected + */ + protected $level = QR_ECLEVEL_L; + + /** + * @var Encoding mode + * @access protected + */ + protected $hint = QR_MODE_8B; + + /** + * @var if true the input string will be converted to uppercase + * @access protected + */ + protected $casesensitive = true; + + /** + * @var structured QR code (not supported yet) + * @access protected + */ + protected $structured = 0; + + /** + * @var mask data + * @access protected + */ + protected $data; + + // FrameFiller + + /** + * @var width + * @access protected + */ + protected $width; + + /** + * @var frame + * @access protected + */ + protected $frame; + + /** + * @var X position of bit + * @access protected + */ + protected $x; + + /** + * @var Y position of bit + * @access protected + */ + protected $y; + + /** + * @var direction + * @access protected + */ + protected $dir; + + /** + * @var single bit + * @access protected + */ + protected $bit; + + // ---- QRrawcode ---- + + /** + * @var data code + * @access protected + */ + protected $datacode = array(); + + /** + * @var error correction code + * @access protected + */ + protected $ecccode = array(); + + /** + * @var blocks + * @access protected + */ + protected $blocks; + + /** + * @var Reed-Solomon blocks + * @access protected + */ + protected $rsblocks = array(); //of RSblock + + /** + * @var counter + * @access protected + */ + protected $count; + + /** + * @var data length + * @access protected + */ + protected $dataLength; + + /** + * @var error correction length + * @access protected + */ + protected $eccLength; + + /** + * @var b1 + * @access protected + */ + protected $b1; + + // ---- QRmask ---- + + /** + * @var run length + * @access protected + */ + protected $runLength = array(); + + // ---- QRsplit ---- + + /** + * @var input data string + * @access protected + */ + protected $dataStr = ''; + + /** + * @var input items + * @access protected + */ + protected $items; + + // Reed-Solomon items + + /** + * @var Reed-Solomon items + * @access protected + */ + protected $rsitems = array(); + + /** + * @var array of frames + * @access protected + */ + protected $frames = array(); + + /** + * @var alphabet-numeric convesion table + * @access protected + */ + protected $anTable = array( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // + ); + + /** + * @var array Table of the capacity of symbols + * See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004. + * @access protected + */ + protected $capacity = array( + array( 0, 0, 0, array( 0, 0, 0, 0)), // + array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 + array( 25, 44, 7, array( 10, 16, 22, 28)), // + array( 29, 70, 7, array( 15, 26, 36, 44)), // + array( 33, 100, 7, array( 20, 36, 52, 64)), // + array( 37, 134, 7, array( 26, 48, 72, 88)), // 5 + array( 41, 172, 7, array( 36, 64, 96, 112)), // + array( 45, 196, 0, array( 40, 72, 108, 130)), // + array( 49, 242, 0, array( 48, 88, 132, 156)), // + array( 53, 292, 0, array( 60, 110, 160, 192)), // + array( 57, 346, 0, array( 72, 130, 192, 224)), // 10 + array( 61, 404, 0, array( 80, 150, 224, 264)), // + array( 65, 466, 0, array( 96, 176, 260, 308)), // + array( 69, 532, 0, array( 104, 198, 288, 352)), // + array( 73, 581, 3, array( 120, 216, 320, 384)), // + array( 77, 655, 3, array( 132, 240, 360, 432)), // 15 + array( 81, 733, 3, array( 144, 280, 408, 480)), // + array( 85, 815, 3, array( 168, 308, 448, 532)), // + array( 89, 901, 3, array( 180, 338, 504, 588)), // + array( 93, 991, 3, array( 196, 364, 546, 650)), // + array( 97, 1085, 3, array( 224, 416, 600, 700)), // 20 + array(101, 1156, 4, array( 224, 442, 644, 750)), // + array(105, 1258, 4, array( 252, 476, 690, 816)), // + array(109, 1364, 4, array( 270, 504, 750, 900)), // + array(113, 1474, 4, array( 300, 560, 810, 960)), // + array(117, 1588, 4, array( 312, 588, 870, 1050)), // 25 + array(121, 1706, 4, array( 336, 644, 952, 1110)), // + array(125, 1828, 4, array( 360, 700, 1020, 1200)), // + array(129, 1921, 3, array( 390, 728, 1050, 1260)), // + array(133, 2051, 3, array( 420, 784, 1140, 1350)), // + array(137, 2185, 3, array( 450, 812, 1200, 1440)), // 30 + array(141, 2323, 3, array( 480, 868, 1290, 1530)), // + array(145, 2465, 3, array( 510, 924, 1350, 1620)), // + array(149, 2611, 3, array( 540, 980, 1440, 1710)), // + array(153, 2761, 3, array( 570, 1036, 1530, 1800)), // + array(157, 2876, 0, array( 570, 1064, 1590, 1890)), // 35 + array(161, 3034, 0, array( 600, 1120, 1680, 1980)), // + array(165, 3196, 0, array( 630, 1204, 1770, 2100)), // + array(169, 3362, 0, array( 660, 1260, 1860, 2220)), // + array(173, 3532, 0, array( 720, 1316, 1950, 2310)), // + array(177, 3706, 0, array( 750, 1372, 2040, 2430)) // 40 + ); + + /** + * @var array Length indicator + * @access protected + */ + protected $lengthTableBits = array( + array(10, 12, 14), + array( 9, 11, 13), + array( 8, 16, 16), + array( 8, 10, 12) + ); + + /** + * @var array Table of the error correction code (Reed-Solomon block) + * See Table 12-16 (pp.30-36), JIS X0510:2004. + * @access protected + */ + protected $eccTable = array( + array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), // + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1 + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // + array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)), // + array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)), // + array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5 + array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)), // + array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)), // + array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)), // + array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)), // + array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), // 10 + array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)), // + array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)), // + array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)), // + array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)), // + array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), // 15 + array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)), // + array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)), // + array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)), // + array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)), // + array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), // 20 + array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)), // + array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)), // + array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)), // + array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)), // + array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), // 25 + array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)), // + array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)), // + array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), // + array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)), // + array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), // 30 + array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)), // + array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)), // + array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)), // + array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)), // + array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), // 35 + array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), // + array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)), // + array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), // + array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)), // + array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)) // 40 + ); + + /** + * @var array Positions of alignment patterns. + * This array includes only the second and the third position of the alignment patterns. Rest of them can be calculated from the distance between them. + * See Table 1 in Appendix E (pp.71) of JIS X0510:2004. + * @access protected + */ + protected $alignmentPattern = array( + array( 0, 0), + array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5 + array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 + array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), // 11-15 + array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), // 16-20 + array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), // 21-25 + array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), // 26-30 + array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), // 31-35 + array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58) // 35-40 + ); + + /** + * @var array Version information pattern (BCH coded). + * See Table 1 in Appendix D (pp.68) of JIS X0510:2004. + * size: [QRSPEC_VERSION_MAX - 6] + * @access protected + */ + protected $versionPattern = array( + 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, // + 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, // + 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, // + 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, // + 0x27541, 0x28c69 + ); + + /** + * @var array Format information + * @access protected + */ + protected $formatInfo = array( + array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), // + array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), // + array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), // + array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) // + ); + + + // ------------------------------------------------- + // ------------------------------------------------- + + + /** + * This is the class constructor. + * Creates a QRcode object + * @param string $code code to represent using QRcode + * @param string $eclevel error level:
  • L : About 7% or less errors can be corrected.
  • M : About 15% or less errors can be corrected.
  • Q : About 25% or less errors can be corrected.
  • H : About 30% or less errors can be corrected.
+ * @access public + * @since 1.0.000 + */ + public function __construct($code, $eclevel = 'L') { + $barcode_array = array(); + if ((is_null($code)) OR ($code == '\0') OR ($code == '')) { + return false; + } + // set error correction level + $this->level = array_search($eclevel, array('L', 'M', 'Q', 'H')); + if ($this->level === false) { + $this->level = QR_ECLEVEL_L; + } + if (($this->hint != QR_MODE_8B) AND ($this->hint != QR_MODE_KJ)) { + return false; + } + if (($this->version < 0) OR ($this->version > QRSPEC_VERSION_MAX)) { + return false; + } + $this->items = array(); + $this->encodeString($code); + $qrTab = $this->binarize($this->data); + $size = count($qrTab); + $barcode_array['num_rows'] = $size; + $barcode_array['num_cols'] = $size; + $barcode_array['bcode'] = array(); + foreach ($qrTab as $line) { + $arrAdd = array(); + foreach (str_split($line) as $char) { + $arrAdd[] = ($char=='1')?1:0; + } + $barcode_array['bcode'][] = $arrAdd; + } + $this->barcode_array = $barcode_array; + } + + /** + * Returns a barcode array which is readable by TCPDF + * @return array barcode array readable by TCPDF; + * @access public + */ + public function getBarcodeArray() { + return $this->barcode_array; + } + + /** + * Convert the frame in binary form + * @param array $frame array to binarize + * @return array frame in binary form + */ + protected function binarize($frame) { + $len = count($frame); + // the frame is square (width = height) + foreach ($frame as &$frameLine) { + for ($i=0; $i<$len; $i++) { + $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0'; + } + } + return $frame; + } + + /** + * Encode the input string to QR code + * @param string $string input string to encode + */ + protected function encodeString($string) { + $this->dataStr = $string; + if (!$this->casesensitive) { + $this->toUpper(); + } + $ret = $this->splitString(); + if ($ret < 0) { + return NULL; + } + $this->encodeMask(-1); + } + + /** + * Encode mask + * @param int $mask masking mode + */ + protected function encodeMask($mask) { + $spec = array(0, 0, 0, 0, 0); + $this->datacode = $this->getByteStream($this->items); + if (is_null($this->datacode)) { + return NULL; + } + $spec = $this->getEccSpec($this->version, $this->level, $spec); + $this->b1 = $this->rsBlockNum1($spec); + $this->dataLength = $this->rsDataLength($spec); + $this->eccLength = $this->rsEccLength($spec); + $this->ecccode = array_fill(0, $this->eccLength, 0); + $this->blocks = $this->rsBlockNum($spec); + $ret = $this->init($spec); + if ($ret < 0) { + return NULL; + } + $this->count = 0; + $this->width = $this->getWidth($this->version); + $this->frame = $this->newFrame($this->version); + $this->x = $this->width - 1; + $this->y = $this->width - 1; + $this->dir = -1; + $this->bit = -1; + // inteleaved data and ecc codes + for ($i=0; $i < ($this->dataLength + $this->eccLength); $i++) { + $code = $this->getCode(); + $bit = 0x80; + for ($j=0; $j<8; $j++) { + $addr = $this->getNextPosition(); + $this->setFrameAt($addr, 0x02 | (($bit & $code) != 0)); + $bit = $bit >> 1; + } + } + // remainder bits + $j = $this->getRemainder($this->version); + for ($i=0; $i<$j; $i++) { + $addr = $this->getNextPosition(); + $this->setFrameAt($addr, 0x02); + } + // masking + $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0); + if ($mask < 0) { + if (QR_FIND_BEST_MASK) { + $masked = $this->mask($this->width, $this->frame, $this->level); + } else { + $masked = $this->makeMask($this->width, $this->frame, (intval(QR_DEFAULT_MASK) % 8), $this->level); + } + } else { + $masked = $this->makeMask($this->width, $this->frame, $mask, $this->level); + } + if ($masked == NULL) { + return NULL; + } + $this->data = $masked; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // FrameFiller + + /** + * Set frame value at specified position + * @param array $at x,y position + * @param int $val value of the character to set + */ + protected function setFrameAt($at, $val) { + $this->frame[$at['y']][$at['x']] = chr($val); + } + + /** + * Get frame value at specified position + * @param array $at x,y position + * @return value at specified position + */ + protected function getFrameAt($at) { + return ord($this->frame[$at['y']][$at['x']]); + } + + /** + * Return the next frame position + * @return array of x,y coordinates + */ + protected function getNextPosition() { + do { + if ($this->bit == -1) { + $this->bit = 0; + return array('x'=>$this->x, 'y'=>$this->y); + } + $x = $this->x; + $y = $this->y; + $w = $this->width; + if ($this->bit == 0) { + $x--; + $this->bit++; + } else { + $x++; + $y += $this->dir; + $this->bit--; + } + if ($this->dir < 0) { + if ($y < 0) { + $y = 0; + $x -= 2; + $this->dir = 1; + if ($x == 6) { + $x--; + $y = 9; + } + } + } else { + if ($y == $w) { + $y = $w - 1; + $x -= 2; + $this->dir = -1; + if ($x == 6) { + $x--; + $y -= 8; + } + } + } + if (($x < 0) OR ($y < 0)) { + return NULL; + } + $this->x = $x; + $this->y = $y; + } while(ord($this->frame[$y][$x]) & 0x80); + return array('x'=>$x, 'y'=>$y); + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRrawcode + + /** + * Initialize code. + * @param array $spec array of ECC specification + * @return 0 in case of success, -1 in case of error + */ + protected function init($spec) { + $dl = $this->rsDataCodes1($spec); + $el = $this->rsEccCodes1($spec); + $rs = $this->init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + $blockNo = 0; + $dataPos = 0; + $eccPos = 0; + $endfor = $this->rsBlockNum1($spec); + for ($i=0; $i < $endfor; ++$i) { + $ecc = array_slice($this->ecccode, $eccPos); + $this->rsblocks[$blockNo] = array(); + $this->rsblocks[$blockNo]['dataLength'] = $dl; + $this->rsblocks[$blockNo]['data'] = array_slice($this->datacode, $dataPos); + $this->rsblocks[$blockNo]['eccLength'] = $el; + $ecc = $this->encode_rs_char($rs, $this->rsblocks[$blockNo]['data'], $ecc); + $this->rsblocks[$blockNo]['ecc'] = $ecc; + $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + if ($this->rsBlockNum2($spec) == 0) { + return 0; + } + $dl = $this->rsDataCodes2($spec); + $el = $this->rsEccCodes2($spec); + $rs = $this->init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + if ($rs == NULL) { + return -1; + } + $endfor = $this->rsBlockNum2($spec); + for ($i=0; $i < $endfor; ++$i) { + $ecc = array_slice($this->ecccode, $eccPos); + $this->rsblocks[$blockNo] = array(); + $this->rsblocks[$blockNo]['dataLength'] = $dl; + $this->rsblocks[$blockNo]['data'] = array_slice($this->datacode, $dataPos); + $this->rsblocks[$blockNo]['eccLength'] = $el; + $ecc = $this->encode_rs_char($rs, $this->rsblocks[$blockNo]['data'], $ecc); + $this->rsblocks[$blockNo]['ecc'] = $ecc; + $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc); + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + return 0; + } + + /** + * Return Reed-Solomon block code. + * @return array rsblocks + */ + protected function getCode() { + if ($this->count < $this->dataLength) { + $row = $this->count % $this->blocks; + $col = $this->count / $this->blocks; + if ($col >= $this->rsblocks[0]['dataLength']) { + $row += $this->b1; + } + $ret = $this->rsblocks[$row]['data'][$col]; + } elseif ($this->count < $this->dataLength + $this->eccLength) { + $row = ($this->count - $this->dataLength) % $this->blocks; + $col = ($this->count - $this->dataLength) / $this->blocks; + $ret = $this->rsblocks[$row]['ecc'][$col]; + } else { + return 0; + } + $this->count++; + return $ret; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRmask + + /** + * Write Format Information on frame and returns the number of black bits + * @param int $width frame width + * @param array $frame frame + * @param array $mask masking mode + * @param int $level error correction level + * @return int blacks + */ + protected function writeFormatInformation($width, &$frame, $mask, $level) { + $blacks = 0; + $format = $this->getFormatInfo($mask, $level); + for ($i=0; $i<8; ++$i) { + if ($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + $frame[8][$width - 1 - $i] = chr($v); + if ($i < 6) { + $frame[$i][8] = chr($v); + } else { + $frame[$i + 1][8] = chr($v); + } + $format = $format >> 1; + } + for ($i=0; $i<7; ++$i) { + if ($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + $frame[$width - 7 + $i][8] = chr($v); + if ($i == 0) { + $frame[8][7] = chr($v); + } else { + $frame[8][6 - $i] = chr($v); + } + $format = $format >> 1; + } + return $blacks; + } + + /** + * mask0 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask0($x, $y) { + return ($x + $y) & 1; + } + + /** + * mask1 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask1($x, $y) { + return ($y & 1); + } + + /** + * mask2 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask2($x, $y) { + return ($x % 3); + } + + /** + * mask3 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask3($x, $y) { + return ($x + $y) % 3; + } + + /** + * mask4 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask4($x, $y) { + return (((int)($y / 2)) + ((int)($x / 3))) & 1; + } + + /** + * mask5 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask5($x, $y) { + return (($x * $y) & 1) + ($x * $y) % 3; + } + + /** + * mask6 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask6($x, $y) { + return ((($x * $y) & 1) + ($x * $y) % 3) & 1; + } + + /** + * mask7 + * @param int $x X position + * @param int $y Y position + * @return int mask + */ + protected function mask7($x, $y) { + return ((($x * $y) % 3) + (($x + $y) & 1)) & 1; + } + + /** + * Return bitmask + * @param int $maskNo mask number + * @param int $width width + * @param array $frame frame + * @return array bitmask + */ + protected function generateMaskNo($maskNo, $width, $frame) { + $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); + for ($y=0; $y<$width; ++$y) { + for ($x=0; $x<$width; ++$x) { + if (ord($frame[$y][$x]) & 0x80) { + $bitMask[$y][$x] = 0; + } else { + $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y); + $bitMask[$y][$x] = ($maskFunc == 0)?1:0; + } + } + } + return $bitMask; + } + + /** + * makeMaskNo + * @param int $maskNo + * @param int $width + * @param int $s + * @param int $d + * @param boolean $maskGenOnly + * @return int b + */ + protected function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly=false) { + $b = 0; + $bitMask = array(); + $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); + if ($maskGenOnly) { + return; + } + $d = $s; + for ($y=0; $y<$width; ++$y) { + for ($x=0; $x<$width; ++$x) { + if ($bitMask[$y][$x] == 1) { + $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]); + } + $b += (int)(ord($d[$y][$x]) & 1); + } + } + return $b; + } + + /** + * makeMask + * @param int $width + * @param array $frame + * @param int $maskNo + * @param int $level + * @return array mask + */ + protected function makeMask($width, $frame, $maskNo, $level) { + $masked = array_fill(0, $width, str_repeat("\0", $width)); + $this->makeMaskNo($maskNo, $width, $frame, $masked); + $this->writeFormatInformation($width, $masked, $maskNo, $level); + return $masked; + } + + /** + * calcN1N3 + * @param int $length + * @return int demerit + */ + protected function calcN1N3($length) { + $demerit = 0; + for ($i=0; $i<$length; ++$i) { + if ($this->runLength[$i] >= 5) { + $demerit += (N1 + ($this->runLength[$i] - 5)); + } + if ($i & 1) { + if (($i >= 3) AND ($i < ($length-2)) AND ($this->runLength[$i] % 3 == 0)) { + $fact = (int)($this->runLength[$i] / 3); + if (($this->runLength[$i-2] == $fact) + AND ($this->runLength[$i-1] == $fact) + AND ($this->runLength[$i+1] == $fact) + AND ($this->runLength[$i+2] == $fact)) { + if (($this->runLength[$i-3] < 0) OR ($this->runLength[$i-3] >= (4 * $fact))) { + $demerit += N3; + } elseif ((($i+3) >= $length) OR ($this->runLength[$i+3] >= (4 * $fact))) { + $demerit += N3; + } + } + } + } + } + return $demerit; + } + + /** + * evaluateSymbol + * @param int $width + * @param array $frame + * @return int demerit + */ + protected function evaluateSymbol($width, $frame) { + $head = 0; + $demerit = 0; + for ($y=0; $y<$width; ++$y) { + $head = 0; + $this->runLength[0] = 1; + $frameY = $frame[$y]; + if ($y > 0) { + $frameYM = $frame[$y-1]; + } + for ($x=0; $x<$width; ++$x) { + if (($x > 0) AND ($y > 0)) { + $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]); + $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]); + if (($b22 | ($w22 ^ 1)) & 1) { + $demerit += N2; + } + } + if (($x == 0) AND (ord($frameY[$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } elseif ($x > 0) { + if ((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + $demerit += $this->calcN1N3($head+1); + } + for ($x=0; $x<$width; ++$x) { + $head = 0; + $this->runLength[0] = 1; + for ($y=0; $y<$width; ++$y) { + if (($y == 0) AND (ord($frame[$y][$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } elseif ($y > 0) { + if ((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + $demerit += $this->calcN1N3($head+1); + } + return $demerit; + } + + /** + * mask + * @param int $width + * @param array $frame + * @param int $level + * @return array best mask + */ + protected function mask($width, $frame, $level) { + $minDemerit = PHP_INT_MAX; + $bestMaskNum = 0; + $bestMask = array(); + $checked_masks = array(0, 1, 2, 3, 4, 5, 6, 7); + if (QR_FIND_FROM_RANDOM !== false) { + $howManuOut = 8 - (QR_FIND_FROM_RANDOM % 9); + for ($i = 0; $i < $howManuOut; ++$i) { + $remPos = rand (0, count($checked_masks)-1); + unset($checked_masks[$remPos]); + $checked_masks = array_values($checked_masks); + } + } + $bestMask = $frame; + foreach ($checked_masks as $i) { + $mask = array_fill(0, $width, str_repeat("\0", $width)); + $demerit = 0; + $blacks = 0; + $blacks = $this->makeMaskNo($i, $width, $frame, $mask); + $blacks += $this->writeFormatInformation($width, $mask, $i, $level); + $blacks = (int)(100 * $blacks / ($width * $width)); + $demerit = (int)((int)(abs($blacks - 50) / 5) * N4); + $demerit += $this->evaluateSymbol($width, $mask); + if ($demerit < $minDemerit) { + $minDemerit = $demerit; + $bestMask = $mask; + $bestMaskNum = $i; + } + } + return $bestMask; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRsplit + + /** + * Return true if the character at specified position is a number + * @param string $str string + * @param int $pos characted position + * @return boolean true of false + */ + protected function isdigitat($str, $pos) { + if ($pos >= strlen($str)) { + return false; + } + return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9'))); + } + + /** + * Return true if the character at specified position is an alphanumeric character + * @param string $str string + * @param int $pos characted position + * @return boolean true of false + */ + protected function isalnumat($str, $pos) { + if ($pos >= strlen($str)) { + return false; + } + return ($this->lookAnTable(ord($str[$pos])) >= 0); + } + + /** + * identifyMode + * @param int $pos + * @return int mode + */ + protected function identifyMode($pos) { + if ($pos >= strlen($this->dataStr)) { + return QR_MODE_NL; + } + $c = $this->dataStr[$pos]; + if ($this->isdigitat($this->dataStr, $pos)) { + return QR_MODE_NM; + } elseif ($this->isalnumat($this->dataStr, $pos)) { + return QR_MODE_AN; + } elseif ($this->hint == QR_MODE_KJ) { + if ($pos+1 < strlen($this->dataStr)) { + $d = $this->dataStr[$pos+1]; + $word = (ord($c) << 8) | ord($d); + if (($word >= 0x8140 && $word <= 0x9ffc) OR ($word >= 0xe040 && $word <= 0xebbf)) { + return QR_MODE_KJ; + } + } + } + return QR_MODE_8B; + } + + /** + * eatNum + * @return int run + */ + protected function eatNum() { + $ln = $this->lengthIndicator(QR_MODE_NM, $this->version); + $p = 0; + while($this->isdigitat($this->dataStr, $p)) { + $p++; + } + $run = $p; + $mode = $this->identifyMode($p); + if ($mode == QR_MODE_8B) { + $dif = $this->estimateBitsModeNum($run) + 4 + $ln + + $this->estimateBitsMode8(1) // + 4 + l8 + - $this->estimateBitsMode8($run + 1); // - 4 - l8 + if ($dif > 0) { + return $this->eat8(); + } + } + if ($mode == QR_MODE_AN) { + $dif = $this->estimateBitsModeNum($run) + 4 + $ln + + $this->estimateBitsModeAn(1) // + 4 + la + - $this->estimateBitsModeAn($run + 1);// - 4 - la + if ($dif > 0) { + return $this->eatAn(); + } + } + $this->items = $this->appendNewInputItem($this->items, QR_MODE_NM, $run, str_split($this->dataStr)); + return $run; + } + + /** + * eatAn + * @return int run + */ + protected function eatAn() { + $la = $this->lengthIndicator(QR_MODE_AN, $this->version); + $ln = $this->lengthIndicator(QR_MODE_NM, $this->version); + $p = 0; + while($this->isalnumat($this->dataStr, $p)) { + if ($this->isdigitat($this->dataStr, $p)) { + $q = $p; + while($this->isdigitat($this->dataStr, $q)) { + $q++; + } + $dif = $this->estimateBitsModeAn($p) // + 4 + la + + $this->estimateBitsModeNum($q - $p) + 4 + $ln + - $this->estimateBitsModeAn($q); // - 4 - la + if ($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + $run = $p; + if (!$this->isalnumat($this->dataStr, $p)) { + $dif = $this->estimateBitsModeAn($run) + 4 + $la + + $this->estimateBitsMode8(1) // + 4 + l8 + - $this->estimateBitsMode8($run + 1); // - 4 - l8 + if ($dif > 0) { + return $this->eat8(); + } + } + $this->items = $this->appendNewInputItem($this->items, QR_MODE_AN, $run, str_split($this->dataStr)); + return $run; + } + + /** + * eatKanji + * @return int run + */ + protected function eatKanji() { + $p = 0; + while($this->identifyMode($p) == QR_MODE_KJ) { + $p += 2; + } + $this->items = $this->appendNewInputItem($this->items, QR_MODE_KJ, $p, str_split($this->dataStr)); + return $run; + } + + /** + * eat8 + * @return int run + */ + protected function eat8() { + $la = $this->lengthIndicator(QR_MODE_AN, $this->version); + $ln = $this->lengthIndicator(QR_MODE_NM, $this->version); + $p = 1; + $dataStrLen = strlen($this->dataStr); + while($p < $dataStrLen) { + $mode = $this->identifyMode($p); + if ($mode == QR_MODE_KJ) { + break; + } + if ($mode == QR_MODE_NM) { + $q = $p; + while($this->isdigitat($this->dataStr, $q)) { + $q++; + } + $dif = $this->estimateBitsMode8($p) // + 4 + l8 + + $this->estimateBitsModeNum($q - $p) + 4 + $ln + - $this->estimateBitsMode8($q); // - 4 - l8 + if ($dif < 0) { + break; + } else { + $p = $q; + } + } elseif ($mode == QR_MODE_AN) { + $q = $p; + while($this->isalnumat($this->dataStr, $q)) { + $q++; + } + $dif = $this->estimateBitsMode8($p) // + 4 + l8 + + $this->estimateBitsModeAn($q - $p) + 4 + $la + - $this->estimateBitsMode8($q); // - 4 - l8 + if ($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + $run = $p; + $this->items = $this->appendNewInputItem($this->items, QR_MODE_8B, $run, str_split($this->dataStr)); + return $run; + } + + /** + * splitString + */ + protected function splitString() { + while (strlen($this->dataStr) > 0) { + if ($this->dataStr == '') { + return 0; + } + $mode = $this->identifyMode(0); + switch ($mode) { + case QR_MODE_NM: { + $length = $this->eatNum(); + break; + } + case QR_MODE_AN: { + $length = $this->eatAn(); + break; + } + case QR_MODE_KJ: { + if ($hint == QR_MODE_KJ) { + $length = $this->eatKanji(); + } else { + $length = $this->eat8(); + } + break; + } + default: { + $length = $this->eat8(); + break; + } + } + if ($length == 0) { + return 0; + } + if ($length < 0) { + return -1; + } + $this->dataStr = substr($this->dataStr, $length); + } + } + + /** + * toUpper + */ + protected function toUpper() { + $stringLen = strlen($this->dataStr); + $p = 0; + while ($p < $stringLen) { + $mode = $this->identifyMode(substr($this->dataStr, $p), $this->hint); + if ($mode == QR_MODE_KJ) { + $p += 2; + } else { + if ((ord($this->dataStr[$p]) >= ord('a')) AND (ord($this->dataStr[$p]) <= ord('z'))) { + $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); + } + $p++; + } + } + return $this->dataStr; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRinputItem + + /** + * newInputItem + * @param int $mode + * @param int $size + * @param array $data + * @param array $bstream + * @return array input item + */ + protected function newInputItem($mode, $size, $data, $bstream=null) { + $setData = array_slice($data, 0, $size); + if (count($setData) < $size) { + $setData = array_merge($setData, array_fill(0, ($size - count($setData)), 0)); + } + if (!$this->check($mode, $size, $setData)) { + return NULL; + } + $inputitem = array(); + $inputitem['mode'] = $mode; + $inputitem['size'] = $size; + $inputitem['data'] = $setData; + $inputitem['bstream'] = $bstream; + return $inputitem; + } + + /** + * encodeModeNum + * @param array $inputitem + * @param int $version + * @return array input item + */ + protected function encodeModeNum($inputitem, $version) { + $words = (int)($inputitem['size'] / 3); + $inputitem['bstream'] = array(); + $val = 0x1; + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, $val); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_NM, $version), $inputitem['size']); + for ($i=0; $i < $words; ++$i) { + $val = (ord($inputitem['data'][$i*3 ]) - ord('0')) * 100; + $val += (ord($inputitem['data'][$i*3+1]) - ord('0')) * 10; + $val += (ord($inputitem['data'][$i*3+2]) - ord('0')); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 10, $val); + } + if ($inputitem['size'] - $words * 3 == 1) { + $val = ord($inputitem['data'][$words*3]) - ord('0'); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, $val); + } elseif (($inputitem['size'] - ($words * 3)) == 2) { + $val = (ord($inputitem['data'][$words*3 ]) - ord('0')) * 10; + $val += (ord($inputitem['data'][$words*3+1]) - ord('0')); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 7, $val); + } + return $inputitem; + } + + /** + * encodeModeAn + * @param array $inputitem + * @param int $version + * @return array input item + */ + protected function encodeModeAn($inputitem, $version) { + $words = (int)($inputitem['size'] / 2); + $inputitem['bstream'] = array(); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x02); + $inputitem['bstream'] = $this->appendNum(v, $this->lengthIndicator(QR_MODE_AN, $version), $inputitem['size']); + for ($i=0; $i < $words; ++$i) { + $val = (int)$this->lookAnTable(ord($inputitem['data'][$i*2 ])) * 45; + $val += (int)$this->lookAnTable(ord($inputitem['data'][$i*2+1])); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 11, $val); + } + if ($inputitem['size'] & 1) { + $val = $this->lookAnTable(ord($inputitem['data'][($words * 2)])); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 6, $val); + } + return $inputitem; + } + + /** + * encodeMode8 + * @param array $inputitem + * @param int $version + * @return array input item + */ + protected function encodeMode8($inputitem, $version) { + $inputitem['bstream'] = array(); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x4); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_8B, $version), $inputitem['size']); + for ($i=0; $i < $inputitem['size']; ++$i) { + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 8, ord($inputitem['data'][$i])); + } + return $inputitem; + } + + /** + * encodeModeKanji + * @param array $inputitem + * @param int $version + * @return array input item + */ + protected function encodeModeKanji($inputitem, $version) { + $inputitem['bstream'] = array(); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x8); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], $this->lengthIndicator(QR_MODE_KJ, $version), (int)($inputitem['size'] / 2)); + for ($i=0; $i<$inputitem['size']; $i+=2) { + $val = (ord($inputitem['data'][$i]) << 8) | ord($inputitem['data'][$i+1]); + if ($val <= 0x9ffc) { + $val -= 0x8140; + } else { + $val -= 0xc140; + } + $h = ($val >> 8) * 0xc0; + $val = ($val & 0xff) + $h; + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 13, $val); + } + return $inputitem; + } + + /** + * encodeModeStructure + * @param array $inputitem + * @return array input item + */ + protected function encodeModeStructure($inputitem) { + $inputitem['bstream'] = array(); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, 0x03); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, ord($inputitem['data'][1]) - 1); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 4, ord($inputitem['data'][0]) - 1); + $inputitem['bstream'] = $this->appendNum($inputitem['bstream'], 8, ord($inputitem['data'][2])); + return $inputitem; + } + + /** + * encodeBitStream + * @param array $inputitem + * @param int $version + * @return array input item + */ + protected function encodeBitStream($inputitem, $version) { + $inputitem['bstream'] = array(); + $words = $this->maximumWords($inputitem['mode'], $version); + if ($inputitem['size'] > $words) { + $st1 = $this->newInputItem($inputitem['mode'], $words, $inputitem['data']); + $st2 = $this->newInputItem($inputitem['mode'], $inputitem['size'] - $words, array_slice($inputitem['data'], $words)); + $st1 = $this->encodeBitStream($st1, $version); + $st2 = $this->encodeBitStream($st2, $version); + $inputitem['bstream'] = array(); + $inputitem['bstream'] = $this->appendBitstream($inputitem['bstream'], $st1['bstream']); + $inputitem['bstream'] = $this->appendBitstream($inputitem['bstream'], $st2['bstream']); + } else { + switch($inputitem['mode']) { + case QR_MODE_NM: { + $inputitem = $this->encodeModeNum($inputitem, $version); + break; + } + case QR_MODE_AN: { + $inputitem = $this->encodeModeAn($inputitem, $version); + break; + } + case QR_MODE_8B: { + $inputitem = $this->encodeMode8($inputitem, $version); + break; + } + case QR_MODE_KJ: { + $inputitem = $this->encodeModeKanji($inputitem, $version); + break; + } + case QR_MODE_ST: { + $inputitem = $this->encodeModeStructure($inputitem); + break; + } + default: { + break; + } + } + } + return $inputitem; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRinput + + /** + * Append data to an input object. + * The data is copied and appended to the input object. + * @param array items input items + * @param int $mode encoding mode. + * @param int $size size of data (byte). + * @param array $data array of input data. + * @return items + * + */ + protected function appendNewInputItem($items, $mode, $size, $data) { + $items[] = $this->newInputItem($mode, $size, $data); + return $items; + } + + /** + * insertStructuredAppendHeader + * @param array $items + * @param int $size + * @param int $index + * @param int $parity + * @return array items + */ + protected function insertStructuredAppendHeader($items, $size, $index, $parity) { + if ($size > MAX_STRUCTURED_SYMBOLS) { + return -1; + } + if (($index <= 0) OR ($index > MAX_STRUCTURED_SYMBOLS)) { + return -1; + } + $buf = array($size, $index, $parity); + $entry = $this->newInputItem(QR_MODE_ST, 3, buf); + array_unshift($items, $entry); + return $items; + } + + /** + * calcParity + * @param array $items + * @return int parity + */ + protected function calcParity($items) { + $parity = 0; + foreach ($items as $item) { + if ($item['mode'] != QR_MODE_ST) { + for ($i=$item['size']-1; $i>=0; --$i) { + $parity ^= $item['data'][$i]; + } + } + } + return $parity; + } + + /** + * checkModeNum + * @param int $size + * @param array $data + * @return boolean true or false + */ + protected function checkModeNum($size, $data) { + for ($i=0; $i<$size; ++$i) { + if ((ord($data[$i]) < ord('0')) OR (ord($data[$i]) > ord('9'))){ + return false; + } + } + return true; + } + + /** + * estimateBitsModeNum + * @param int $size + * @return int number of bits + */ + protected function estimateBitsModeNum($size) { + $w = (int)$size / 3; + $bits = $w * 10; + switch($size - $w * 3) { + case 1: { + $bits += 4; + break; + } + case 2: { + $bits += 7; + break; + } + default: { + break; + } + } + return $bits; + } + + /** + * Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19). + * @param int $c character value + * @return value + */ + protected function lookAnTable($c) { + return (($c > 127)?-1:$this->anTable[$c]); + } + + /** + * checkModeAn + * @param int $size + * @param array $data + * @return boolean true or false + */ + protected function checkModeAn($size, $data) { + for ($i=0; $i<$size; ++$i) { + if ($this->lookAnTable(ord($data[$i])) == -1) { + return false; + } + } + return true; + } + + /** + * estimateBitsModeAn + * @param int $size + * @return int number of bits + */ + protected function estimateBitsModeAn($size) { + $w = (int)($size / 2); + $bits = $w * 11; + if ($size & 1) { + $bits += 6; + } + return $bits; + } + + /** + * estimateBitsMode8 + * @param int $size + * @return int number of bits + */ + protected function estimateBitsMode8($size) { + return $size * 8; + } + + /** + * estimateBitsModeKanji + * @param int $size + * @return int number of bits + */ + protected function estimateBitsModeKanji($size) { + return (int)(($size / 2) * 13); + } + + /** + * checkModeKanji + * @param int $size + * @param array $data + * @return boolean true or false + */ + protected function checkModeKanji($size, $data) { + if ($size & 1) { + return false; + } + for ($i=0; $i<$size; $i+=2) { + $val = (ord($data[$i]) << 8) | ord($data[$i+1]); + if (($val < 0x8140) OR (($val > 0x9ffc) AND ($val < 0xe040)) OR ($val > 0xebbf)) { + return false; + } + } + return true; + } + + /** + * Validate the input data. + * @param int $mode encoding mode. + * @param int $size size of data (byte). + * @param array data data to validate + * @return boolean true in case of valid data, false otherwise + */ + protected function check($mode, $size, $data) { + if ($size <= 0) { + return false; + } + switch($mode) { + case QR_MODE_NM: { + return $this->checkModeNum($size, $data); + } + case QR_MODE_AN: { + return $this->checkModeAn($size, $data); + } + case QR_MODE_KJ: { + return $this->checkModeKanji($size, $data); + } + case QR_MODE_8B: { + return true; + } + case QR_MODE_ST: { + return true; + } + default: { + break; + } + } + return false; + } + + /** + * estimateBitStreamSize + * @param array $items + * @param int $version + * @return int bits + */ + protected function estimateBitStreamSize($items, $version) { + $bits = 0; + if ($version == 0) { + $version = 1; + } + foreach ($items as $item) { + switch($item['mode']) { + case QR_MODE_NM: { + $bits = $this->estimateBitsModeNum($item['size']); + break; + } + case QR_MODE_AN: { + $bits = $this->estimateBitsModeAn($item['size']); + break; + } + case QR_MODE_8B: { + $bits = $this->estimateBitsMode8($item['size']); + break; + } + case QR_MODE_KJ: { + $bits = $this->estimateBitsModeKanji($item['size']); + break; + } + case QR_MODE_ST: { + return STRUCTURE_HEADER_BITS; + } + default: { + return 0; + } + } + $l = $this->lengthIndicator($item['mode'], $version); + $m = 1 << $l; + $num = (int)(($item['size'] + $m - 1) / $m); + $bits += $num * (4 + $l); + } + return $bits; + } + + /** + * estimateVersion + * @param array $items + * @return int version + */ + protected function estimateVersion($items) { + $version = 0; + $prev = 0; + do { + $prev = $version; + $bits = $this->estimateBitStreamSize($items, $prev); + $version = $this->getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if ($version < 0) { + return -1; + } + } while ($version > $prev); + return $version; + } + + /** + * lengthOfCode + * @param int $mode + * @param int $version + * @param int $bits + * @return int size + */ + protected function lengthOfCode($mode, $version, $bits) { + $payload = $bits - 4 - $this->lengthIndicator($mode, $version); + switch($mode) { + case QR_MODE_NM: { + $chunks = (int)($payload / 10); + $remain = $payload - $chunks * 10; + $size = $chunks * 3; + if ($remain >= 7) { + $size += 2; + } elseif ($remain >= 4) { + $size += 1; + } + break; + } + case QR_MODE_AN: { + $chunks = (int)($payload / 11); + $remain = $payload - $chunks * 11; + $size = $chunks * 2; + if ($remain >= 6) { + ++$size; + } + break; + } + case QR_MODE_8B: { + $size = (int)($payload / 8); + break; + } + case QR_MODE_KJ: { + $size = (int)(($payload / 13) * 2); + break; + } + case QR_MODE_ST: { + $size = (int)($payload / 8); + break; + } + default: { + $size = 0; + break; + } + } + $maxsize = $this->maximumWords($mode, $version); + if ($size < 0) { + $size = 0; + } + if ($size > $maxsize) { + $size = $maxsize; + } + return $size; + } + + /** + * createBitStream + * @param array $items + * @return array of items and total bits + */ + protected function createBitStream($items) { + $total = 0; + foreach ($items as $key => $item) { + $items[$key] = $this->encodeBitStream($item, $this->version); + $bits = count($items[$key]['bstream']); + $total += $bits; + } + return array($items, $total); + } + + /** + * convertData + * @param array $items + * @return array items + */ + protected function convertData($items) { + $ver = $this->estimateVersion($items); + if ($ver > $this->version) { + $this->version = $ver; + } + for (;;) { + $cbs = $this->createBitStream($items); + $items = $cbs[0]; + $bits = $cbs[1]; + if ($bits < 0) { + return -1; + } + $ver = $this->getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if ($ver < 0) { + return -1; + } elseif ($ver > $this->version) { + $this->version = $ver; + } else { + break; + } + } + return $items; + } + + /** + * Append Padding Bit to bitstream + * @param array $bstream + * @return array bitstream + */ + protected function appendPaddingBit($bstream) { + $bits = count($bstream); + $maxwords = $this->getDataLength($this->version, $this->level); + $maxbits = $maxwords * 8; + if ($maxbits == $bits) { + return 0; + } + if ($maxbits - $bits < 5) { + return $this->appendNum($bstream, $maxbits - $bits, 0); + } + $bits += 4; + $words = (int)(($bits + 7) / 8); + $padding = array(); + $padding = $this->appendNum($padding, $words * 8 - $bits + 4, 0); + $padlen = $maxwords - $words; + if ($padlen > 0) { + $padbuf = array(); + for ($i=0; $i<$padlen; ++$i) { + $padbuf[$i] = ($i&1)?0x11:0xec; + } + $padding = $this->appendBytes($padding, $padlen, $padbuf); + } + return $this->appendBitstream($bstream, $padding); + } + + /** + * mergeBitStream + * @param array $bstream + * @return array bitstream + */ + protected function mergeBitStream($items) { + $items = $this->convertData($items); + $bstream = array(); + foreach ($items as $item) { + $bstream = $this->appendBitstream($bstream, $item['bstream']); + } + return $bstream; + } + + /** + * Returns a stream of bits. + * @param int $items + * @return array padded merged byte stream + */ + protected function getBitStream($items) { + $bstream = $this->mergeBitStream($items); + return $this->appendPaddingBit($bstream); + } + + /** + * Pack all bit streams padding bits into a byte array. + * @param int $items + * @return array padded merged byte stream + */ + protected function getByteStream($items) { + $bstream = $this->getBitStream($items); + return $this->bitstreamToByte($bstream); + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRbitstream + + /** + * Return an array with zeros + * @param int $setLength array size + * @return array + */ + protected function allocate($setLength) { + return array_fill(0, $setLength, 0); + } + + /** + * Return new bitstream from number + * @param int $bits number of bits + * @param int $num number + * @return array bitstream + */ + protected function newFromNum($bits, $num) { + $bstream = $this->allocate($bits); + $mask = 1 << ($bits - 1); + for ($i=0; $i<$bits; ++$i) { + if ($num & $mask) { + $bstream[$i] = 1; + } else { + $bstream[$i] = 0; + } + $mask = $mask >> 1; + } + return $bstream; + } + + /** + * Return new bitstream from bytes + * @param int $size size + * @param array $data bytes + * @return array bitstream + */ + protected function newFromBytes($size, $data) { + $bstream = $this->allocate($size * 8); + $p=0; + for ($i=0; $i<$size; ++$i) { + $mask = 0x80; + for ($j=0; $j<8; ++$j) { + if ($data[$i] & $mask) { + $bstream[$p] = 1; + } else { + $bstream[$p] = 0; + } + $p++; + $mask = $mask >> 1; + } + } + return $bstream; + } + + /** + * Append one bitstream to another + * @param array $bitstream original bitstream + * @param array $append bitstream to append + * @return array bitstream + */ + protected function appendBitstream($bitstream, $append) { + if ((!is_array($append)) OR (count($append) == 0)) { + return $bitstream; + } + if (count($bitstream) == 0) { + return $append; + } + return array_values(array_merge($bitstream, $append)); + } + + /** + * Append one bitstream created from number to another + * @param array $bitstream original bitstream + * @param int $bits number of bits + * @param int $num number + * @return array bitstream + */ + protected function appendNum($bitstream, $bits, $num) { + if ($bits == 0) { + return 0; + } + $b = $this->newFromNum($bits, $num); + return $this->appendBitstream($bitstream, $b); + } + + /** + * Append one bitstream created from bytes to another + * @param array $bitstream original bitstream + * @param int $size size + * @param array $data bytes + * @return array bitstream + */ + protected function appendBytes($bitstream, $size, $data) { + if ($size == 0) { + return 0; + } + $b = $this->newFromBytes($size, $data); + return $this->appendBitstream($bitstream, $b); + } + + /** + * Convert bitstream to bytes + * @param array $bitstream original bitstream + * @return array of bytes + */ + protected function bitstreamToByte($bstream) { + $size = count($bstream); + if ($size == 0) { + return array(); + } + $data = array_fill(0, (int)(($size + 7) / 8), 0); + $bytes = (int)($size / 8); + $p = 0; + for ($i=0; $i<$bytes; $i++) { + $v = 0; + for ($j=0; $j<8; $j++) { + $v = $v << 1; + $v |= $bstream[$p]; + $p++; + } + $data[$i] = $v; + } + if ($size & 7) { + $v = 0; + for ($j=0; $j<($size & 7); $j++) { + $v = $v << 1; + $v |= $bstream[$p]; + $p++; + } + $data[$bytes] = $v; + } + return $data; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRspec + + /** + * Replace a value on the array at the specified position + * @param array $srctab + * @param int $x X position + * @param int $y Y position + * @param string $repl value to replace + * @param int $replLen length of the repl string + * @return array srctab + */ + protected function qrstrset($srctab, $x, $y, $repl, $replLen=false) { + $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); + return $srctab; + } + + /** + * Return maximum data code length (bytes) for the version. + * @param int $version version + * @param int $level error correction level + * @return int maximum size (bytes) + */ + protected function getDataLength($version, $level) { + return $this->capacity[$version][QRCAP_WORDS] - $this->capacity[$version][QRCAP_EC][$level]; + } + + /** + * Return maximum error correction code length (bytes) for the version. + * @param int $version version + * @param int $level error correction level + * @return int ECC size (bytes) + */ + protected function getECCLength($version, $level){ + return $this->capacity[$version][QRCAP_EC][$level]; + } + + /** + * Return the width of the symbol for the version. + * @param int $version version + * @return int width + */ + protected function getWidth($version) { + return $this->capacity[$version][QRCAP_WIDTH]; + } + + /** + * Return the numer of remainder bits. + * @param int $version version + * @return int number of remainder bits + */ + protected function getRemainder($version) { + return $this->capacity[$version][QRCAP_REMINDER]; + } + + /** + * Return a version number that satisfies the input code length. + * @param int $size input code length (byte) + * @param int $level error correction level + * @return int version number + */ + protected function getMinimumVersion($size, $level) { + for ($i=1; $i <= QRSPEC_VERSION_MAX; ++$i) { + $words = $this->capacity[$i][QRCAP_WORDS] - $this->capacity[$i][QRCAP_EC][$level]; + if ($words >= $size) { + return $i; + } + } + return -1; + } + + /** + * Return the size of length indicator for the mode and version. + * @param int $mode encoding mode + * @param int $version version + * @return int the size of the appropriate length indicator (bits). + */ + protected function lengthIndicator($mode, $version) { + if ($mode == QR_MODE_ST) { + return 0; + } + if ($version <= 9) { + $l = 0; + } elseif ($version <= 26) { + $l = 1; + } else { + $l = 2; + } + return $this->lengthTableBits[$mode][$l]; + } + + /** + * Return the maximum length for the mode and version. + * @param int $mode encoding mode + * @param int $version version + * @return int the maximum length (bytes) + */ + protected function maximumWords($mode, $version) { + if ($mode == QR_MODE_ST) { + return 3; + } + if ($version <= 9) { + $l = 0; + } else if ($version <= 26) { + $l = 1; + } else { + $l = 2; + } + $bits = $this->lengthTableBits[$mode][$l]; + $words = (1 << $bits) - 1; + if ($mode == QR_MODE_KJ) { + $words *= 2; // the number of bytes is required + } + return $words; + } + + /** + * Return an array of ECC specification. + * @param int $version version + * @param int $level error correction level + * @param array $spec an array of ECC specification contains as following: {# of type1 blocks, # of data code, # of ecc code, # of type2 blocks, # of data code} + * @return array spec + */ + protected function getEccSpec($version, $level, $spec) { + if (count($spec) < 5) { + $spec = array(0, 0, 0, 0, 0); + } + $b1 = $this->eccTable[$version][$level][0]; + $b2 = $this->eccTable[$version][$level][1]; + $data = $this->getDataLength($version, $level); + $ecc = $this->getECCLength($version, $level); + if ($b2 == 0) { + $spec[0] = $b1; + $spec[1] = (int)($data / $b1); + $spec[2] = (int)($ecc / $b1); + $spec[3] = 0; + $spec[4] = 0; + } else { + $spec[0] = $b1; + $spec[1] = (int)($data / ($b1 + $b2)); + $spec[2] = (int)($ecc / ($b1 + $b2)); + $spec[3] = $b2; + $spec[4] = $spec[1] + 1; + } + return $spec; + } + + /** + * Put an alignment marker. + * @param array $frame frame + * @param int $width width + * @param int $ox X center coordinate of the pattern + * @param int $oy Y center coordinate of the pattern + * @return array frame + */ + protected function putAlignmentMarker($frame, $ox, $oy) { + $finder = array( + "\xa1\xa1\xa1\xa1\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa0\xa1\xa0\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa1\xa1\xa1\xa1" + ); + $yStart = $oy - 2; + $xStart = $ox - 2; + for ($y=0; $y < 5; $y++) { + $frame = $this->qrstrset($frame, $xStart, $yStart+$y, $finder[$y]); + } + return $frame; + } + + /** + * Put an alignment pattern. + * @param int $version version + * @param array $fram frame + * @param int $width width + * @return array frame + */ + protected function putAlignmentPattern($version, $frame, $width) { + if ($version < 2) { + return $frame; + } + $d = $this->alignmentPattern[$version][1] - $this->alignmentPattern[$version][0]; + if ($d < 0) { + $w = 2; + } else { + $w = (int)(($width - $this->alignmentPattern[$version][0]) / $d + 2); + } + if ($w * $w - 3 == 1) { + $x = $this->alignmentPattern[$version][0]; + $y = $this->alignmentPattern[$version][0]; + $frame = $this->putAlignmentMarker($frame, $x, $y); + return $frame; + } + $cx = $this->alignmentPattern[$version][0]; + $wo = $w - 1; + for ($x=1; $x < $wo; ++$x) { + $frame = $this->putAlignmentMarker($frame, 6, $cx); + $frame = $this->putAlignmentMarker($frame, $cx, 6); + $cx += $d; + } + $cy = $this->alignmentPattern[$version][0]; + for ($y=0; $y < $wo; ++$y) { + $cx = $this->alignmentPattern[$version][0]; + for ($x=0; $x < $wo; ++$x) { + $frame = $this->putAlignmentMarker($frame, $cx, $cy); + $cx += $d; + } + $cy += $d; + } + return $frame; + } + + /** + * Return BCH encoded version information pattern that is used for the symbol of version 7 or greater. Use lower 18 bits. + * @param int $version version + * @return BCH encoded version information pattern + */ + protected function getVersionPattern($version) { + if (($version < 7) OR ($version > QRSPEC_VERSION_MAX)) { + return 0; + } + return $this->versionPattern[($version - 7)]; + } + + /** + * Return BCH encoded format information pattern. + * @param array $mask + * @param int $level error correction level + * @return BCH encoded format information pattern + */ + protected function getFormatInfo($mask, $level) { + if (($mask < 0) OR ($mask > 7)) { + return 0; + } + if (($level < 0) OR ($level > 3)) { + return 0; + } + return $this->formatInfo[$level][$mask]; + } + + /** + * Put a finder pattern. + * @param array $frame frame + * @param int $width width + * @param int $ox X center coordinate of the pattern + * @param int $oy Y center coordinate of the pattern + * @return array frame + */ + protected function putFinderPattern($frame, $ox, $oy) { + $finder = array( + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" + ); + for ($y=0; $y < 7; $y++) { + $frame = $this->qrstrset($frame, $ox, ($oy + $y), $finder[$y]); + } + return $frame; + } + + /** + * Return a copy of initialized frame. + * @param int $version version + * @return Array of unsigned char. + */ + protected function createFrame($version) { + $width = $this->capacity[$version][QRCAP_WIDTH]; + $frameLine = str_repeat ("\0", $width); + $frame = array_fill(0, $width, $frameLine); + // Finder pattern + $frame = $this->putFinderPattern($frame, 0, 0); + $frame = $this->putFinderPattern($frame, $width - 7, 0); + $frame = $this->putFinderPattern($frame, 0, $width - 7); + // Separator + $yOffset = $width - 7; + for ($y=0; $y < 7; ++$y) { + $frame[$y][7] = "\xc0"; + $frame[$y][$width - 8] = "\xc0"; + $frame[$yOffset][7] = "\xc0"; + ++$yOffset; + } + $setPattern = str_repeat("\xc0", 8); + $frame = $this->qrstrset($frame, 0, 7, $setPattern); + $frame = $this->qrstrset($frame, $width-8, 7, $setPattern); + $frame = $this->qrstrset($frame, 0, $width - 8, $setPattern); + // Format info + $setPattern = str_repeat("\x84", 9); + $frame = $this->qrstrset($frame, 0, 8, $setPattern); + $frame = $this->qrstrset($frame, $width - 8, 8, $setPattern, 8); + $yOffset = $width - 8; + for ($y=0; $y < 8; ++$y,++$yOffset) { + $frame[$y][8] = "\x84"; + $frame[$yOffset][8] = "\x84"; + } + // Timing pattern + $wo = $width - 15; + for ($i=1; $i < $wo; ++$i) { + $frame[6][7+$i] = chr(0x90 | ($i & 1)); + $frame[7+$i][6] = chr(0x90 | ($i & 1)); + } + // Alignment pattern + $frame = $this->putAlignmentPattern($version, $frame, $width); + // Version information + if ($version >= 7) { + $vinf = $this->getVersionPattern($version); + $v = $vinf; + for ($x=0; $x<6; ++$x) { + for ($y=0; $y<3; ++$y) { + $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + $v = $vinf; + for ($y=0; $y<6; ++$y) { + for ($x=0; $x<3; ++$x) { + $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + } + // and a little bit... + $frame[$width - 8][8] = "\x81"; + return $frame; + } + + /** + * Set new frame for the specified version. + * @param int $version version + * @return Array of unsigned char. + */ + protected function newFrame($version) { + if (($version < 1) OR ($version > QRSPEC_VERSION_MAX)) { + return NULL; + } + if (!isset($this->frames[$version])) { + $this->frames[$version] = $this->createFrame($version); + } + if (is_null($this->frames[$version])) { + return NULL; + } + return $this->frames[$version]; + } + + /** + * Return block number 0 + * @param array $spec + * @return int value + */ + protected function rsBlockNum($spec) { + return ($spec[0] + $spec[3]); + } + + /** + * Return block number 1 + * @param array $spec + * @return int value + */ + protected function rsBlockNum1($spec) { + return $spec[0]; + } + + /** + * Return data codes 1 + * @param array $spec + * @return int value + */ + protected function rsDataCodes1($spec) { + return $spec[1]; + } + + /** + * Return ecc codes 1 + * @param array $spec + * @return int value + */ + protected function rsEccCodes1($spec) { + return $spec[2]; + } + + /** + * Return block number 2 + * @param array $spec + * @return int value + */ + protected function rsBlockNum2($spec) { + return $spec[3]; + } + + /** + * Return data codes 2 + * @param array $spec + * @return int value + */ + protected function rsDataCodes2($spec) { + return $spec[4]; + } + + /** + * Return ecc codes 2 + * @param array $spec + * @return int value + */ + protected function rsEccCodes2($spec) { + return $spec[2]; + } + + /** + * Return data length + * @param array $spec + * @return int value + */ + protected function rsDataLength($spec) { + return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); + } + + /** + * Return ecc length + * @param array $spec + * @return int value + */ + protected function rsEccLength($spec) { + return ($spec[0] + $spec[3]) * $spec[2]; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRrs + + /** + * Initialize a Reed-Solomon codec and add it to existing rsitems + * @param int $symsize symbol size, bits + * @param int $gfpoly Field generator polynomial coefficients + * @param int $fcr first root of RS code generator polynomial, index form + * @param int $prim primitive element to generate polynomial roots + * @param int $nroots RS code generator polynomial degree (number of roots) + * @param int $pad padding bytes at front of shortened block + * @return array Array of RS values:
  • mm = Bits per symbol;
  • nn = Symbols per block;
  • alpha_to = log lookup table array;
  • index_of = Antilog lookup table array;
  • genpoly = Generator polynomial array;
  • nroots = Number of generator;
  • roots = number of parity symbols;
  • fcr = First consecutive root, index form;
  • prim = Primitive element, index form;
  • iprim = prim-th root of 1, index form;
  • pad = Padding bytes in shortened block;
  • gfpoly
. + */ + protected function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) { + foreach ($this->rsitems as $rs) { + if (($rs['pad'] != $pad) OR ($rs['nroots'] != $nroots) OR ($rs['mm'] != $symsize) + OR ($rs['gfpoly'] != $gfpoly) OR ($rs['fcr'] != $fcr) OR ($rs['prim'] != $prim)) { + continue; + } + return $rs; + } + $rs = $this->init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad); + array_unshift($this->rsitems, $rs); + return $rs; + } + + // - - - - - - - - - - - - - - - - - - - - - - - - - + + // QRrsItem + + /** + * modnn + * @param array RS values + * @param int $x X position + * @return int X osition + */ + protected function modnn($rs, $x) { + while ($x >= $rs['nn']) { + $x -= $rs['nn']; + $x = ($x >> $rs['mm']) + ($x & $rs['nn']); + } + return $x; + } + + /** + * Initialize a Reed-Solomon codec and returns an array of values. + * @param int $symsize symbol size, bits + * @param int $gfpoly Field generator polynomial coefficients + * @param int $fcr first root of RS code generator polynomial, index form + * @param int $prim primitive element to generate polynomial roots + * @param int $nroots RS code generator polynomial degree (number of roots) + * @param int $pad padding bytes at front of shortened block + * @return array Array of RS values:
  • mm = Bits per symbol;
  • nn = Symbols per block;
  • alpha_to = log lookup table array;
  • index_of = Antilog lookup table array;
  • genpoly = Generator polynomial array;
  • nroots = Number of generator;
  • roots = number of parity symbols;
  • fcr = First consecutive root, index form;
  • prim = Primitive element, index form;
  • iprim = prim-th root of 1, index form;
  • pad = Padding bytes in shortened block;
  • gfpoly
. + */ + protected function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) { + // Based on Reed solomon encoder by Phil Karn, KA9Q (GNU-LGPLv2) + $rs = null; + // Check parameter ranges + if (($symsize < 0) OR ($symsize > 8)) { + return $rs; + } + if (($fcr < 0) OR ($fcr >= (1<<$symsize))) { + return $rs; + } + if (($prim <= 0) OR ($prim >= (1<<$symsize))) { + return $rs; + } + if (($nroots < 0) OR ($nroots >= (1<<$symsize))) { + return $rs; + } + if (($pad < 0) OR ($pad >= ((1<<$symsize) -1 - $nroots))) { + return $rs; + } + $rs = array(); + $rs['mm'] = $symsize; + $rs['nn'] = (1 << $symsize) - 1; + $rs['pad'] = $pad; + $rs['alpha_to'] = array_fill(0, ($rs['nn'] + 1), 0); + $rs['index_of'] = array_fill(0, ($rs['nn'] + 1), 0); + // PHP style macro replacement ;) + $NN =& $rs['nn']; + $A0 =& $NN; + // Generate Galois field lookup tables + $rs['index_of'][0] = $A0; // log(zero) = -inf + $rs['alpha_to'][$A0] = 0; // alpha**-inf = 0 + $sr = 1; + for ($i=0; $i<$rs['nn']; ++$i) { + $rs['index_of'][$sr] = $i; + $rs['alpha_to'][$i] = $sr; + $sr <<= 1; + if ($sr & (1 << $symsize)) { + $sr ^= $gfpoly; + } + $sr &= $rs['nn']; + } + if ($sr != 1) { + // field generator polynomial is not primitive! + return NULL; + } + // Form RS code generator polynomial from its roots + $rs['genpoly'] = array_fill(0, ($nroots + 1), 0); + $rs['fcr'] = $fcr; + $rs['prim'] = $prim; + $rs['nroots'] = $nroots; + $rs['gfpoly'] = $gfpoly; + // Find prim-th root of 1, used in decoding + for ($iprim=1; ($iprim % $prim) != 0; $iprim += $rs['nn']) { + ; // intentional empty-body loop! + } + $rs['iprim'] = (int)($iprim / $prim); + $rs['genpoly'][0] = 1; + + + for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) { + $rs['genpoly'][$i+1] = 1; + // Multiply rs->genpoly[] by @**(root + x) + for ($j = $i; $j > 0; --$j) { + if ($rs['genpoly'][$j] != 0) { + $rs['genpoly'][$j] = $rs['genpoly'][$j-1] ^ $rs['alpha_to'][$this->modnn($rs, $rs['index_of'][$rs['genpoly'][$j]] + $root)]; + } else { + $rs['genpoly'][$j] = $rs['genpoly'][$j-1]; + } + } + // rs->genpoly[0] can never be zero + $rs['genpoly'][0] = $rs['alpha_to'][$this->modnn($rs, $rs['index_of'][$rs['genpoly'][0]] + $root)]; + } + // convert rs->genpoly[] to index form for quicker encoding + for ($i = 0; $i <= $nroots; ++$i) { + $rs['genpoly'][$i] = $rs['index_of'][$rs['genpoly'][$i]]; + } + return $rs; + } + + /** + * Encode a Reed-Solomon codec and returns the parity array + * @param array $rs RS values + * @param array $data data + * @param array $parity parity + * @return parity array + */ + protected function encode_rs_char($rs, $data, $parity) { + $MM =& $rs['mm']; // bits per symbol + $NN =& $rs['nn']; // the total number of symbols in a RS block + $ALPHA_TO =& $rs['alpha_to']; // the address of an array of NN elements to convert Galois field elements in index (log) form to polynomial form + $INDEX_OF =& $rs['index_of']; // the address of an array of NN elements to convert Galois field elements in polynomial form to index (log) form + $GENPOLY =& $rs['genpoly']; // an array of NROOTS+1 elements containing the generator polynomial in index form + $NROOTS =& $rs['nroots']; // the number of roots in the RS code generator polynomial, which is the same as the number of parity symbols in a block + $FCR =& $rs['fcr']; // first consecutive root, index form + $PRIM =& $rs['prim']; // primitive element, index form + $IPRIM =& $rs['iprim']; // prim-th root of 1, index form + $PAD =& $rs['pad']; // the number of pad symbols in a block + $A0 =& $NN; + $parity = array_fill(0, $NROOTS, 0); + for ($i=0; $i < ($NN - $NROOTS - $PAD); $i++) { + $feedback = $INDEX_OF[$data[$i] ^ $parity[0]]; + if ($feedback != $A0) { + // feedback term is non-zero + // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must + // always be for the polynomials constructed by init_rs() + $feedback = $this->modnn($rs, $NN - $GENPOLY[$NROOTS] + $feedback); + for ($j=1; $j < $NROOTS; ++$j) { + $parity[$j] ^= $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[($NROOTS - $j)])]; + } + } + // Shift + array_shift($parity); + if ($feedback != $A0) { + array_push($parity, $ALPHA_TO[$this->modnn($rs, $feedback + $GENPOLY[0])]); + } else { + array_push($parity, 0); + } + } + return $parity; + } + + } // end QRcode class + +} // END OF "class_exists QRcode" diff --git a/vendor/phpqrcode/index.php b/vendor/phpqrcode/index.php new file mode 100644 index 0000000..9e14b7e --- /dev/null +++ b/vendor/phpqrcode/index.php @@ -0,0 +1,94 @@ + + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + echo "

PHP QR Code


"; + + //set it to writable location, a place for temp generated PNG files + $PNG_TEMP_DIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'temp'.DIRECTORY_SEPARATOR; + + //html PNG location prefix + $PNG_WEB_DIR = 'temp/'; + + include "qrlib.php"; + + //ofcourse we need rights to create temp dir + if (!file_exists($PNG_TEMP_DIR)) + mkdir($PNG_TEMP_DIR); + + + $filename = $PNG_TEMP_DIR.'test.png'; + + //processing form input + //remember to sanitize user input in real-life solution !!! + $errorCorrectionLevel = 'L'; + if (isset($_REQUEST['level']) && in_array($_REQUEST['level'], array('L','M','Q','H'))) + $errorCorrectionLevel = $_REQUEST['level']; + + $matrixPointSize = 4; + if (isset($_REQUEST['size'])) + $matrixPointSize = min(max((int)$_REQUEST['size'], 1), 10); + + + if (isset($_REQUEST['data'])) { + + //it's very important! + if (trim($_REQUEST['data']) == '') + die('data cannot be empty! back'); + + // user data + $filename = $PNG_TEMP_DIR.'test'.md5($_REQUEST['data'].'|'.$errorCorrectionLevel.'|'.$matrixPointSize).'.png'; + QRcode::png($_REQUEST['data'], $filename, $errorCorrectionLevel, $matrixPointSize, 2); + + } else { + + //default data + echo 'You can provide data in GET parameter: like that
'; + QRcode::png('PHP QR Code :)', $filename, $errorCorrectionLevel, $matrixPointSize, 2); + + } + + //display generated file + echo '
'; + + //config form + echo '
+ Data:   + ECC:   + Size:   +

'; + + // benchmark + QRtools::timeBenchmark(); + + \ No newline at end of file diff --git a/vendor/phpqrcode/phpqrcode.php b/vendor/phpqrcode/phpqrcode.php new file mode 100644 index 0000000..80adb9d --- /dev/null +++ b/vendor/phpqrcode/phpqrcode.php @@ -0,0 +1,3312 @@ + + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + + +/* + * Version: 1.1.4 + * Build: 2010100721 + */ + + + +//---- qrconst.php ----------------------------- + + + + + +/* + * PHP QR Code encoder + * + * Common constants + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + // Encoding modes + + define('QR_MODE_NUL', -1); + define('QR_MODE_NUM', 0); + define('QR_MODE_AN', 1); + define('QR_MODE_8', 2); + define('QR_MODE_KANJI', 3); + define('QR_MODE_STRUCTURE', 4); + + // Levels of error correction. + + define('QR_ECLEVEL_L', 0); + define('QR_ECLEVEL_M', 1); + define('QR_ECLEVEL_Q', 2); + define('QR_ECLEVEL_H', 3); + + // Supported output formats + + define('QR_FORMAT_TEXT', 0); + define('QR_FORMAT_PNG', 1); + + class qrstr { + public static function set(&$srctab, $x, $y, $repl, $replLen = false) { + $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); + } + } + + + +//---- merged_config.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Config file, tuned-up for merged verion + */ + + define('QR_CACHEABLE', false); // use cache - more disk reads but less CPU power, masks and format templates are stored there + define('QR_CACHE_DIR', false); // used when QR_CACHEABLE === true + define('QR_LOG_DIR', false); // default error logs dir + + define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code + define('QR_FIND_FROM_RANDOM', 2); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly + define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false + + define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images + + + + +//---- qrtools.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Toolset, handy and debug utilites. + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRtools { + + //---------------------------------------------------------------------- + public static function binarize($frame) + { + $len = count($frame); + foreach ($frame as &$frameLine) { + + for($i=0; $i<$len; $i++) { + $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0'; + } + } + + return $frame; + } + + //---------------------------------------------------------------------- + public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037') + { + $barcode_array = array(); + + if (!is_array($mode)) + $mode = explode(',', $mode); + + $eccLevel = 'L'; + + if (count($mode) > 1) { + $eccLevel = $mode[1]; + } + + $qrTab = QRcode::text($code, false, $eccLevel); + $size = count($qrTab); + + $barcode_array['num_rows'] = $size; + $barcode_array['num_cols'] = $size; + $barcode_array['bcode'] = array(); + + foreach ($qrTab as $line) { + $arrAdd = array(); + foreach(str_split($line) as $char) + $arrAdd[] = ($char=='1')?1:0; + $barcode_array['bcode'][] = $arrAdd; + } + + return $barcode_array; + } + + //---------------------------------------------------------------------- + public static function clearCache() + { + self::$frames = array(); + } + + //---------------------------------------------------------------------- + public static function buildCache() + { + QRtools::markTime('before_build_cache'); + + $mask = new QRmask(); + for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) { + $frame = QRspec::newFrame($a); + if (QR_IMAGE) { + $fileName = QR_CACHE_DIR.'frame_'.$a.'.png'; + QRimage::png(self::binarize($frame), $fileName, 1, 0); + } + + $width = count($frame); + $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); + for ($maskNo=0; $maskNo<8; $maskNo++) + $mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true); + } + + QRtools::markTime('after_build_cache'); + } + + //---------------------------------------------------------------------- + public static function log($outfile, $err) + { + if (QR_LOG_DIR !== false) { + if ($err != '') { + if ($outfile !== false) { + file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); + } else { + file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); + } + } + } + } + + //---------------------------------------------------------------------- + public static function dumpMask($frame) + { + $width = count($frame); + for($y=0;$y<$width;$y++) { + for($x=0;$x<$width;$x++) { + echo ord($frame[$y][$x]).','; + } + } + } + + //---------------------------------------------------------------------- + public static function markTime($markerId) + { + list($usec, $sec) = explode(" ", microtime()); + $time = ((float)$usec + (float)$sec); + + if (!isset($GLOBALS['qr_time_bench'])) + $GLOBALS['qr_time_bench'] = array(); + + $GLOBALS['qr_time_bench'][$markerId] = $time; + } + + //---------------------------------------------------------------------- + public static function timeBenchmark() + { + self::markTime('finish'); + + $lastTime = 0; + $startTime = 0; + $p = 0; + + echo ' + + '; + + foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) { + if ($p > 0) { + echo ''; + } else { + $startTime = $thisTime; + } + + $p++; + $lastTime = $thisTime; + } + + echo ' + + +
BENCHMARK
till '.$markerId.': '.number_format($thisTime-$lastTime, 6).'s
TOTAL: '.number_format($lastTime-$startTime, 6).'s
'; + } + + } + + //########################################################################## + + QRtools::markTime('start'); + + + + +//---- qrspec.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * QR Code specifications + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('QRSPEC_VERSION_MAX', 40); + define('QRSPEC_WIDTH_MAX', 177); + + define('QRCAP_WIDTH', 0); + define('QRCAP_WORDS', 1); + define('QRCAP_REMINDER', 2); + define('QRCAP_EC', 3); + + class QRspec { + + public static $capacity = array( + array( 0, 0, 0, array( 0, 0, 0, 0)), + array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 + array( 25, 44, 7, array( 10, 16, 22, 28)), + array( 29, 70, 7, array( 15, 26, 36, 44)), + array( 33, 100, 7, array( 20, 36, 52, 64)), + array( 37, 134, 7, array( 26, 48, 72, 88)), // 5 + array( 41, 172, 7, array( 36, 64, 96, 112)), + array( 45, 196, 0, array( 40, 72, 108, 130)), + array( 49, 242, 0, array( 48, 88, 132, 156)), + array( 53, 292, 0, array( 60, 110, 160, 192)), + array( 57, 346, 0, array( 72, 130, 192, 224)), //10 + array( 61, 404, 0, array( 80, 150, 224, 264)), + array( 65, 466, 0, array( 96, 176, 260, 308)), + array( 69, 532, 0, array( 104, 198, 288, 352)), + array( 73, 581, 3, array( 120, 216, 320, 384)), + array( 77, 655, 3, array( 132, 240, 360, 432)), //15 + array( 81, 733, 3, array( 144, 280, 408, 480)), + array( 85, 815, 3, array( 168, 308, 448, 532)), + array( 89, 901, 3, array( 180, 338, 504, 588)), + array( 93, 991, 3, array( 196, 364, 546, 650)), + array( 97, 1085, 3, array( 224, 416, 600, 700)), //20 + array(101, 1156, 4, array( 224, 442, 644, 750)), + array(105, 1258, 4, array( 252, 476, 690, 816)), + array(109, 1364, 4, array( 270, 504, 750, 900)), + array(113, 1474, 4, array( 300, 560, 810, 960)), + array(117, 1588, 4, array( 312, 588, 870, 1050)), //25 + array(121, 1706, 4, array( 336, 644, 952, 1110)), + array(125, 1828, 4, array( 360, 700, 1020, 1200)), + array(129, 1921, 3, array( 390, 728, 1050, 1260)), + array(133, 2051, 3, array( 420, 784, 1140, 1350)), + array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30 + array(141, 2323, 3, array( 480, 868, 1290, 1530)), + array(145, 2465, 3, array( 510, 924, 1350, 1620)), + array(149, 2611, 3, array( 540, 980, 1440, 1710)), + array(153, 2761, 3, array( 570, 1036, 1530, 1800)), + array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35 + array(161, 3034, 0, array( 600, 1120, 1680, 1980)), + array(165, 3196, 0, array( 630, 1204, 1770, 2100)), + array(169, 3362, 0, array( 660, 1260, 1860, 2220)), + array(173, 3532, 0, array( 720, 1316, 1950, 2310)), + array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40 + ); + + //---------------------------------------------------------------------- + public static function getDataLength($version, $level) + { + return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level]; + } + + //---------------------------------------------------------------------- + public static function getECCLength($version, $level) + { + return self::$capacity[$version][QRCAP_EC][$level]; + } + + //---------------------------------------------------------------------- + public static function getWidth($version) + { + return self::$capacity[$version][QRCAP_WIDTH]; + } + + //---------------------------------------------------------------------- + public static function getRemainder($version) + { + return self::$capacity[$version][QRCAP_REMINDER]; + } + + //---------------------------------------------------------------------- + public static function getMinimumVersion($size, $level) + { + + for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) { + $words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level]; + if($words >= $size) + return $i; + } + + return -1; + } + + //###################################################################### + + public static $lengthTableBits = array( + array(10, 12, 14), + array( 9, 11, 13), + array( 8, 16, 16), + array( 8, 10, 12) + ); + + //---------------------------------------------------------------------- + public static function lengthIndicator($mode, $version) + { + if ($mode == QR_MODE_STRUCTURE) + return 0; + + if ($version <= 9) { + $l = 0; + } else if ($version <= 26) { + $l = 1; + } else { + $l = 2; + } + + return self::$lengthTableBits[$mode][$l]; + } + + //---------------------------------------------------------------------- + public static function maximumWords($mode, $version) + { + if($mode == QR_MODE_STRUCTURE) + return 3; + + if($version <= 9) { + $l = 0; + } else if($version <= 26) { + $l = 1; + } else { + $l = 2; + } + + $bits = self::$lengthTableBits[$mode][$l]; + $words = (1 << $bits) - 1; + + if($mode == QR_MODE_KANJI) { + $words *= 2; // the number of bytes is required + } + + return $words; + } + + // Error correction code ----------------------------------------------- + // Table of the error correction code (Reed-Solomon block) + // See Table 12-16 (pp.30-36), JIS X0510:2004. + + public static $eccTable = array( + array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1 + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), + array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)), + array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)), + array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5 + array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)), + array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)), + array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)), + array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)), + array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10 + array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)), + array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)), + array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)), + array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)), + array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15 + array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)), + array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)), + array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)), + array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)), + array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20 + array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)), + array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)), + array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)), + array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)), + array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25 + array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)), + array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)), + array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), + array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)), + array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30 + array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)), + array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)), + array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)), + array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)), + array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35 + array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), + array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)), + array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), + array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)), + array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40 + ); + + //---------------------------------------------------------------------- + // CACHEABLE!!! + + public static function getEccSpec($version, $level, array &$spec) + { + if (count($spec) < 5) { + $spec = array(0,0,0,0,0); + } + + $b1 = self::$eccTable[$version][$level][0]; + $b2 = self::$eccTable[$version][$level][1]; + $data = self::getDataLength($version, $level); + $ecc = self::getECCLength($version, $level); + + if($b2 == 0) { + $spec[0] = $b1; + $spec[1] = (int)($data / $b1); + $spec[2] = (int)($ecc / $b1); + $spec[3] = 0; + $spec[4] = 0; + } else { + $spec[0] = $b1; + $spec[1] = (int)($data / ($b1 + $b2)); + $spec[2] = (int)($ecc / ($b1 + $b2)); + $spec[3] = $b2; + $spec[4] = $spec[1] + 1; + } + } + + // Alignment pattern --------------------------------------------------- + + // Positions of alignment patterns. + // This array includes only the second and the third position of the + // alignment patterns. Rest of them can be calculated from the distance + // between them. + + // See Table 1 in Appendix E (pp.71) of JIS X0510:2004. + + public static $alignmentPattern = array( + array( 0, 0), + array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5 + array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 + array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15 + array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20 + array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25 + array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30 + array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35 + array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40 + ); + + + /** -------------------------------------------------------------------- + * Put an alignment marker. + * @param frame + * @param width + * @param ox,oy center coordinate of the pattern + */ + public static function putAlignmentMarker(array &$frame, $ox, $oy) + { + $finder = array( + "\xa1\xa1\xa1\xa1\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa0\xa1\xa0\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa1\xa1\xa1\xa1" + ); + + $yStart = $oy-2; + $xStart = $ox-2; + + for($y=0; $y<5; $y++) { + QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]); + } + } + + //---------------------------------------------------------------------- + public static function putAlignmentPattern($version, &$frame, $width) + { + if($version < 2) + return; + + $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0]; + if($d < 0) { + $w = 2; + } else { + $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2); + } + + if($w * $w - 3 == 1) { + $x = self::$alignmentPattern[$version][0]; + $y = self::$alignmentPattern[$version][0]; + self::putAlignmentMarker($frame, $x, $y); + return; + } + + $cx = self::$alignmentPattern[$version][0]; + for($x=1; $x<$w - 1; $x++) { + self::putAlignmentMarker($frame, 6, $cx); + self::putAlignmentMarker($frame, $cx, 6); + $cx += $d; + } + + $cy = self::$alignmentPattern[$version][0]; + for($y=0; $y<$w-1; $y++) { + $cx = self::$alignmentPattern[$version][0]; + for($x=0; $x<$w-1; $x++) { + self::putAlignmentMarker($frame, $cx, $cy); + $cx += $d; + } + $cy += $d; + } + } + + // Version information pattern ----------------------------------------- + + // Version information pattern (BCH coded). + // See Table 1 in Appendix D (pp.68) of JIS X0510:2004. + + // size: [QRSPEC_VERSION_MAX - 6] + + public static $versionPattern = array( + 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, + 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, + 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, + 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, + 0x27541, 0x28c69 + ); + + //---------------------------------------------------------------------- + public static function getVersionPattern($version) + { + if($version < 7 || $version > QRSPEC_VERSION_MAX) + return 0; + + return self::$versionPattern[$version -7]; + } + + // Format information -------------------------------------------------- + // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib) + + public static $formatInfo = array( + array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), + array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), + array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), + array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) + ); + + public static function getFormatInfo($mask, $level) + { + if($mask < 0 || $mask > 7) + return 0; + + if($level < 0 || $level > 3) + return 0; + + return self::$formatInfo[$level][$mask]; + } + + // Frame --------------------------------------------------------------- + // Cache of initial frames. + + public static $frames = array(); + + /** -------------------------------------------------------------------- + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ + public static function putFinderPattern(&$frame, $ox, $oy) + { + $finder = array( + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" + ); + + for($y=0; $y<7; $y++) { + QRstr::set($frame, $ox, $oy+$y, $finder[$y]); + } + } + + //---------------------------------------------------------------------- + public static function createFrame($version) + { + $width = self::$capacity[$version][QRCAP_WIDTH]; + $frameLine = str_repeat ("\0", $width); + $frame = array_fill(0, $width, $frameLine); + + // Finder pattern + self::putFinderPattern($frame, 0, 0); + self::putFinderPattern($frame, $width - 7, 0); + self::putFinderPattern($frame, 0, $width - 7); + + // Separator + $yOffset = $width - 7; + + for($y=0; $y<7; $y++) { + $frame[$y][7] = "\xc0"; + $frame[$y][$width - 8] = "\xc0"; + $frame[$yOffset][7] = "\xc0"; + $yOffset++; + } + + $setPattern = str_repeat("\xc0", 8); + + QRstr::set($frame, 0, 7, $setPattern); + QRstr::set($frame, $width-8, 7, $setPattern); + QRstr::set($frame, 0, $width - 8, $setPattern); + + // Format info + $setPattern = str_repeat("\x84", 9); + QRstr::set($frame, 0, 8, $setPattern); + QRstr::set($frame, $width - 8, 8, $setPattern, 8); + + $yOffset = $width - 8; + + for($y=0; $y<8; $y++,$yOffset++) { + $frame[$y][8] = "\x84"; + $frame[$yOffset][8] = "\x84"; + } + + // Timing pattern + + for($i=1; $i<$width-15; $i++) { + $frame[6][7+$i] = chr(0x90 | ($i & 1)); + $frame[7+$i][6] = chr(0x90 | ($i & 1)); + } + + // Alignment pattern + self::putAlignmentPattern($version, $frame, $width); + + // Version information + if($version >= 7) { + $vinf = self::getVersionPattern($version); + + $v = $vinf; + + for($x=0; $x<6; $x++) { + for($y=0; $y<3; $y++) { + $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + + $v = $vinf; + for($y=0; $y<6; $y++) { + for($x=0; $x<3; $x++) { + $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + } + + // and a little bit... + $frame[$width - 8][8] = "\x81"; + + return $frame; + } + + //---------------------------------------------------------------------- + public static function debug($frame, $binary_mode = false) + { + if ($binary_mode) { + + foreach ($frame as &$frameLine) { + $frameLine = join('  ', explode('0', $frameLine)); + $frameLine = join('██', explode('1', $frameLine)); + } + + ?> + +


        '; + echo join("
        ", $frame); + echo '






'; + + } else { + + foreach ($frame as &$frameLine) { + $frameLine = join(' ', explode("\xc0", $frameLine)); + $frameLine = join('▒', explode("\xc1", $frameLine)); + $frameLine = join(' ', explode("\xa0", $frameLine)); + $frameLine = join('▒', explode("\xa1", $frameLine)); + $frameLine = join('◇', explode("\x84", $frameLine)); //format 0 + $frameLine = join('◆', explode("\x85", $frameLine)); //format 1 + $frameLine = join('☢', explode("\x81", $frameLine)); //special bit + $frameLine = join(' ', explode("\x90", $frameLine)); //clock 0 + $frameLine = join('◷', explode("\x91", $frameLine)); //clock 1 + $frameLine = join(' ', explode("\x88", $frameLine)); //version + $frameLine = join('▒', explode("\x89", $frameLine)); //version + $frameLine = join('♦', explode("\x01", $frameLine)); + $frameLine = join('⋅', explode("\0", $frameLine)); + } + + ?> + + "; + echo join("
", $frame); + echo "
"; + + } + } + + //---------------------------------------------------------------------- + public static function serial($frame) + { + return gzcompress(join("\n", $frame), 9); + } + + //---------------------------------------------------------------------- + public static function unserial($code) + { + return explode("\n", gzuncompress($code)); + } + + //---------------------------------------------------------------------- + public static function newFrame($version) + { + if($version < 1 || $version > QRSPEC_VERSION_MAX) + return null; + + if(!isset(self::$frames[$version])) { + + $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat'; + + if (QR_CACHEABLE) { + if (file_exists($fileName)) { + self::$frames[$version] = self::unserial(file_get_contents($fileName)); + } else { + self::$frames[$version] = self::createFrame($version); + file_put_contents($fileName, self::serial(self::$frames[$version])); + } + } else { + self::$frames[$version] = self::createFrame($version); + } + } + + if(is_null(self::$frames[$version])) + return null; + + return self::$frames[$version]; + } + + //---------------------------------------------------------------------- + public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; } + public static function rsBlockNum1($spec) { return $spec[0]; } + public static function rsDataCodes1($spec) { return $spec[1]; } + public static function rsEccCodes1($spec) { return $spec[2]; } + public static function rsBlockNum2($spec) { return $spec[3]; } + public static function rsDataCodes2($spec) { return $spec[4]; } + public static function rsEccCodes2($spec) { return $spec[2]; } + public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); } + public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; } + + } + + + +//---- qrimage.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Image output of code using GD2 + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('QR_IMAGE', true); + + class QRimage { + + //---------------------------------------------------------------------- + public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE) + { + $image = self::image($frame, $pixelPerPoint, $outerFrame); + + if ($filename === false) { + Header("Content-type: image/png"); + ImagePng($image); + } else { + if($saveandprint===TRUE){ + ImagePng($image, $filename); + header("Content-type: image/png"); + ImagePng($image); + }else{ + ImagePng($image, $filename); + } + } + + ImageDestroy($image); + } + + //---------------------------------------------------------------------- + public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85) + { + $image = self::image($frame, $pixelPerPoint, $outerFrame); + + if ($filename === false) { + Header("Content-type: image/jpeg"); + ImageJpeg($image, null, $q); + } else { + ImageJpeg($image, $filename, $q); + } + + ImageDestroy($image); + } + + //---------------------------------------------------------------------- + private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4) + { + $h = count($frame); + $w = strlen($frame[0]); + + $imgW = $w + 2*$outerFrame; + $imgH = $h + 2*$outerFrame; + + $base_image =ImageCreate($imgW, $imgH); + + $col[0] = ImageColorAllocate($base_image,255,255,255); + $col[1] = ImageColorAllocate($base_image,0,0,0); + + imagefill($base_image, 0, 0, $col[0]); + + for($y=0; $y<$h; $y++) { + for($x=0; $x<$w; $x++) { + if ($frame[$y][$x] == '1') { + ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]); + } + } + } + + $target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint); + ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH); + ImageDestroy($base_image); + + return $target_image; + } + } + + + +//---- qrinput.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Input encoding class + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('STRUCTURE_HEADER_BITS', 20); + define('MAX_STRUCTURED_SYMBOLS', 16); + + class QRinputItem { + + public $mode; + public $size; + public $data; + public $bstream; + + public function __construct($mode, $size, $data, $bstream = null) + { + $setData = array_slice($data, 0, $size); + + if (count($setData) < $size) { + $setData = array_merge($setData, array_fill(0,$size-count($setData),0)); + } + + if(!QRinput::check($mode, $size, $setData)) { + throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData)); + return null; + } + + $this->mode = $mode; + $this->size = $size; + $this->data = $setData; + $this->bstream = $bstream; + } + + //---------------------------------------------------------------------- + public function encodeModeNum($version) + { + try { + + $words = (int)($this->size / 3); + $bs = new QRbitstream(); + + $val = 0x1; + $bs->appendNum(4, $val); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size); + + for($i=0; $i<$words; $i++) { + $val = (ord($this->data[$i*3 ]) - ord('0')) * 100; + $val += (ord($this->data[$i*3+1]) - ord('0')) * 10; + $val += (ord($this->data[$i*3+2]) - ord('0')); + $bs->appendNum(10, $val); + } + + if($this->size - $words * 3 == 1) { + $val = ord($this->data[$words*3]) - ord('0'); + $bs->appendNum(4, $val); + } else if($this->size - $words * 3 == 2) { + $val = (ord($this->data[$words*3 ]) - ord('0')) * 10; + $val += (ord($this->data[$words*3+1]) - ord('0')); + $bs->appendNum(7, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeAn($version) + { + try { + $words = (int)($this->size / 2); + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x02); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size); + + for($i=0; $i<$words; $i++) { + $val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45; + $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1])); + + $bs->appendNum(11, $val); + } + + if($this->size & 1) { + $val = QRinput::lookAnTable(ord($this->data[$words * 2])); + $bs->appendNum(6, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeMode8($version) + { + try { + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x4); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size); + + for($i=0; $i<$this->size; $i++) { + $bs->appendNum(8, ord($this->data[$i])); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeKanji($version) + { + try { + + $bs = new QRbitrtream(); + + $bs->appendNum(4, 0x8); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2)); + + for($i=0; $i<$this->size; $i+=2) { + $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]); + if($val <= 0x9ffc) { + $val -= 0x8140; + } else { + $val -= 0xc140; + } + + $h = ($val >> 8) * 0xc0; + $val = ($val & 0xff) + $h; + + $bs->appendNum(13, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeStructure() + { + try { + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x03); + $bs->appendNum(4, ord($this->data[1]) - 1); + $bs->appendNum(4, ord($this->data[0]) - 1); + $bs->appendNum(8, ord($this->data[2])); + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function estimateBitStreamSizeOfEntry($version) + { + $bits = 0; + + if($version == 0) + $version = 1; + + switch($this->mode) { + case QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break; + case QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break; + case QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break; + case QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break; + case QR_MODE_STRUCTURE: return STRUCTURE_HEADER_BITS; + default: + return 0; + } + + $l = QRspec::lengthIndicator($this->mode, $version); + $m = 1 << $l; + $num = (int)(($this->size + $m - 1) / $m); + + $bits += $num * (4 + $l); + + return $bits; + } + + //---------------------------------------------------------------------- + public function encodeBitStream($version) + { + try { + + unset($this->bstream); + $words = QRspec::maximumWords($this->mode, $version); + + if($this->size > $words) { + + $st1 = new QRinputItem($this->mode, $words, $this->data); + $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words)); + + $st1->encodeBitStream($version); + $st2->encodeBitStream($version); + + $this->bstream = new QRbitstream(); + $this->bstream->append($st1->bstream); + $this->bstream->append($st2->bstream); + + unset($st1); + unset($st2); + + } else { + + $ret = 0; + + switch($this->mode) { + case QR_MODE_NUM: $ret = $this->encodeModeNum($version); break; + case QR_MODE_AN: $ret = $this->encodeModeAn($version); break; + case QR_MODE_8: $ret = $this->encodeMode8($version); break; + case QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break; + case QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break; + + default: + break; + } + + if($ret < 0) + return -1; + } + + return $this->bstream->size(); + + } catch (Exception $e) { + return -1; + } + } + }; + + //########################################################################## + + class QRinput { + + public $items; + + private $version; + private $level; + + //---------------------------------------------------------------------- + public function __construct($version = 0, $level = QR_ECLEVEL_L) + { + if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) { + throw new Exception('Invalid version no'); + return NULL; + } + + $this->version = $version; + $this->level = $level; + } + + //---------------------------------------------------------------------- + public function getVersion() + { + return $this->version; + } + + //---------------------------------------------------------------------- + public function setVersion($version) + { + if($version < 0 || $version > QRSPEC_VERSION_MAX) { + throw new Exception('Invalid version no'); + return -1; + } + + $this->version = $version; + + return 0; + } + + //---------------------------------------------------------------------- + public function getErrorCorrectionLevel() + { + return $this->level; + } + + //---------------------------------------------------------------------- + public function setErrorCorrectionLevel($level) + { + if($level > QR_ECLEVEL_H) { + throw new Exception('Invalid ECLEVEL'); + return -1; + } + + $this->level = $level; + + return 0; + } + + //---------------------------------------------------------------------- + public function appendEntry(QRinputItem $entry) + { + $this->items[] = $entry; + } + + //---------------------------------------------------------------------- + public function append($mode, $size, $data) + { + try { + $entry = new QRinputItem($mode, $size, $data); + $this->items[] = $entry; + return 0; + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + + public function insertStructuredAppendHeader($size, $index, $parity) + { + if( $size > MAX_STRUCTURED_SYMBOLS ) { + throw new Exception('insertStructuredAppendHeader wrong size'); + } + + if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) { + throw new Exception('insertStructuredAppendHeader wrong index'); + } + + $buf = array($size, $index, $parity); + + try { + $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf); + array_unshift($this->items, $entry); + return 0; + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function calcParity() + { + $parity = 0; + + foreach($this->items as $item) { + if($item->mode != QR_MODE_STRUCTURE) { + for($i=$item->size-1; $i>=0; $i--) { + $parity ^= $item->data[$i]; + } + } + } + + return $parity; + } + + //---------------------------------------------------------------------- + public static function checkModeNum($size, $data) + { + for($i=0; $i<$size; $i++) { + if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){ + return false; + } + } + + return true; + } + + //---------------------------------------------------------------------- + public static function estimateBitsModeNum($size) + { + $w = (int)$size / 3; + $bits = $w * 10; + + switch($size - $w * 3) { + case 1: + $bits += 4; + break; + case 2: + $bits += 7; + break; + default: + break; + } + + return $bits; + } + + //---------------------------------------------------------------------- + public static $anTable = array( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + ); + + //---------------------------------------------------------------------- + public static function lookAnTable($c) + { + return (($c > 127)?-1:self::$anTable[$c]); + } + + //---------------------------------------------------------------------- + public static function checkModeAn($size, $data) + { + for($i=0; $i<$size; $i++) { + if (self::lookAnTable(ord($data[$i])) == -1) { + return false; + } + } + + return true; + } + + //---------------------------------------------------------------------- + public static function estimateBitsModeAn($size) + { + $w = (int)($size / 2); + $bits = $w * 11; + + if($size & 1) { + $bits += 6; + } + + return $bits; + } + + //---------------------------------------------------------------------- + public static function estimateBitsMode8($size) + { + return $size * 8; + } + + //---------------------------------------------------------------------- + public function estimateBitsModeKanji($size) + { + return (int)(($size / 2) * 13); + } + + //---------------------------------------------------------------------- + public static function checkModeKanji($size, $data) + { + if($size & 1) + return false; + + for($i=0; $i<$size; $i+=2) { + $val = (ord($data[$i]) << 8) | ord($data[$i+1]); + if( $val < 0x8140 + || ($val > 0x9ffc && $val < 0xe040) + || $val > 0xebbf) { + return false; + } + } + + return true; + } + + /*********************************************************************** + * Validation + **********************************************************************/ + + public static function check($mode, $size, $data) + { + if($size <= 0) + return false; + + switch($mode) { + case QR_MODE_NUM: return self::checkModeNum($size, $data); break; + case QR_MODE_AN: return self::checkModeAn($size, $data); break; + case QR_MODE_KANJI: return self::checkModeKanji($size, $data); break; + case QR_MODE_8: return true; break; + case QR_MODE_STRUCTURE: return true; break; + + default: + break; + } + + return false; + } + + + //---------------------------------------------------------------------- + public function estimateBitStreamSize($version) + { + $bits = 0; + + foreach($this->items as $item) { + $bits += $item->estimateBitStreamSizeOfEntry($version); + } + + return $bits; + } + + //---------------------------------------------------------------------- + public function estimateVersion() + { + $version = 0; + $prev = 0; + do { + $prev = $version; + $bits = $this->estimateBitStreamSize($prev); + $version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if ($version < 0) { + return -1; + } + } while ($version > $prev); + + return $version; + } + + //---------------------------------------------------------------------- + public static function lengthOfCode($mode, $version, $bits) + { + $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version); + switch($mode) { + case QR_MODE_NUM: + $chunks = (int)($payload / 10); + $remain = $payload - $chunks * 10; + $size = $chunks * 3; + if($remain >= 7) { + $size += 2; + } else if($remain >= 4) { + $size += 1; + } + break; + case QR_MODE_AN: + $chunks = (int)($payload / 11); + $remain = $payload - $chunks * 11; + $size = $chunks * 2; + if($remain >= 6) + $size++; + break; + case QR_MODE_8: + $size = (int)($payload / 8); + break; + case QR_MODE_KANJI: + $size = (int)(($payload / 13) * 2); + break; + case QR_MODE_STRUCTURE: + $size = (int)($payload / 8); + break; + default: + $size = 0; + break; + } + + $maxsize = QRspec::maximumWords($mode, $version); + if($size < 0) $size = 0; + if($size > $maxsize) $size = $maxsize; + + return $size; + } + + //---------------------------------------------------------------------- + public function createBitStream() + { + $total = 0; + + foreach($this->items as $item) { + $bits = $item->encodeBitStream($this->version); + + if($bits < 0) + return -1; + + $total += $bits; + } + + return $total; + } + + //---------------------------------------------------------------------- + public function convertData() + { + $ver = $this->estimateVersion(); + if($ver > $this->getVersion()) { + $this->setVersion($ver); + } + + for(;;) { + $bits = $this->createBitStream(); + + if($bits < 0) + return -1; + + $ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if($ver < 0) { + throw new Exception('WRONG VERSION'); + return -1; + } else if($ver > $this->getVersion()) { + $this->setVersion($ver); + } else { + break; + } + } + + return 0; + } + + //---------------------------------------------------------------------- + public function appendPaddingBit(&$bstream) + { + $bits = $bstream->size(); + $maxwords = QRspec::getDataLength($this->version, $this->level); + $maxbits = $maxwords * 8; + + if ($maxbits == $bits) { + return 0; + } + + if ($maxbits - $bits < 5) { + return $bstream->appendNum($maxbits - $bits, 0); + } + + $bits += 4; + $words = (int)(($bits + 7) / 8); + + $padding = new QRbitstream(); + $ret = $padding->appendNum($words * 8 - $bits + 4, 0); + + if($ret < 0) + return $ret; + + $padlen = $maxwords - $words; + + if($padlen > 0) { + + $padbuf = array(); + for($i=0; $i<$padlen; $i++) { + $padbuf[$i] = ($i&1)?0x11:0xec; + } + + $ret = $padding->appendBytes($padlen, $padbuf); + + if($ret < 0) + return $ret; + + } + + $ret = $bstream->append($padding); + + return $ret; + } + + //---------------------------------------------------------------------- + public function mergeBitStream() + { + if($this->convertData() < 0) { + return null; + } + + $bstream = new QRbitstream(); + + foreach($this->items as $item) { + $ret = $bstream->append($item->bstream); + if($ret < 0) { + return null; + } + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function getBitStream() + { + + $bstream = $this->mergeBitStream(); + + if($bstream == null) { + return null; + } + + $ret = $this->appendPaddingBit($bstream); + if($ret < 0) { + return null; + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function getByteStream() + { + $bstream = $this->getBitStream(); + if($bstream == null) { + return null; + } + + return $bstream->toByte(); + } + } + + + + + + +//---- qrbitstream.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Bitstream class + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRbitstream { + + public $data = array(); + + //---------------------------------------------------------------------- + public function size() + { + return count($this->data); + } + + //---------------------------------------------------------------------- + public function allocate($setLength) + { + $this->data = array_fill(0, $setLength, 0); + return 0; + } + + //---------------------------------------------------------------------- + public static function newFromNum($bits, $num) + { + $bstream = new QRbitstream(); + $bstream->allocate($bits); + + $mask = 1 << ($bits - 1); + for($i=0; $i<$bits; $i++) { + if($num & $mask) { + $bstream->data[$i] = 1; + } else { + $bstream->data[$i] = 0; + } + $mask = $mask >> 1; + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public static function newFromBytes($size, $data) + { + $bstream = new QRbitstream(); + $bstream->allocate($size * 8); + $p=0; + + for($i=0; $i<$size; $i++) { + $mask = 0x80; + for($j=0; $j<8; $j++) { + if($data[$i] & $mask) { + $bstream->data[$p] = 1; + } else { + $bstream->data[$p] = 0; + } + $p++; + $mask = $mask >> 1; + } + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function append(QRbitstream $arg) + { + if (is_null($arg)) { + return -1; + } + + if($arg->size() == 0) { + return 0; + } + + if($this->size() == 0) { + $this->data = $arg->data; + return 0; + } + + $this->data = array_values(array_merge($this->data, $arg->data)); + + return 0; + } + + //---------------------------------------------------------------------- + public function appendNum($bits, $num) + { + if ($bits == 0) + return 0; + + $b = QRbitstream::newFromNum($bits, $num); + + if(is_null($b)) + return -1; + + $ret = $this->append($b); + unset($b); + + return $ret; + } + + //---------------------------------------------------------------------- + public function appendBytes($size, $data) + { + if ($size == 0) + return 0; + + $b = QRbitstream::newFromBytes($size, $data); + + if(is_null($b)) + return -1; + + $ret = $this->append($b); + unset($b); + + return $ret; + } + + //---------------------------------------------------------------------- + public function toByte() + { + + $size = $this->size(); + + if($size == 0) { + return array(); + } + + $data = array_fill(0, (int)(($size + 7) / 8), 0); + $bytes = (int)($size / 8); + + $p = 0; + + for($i=0; $i<$bytes; $i++) { + $v = 0; + for($j=0; $j<8; $j++) { + $v = $v << 1; + $v |= $this->data[$p]; + $p++; + } + $data[$i] = $v; + } + + if($size & 7) { + $v = 0; + for($j=0; $j<($size & 7); $j++) { + $v = $v << 1; + $v |= $this->data[$p]; + $p++; + } + $data[$bytes] = $v; + } + + return $data; + } + + } + + + + +//---- qrsplit.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Input splitting classes + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + class QRsplit { + + public $dataStr = ''; + public $input; + public $modeHint; + + //---------------------------------------------------------------------- + public function __construct($dataStr, $input, $modeHint) + { + $this->dataStr = $dataStr; + $this->input = $input; + $this->modeHint = $modeHint; + } + + //---------------------------------------------------------------------- + public static function isdigitat($str, $pos) + { + if ($pos >= strlen($str)) + return false; + + return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9'))); + } + + //---------------------------------------------------------------------- + public static function isalnumat($str, $pos) + { + if ($pos >= strlen($str)) + return false; + + return (QRinput::lookAnTable(ord($str[$pos])) >= 0); + } + + //---------------------------------------------------------------------- + public function identifyMode($pos) + { + if ($pos >= strlen($this->dataStr)) + return QR_MODE_NUL; + + $c = $this->dataStr[$pos]; + + if(self::isdigitat($this->dataStr, $pos)) { + return QR_MODE_NUM; + } else if(self::isalnumat($this->dataStr, $pos)) { + return QR_MODE_AN; + } else if($this->modeHint == QR_MODE_KANJI) { + + if ($pos+1 < strlen($this->dataStr)) + { + $d = $this->dataStr[$pos+1]; + $word = (ord($c) << 8) | ord($d); + if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) { + return QR_MODE_KANJI; + } + } + } + + return QR_MODE_8; + } + + //---------------------------------------------------------------------- + public function eatNum() + { + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 0; + while(self::isdigitat($this->dataStr, $p)) { + $p++; + } + + $run = $p; + $mode = $this->identifyMode($p); + + if($mode == QR_MODE_8) { + $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln + + QRinput::estimateBitsMode8(1) // + 4 + l8 + - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 + if($dif > 0) { + return $this->eat8(); + } + } + if($mode == QR_MODE_AN) { + $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln + + QRinput::estimateBitsModeAn(1) // + 4 + la + - QRinput::estimateBitsModeAn($run + 1);// - 4 - la + if($dif > 0) { + return $this->eatAn(); + } + } + + $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eatAn() + { + $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 0; + + while(self::isalnumat($this->dataStr, $p)) { + if(self::isdigitat($this->dataStr, $p)) { + $q = $p; + while(self::isdigitat($this->dataStr, $q)) { + $q++; + } + + $dif = QRinput::estimateBitsModeAn($p) // + 4 + la + + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln + - QRinput::estimateBitsModeAn($q); // - 4 - la + + if($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + + $run = $p; + + if(!self::isalnumat($this->dataStr, $p)) { + $dif = QRinput::estimateBitsModeAn($run) + 4 + $la + + QRinput::estimateBitsMode8(1) // + 4 + l8 + - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 + if($dif > 0) { + return $this->eat8(); + } + } + + $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eatKanji() + { + $p = 0; + + while($this->identifyMode($p) == QR_MODE_KANJI) { + $p += 2; + } + + $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eat8() + { + $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 1; + $dataStrLen = strlen($this->dataStr); + + while($p < $dataStrLen) { + + $mode = $this->identifyMode($p); + if($mode == QR_MODE_KANJI) { + break; + } + if($mode == QR_MODE_NUM) { + $q = $p; + while(self::isdigitat($this->dataStr, $q)) { + $q++; + } + $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 + + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln + - QRinput::estimateBitsMode8($q); // - 4 - l8 + if($dif < 0) { + break; + } else { + $p = $q; + } + } else if($mode == QR_MODE_AN) { + $q = $p; + while(self::isalnumat($this->dataStr, $q)) { + $q++; + } + $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 + + QRinput::estimateBitsModeAn($q - $p) + 4 + $la + - QRinput::estimateBitsMode8($q); // - 4 - l8 + if($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + + $run = $p; + $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr)); + + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function splitString() + { + while (strlen($this->dataStr) > 0) + { + if($this->dataStr == '') + return 0; + + $mode = $this->identifyMode(0); + + switch ($mode) { + case QR_MODE_NUM: $length = $this->eatNum(); break; + case QR_MODE_AN: $length = $this->eatAn(); break; + case QR_MODE_KANJI: + if ($hint == QR_MODE_KANJI) + $length = $this->eatKanji(); + else $length = $this->eat8(); + break; + default: $length = $this->eat8(); break; + + } + + if($length == 0) return 0; + if($length < 0) return -1; + + $this->dataStr = substr($this->dataStr, $length); + } + } + + //---------------------------------------------------------------------- + public function toUpper() + { + $stringLen = strlen($this->dataStr); + $p = 0; + + while ($p<$stringLen) { + $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint); + if($mode == QR_MODE_KANJI) { + $p += 2; + } else { + if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) { + $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); + } + $p++; + } + } + + return $this->dataStr; + } + + //---------------------------------------------------------------------- + public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true) + { + if(is_null($string) || $string == '\0' || $string == '') { + throw new Exception('empty string!!!'); + } + + $split = new QRsplit($string, $input, $modeHint); + + if(!$casesensitive) + $split->toUpper(); + + return $split->splitString(); + } + } + + + +//---- qrrscode.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Reed-Solomon error correction support + * + * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + * (libfec is released under the GNU Lesser General Public License.) + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRrsItem { + + public $mm; // Bits per symbol + public $nn; // Symbols per block (= (1<= $this->nn) { + $x -= $this->nn; + $x = ($x >> $this->mm) + ($x & $this->nn); + } + + return $x; + } + + //---------------------------------------------------------------------- + public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) + { + // Common code for intializing a Reed-Solomon control block (char or int symbols) + // Copyright 2004 Phil Karn, KA9Q + // May be used under the terms of the GNU Lesser General Public License (LGPL) + + $rs = null; + + // Check parameter ranges + if($symsize < 0 || $symsize > 8) return $rs; + if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs; + if($prim <= 0 || $prim >= (1<<$symsize)) return $rs; + if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values! + if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding + + $rs = new QRrsItem(); + $rs->mm = $symsize; + $rs->nn = (1<<$symsize)-1; + $rs->pad = $pad; + + $rs->alpha_to = array_fill(0, $rs->nn+1, 0); + $rs->index_of = array_fill(0, $rs->nn+1, 0); + + // PHP style macro replacement ;) + $NN =& $rs->nn; + $A0 =& $NN; + + // Generate Galois field lookup tables + $rs->index_of[0] = $A0; // log(zero) = -inf + $rs->alpha_to[$A0] = 0; // alpha**-inf = 0 + $sr = 1; + + for($i=0; $i<$rs->nn; $i++) { + $rs->index_of[$sr] = $i; + $rs->alpha_to[$i] = $sr; + $sr <<= 1; + if($sr & (1<<$symsize)) { + $sr ^= $gfpoly; + } + $sr &= $rs->nn; + } + + if($sr != 1){ + // field generator polynomial is not primitive! + $rs = NULL; + return $rs; + } + + /* Form RS code generator polynomial from its roots */ + $rs->genpoly = array_fill(0, $nroots+1, 0); + + $rs->fcr = $fcr; + $rs->prim = $prim; + $rs->nroots = $nroots; + $rs->gfpoly = $gfpoly; + + /* Find prim-th root of 1, used in decoding */ + for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn) + ; // intentional empty-body loop! + + $rs->iprim = (int)($iprim / $prim); + $rs->genpoly[0] = 1; + + for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) { + $rs->genpoly[$i+1] = 1; + + // Multiply rs->genpoly[] by @**(root + x) + for ($j = $i; $j > 0; $j--) { + if ($rs->genpoly[$j] != 0) { + $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)]; + } else { + $rs->genpoly[$j] = $rs->genpoly[$j-1]; + } + } + // rs->genpoly[0] can never be zero + $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)]; + } + + // convert rs->genpoly[] to index form for quicker encoding + for ($i = 0; $i <= $nroots; $i++) + $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]]; + + return $rs; + } + + //---------------------------------------------------------------------- + public function encode_rs_char($data, &$parity) + { + $MM =& $this->mm; + $NN =& $this->nn; + $ALPHA_TO =& $this->alpha_to; + $INDEX_OF =& $this->index_of; + $GENPOLY =& $this->genpoly; + $NROOTS =& $this->nroots; + $FCR =& $this->fcr; + $PRIM =& $this->prim; + $IPRIM =& $this->iprim; + $PAD =& $this->pad; + $A0 =& $NN; + + $parity = array_fill(0, $NROOTS, 0); + + for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) { + + $feedback = $INDEX_OF[$data[$i] ^ $parity[0]]; + if($feedback != $A0) { + // feedback term is non-zero + + // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must + // always be for the polynomials constructed by init_rs() + $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback); + + for($j=1;$j<$NROOTS;$j++) { + $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])]; + } + } + + // Shift + array_shift($parity); + if($feedback != $A0) { + array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]); + } else { + array_push($parity, 0); + } + } + } + } + + //########################################################################## + + class QRrs { + + public static $items = array(); + + //---------------------------------------------------------------------- + public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) + { + foreach(self::$items as $rs) { + if($rs->pad != $pad) continue; + if($rs->nroots != $nroots) continue; + if($rs->mm != $symsize) continue; + if($rs->gfpoly != $gfpoly) continue; + if($rs->fcr != $fcr) continue; + if($rs->prim != $prim) continue; + + return $rs; + } + + $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad); + array_unshift(self::$items, $rs); + + return $rs; + } + } + + + +//---- qrmask.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Masking + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('N1', 3); + define('N2', 3); + define('N3', 40); + define('N4', 10); + + class QRmask { + + public $runLength = array(); + + //---------------------------------------------------------------------- + public function __construct() + { + $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0); + } + + //---------------------------------------------------------------------- + public function writeFormatInformation($width, &$frame, $mask, $level) + { + $blacks = 0; + $format = QRspec::getFormatInfo($mask, $level); + + for($i=0; $i<8; $i++) { + if($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + + $frame[8][$width - 1 - $i] = chr($v); + if($i < 6) { + $frame[$i][8] = chr($v); + } else { + $frame[$i + 1][8] = chr($v); + } + $format = $format >> 1; + } + + for($i=0; $i<7; $i++) { + if($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + + $frame[$width - 7 + $i][8] = chr($v); + if($i == 0) { + $frame[8][7] = chr($v); + } else { + $frame[8][6 - $i] = chr($v); + } + + $format = $format >> 1; + } + + return $blacks; + } + + //---------------------------------------------------------------------- + public function mask0($x, $y) { return ($x+$y)&1; } + public function mask1($x, $y) { return ($y&1); } + public function mask2($x, $y) { return ($x%3); } + public function mask3($x, $y) { return ($x+$y)%3; } + public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; } + public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; } + public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; } + public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; } + + //---------------------------------------------------------------------- + private function generateMaskNo($maskNo, $width, $frame) + { + $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); + + for($y=0; $y<$width; $y++) { + for($x=0; $x<$width; $x++) { + if(ord($frame[$y][$x]) & 0x80) { + $bitMask[$y][$x] = 0; + } else { + $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y); + $bitMask[$y][$x] = ($maskFunc == 0)?1:0; + } + + } + } + + return $bitMask; + } + + //---------------------------------------------------------------------- + public static function serial($bitFrame) + { + $codeArr = array(); + + foreach ($bitFrame as $line) + $codeArr[] = join('', $line); + + return gzcompress(join("\n", $codeArr), 9); + } + + //---------------------------------------------------------------------- + public static function unserial($code) + { + $codeArr = array(); + + $codeLines = explode("\n", gzuncompress($code)); + foreach ($codeLines as $line) + $codeArr[] = str_split($line); + + return $codeArr; + } + + //---------------------------------------------------------------------- + public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false) + { + $b = 0; + $bitMask = array(); + + $fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat'; + + if (QR_CACHEABLE) { + if (file_exists($fileName)) { + $bitMask = self::unserial(file_get_contents($fileName)); + } else { + $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); + if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo)) + mkdir(QR_CACHE_DIR.'mask_'.$maskNo); + file_put_contents($fileName, self::serial($bitMask)); + } + } else { + $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); + } + + if ($maskGenOnly) + return; + + $d = $s; + + for($y=0; $y<$width; $y++) { + for($x=0; $x<$width; $x++) { + if($bitMask[$y][$x] == 1) { + $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]); + } + $b += (int)(ord($d[$y][$x]) & 1); + } + } + + return $b; + } + + //---------------------------------------------------------------------- + public function makeMask($width, $frame, $maskNo, $level) + { + $masked = array_fill(0, $width, str_repeat("\0", $width)); + $this->makeMaskNo($maskNo, $width, $frame, $masked); + $this->writeFormatInformation($width, $masked, $maskNo, $level); + + return $masked; + } + + //---------------------------------------------------------------------- + public function calcN1N3($length) + { + $demerit = 0; + + for($i=0; $i<$length; $i++) { + + if($this->runLength[$i] >= 5) { + $demerit += (N1 + ($this->runLength[$i] - 5)); + } + if($i & 1) { + if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) { + $fact = (int)($this->runLength[$i] / 3); + if(($this->runLength[$i-2] == $fact) && + ($this->runLength[$i-1] == $fact) && + ($this->runLength[$i+1] == $fact) && + ($this->runLength[$i+2] == $fact)) { + if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) { + $demerit += N3; + } else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) { + $demerit += N3; + } + } + } + } + } + return $demerit; + } + + //---------------------------------------------------------------------- + public function evaluateSymbol($width, $frame) + { + $head = 0; + $demerit = 0; + + for($y=0; $y<$width; $y++) { + $head = 0; + $this->runLength[0] = 1; + + $frameY = $frame[$y]; + + if ($y>0) + $frameYM = $frame[$y-1]; + + for($x=0; $x<$width; $x++) { + if(($x > 0) && ($y > 0)) { + $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]); + $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]); + + if(($b22 | ($w22 ^ 1))&1) { + $demerit += N2; + } + } + if(($x == 0) && (ord($frameY[$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } else if($x > 0) { + if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + + $demerit += $this->calcN1N3($head+1); + } + + for($x=0; $x<$width; $x++) { + $head = 0; + $this->runLength[0] = 1; + + for($y=0; $y<$width; $y++) { + if($y == 0 && (ord($frame[$y][$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } else if($y > 0) { + if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + + $demerit += $this->calcN1N3($head+1); + } + + return $demerit; + } + + + //---------------------------------------------------------------------- + public function mask($width, $frame, $level) + { + $minDemerit = PHP_INT_MAX; + $bestMaskNum = 0; + $bestMask = array(); + + $checked_masks = array(0,1,2,3,4,5,6,7); + + if (QR_FIND_FROM_RANDOM !== false) { + + $howManuOut = 8-(QR_FIND_FROM_RANDOM % 9); + for ($i = 0; $i < $howManuOut; $i++) { + $remPos = rand (0, count($checked_masks)-1); + unset($checked_masks[$remPos]); + $checked_masks = array_values($checked_masks); + } + + } + + $bestMask = $frame; + + foreach($checked_masks as $i) { + $mask = array_fill(0, $width, str_repeat("\0", $width)); + + $demerit = 0; + $blacks = 0; + $blacks = $this->makeMaskNo($i, $width, $frame, $mask); + $blacks += $this->writeFormatInformation($width, $mask, $i, $level); + $blacks = (int)(100 * $blacks / ($width * $width)); + $demerit = (int)((int)(abs($blacks - 50) / 5) * N4); + $demerit += $this->evaluateSymbol($width, $mask); + + if($demerit < $minDemerit) { + $minDemerit = $demerit; + $bestMask = $mask; + $bestMaskNum = $i; + } + } + + return $bestMask; + } + + //---------------------------------------------------------------------- + } + + + + +//---- qrencode.php ----------------------------- + + + + +/* + * PHP QR Code encoder + * + * Main encoder classes. + * + * Based on libqrencode C library distributed under LGPL 2.1 + * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRrsblock { + public $dataLength; + public $data = array(); + public $eccLength; + public $ecc = array(); + + public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs) + { + $rs->encode_rs_char($data, $ecc); + + $this->dataLength = $dl; + $this->data = $data; + $this->eccLength = $el; + $this->ecc = $ecc; + } + }; + + //########################################################################## + + class QRrawcode { + public $version; + public $datacode = array(); + public $ecccode = array(); + public $blocks; + public $rsblocks = array(); //of RSblock + public $count; + public $dataLength; + public $eccLength; + public $b1; + + //---------------------------------------------------------------------- + public function __construct(QRinput $input) + { + $spec = array(0,0,0,0,0); + + $this->datacode = $input->getByteStream(); + if(is_null($this->datacode)) { + throw new Exception('null imput string'); + } + + QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec); + + $this->version = $input->getVersion(); + $this->b1 = QRspec::rsBlockNum1($spec); + $this->dataLength = QRspec::rsDataLength($spec); + $this->eccLength = QRspec::rsEccLength($spec); + $this->ecccode = array_fill(0, $this->eccLength, 0); + $this->blocks = QRspec::rsBlockNum($spec); + + $ret = $this->init($spec); + if($ret < 0) { + throw new Exception('block alloc error'); + return null; + } + + $this->count = 0; + } + + //---------------------------------------------------------------------- + public function init(array $spec) + { + $dl = QRspec::rsDataCodes1($spec); + $el = QRspec::rsEccCodes1($spec); + $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + + + $blockNo = 0; + $dataPos = 0; + $eccPos = 0; + for($i=0; $iecccode,$eccPos); + $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); + $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); + + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + + if(QRspec::rsBlockNum2($spec) == 0) + return 0; + + $dl = QRspec::rsDataCodes2($spec); + $el = QRspec::rsEccCodes2($spec); + $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + + if($rs == NULL) return -1; + + for($i=0; $iecccode,$eccPos); + $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); + $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); + + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + + return 0; + } + + //---------------------------------------------------------------------- + public function getCode() + { + $ret; + + if($this->count < $this->dataLength) { + $row = $this->count % $this->blocks; + $col = $this->count / $this->blocks; + if($col >= $this->rsblocks[0]->dataLength) { + $row += $this->b1; + } + $ret = $this->rsblocks[$row]->data[$col]; + } else if($this->count < $this->dataLength + $this->eccLength) { + $row = ($this->count - $this->dataLength) % $this->blocks; + $col = ($this->count - $this->dataLength) / $this->blocks; + $ret = $this->rsblocks[$row]->ecc[$col]; + } else { + return 0; + } + $this->count++; + + return $ret; + } + } + + //########################################################################## + + class QRcode { + + public $version; + public $width; + public $data; + + //---------------------------------------------------------------------- + public function encodeMask(QRinput $input, $mask) + { + if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) { + throw new Exception('wrong version'); + } + if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) { + throw new Exception('wrong level'); + } + + $raw = new QRrawcode($input); + + QRtools::markTime('after_raw'); + + $version = $raw->version; + $width = QRspec::getWidth($version); + $frame = QRspec::newFrame($version); + + $filler = new FrameFiller($width, $frame); + if(is_null($filler)) { + return NULL; + } + + // inteleaved data and ecc codes + for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) { + $code = $raw->getCode(); + $bit = 0x80; + for($j=0; $j<8; $j++) { + $addr = $filler->next(); + $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0)); + $bit = $bit >> 1; + } + } + + QRtools::markTime('after_filler'); + + unset($raw); + + // remainder bits + $j = QRspec::getRemainder($version); + for($i=0; $i<$j; $i++) { + $addr = $filler->next(); + $filler->setFrameAt($addr, 0x02); + } + + $frame = $filler->frame; + unset($filler); + + + // masking + $maskObj = new QRmask(); + if($mask < 0) { + + if (QR_FIND_BEST_MASK) { + $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel()); + } else { + $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel()); + } + } else { + $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel()); + } + + if($masked == NULL) { + return NULL; + } + + QRtools::markTime('after_mask'); + + $this->version = $version; + $this->width = $width; + $this->data = $masked; + + return $this; + } + + //---------------------------------------------------------------------- + public function encodeInput(QRinput $input) + { + return $this->encodeMask($input, -1); + } + + //---------------------------------------------------------------------- + public function encodeString8bit($string, $version, $level) + { + if(string == NULL) { + throw new Exception('empty string!'); + return NULL; + } + + $input = new QRinput($version, $level); + if($input == NULL) return NULL; + + $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string)); + if($ret < 0) { + unset($input); + return NULL; + } + return $this->encodeInput($input); + } + + //---------------------------------------------------------------------- + public function encodeString($string, $version, $level, $hint, $casesensitive) + { + + if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) { + throw new Exception('bad hint'); + return NULL; + } + + $input = new QRinput($version, $level); + if($input == NULL) return NULL; + + $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive); + if($ret < 0) { + return NULL; + } + + return $this->encodeInput($input); + } + + //---------------------------------------------------------------------- + public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encodePNG($text, $outfile, $saveandprint=false); + } + + //---------------------------------------------------------------------- + public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encode($text, $outfile); + } + + //---------------------------------------------------------------------- + public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encodeRAW($text, $outfile); + } + } + + //########################################################################## + + class FrameFiller { + + public $width; + public $frame; + public $x; + public $y; + public $dir; + public $bit; + + //---------------------------------------------------------------------- + public function __construct($width, &$frame) + { + $this->width = $width; + $this->frame = $frame; + $this->x = $width - 1; + $this->y = $width - 1; + $this->dir = -1; + $this->bit = -1; + } + + //---------------------------------------------------------------------- + public function setFrameAt($at, $val) + { + $this->frame[$at['y']][$at['x']] = chr($val); + } + + //---------------------------------------------------------------------- + public function getFrameAt($at) + { + return ord($this->frame[$at['y']][$at['x']]); + } + + //---------------------------------------------------------------------- + public function next() + { + do { + + if($this->bit == -1) { + $this->bit = 0; + return array('x'=>$this->x, 'y'=>$this->y); + } + + $x = $this->x; + $y = $this->y; + $w = $this->width; + + if($this->bit == 0) { + $x--; + $this->bit++; + } else { + $x++; + $y += $this->dir; + $this->bit--; + } + + if($this->dir < 0) { + if($y < 0) { + $y = 0; + $x -= 2; + $this->dir = 1; + if($x == 6) { + $x--; + $y = 9; + } + } + } else { + if($y == $w) { + $y = $w - 1; + $x -= 2; + $this->dir = -1; + if($x == 6) { + $x--; + $y -= 8; + } + } + } + if($x < 0 || $y < 0) return null; + + $this->x = $x; + $this->y = $y; + + } while(ord($this->frame[$y][$x]) & 0x80); + + return array('x'=>$x, 'y'=>$y); + } + + } ; + + //########################################################################## + + class QRencode { + + public $casesensitive = true; + public $eightbit = false; + + public $version = 0; + public $size = 3; + public $margin = 4; + + public $structured = 0; // not supported yet + + public $level = QR_ECLEVEL_L; + public $hint = QR_MODE_8; + + //---------------------------------------------------------------------- + public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = new QRencode(); + $enc->size = $size; + $enc->margin = $margin; + + switch ($level.'') { + case '0': + case '1': + case '2': + case '3': + $enc->level = $level; + break; + case 'l': + case 'L': + $enc->level = QR_ECLEVEL_L; + break; + case 'm': + case 'M': + $enc->level = QR_ECLEVEL_M; + break; + case 'q': + case 'Q': + $enc->level = QR_ECLEVEL_Q; + break; + case 'h': + case 'H': + $enc->level = QR_ECLEVEL_H; + break; + } + + return $enc; + } + + //---------------------------------------------------------------------- + public function encodeRAW($intext, $outfile = false) + { + $code = new QRcode(); + + if($this->eightbit) { + $code->encodeString8bit($intext, $this->version, $this->level); + } else { + $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); + } + + return $code->data; + } + + //---------------------------------------------------------------------- + public function encode($intext, $outfile = false) + { + $code = new QRcode(); + + if($this->eightbit) { + $code->encodeString8bit($intext, $this->version, $this->level); + } else { + $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); + } + + QRtools::markTime('after_encode'); + + if ($outfile!== false) { + file_put_contents($outfile, join("\n", QRtools::binarize($code->data))); + } else { + return QRtools::binarize($code->data); + } + } + + //---------------------------------------------------------------------- + public function encodePNG($intext, $outfile = false,$saveandprint=false) + { + try { + + ob_start(); + $tab = $this->encode($intext); + $err = ob_get_contents(); + ob_end_clean(); + + if ($err != '') + QRtools::log($outfile, $err); + + $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin)); + + QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint); + + } catch (Exception $e) { + + QRtools::log($outfile, $e->getMessage()); + + } + } + } + + diff --git a/vendor/phpqrcode/qrbitstream.php b/vendor/phpqrcode/qrbitstream.php new file mode 100644 index 0000000..7d4ec4a --- /dev/null +++ b/vendor/phpqrcode/qrbitstream.php @@ -0,0 +1,180 @@ + + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRbitstream { + + public $data = array(); + + //---------------------------------------------------------------------- + public function size() + { + return count($this->data); + } + + //---------------------------------------------------------------------- + public function allocate($setLength) + { + $this->data = array_fill(0, $setLength, 0); + return 0; + } + + //---------------------------------------------------------------------- + public static function newFromNum($bits, $num) + { + $bstream = new QRbitstream(); + $bstream->allocate($bits); + + $mask = 1 << ($bits - 1); + for($i=0; $i<$bits; $i++) { + if($num & $mask) { + $bstream->data[$i] = 1; + } else { + $bstream->data[$i] = 0; + } + $mask = $mask >> 1; + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public static function newFromBytes($size, $data) + { + $bstream = new QRbitstream(); + $bstream->allocate($size * 8); + $p=0; + + for($i=0; $i<$size; $i++) { + $mask = 0x80; + for($j=0; $j<8; $j++) { + if($data[$i] & $mask) { + $bstream->data[$p] = 1; + } else { + $bstream->data[$p] = 0; + } + $p++; + $mask = $mask >> 1; + } + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function append(QRbitstream $arg) + { + if (is_null($arg)) { + return -1; + } + + if($arg->size() == 0) { + return 0; + } + + if($this->size() == 0) { + $this->data = $arg->data; + return 0; + } + + $this->data = array_values(array_merge($this->data, $arg->data)); + + return 0; + } + + //---------------------------------------------------------------------- + public function appendNum($bits, $num) + { + if ($bits == 0) + return 0; + + $b = QRbitstream::newFromNum($bits, $num); + + if(is_null($b)) + return -1; + + $ret = $this->append($b); + unset($b); + + return $ret; + } + + //---------------------------------------------------------------------- + public function appendBytes($size, $data) + { + if ($size == 0) + return 0; + + $b = QRbitstream::newFromBytes($size, $data); + + if(is_null($b)) + return -1; + + $ret = $this->append($b); + unset($b); + + return $ret; + } + + //---------------------------------------------------------------------- + public function toByte() + { + + $size = $this->size(); + + if($size == 0) { + return array(); + } + + $data = array_fill(0, (int)(($size + 7) / 8), 0); + $bytes = (int)($size / 8); + + $p = 0; + + for($i=0; $i<$bytes; $i++) { + $v = 0; + for($j=0; $j<8; $j++) { + $v = $v << 1; + $v |= $this->data[$p]; + $p++; + } + $data[$i] = $v; + } + + if($size & 7) { + $v = 0; + for($j=0; $j<($size & 7); $j++) { + $v = $v << 1; + $v |= $this->data[$p]; + $p++; + } + $data[$bytes] = $v; + } + + return $data; + } + + } diff --git a/vendor/phpqrcode/qrconfig.php b/vendor/phpqrcode/qrconfig.php new file mode 100644 index 0000000..e53dff8 --- /dev/null +++ b/vendor/phpqrcode/qrconfig.php @@ -0,0 +1,17 @@ + + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + // Encoding modes + + define('QR_MODE_NUL', -1); + define('QR_MODE_NUM', 0); + define('QR_MODE_AN', 1); + define('QR_MODE_8', 2); + define('QR_MODE_KANJI', 3); + define('QR_MODE_STRUCTURE', 4); + + // Levels of error correction. + + define('QR_ECLEVEL_L', 0); + define('QR_ECLEVEL_M', 1); + define('QR_ECLEVEL_Q', 2); + define('QR_ECLEVEL_H', 3); + + // Supported output formats + + define('QR_FORMAT_TEXT', 0); + define('QR_FORMAT_PNG', 1); + + class qrstr { + public static function set(&$srctab, $x, $y, $repl, $replLen = false) { + $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false)?substr($repl,0,$replLen):$repl, $x, ($replLen !== false)?$replLen:strlen($repl)); + } + } \ No newline at end of file diff --git a/vendor/phpqrcode/qrencode.php b/vendor/phpqrcode/qrencode.php new file mode 100644 index 0000000..4b77a5b --- /dev/null +++ b/vendor/phpqrcode/qrencode.php @@ -0,0 +1,502 @@ + + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRrsblock { + public $dataLength; + public $data = array(); + public $eccLength; + public $ecc = array(); + + public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs) + { + $rs->encode_rs_char($data, $ecc); + + $this->dataLength = $dl; + $this->data = $data; + $this->eccLength = $el; + $this->ecc = $ecc; + } + }; + + //########################################################################## + + class QRrawcode { + public $version; + public $datacode = array(); + public $ecccode = array(); + public $blocks; + public $rsblocks = array(); //of RSblock + public $count; + public $dataLength; + public $eccLength; + public $b1; + + //---------------------------------------------------------------------- + public function __construct(QRinput $input) + { + $spec = array(0,0,0,0,0); + + $this->datacode = $input->getByteStream(); + if(is_null($this->datacode)) { + throw new Exception('null imput string'); + } + + QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec); + + $this->version = $input->getVersion(); + $this->b1 = QRspec::rsBlockNum1($spec); + $this->dataLength = QRspec::rsDataLength($spec); + $this->eccLength = QRspec::rsEccLength($spec); + $this->ecccode = array_fill(0, $this->eccLength, 0); + $this->blocks = QRspec::rsBlockNum($spec); + + $ret = $this->init($spec); + if($ret < 0) { + throw new Exception('block alloc error'); + return null; + } + + $this->count = 0; + } + + //---------------------------------------------------------------------- + public function init(array $spec) + { + $dl = QRspec::rsDataCodes1($spec); + $el = QRspec::rsEccCodes1($spec); + $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + + + $blockNo = 0; + $dataPos = 0; + $eccPos = 0; + for($i=0; $iecccode,$eccPos); + $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); + $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); + + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + + if(QRspec::rsBlockNum2($spec) == 0) + return 0; + + $dl = QRspec::rsDataCodes2($spec); + $el = QRspec::rsEccCodes2($spec); + $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); + + if($rs == NULL) return -1; + + for($i=0; $iecccode,$eccPos); + $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); + $this->ecccode = array_merge(array_slice($this->ecccode,0, $eccPos), $ecc); + + $dataPos += $dl; + $eccPos += $el; + $blockNo++; + } + + return 0; + } + + //---------------------------------------------------------------------- + public function getCode() + { + $ret; + + if($this->count < $this->dataLength) { + $row = $this->count % $this->blocks; + $col = $this->count / $this->blocks; + if($col >= $this->rsblocks[0]->dataLength) { + $row += $this->b1; + } + $ret = $this->rsblocks[$row]->data[$col]; + } else if($this->count < $this->dataLength + $this->eccLength) { + $row = ($this->count - $this->dataLength) % $this->blocks; + $col = ($this->count - $this->dataLength) / $this->blocks; + $ret = $this->rsblocks[$row]->ecc[$col]; + } else { + return 0; + } + $this->count++; + + return $ret; + } + } + + //########################################################################## + + class QRcode { + + public $version; + public $width; + public $data; + + //---------------------------------------------------------------------- + public function encodeMask(QRinput $input, $mask) + { + if($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) { + throw new Exception('wrong version'); + } + if($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) { + throw new Exception('wrong level'); + } + + $raw = new QRrawcode($input); + + QRtools::markTime('after_raw'); + + $version = $raw->version; + $width = QRspec::getWidth($version); + $frame = QRspec::newFrame($version); + + $filler = new FrameFiller($width, $frame); + if(is_null($filler)) { + return NULL; + } + + // inteleaved data and ecc codes + for($i=0; $i<$raw->dataLength + $raw->eccLength; $i++) { + $code = $raw->getCode(); + $bit = 0x80; + for($j=0; $j<8; $j++) { + $addr = $filler->next(); + $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0)); + $bit = $bit >> 1; + } + } + + QRtools::markTime('after_filler'); + + unset($raw); + + // remainder bits + $j = QRspec::getRemainder($version); + for($i=0; $i<$j; $i++) { + $addr = $filler->next(); + $filler->setFrameAt($addr, 0x02); + } + + $frame = $filler->frame; + unset($filler); + + + // masking + $maskObj = new QRmask(); + if($mask < 0) { + + if (QR_FIND_BEST_MASK) { + $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel()); + } else { + $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel()); + } + } else { + $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel()); + } + + if($masked == NULL) { + return NULL; + } + + QRtools::markTime('after_mask'); + + $this->version = $version; + $this->width = $width; + $this->data = $masked; + + return $this; + } + + //---------------------------------------------------------------------- + public function encodeInput(QRinput $input) + { + return $this->encodeMask($input, -1); + } + + //---------------------------------------------------------------------- + public function encodeString8bit($string, $version, $level) + { + if(string == NULL) { + throw new Exception('empty string!'); + return NULL; + } + + $input = new QRinput($version, $level); + if($input == NULL) return NULL; + + $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string)); + if($ret < 0) { + unset($input); + return NULL; + } + return $this->encodeInput($input); + } + + //---------------------------------------------------------------------- + public function encodeString($string, $version, $level, $hint, $casesensitive) + { + + if($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) { + throw new Exception('bad hint'); + return NULL; + } + + $input = new QRinput($version, $level); + if($input == NULL) return NULL; + + $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive); + if($ret < 0) { + return NULL; + } + + return $this->encodeInput($input); + } + + //---------------------------------------------------------------------- + public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint=false) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encodePNG($text, $outfile, $saveandprint=false); + } + + //---------------------------------------------------------------------- + public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encode($text, $outfile); + } + + //---------------------------------------------------------------------- + public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = QRencode::factory($level, $size, $margin); + return $enc->encodeRAW($text, $outfile); + } + } + + //########################################################################## + + class FrameFiller { + + public $width; + public $frame; + public $x; + public $y; + public $dir; + public $bit; + + //---------------------------------------------------------------------- + public function __construct($width, &$frame) + { + $this->width = $width; + $this->frame = $frame; + $this->x = $width - 1; + $this->y = $width - 1; + $this->dir = -1; + $this->bit = -1; + } + + //---------------------------------------------------------------------- + public function setFrameAt($at, $val) + { + $this->frame[$at['y']][$at['x']] = chr($val); + } + + //---------------------------------------------------------------------- + public function getFrameAt($at) + { + return ord($this->frame[$at['y']][$at['x']]); + } + + //---------------------------------------------------------------------- + public function next() + { + do { + + if($this->bit == -1) { + $this->bit = 0; + return array('x'=>$this->x, 'y'=>$this->y); + } + + $x = $this->x; + $y = $this->y; + $w = $this->width; + + if($this->bit == 0) { + $x--; + $this->bit++; + } else { + $x++; + $y += $this->dir; + $this->bit--; + } + + if($this->dir < 0) { + if($y < 0) { + $y = 0; + $x -= 2; + $this->dir = 1; + if($x == 6) { + $x--; + $y = 9; + } + } + } else { + if($y == $w) { + $y = $w - 1; + $x -= 2; + $this->dir = -1; + if($x == 6) { + $x--; + $y -= 8; + } + } + } + if($x < 0 || $y < 0) return null; + + $this->x = $x; + $this->y = $y; + + } while(ord($this->frame[$y][$x]) & 0x80); + + return array('x'=>$x, 'y'=>$y); + } + + } ; + + //########################################################################## + + class QRencode { + + public $casesensitive = true; + public $eightbit = false; + + public $version = 0; + public $size = 3; + public $margin = 4; + + public $structured = 0; // not supported yet + + public $level = QR_ECLEVEL_L; + public $hint = QR_MODE_8; + + //---------------------------------------------------------------------- + public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4) + { + $enc = new QRencode(); + $enc->size = $size; + $enc->margin = $margin; + + switch ($level.'') { + case '0': + case '1': + case '2': + case '3': + $enc->level = $level; + break; + case 'l': + case 'L': + $enc->level = QR_ECLEVEL_L; + break; + case 'm': + case 'M': + $enc->level = QR_ECLEVEL_M; + break; + case 'q': + case 'Q': + $enc->level = QR_ECLEVEL_Q; + break; + case 'h': + case 'H': + $enc->level = QR_ECLEVEL_H; + break; + } + + return $enc; + } + + //---------------------------------------------------------------------- + public function encodeRAW($intext, $outfile = false) + { + $code = new QRcode(); + + if($this->eightbit) { + $code->encodeString8bit($intext, $this->version, $this->level); + } else { + $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); + } + + return $code->data; + } + + //---------------------------------------------------------------------- + public function encode($intext, $outfile = false) + { + $code = new QRcode(); + + if($this->eightbit) { + $code->encodeString8bit($intext, $this->version, $this->level); + } else { + $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); + } + + QRtools::markTime('after_encode'); + + if ($outfile!== false) { + file_put_contents($outfile, join("\n", QRtools::binarize($code->data))); + } else { + return QRtools::binarize($code->data); + } + } + + //---------------------------------------------------------------------- + public function encodePNG($intext, $outfile = false,$saveandprint=false) + { + try { + + ob_start(); + $tab = $this->encode($intext); + $err = ob_get_contents(); + ob_end_clean(); + + if ($err != '') + QRtools::log($outfile, $err); + + $maxSize = (int)(QR_PNG_MAXIMUM_SIZE / (count($tab)+2*$this->margin)); + + QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin,$saveandprint); + + } catch (Exception $e) { + + QRtools::log($outfile, $e->getMessage()); + + } + } + } diff --git a/vendor/phpqrcode/qrimage.php b/vendor/phpqrcode/qrimage.php new file mode 100644 index 0000000..10b0a6e --- /dev/null +++ b/vendor/phpqrcode/qrimage.php @@ -0,0 +1,95 @@ + + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('QR_IMAGE', true); + + class QRimage { + + //---------------------------------------------------------------------- + public static function png($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4,$saveandprint=FALSE) + { + $image = self::image($frame, $pixelPerPoint, $outerFrame); + + if ($filename === false) { + Header("Content-type: image/png"); + ImagePng($image); + } else { + if($saveandprint===TRUE){ + ImagePng($image, $filename); + header("Content-type: image/png"); + ImagePng($image); + }else{ + ImagePng($image, $filename); + } + } + + ImageDestroy($image); + } + + //---------------------------------------------------------------------- + public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85) + { + $image = self::image($frame, $pixelPerPoint, $outerFrame); + + if ($filename === false) { + Header("Content-type: image/jpeg"); + ImageJpeg($image, null, $q); + } else { + ImageJpeg($image, $filename, $q); + } + + ImageDestroy($image); + } + + //---------------------------------------------------------------------- + private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4) + { + $h = count($frame); + $w = strlen($frame[0]); + + $imgW = $w + 2*$outerFrame; + $imgH = $h + 2*$outerFrame; + + $base_image =ImageCreate($imgW, $imgH); + + $col[0] = ImageColorAllocate($base_image,255,255,255); + $col[1] = ImageColorAllocate($base_image,0,0,0); + + imagefill($base_image, 0, 0, $col[0]); + + for($y=0; $y<$h; $y++) { + for($x=0; $x<$w; $x++) { + if ($frame[$y][$x] == '1') { + ImageSetPixel($base_image,$x+$outerFrame,$y+$outerFrame,$col[1]); + } + } + } + + $target_image =ImageCreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint); + ImageCopyResized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH); + ImageDestroy($base_image); + + return $target_image; + } + } \ No newline at end of file diff --git a/vendor/phpqrcode/qrinput.php b/vendor/phpqrcode/qrinput.php new file mode 100644 index 0000000..0f6d7f9 --- /dev/null +++ b/vendor/phpqrcode/qrinput.php @@ -0,0 +1,729 @@ + + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('STRUCTURE_HEADER_BITS', 20); + define('MAX_STRUCTURED_SYMBOLS', 16); + + class QRinputItem { + + public $mode; + public $size; + public $data; + public $bstream; + + public function __construct($mode, $size, $data, $bstream = null) + { + $setData = array_slice($data, 0, $size); + + if (count($setData) < $size) { + $setData = array_merge($setData, array_fill(0,$size-count($setData),0)); + } + + if(!QRinput::check($mode, $size, $setData)) { + throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData)); + return null; + } + + $this->mode = $mode; + $this->size = $size; + $this->data = $setData; + $this->bstream = $bstream; + } + + //---------------------------------------------------------------------- + public function encodeModeNum($version) + { + try { + + $words = (int)($this->size / 3); + $bs = new QRbitstream(); + + $val = 0x1; + $bs->appendNum(4, $val); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size); + + for($i=0; $i<$words; $i++) { + $val = (ord($this->data[$i*3 ]) - ord('0')) * 100; + $val += (ord($this->data[$i*3+1]) - ord('0')) * 10; + $val += (ord($this->data[$i*3+2]) - ord('0')); + $bs->appendNum(10, $val); + } + + if($this->size - $words * 3 == 1) { + $val = ord($this->data[$words*3]) - ord('0'); + $bs->appendNum(4, $val); + } else if($this->size - $words * 3 == 2) { + $val = (ord($this->data[$words*3 ]) - ord('0')) * 10; + $val += (ord($this->data[$words*3+1]) - ord('0')); + $bs->appendNum(7, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeAn($version) + { + try { + $words = (int)($this->size / 2); + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x02); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size); + + for($i=0; $i<$words; $i++) { + $val = (int)QRinput::lookAnTable(ord($this->data[$i*2 ])) * 45; + $val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1])); + + $bs->appendNum(11, $val); + } + + if($this->size & 1) { + $val = QRinput::lookAnTable(ord($this->data[$words * 2])); + $bs->appendNum(6, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeMode8($version) + { + try { + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x4); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size); + + for($i=0; $i<$this->size; $i++) { + $bs->appendNum(8, ord($this->data[$i])); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeKanji($version) + { + try { + + $bs = new QRbitrtream(); + + $bs->appendNum(4, 0x8); + $bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2)); + + for($i=0; $i<$this->size; $i+=2) { + $val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]); + if($val <= 0x9ffc) { + $val -= 0x8140; + } else { + $val -= 0xc140; + } + + $h = ($val >> 8) * 0xc0; + $val = ($val & 0xff) + $h; + + $bs->appendNum(13, $val); + } + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function encodeModeStructure() + { + try { + $bs = new QRbitstream(); + + $bs->appendNum(4, 0x03); + $bs->appendNum(4, ord($this->data[1]) - 1); + $bs->appendNum(4, ord($this->data[0]) - 1); + $bs->appendNum(8, ord($this->data[2])); + + $this->bstream = $bs; + return 0; + + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function estimateBitStreamSizeOfEntry($version) + { + $bits = 0; + + if($version == 0) + $version = 1; + + switch($this->mode) { + case QR_MODE_NUM: $bits = QRinput::estimateBitsModeNum($this->size); break; + case QR_MODE_AN: $bits = QRinput::estimateBitsModeAn($this->size); break; + case QR_MODE_8: $bits = QRinput::estimateBitsMode8($this->size); break; + case QR_MODE_KANJI: $bits = QRinput::estimateBitsModeKanji($this->size);break; + case QR_MODE_STRUCTURE: return STRUCTURE_HEADER_BITS; + default: + return 0; + } + + $l = QRspec::lengthIndicator($this->mode, $version); + $m = 1 << $l; + $num = (int)(($this->size + $m - 1) / $m); + + $bits += $num * (4 + $l); + + return $bits; + } + + //---------------------------------------------------------------------- + public function encodeBitStream($version) + { + try { + + unset($this->bstream); + $words = QRspec::maximumWords($this->mode, $version); + + if($this->size > $words) { + + $st1 = new QRinputItem($this->mode, $words, $this->data); + $st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words)); + + $st1->encodeBitStream($version); + $st2->encodeBitStream($version); + + $this->bstream = new QRbitstream(); + $this->bstream->append($st1->bstream); + $this->bstream->append($st2->bstream); + + unset($st1); + unset($st2); + + } else { + + $ret = 0; + + switch($this->mode) { + case QR_MODE_NUM: $ret = $this->encodeModeNum($version); break; + case QR_MODE_AN: $ret = $this->encodeModeAn($version); break; + case QR_MODE_8: $ret = $this->encodeMode8($version); break; + case QR_MODE_KANJI: $ret = $this->encodeModeKanji($version);break; + case QR_MODE_STRUCTURE: $ret = $this->encodeModeStructure(); break; + + default: + break; + } + + if($ret < 0) + return -1; + } + + return $this->bstream->size(); + + } catch (Exception $e) { + return -1; + } + } + }; + + //########################################################################## + + class QRinput { + + public $items; + + private $version; + private $level; + + //---------------------------------------------------------------------- + public function __construct($version = 0, $level = QR_ECLEVEL_L) + { + if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) { + throw new Exception('Invalid version no'); + return NULL; + } + + $this->version = $version; + $this->level = $level; + } + + //---------------------------------------------------------------------- + public function getVersion() + { + return $this->version; + } + + //---------------------------------------------------------------------- + public function setVersion($version) + { + if($version < 0 || $version > QRSPEC_VERSION_MAX) { + throw new Exception('Invalid version no'); + return -1; + } + + $this->version = $version; + + return 0; + } + + //---------------------------------------------------------------------- + public function getErrorCorrectionLevel() + { + return $this->level; + } + + //---------------------------------------------------------------------- + public function setErrorCorrectionLevel($level) + { + if($level > QR_ECLEVEL_H) { + throw new Exception('Invalid ECLEVEL'); + return -1; + } + + $this->level = $level; + + return 0; + } + + //---------------------------------------------------------------------- + public function appendEntry(QRinputItem $entry) + { + $this->items[] = $entry; + } + + //---------------------------------------------------------------------- + public function append($mode, $size, $data) + { + try { + $entry = new QRinputItem($mode, $size, $data); + $this->items[] = $entry; + return 0; + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + + public function insertStructuredAppendHeader($size, $index, $parity) + { + if( $size > MAX_STRUCTURED_SYMBOLS ) { + throw new Exception('insertStructuredAppendHeader wrong size'); + } + + if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) { + throw new Exception('insertStructuredAppendHeader wrong index'); + } + + $buf = array($size, $index, $parity); + + try { + $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf); + array_unshift($this->items, $entry); + return 0; + } catch (Exception $e) { + return -1; + } + } + + //---------------------------------------------------------------------- + public function calcParity() + { + $parity = 0; + + foreach($this->items as $item) { + if($item->mode != QR_MODE_STRUCTURE) { + for($i=$item->size-1; $i>=0; $i--) { + $parity ^= $item->data[$i]; + } + } + } + + return $parity; + } + + //---------------------------------------------------------------------- + public static function checkModeNum($size, $data) + { + for($i=0; $i<$size; $i++) { + if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){ + return false; + } + } + + return true; + } + + //---------------------------------------------------------------------- + public static function estimateBitsModeNum($size) + { + $w = (int)$size / 3; + $bits = $w * 10; + + switch($size - $w * 3) { + case 1: + $bits += 4; + break; + case 2: + $bits += 7; + break; + default: + break; + } + + return $bits; + } + + //---------------------------------------------------------------------- + public static $anTable = array( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + ); + + //---------------------------------------------------------------------- + public static function lookAnTable($c) + { + return (($c > 127)?-1:self::$anTable[$c]); + } + + //---------------------------------------------------------------------- + public static function checkModeAn($size, $data) + { + for($i=0; $i<$size; $i++) { + if (self::lookAnTable(ord($data[$i])) == -1) { + return false; + } + } + + return true; + } + + //---------------------------------------------------------------------- + public static function estimateBitsModeAn($size) + { + $w = (int)($size / 2); + $bits = $w * 11; + + if($size & 1) { + $bits += 6; + } + + return $bits; + } + + //---------------------------------------------------------------------- + public static function estimateBitsMode8($size) + { + return $size * 8; + } + + //---------------------------------------------------------------------- + public function estimateBitsModeKanji($size) + { + return (int)(($size / 2) * 13); + } + + //---------------------------------------------------------------------- + public static function checkModeKanji($size, $data) + { + if($size & 1) + return false; + + for($i=0; $i<$size; $i+=2) { + $val = (ord($data[$i]) << 8) | ord($data[$i+1]); + if( $val < 0x8140 + || ($val > 0x9ffc && $val < 0xe040) + || $val > 0xebbf) { + return false; + } + } + + return true; + } + + /*********************************************************************** + * Validation + **********************************************************************/ + + public static function check($mode, $size, $data) + { + if($size <= 0) + return false; + + switch($mode) { + case QR_MODE_NUM: return self::checkModeNum($size, $data); break; + case QR_MODE_AN: return self::checkModeAn($size, $data); break; + case QR_MODE_KANJI: return self::checkModeKanji($size, $data); break; + case QR_MODE_8: return true; break; + case QR_MODE_STRUCTURE: return true; break; + + default: + break; + } + + return false; + } + + + //---------------------------------------------------------------------- + public function estimateBitStreamSize($version) + { + $bits = 0; + + foreach($this->items as $item) { + $bits += $item->estimateBitStreamSizeOfEntry($version); + } + + return $bits; + } + + //---------------------------------------------------------------------- + public function estimateVersion() + { + $version = 0; + $prev = 0; + do { + $prev = $version; + $bits = $this->estimateBitStreamSize($prev); + $version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if ($version < 0) { + return -1; + } + } while ($version > $prev); + + return $version; + } + + //---------------------------------------------------------------------- + public static function lengthOfCode($mode, $version, $bits) + { + $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version); + switch($mode) { + case QR_MODE_NUM: + $chunks = (int)($payload / 10); + $remain = $payload - $chunks * 10; + $size = $chunks * 3; + if($remain >= 7) { + $size += 2; + } else if($remain >= 4) { + $size += 1; + } + break; + case QR_MODE_AN: + $chunks = (int)($payload / 11); + $remain = $payload - $chunks * 11; + $size = $chunks * 2; + if($remain >= 6) + $size++; + break; + case QR_MODE_8: + $size = (int)($payload / 8); + break; + case QR_MODE_KANJI: + $size = (int)(($payload / 13) * 2); + break; + case QR_MODE_STRUCTURE: + $size = (int)($payload / 8); + break; + default: + $size = 0; + break; + } + + $maxsize = QRspec::maximumWords($mode, $version); + if($size < 0) $size = 0; + if($size > $maxsize) $size = $maxsize; + + return $size; + } + + //---------------------------------------------------------------------- + public function createBitStream() + { + $total = 0; + + foreach($this->items as $item) { + $bits = $item->encodeBitStream($this->version); + + if($bits < 0) + return -1; + + $total += $bits; + } + + return $total; + } + + //---------------------------------------------------------------------- + public function convertData() + { + $ver = $this->estimateVersion(); + if($ver > $this->getVersion()) { + $this->setVersion($ver); + } + + for(;;) { + $bits = $this->createBitStream(); + + if($bits < 0) + return -1; + + $ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level); + if($ver < 0) { + throw new Exception('WRONG VERSION'); + return -1; + } else if($ver > $this->getVersion()) { + $this->setVersion($ver); + } else { + break; + } + } + + return 0; + } + + //---------------------------------------------------------------------- + public function appendPaddingBit(&$bstream) + { + $bits = $bstream->size(); + $maxwords = QRspec::getDataLength($this->version, $this->level); + $maxbits = $maxwords * 8; + + if ($maxbits == $bits) { + return 0; + } + + if ($maxbits - $bits < 5) { + return $bstream->appendNum($maxbits - $bits, 0); + } + + $bits += 4; + $words = (int)(($bits + 7) / 8); + + $padding = new QRbitstream(); + $ret = $padding->appendNum($words * 8 - $bits + 4, 0); + + if($ret < 0) + return $ret; + + $padlen = $maxwords - $words; + + if($padlen > 0) { + + $padbuf = array(); + for($i=0; $i<$padlen; $i++) { + $padbuf[$i] = ($i&1)?0x11:0xec; + } + + $ret = $padding->appendBytes($padlen, $padbuf); + + if($ret < 0) + return $ret; + + } + + $ret = $bstream->append($padding); + + return $ret; + } + + //---------------------------------------------------------------------- + public function mergeBitStream() + { + if($this->convertData() < 0) { + return null; + } + + $bstream = new QRbitstream(); + + foreach($this->items as $item) { + $ret = $bstream->append($item->bstream); + if($ret < 0) { + return null; + } + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function getBitStream() + { + + $bstream = $this->mergeBitStream(); + + if($bstream == null) { + return null; + } + + $ret = $this->appendPaddingBit($bstream); + if($ret < 0) { + return null; + } + + return $bstream; + } + + //---------------------------------------------------------------------- + public function getByteStream() + { + $bstream = $this->getBitStream(); + if($bstream == null) { + return null; + } + + return $bstream->toByte(); + } + } + + + \ No newline at end of file diff --git a/vendor/phpqrcode/qrlib.php b/vendor/phpqrcode/qrlib.php new file mode 100644 index 0000000..d55c4af --- /dev/null +++ b/vendor/phpqrcode/qrlib.php @@ -0,0 +1,43 @@ + + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + $QR_BASEDIR = dirname(__FILE__).DIRECTORY_SEPARATOR; + + // Required libs + + include $QR_BASEDIR."qrconst.php"; + include $QR_BASEDIR."qrconfig.php"; + include $QR_BASEDIR."qrtools.php"; + include $QR_BASEDIR."qrspec.php"; + include $QR_BASEDIR."qrimage.php"; + include $QR_BASEDIR."qrinput.php"; + include $QR_BASEDIR."qrbitstream.php"; + include $QR_BASEDIR."qrsplit.php"; + include $QR_BASEDIR."qrrscode.php"; + include $QR_BASEDIR."qrmask.php"; + include $QR_BASEDIR."qrencode.php"; + diff --git a/vendor/phpqrcode/qrmask.php b/vendor/phpqrcode/qrmask.php new file mode 100644 index 0000000..b14d7ae --- /dev/null +++ b/vendor/phpqrcode/qrmask.php @@ -0,0 +1,328 @@ + + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('N1', 3); + define('N2', 3); + define('N3', 40); + define('N4', 10); + + class QRmask { + + public $runLength = array(); + + //---------------------------------------------------------------------- + public function __construct() + { + $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0); + } + + //---------------------------------------------------------------------- + public function writeFormatInformation($width, &$frame, $mask, $level) + { + $blacks = 0; + $format = QRspec::getFormatInfo($mask, $level); + + for($i=0; $i<8; $i++) { + if($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + + $frame[8][$width - 1 - $i] = chr($v); + if($i < 6) { + $frame[$i][8] = chr($v); + } else { + $frame[$i + 1][8] = chr($v); + } + $format = $format >> 1; + } + + for($i=0; $i<7; $i++) { + if($format & 1) { + $blacks += 2; + $v = 0x85; + } else { + $v = 0x84; + } + + $frame[$width - 7 + $i][8] = chr($v); + if($i == 0) { + $frame[8][7] = chr($v); + } else { + $frame[8][6 - $i] = chr($v); + } + + $format = $format >> 1; + } + + return $blacks; + } + + //---------------------------------------------------------------------- + public function mask0($x, $y) { return ($x+$y)&1; } + public function mask1($x, $y) { return ($y&1); } + public function mask2($x, $y) { return ($x%3); } + public function mask3($x, $y) { return ($x+$y)%3; } + public function mask4($x, $y) { return (((int)($y/2))+((int)($x/3)))&1; } + public function mask5($x, $y) { return (($x*$y)&1)+($x*$y)%3; } + public function mask6($x, $y) { return ((($x*$y)&1)+($x*$y)%3)&1; } + public function mask7($x, $y) { return ((($x*$y)%3)+(($x+$y)&1))&1; } + + //---------------------------------------------------------------------- + private function generateMaskNo($maskNo, $width, $frame) + { + $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); + + for($y=0; $y<$width; $y++) { + for($x=0; $x<$width; $x++) { + if(ord($frame[$y][$x]) & 0x80) { + $bitMask[$y][$x] = 0; + } else { + $maskFunc = call_user_func(array($this, 'mask'.$maskNo), $x, $y); + $bitMask[$y][$x] = ($maskFunc == 0)?1:0; + } + + } + } + + return $bitMask; + } + + //---------------------------------------------------------------------- + public static function serial($bitFrame) + { + $codeArr = array(); + + foreach ($bitFrame as $line) + $codeArr[] = join('', $line); + + return gzcompress(join("\n", $codeArr), 9); + } + + //---------------------------------------------------------------------- + public static function unserial($code) + { + $codeArr = array(); + + $codeLines = explode("\n", gzuncompress($code)); + foreach ($codeLines as $line) + $codeArr[] = str_split($line); + + return $codeArr; + } + + //---------------------------------------------------------------------- + public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false) + { + $b = 0; + $bitMask = array(); + + $fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat'; + + if (QR_CACHEABLE) { + if (file_exists($fileName)) { + $bitMask = self::unserial(file_get_contents($fileName)); + } else { + $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); + if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo)) + mkdir(QR_CACHE_DIR.'mask_'.$maskNo); + file_put_contents($fileName, self::serial($bitMask)); + } + } else { + $bitMask = $this->generateMaskNo($maskNo, $width, $s, $d); + } + + if ($maskGenOnly) + return; + + $d = $s; + + for($y=0; $y<$width; $y++) { + for($x=0; $x<$width; $x++) { + if($bitMask[$y][$x] == 1) { + $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int)$bitMask[$y][$x]); + } + $b += (int)(ord($d[$y][$x]) & 1); + } + } + + return $b; + } + + //---------------------------------------------------------------------- + public function makeMask($width, $frame, $maskNo, $level) + { + $masked = array_fill(0, $width, str_repeat("\0", $width)); + $this->makeMaskNo($maskNo, $width, $frame, $masked); + $this->writeFormatInformation($width, $masked, $maskNo, $level); + + return $masked; + } + + //---------------------------------------------------------------------- + public function calcN1N3($length) + { + $demerit = 0; + + for($i=0; $i<$length; $i++) { + + if($this->runLength[$i] >= 5) { + $demerit += (N1 + ($this->runLength[$i] - 5)); + } + if($i & 1) { + if(($i >= 3) && ($i < ($length-2)) && ($this->runLength[$i] % 3 == 0)) { + $fact = (int)($this->runLength[$i] / 3); + if(($this->runLength[$i-2] == $fact) && + ($this->runLength[$i-1] == $fact) && + ($this->runLength[$i+1] == $fact) && + ($this->runLength[$i+2] == $fact)) { + if(($this->runLength[$i-3] < 0) || ($this->runLength[$i-3] >= (4 * $fact))) { + $demerit += N3; + } else if((($i+3) >= $length) || ($this->runLength[$i+3] >= (4 * $fact))) { + $demerit += N3; + } + } + } + } + } + return $demerit; + } + + //---------------------------------------------------------------------- + public function evaluateSymbol($width, $frame) + { + $head = 0; + $demerit = 0; + + for($y=0; $y<$width; $y++) { + $head = 0; + $this->runLength[0] = 1; + + $frameY = $frame[$y]; + + if ($y>0) + $frameYM = $frame[$y-1]; + + for($x=0; $x<$width; $x++) { + if(($x > 0) && ($y > 0)) { + $b22 = ord($frameY[$x]) & ord($frameY[$x-1]) & ord($frameYM[$x]) & ord($frameYM[$x-1]); + $w22 = ord($frameY[$x]) | ord($frameY[$x-1]) | ord($frameYM[$x]) | ord($frameYM[$x-1]); + + if(($b22 | ($w22 ^ 1))&1) { + $demerit += N2; + } + } + if(($x == 0) && (ord($frameY[$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } else if($x > 0) { + if((ord($frameY[$x]) ^ ord($frameY[$x-1])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + + $demerit += $this->calcN1N3($head+1); + } + + for($x=0; $x<$width; $x++) { + $head = 0; + $this->runLength[0] = 1; + + for($y=0; $y<$width; $y++) { + if($y == 0 && (ord($frame[$y][$x]) & 1)) { + $this->runLength[0] = -1; + $head = 1; + $this->runLength[$head] = 1; + } else if($y > 0) { + if((ord($frame[$y][$x]) ^ ord($frame[$y-1][$x])) & 1) { + $head++; + $this->runLength[$head] = 1; + } else { + $this->runLength[$head]++; + } + } + } + + $demerit += $this->calcN1N3($head+1); + } + + return $demerit; + } + + + //---------------------------------------------------------------------- + public function mask($width, $frame, $level) + { + $minDemerit = PHP_INT_MAX; + $bestMaskNum = 0; + $bestMask = array(); + + $checked_masks = array(0,1,2,3,4,5,6,7); + + if (QR_FIND_FROM_RANDOM !== false) { + + $howManuOut = 8-(QR_FIND_FROM_RANDOM % 9); + for ($i = 0; $i < $howManuOut; $i++) { + $remPos = rand (0, count($checked_masks)-1); + unset($checked_masks[$remPos]); + $checked_masks = array_values($checked_masks); + } + + } + + $bestMask = $frame; + + foreach($checked_masks as $i) { + $mask = array_fill(0, $width, str_repeat("\0", $width)); + + $demerit = 0; + $blacks = 0; + $blacks = $this->makeMaskNo($i, $width, $frame, $mask); + $blacks += $this->writeFormatInformation($width, $mask, $i, $level); + $blacks = (int)(100 * $blacks / ($width * $width)); + $demerit = (int)((int)(abs($blacks - 50) / 5) * N4); + $demerit += $this->evaluateSymbol($width, $mask); + + if($demerit < $minDemerit) { + $minDemerit = $demerit; + $bestMask = $mask; + $bestMaskNum = $i; + } + } + + return $bestMask; + } + + //---------------------------------------------------------------------- + } diff --git a/vendor/phpqrcode/qrrscode.php b/vendor/phpqrcode/qrrscode.php new file mode 100644 index 0000000..591129a --- /dev/null +++ b/vendor/phpqrcode/qrrscode.php @@ -0,0 +1,210 @@ + + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRrsItem { + + public $mm; // Bits per symbol + public $nn; // Symbols per block (= (1<= $this->nn) { + $x -= $this->nn; + $x = ($x >> $this->mm) + ($x & $this->nn); + } + + return $x; + } + + //---------------------------------------------------------------------- + public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) + { + // Common code for intializing a Reed-Solomon control block (char or int symbols) + // Copyright 2004 Phil Karn, KA9Q + // May be used under the terms of the GNU Lesser General Public License (LGPL) + + $rs = null; + + // Check parameter ranges + if($symsize < 0 || $symsize > 8) return $rs; + if($fcr < 0 || $fcr >= (1<<$symsize)) return $rs; + if($prim <= 0 || $prim >= (1<<$symsize)) return $rs; + if($nroots < 0 || $nroots >= (1<<$symsize)) return $rs; // Can't have more roots than symbol values! + if($pad < 0 || $pad >= ((1<<$symsize) -1 - $nroots)) return $rs; // Too much padding + + $rs = new QRrsItem(); + $rs->mm = $symsize; + $rs->nn = (1<<$symsize)-1; + $rs->pad = $pad; + + $rs->alpha_to = array_fill(0, $rs->nn+1, 0); + $rs->index_of = array_fill(0, $rs->nn+1, 0); + + // PHP style macro replacement ;) + $NN =& $rs->nn; + $A0 =& $NN; + + // Generate Galois field lookup tables + $rs->index_of[0] = $A0; // log(zero) = -inf + $rs->alpha_to[$A0] = 0; // alpha**-inf = 0 + $sr = 1; + + for($i=0; $i<$rs->nn; $i++) { + $rs->index_of[$sr] = $i; + $rs->alpha_to[$i] = $sr; + $sr <<= 1; + if($sr & (1<<$symsize)) { + $sr ^= $gfpoly; + } + $sr &= $rs->nn; + } + + if($sr != 1){ + // field generator polynomial is not primitive! + $rs = NULL; + return $rs; + } + + /* Form RS code generator polynomial from its roots */ + $rs->genpoly = array_fill(0, $nroots+1, 0); + + $rs->fcr = $fcr; + $rs->prim = $prim; + $rs->nroots = $nroots; + $rs->gfpoly = $gfpoly; + + /* Find prim-th root of 1, used in decoding */ + for($iprim=1;($iprim % $prim) != 0;$iprim += $rs->nn) + ; // intentional empty-body loop! + + $rs->iprim = (int)($iprim / $prim); + $rs->genpoly[0] = 1; + + for ($i = 0,$root=$fcr*$prim; $i < $nroots; $i++, $root += $prim) { + $rs->genpoly[$i+1] = 1; + + // Multiply rs->genpoly[] by @**(root + x) + for ($j = $i; $j > 0; $j--) { + if ($rs->genpoly[$j] != 0) { + $rs->genpoly[$j] = $rs->genpoly[$j-1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)]; + } else { + $rs->genpoly[$j] = $rs->genpoly[$j-1]; + } + } + // rs->genpoly[0] can never be zero + $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)]; + } + + // convert rs->genpoly[] to index form for quicker encoding + for ($i = 0; $i <= $nroots; $i++) + $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]]; + + return $rs; + } + + //---------------------------------------------------------------------- + public function encode_rs_char($data, &$parity) + { + $MM =& $this->mm; + $NN =& $this->nn; + $ALPHA_TO =& $this->alpha_to; + $INDEX_OF =& $this->index_of; + $GENPOLY =& $this->genpoly; + $NROOTS =& $this->nroots; + $FCR =& $this->fcr; + $PRIM =& $this->prim; + $IPRIM =& $this->iprim; + $PAD =& $this->pad; + $A0 =& $NN; + + $parity = array_fill(0, $NROOTS, 0); + + for($i=0; $i< ($NN-$NROOTS-$PAD); $i++) { + + $feedback = $INDEX_OF[$data[$i] ^ $parity[0]]; + if($feedback != $A0) { + // feedback term is non-zero + + // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must + // always be for the polynomials constructed by init_rs() + $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback); + + for($j=1;$j<$NROOTS;$j++) { + $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS-$j])]; + } + } + + // Shift + array_shift($parity); + if($feedback != $A0) { + array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]); + } else { + array_push($parity, 0); + } + } + } + } + + //########################################################################## + + class QRrs { + + public static $items = array(); + + //---------------------------------------------------------------------- + public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad) + { + foreach(self::$items as $rs) { + if($rs->pad != $pad) continue; + if($rs->nroots != $nroots) continue; + if($rs->mm != $symsize) continue; + if($rs->gfpoly != $gfpoly) continue; + if($rs->fcr != $fcr) continue; + if($rs->prim != $prim) continue; + + return $rs; + } + + $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad); + array_unshift(self::$items, $rs); + + return $rs; + } + } \ No newline at end of file diff --git a/vendor/phpqrcode/qrspec.php b/vendor/phpqrcode/qrspec.php new file mode 100644 index 0000000..92aea0c --- /dev/null +++ b/vendor/phpqrcode/qrspec.php @@ -0,0 +1,592 @@ + + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + define('QRSPEC_VERSION_MAX', 40); + define('QRSPEC_WIDTH_MAX', 177); + + define('QRCAP_WIDTH', 0); + define('QRCAP_WORDS', 1); + define('QRCAP_REMINDER', 2); + define('QRCAP_EC', 3); + + class QRspec { + + public static $capacity = array( + array( 0, 0, 0, array( 0, 0, 0, 0)), + array( 21, 26, 0, array( 7, 10, 13, 17)), // 1 + array( 25, 44, 7, array( 10, 16, 22, 28)), + array( 29, 70, 7, array( 15, 26, 36, 44)), + array( 33, 100, 7, array( 20, 36, 52, 64)), + array( 37, 134, 7, array( 26, 48, 72, 88)), // 5 + array( 41, 172, 7, array( 36, 64, 96, 112)), + array( 45, 196, 0, array( 40, 72, 108, 130)), + array( 49, 242, 0, array( 48, 88, 132, 156)), + array( 53, 292, 0, array( 60, 110, 160, 192)), + array( 57, 346, 0, array( 72, 130, 192, 224)), //10 + array( 61, 404, 0, array( 80, 150, 224, 264)), + array( 65, 466, 0, array( 96, 176, 260, 308)), + array( 69, 532, 0, array( 104, 198, 288, 352)), + array( 73, 581, 3, array( 120, 216, 320, 384)), + array( 77, 655, 3, array( 132, 240, 360, 432)), //15 + array( 81, 733, 3, array( 144, 280, 408, 480)), + array( 85, 815, 3, array( 168, 308, 448, 532)), + array( 89, 901, 3, array( 180, 338, 504, 588)), + array( 93, 991, 3, array( 196, 364, 546, 650)), + array( 97, 1085, 3, array( 224, 416, 600, 700)), //20 + array(101, 1156, 4, array( 224, 442, 644, 750)), + array(105, 1258, 4, array( 252, 476, 690, 816)), + array(109, 1364, 4, array( 270, 504, 750, 900)), + array(113, 1474, 4, array( 300, 560, 810, 960)), + array(117, 1588, 4, array( 312, 588, 870, 1050)), //25 + array(121, 1706, 4, array( 336, 644, 952, 1110)), + array(125, 1828, 4, array( 360, 700, 1020, 1200)), + array(129, 1921, 3, array( 390, 728, 1050, 1260)), + array(133, 2051, 3, array( 420, 784, 1140, 1350)), + array(137, 2185, 3, array( 450, 812, 1200, 1440)), //30 + array(141, 2323, 3, array( 480, 868, 1290, 1530)), + array(145, 2465, 3, array( 510, 924, 1350, 1620)), + array(149, 2611, 3, array( 540, 980, 1440, 1710)), + array(153, 2761, 3, array( 570, 1036, 1530, 1800)), + array(157, 2876, 0, array( 570, 1064, 1590, 1890)), //35 + array(161, 3034, 0, array( 600, 1120, 1680, 1980)), + array(165, 3196, 0, array( 630, 1204, 1770, 2100)), + array(169, 3362, 0, array( 660, 1260, 1860, 2220)), + array(173, 3532, 0, array( 720, 1316, 1950, 2310)), + array(177, 3706, 0, array( 750, 1372, 2040, 2430)) //40 + ); + + //---------------------------------------------------------------------- + public static function getDataLength($version, $level) + { + return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level]; + } + + //---------------------------------------------------------------------- + public static function getECCLength($version, $level) + { + return self::$capacity[$version][QRCAP_EC][$level]; + } + + //---------------------------------------------------------------------- + public static function getWidth($version) + { + return self::$capacity[$version][QRCAP_WIDTH]; + } + + //---------------------------------------------------------------------- + public static function getRemainder($version) + { + return self::$capacity[$version][QRCAP_REMINDER]; + } + + //---------------------------------------------------------------------- + public static function getMinimumVersion($size, $level) + { + + for($i=1; $i<= QRSPEC_VERSION_MAX; $i++) { + $words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level]; + if($words >= $size) + return $i; + } + + return -1; + } + + //###################################################################### + + public static $lengthTableBits = array( + array(10, 12, 14), + array( 9, 11, 13), + array( 8, 16, 16), + array( 8, 10, 12) + ); + + //---------------------------------------------------------------------- + public static function lengthIndicator($mode, $version) + { + if ($mode == QR_MODE_STRUCTURE) + return 0; + + if ($version <= 9) { + $l = 0; + } else if ($version <= 26) { + $l = 1; + } else { + $l = 2; + } + + return self::$lengthTableBits[$mode][$l]; + } + + //---------------------------------------------------------------------- + public static function maximumWords($mode, $version) + { + if($mode == QR_MODE_STRUCTURE) + return 3; + + if($version <= 9) { + $l = 0; + } else if($version <= 26) { + $l = 1; + } else { + $l = 2; + } + + $bits = self::$lengthTableBits[$mode][$l]; + $words = (1 << $bits) - 1; + + if($mode == QR_MODE_KANJI) { + $words *= 2; // the number of bytes is required + } + + return $words; + } + + // Error correction code ----------------------------------------------- + // Table of the error correction code (Reed-Solomon block) + // See Table 12-16 (pp.30-36), JIS X0510:2004. + + public static $eccTable = array( + array(array( 0, 0), array( 0, 0), array( 0, 0), array( 0, 0)), + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), // 1 + array(array( 1, 0), array( 1, 0), array( 1, 0), array( 1, 0)), + array(array( 1, 0), array( 1, 0), array( 2, 0), array( 2, 0)), + array(array( 1, 0), array( 2, 0), array( 2, 0), array( 4, 0)), + array(array( 1, 0), array( 2, 0), array( 2, 2), array( 2, 2)), // 5 + array(array( 2, 0), array( 4, 0), array( 4, 0), array( 4, 0)), + array(array( 2, 0), array( 4, 0), array( 2, 4), array( 4, 1)), + array(array( 2, 0), array( 2, 2), array( 4, 2), array( 4, 2)), + array(array( 2, 0), array( 3, 2), array( 4, 4), array( 4, 4)), + array(array( 2, 2), array( 4, 1), array( 6, 2), array( 6, 2)), //10 + array(array( 4, 0), array( 1, 4), array( 4, 4), array( 3, 8)), + array(array( 2, 2), array( 6, 2), array( 4, 6), array( 7, 4)), + array(array( 4, 0), array( 8, 1), array( 8, 4), array(12, 4)), + array(array( 3, 1), array( 4, 5), array(11, 5), array(11, 5)), + array(array( 5, 1), array( 5, 5), array( 5, 7), array(11, 7)), //15 + array(array( 5, 1), array( 7, 3), array(15, 2), array( 3, 13)), + array(array( 1, 5), array(10, 1), array( 1, 15), array( 2, 17)), + array(array( 5, 1), array( 9, 4), array(17, 1), array( 2, 19)), + array(array( 3, 4), array( 3, 11), array(17, 4), array( 9, 16)), + array(array( 3, 5), array( 3, 13), array(15, 5), array(15, 10)), //20 + array(array( 4, 4), array(17, 0), array(17, 6), array(19, 6)), + array(array( 2, 7), array(17, 0), array( 7, 16), array(34, 0)), + array(array( 4, 5), array( 4, 14), array(11, 14), array(16, 14)), + array(array( 6, 4), array( 6, 14), array(11, 16), array(30, 2)), + array(array( 8, 4), array( 8, 13), array( 7, 22), array(22, 13)), //25 + array(array(10, 2), array(19, 4), array(28, 6), array(33, 4)), + array(array( 8, 4), array(22, 3), array( 8, 26), array(12, 28)), + array(array( 3, 10), array( 3, 23), array( 4, 31), array(11, 31)), + array(array( 7, 7), array(21, 7), array( 1, 37), array(19, 26)), + array(array( 5, 10), array(19, 10), array(15, 25), array(23, 25)), //30 + array(array(13, 3), array( 2, 29), array(42, 1), array(23, 28)), + array(array(17, 0), array(10, 23), array(10, 35), array(19, 35)), + array(array(17, 1), array(14, 21), array(29, 19), array(11, 46)), + array(array(13, 6), array(14, 23), array(44, 7), array(59, 1)), + array(array(12, 7), array(12, 26), array(39, 14), array(22, 41)), //35 + array(array( 6, 14), array( 6, 34), array(46, 10), array( 2, 64)), + array(array(17, 4), array(29, 14), array(49, 10), array(24, 46)), + array(array( 4, 18), array(13, 32), array(48, 14), array(42, 32)), + array(array(20, 4), array(40, 7), array(43, 22), array(10, 67)), + array(array(19, 6), array(18, 31), array(34, 34), array(20, 61)),//40 + ); + + //---------------------------------------------------------------------- + // CACHEABLE!!! + + public static function getEccSpec($version, $level, array &$spec) + { + if (count($spec) < 5) { + $spec = array(0,0,0,0,0); + } + + $b1 = self::$eccTable[$version][$level][0]; + $b2 = self::$eccTable[$version][$level][1]; + $data = self::getDataLength($version, $level); + $ecc = self::getECCLength($version, $level); + + if($b2 == 0) { + $spec[0] = $b1; + $spec[1] = (int)($data / $b1); + $spec[2] = (int)($ecc / $b1); + $spec[3] = 0; + $spec[4] = 0; + } else { + $spec[0] = $b1; + $spec[1] = (int)($data / ($b1 + $b2)); + $spec[2] = (int)($ecc / ($b1 + $b2)); + $spec[3] = $b2; + $spec[4] = $spec[1] + 1; + } + } + + // Alignment pattern --------------------------------------------------- + + // Positions of alignment patterns. + // This array includes only the second and the third position of the + // alignment patterns. Rest of them can be calculated from the distance + // between them. + + // See Table 1 in Appendix E (pp.71) of JIS X0510:2004. + + public static $alignmentPattern = array( + array( 0, 0), + array( 0, 0), array(18, 0), array(22, 0), array(26, 0), array(30, 0), // 1- 5 + array(34, 0), array(22, 38), array(24, 42), array(26, 46), array(28, 50), // 6-10 + array(30, 54), array(32, 58), array(34, 62), array(26, 46), array(26, 48), //11-15 + array(26, 50), array(30, 54), array(30, 56), array(30, 58), array(34, 62), //16-20 + array(28, 50), array(26, 50), array(30, 54), array(28, 54), array(32, 58), //21-25 + array(30, 58), array(34, 62), array(26, 50), array(30, 54), array(26, 52), //26-30 + array(30, 56), array(34, 60), array(30, 58), array(34, 62), array(30, 54), //31-35 + array(24, 50), array(28, 54), array(32, 58), array(26, 54), array(30, 58), //35-40 + ); + + + /** -------------------------------------------------------------------- + * Put an alignment marker. + * @param frame + * @param width + * @param ox,oy center coordinate of the pattern + */ + public static function putAlignmentMarker(array &$frame, $ox, $oy) + { + $finder = array( + "\xa1\xa1\xa1\xa1\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa0\xa1\xa0\xa1", + "\xa1\xa0\xa0\xa0\xa1", + "\xa1\xa1\xa1\xa1\xa1" + ); + + $yStart = $oy-2; + $xStart = $ox-2; + + for($y=0; $y<5; $y++) { + QRstr::set($frame, $xStart, $yStart+$y, $finder[$y]); + } + } + + //---------------------------------------------------------------------- + public static function putAlignmentPattern($version, &$frame, $width) + { + if($version < 2) + return; + + $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0]; + if($d < 0) { + $w = 2; + } else { + $w = (int)(($width - self::$alignmentPattern[$version][0]) / $d + 2); + } + + if($w * $w - 3 == 1) { + $x = self::$alignmentPattern[$version][0]; + $y = self::$alignmentPattern[$version][0]; + self::putAlignmentMarker($frame, $x, $y); + return; + } + + $cx = self::$alignmentPattern[$version][0]; + for($x=1; $x<$w - 1; $x++) { + self::putAlignmentMarker($frame, 6, $cx); + self::putAlignmentMarker($frame, $cx, 6); + $cx += $d; + } + + $cy = self::$alignmentPattern[$version][0]; + for($y=0; $y<$w-1; $y++) { + $cx = self::$alignmentPattern[$version][0]; + for($x=0; $x<$w-1; $x++) { + self::putAlignmentMarker($frame, $cx, $cy); + $cx += $d; + } + $cy += $d; + } + } + + // Version information pattern ----------------------------------------- + + // Version information pattern (BCH coded). + // See Table 1 in Appendix D (pp.68) of JIS X0510:2004. + + // size: [QRSPEC_VERSION_MAX - 6] + + public static $versionPattern = array( + 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, + 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, + 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, + 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, + 0x27541, 0x28c69 + ); + + //---------------------------------------------------------------------- + public static function getVersionPattern($version) + { + if($version < 7 || $version > QRSPEC_VERSION_MAX) + return 0; + + return self::$versionPattern[$version -7]; + } + + // Format information -------------------------------------------------- + // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib) + + public static $formatInfo = array( + array(0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976), + array(0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0), + array(0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed), + array(0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b) + ); + + public static function getFormatInfo($mask, $level) + { + if($mask < 0 || $mask > 7) + return 0; + + if($level < 0 || $level > 3) + return 0; + + return self::$formatInfo[$level][$mask]; + } + + // Frame --------------------------------------------------------------- + // Cache of initial frames. + + public static $frames = array(); + + /** -------------------------------------------------------------------- + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ + public static function putFinderPattern(&$frame, $ox, $oy) + { + $finder = array( + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc1\xc1\xc1\xc0\xc1", + "\xc1\xc0\xc0\xc0\xc0\xc0\xc1", + "\xc1\xc1\xc1\xc1\xc1\xc1\xc1" + ); + + for($y=0; $y<7; $y++) { + QRstr::set($frame, $ox, $oy+$y, $finder[$y]); + } + } + + //---------------------------------------------------------------------- + public static function createFrame($version) + { + $width = self::$capacity[$version][QRCAP_WIDTH]; + $frameLine = str_repeat ("\0", $width); + $frame = array_fill(0, $width, $frameLine); + + // Finder pattern + self::putFinderPattern($frame, 0, 0); + self::putFinderPattern($frame, $width - 7, 0); + self::putFinderPattern($frame, 0, $width - 7); + + // Separator + $yOffset = $width - 7; + + for($y=0; $y<7; $y++) { + $frame[$y][7] = "\xc0"; + $frame[$y][$width - 8] = "\xc0"; + $frame[$yOffset][7] = "\xc0"; + $yOffset++; + } + + $setPattern = str_repeat("\xc0", 8); + + QRstr::set($frame, 0, 7, $setPattern); + QRstr::set($frame, $width-8, 7, $setPattern); + QRstr::set($frame, 0, $width - 8, $setPattern); + + // Format info + $setPattern = str_repeat("\x84", 9); + QRstr::set($frame, 0, 8, $setPattern); + QRstr::set($frame, $width - 8, 8, $setPattern, 8); + + $yOffset = $width - 8; + + for($y=0; $y<8; $y++,$yOffset++) { + $frame[$y][8] = "\x84"; + $frame[$yOffset][8] = "\x84"; + } + + // Timing pattern + + for($i=1; $i<$width-15; $i++) { + $frame[6][7+$i] = chr(0x90 | ($i & 1)); + $frame[7+$i][6] = chr(0x90 | ($i & 1)); + } + + // Alignment pattern + self::putAlignmentPattern($version, $frame, $width); + + // Version information + if($version >= 7) { + $vinf = self::getVersionPattern($version); + + $v = $vinf; + + for($x=0; $x<6; $x++) { + for($y=0; $y<3; $y++) { + $frame[($width - 11)+$y][$x] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + + $v = $vinf; + for($y=0; $y<6; $y++) { + for($x=0; $x<3; $x++) { + $frame[$y][$x+($width - 11)] = chr(0x88 | ($v & 1)); + $v = $v >> 1; + } + } + } + + // and a little bit... + $frame[$width - 8][8] = "\x81"; + + return $frame; + } + + //---------------------------------------------------------------------- + public static function debug($frame, $binary_mode = false) + { + if ($binary_mode) { + + foreach ($frame as &$frameLine) { + $frameLine = join('  ', explode('0', $frameLine)); + $frameLine = join('██', explode('1', $frameLine)); + } + + ?> + +


        '; + echo join("
        ", $frame); + echo '






'; + + } else { + + foreach ($frame as &$frameLine) { + $frameLine = join(' ', explode("\xc0", $frameLine)); + $frameLine = join('▒', explode("\xc1", $frameLine)); + $frameLine = join(' ', explode("\xa0", $frameLine)); + $frameLine = join('▒', explode("\xa1", $frameLine)); + $frameLine = join('◇', explode("\x84", $frameLine)); //format 0 + $frameLine = join('◆', explode("\x85", $frameLine)); //format 1 + $frameLine = join('☢', explode("\x81", $frameLine)); //special bit + $frameLine = join(' ', explode("\x90", $frameLine)); //clock 0 + $frameLine = join('◷', explode("\x91", $frameLine)); //clock 1 + $frameLine = join(' ', explode("\x88", $frameLine)); //version + $frameLine = join('▒', explode("\x89", $frameLine)); //version + $frameLine = join('♦', explode("\x01", $frameLine)); + $frameLine = join('⋅', explode("\0", $frameLine)); + } + + ?> + + "; + echo join("
", $frame); + echo "
"; + + } + } + + //---------------------------------------------------------------------- + public static function serial($frame) + { + return gzcompress(join("\n", $frame), 9); + } + + //---------------------------------------------------------------------- + public static function unserial($code) + { + return explode("\n", gzuncompress($code)); + } + + //---------------------------------------------------------------------- + public static function newFrame($version) + { + if($version < 1 || $version > QRSPEC_VERSION_MAX) + return null; + + if(!isset(self::$frames[$version])) { + + $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat'; + + if (QR_CACHEABLE) { + if (file_exists($fileName)) { + self::$frames[$version] = self::unserial(file_get_contents($fileName)); + } else { + self::$frames[$version] = self::createFrame($version); + file_put_contents($fileName, self::serial(self::$frames[$version])); + } + } else { + self::$frames[$version] = self::createFrame($version); + } + } + + if(is_null(self::$frames[$version])) + return null; + + return self::$frames[$version]; + } + + //---------------------------------------------------------------------- + public static function rsBlockNum($spec) { return $spec[0] + $spec[3]; } + public static function rsBlockNum1($spec) { return $spec[0]; } + public static function rsDataCodes1($spec) { return $spec[1]; } + public static function rsEccCodes1($spec) { return $spec[2]; } + public static function rsBlockNum2($spec) { return $spec[3]; } + public static function rsDataCodes2($spec) { return $spec[4]; } + public static function rsEccCodes2($spec) { return $spec[2]; } + public static function rsDataLength($spec) { return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]); } + public static function rsEccLength($spec) { return ($spec[0] + $spec[3]) * $spec[2]; } + + } \ No newline at end of file diff --git a/vendor/phpqrcode/qrsplit.php b/vendor/phpqrcode/qrsplit.php new file mode 100644 index 0000000..d75b827 --- /dev/null +++ b/vendor/phpqrcode/qrsplit.php @@ -0,0 +1,311 @@ + + * + * PHP QR Code is distributed under LGPL 3 + * Copyright (C) 2010 Dominik Dzienia + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + class QRsplit { + + public $dataStr = ''; + public $input; + public $modeHint; + + //---------------------------------------------------------------------- + public function __construct($dataStr, $input, $modeHint) + { + $this->dataStr = $dataStr; + $this->input = $input; + $this->modeHint = $modeHint; + } + + //---------------------------------------------------------------------- + public static function isdigitat($str, $pos) + { + if ($pos >= strlen($str)) + return false; + + return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9'))); + } + + //---------------------------------------------------------------------- + public static function isalnumat($str, $pos) + { + if ($pos >= strlen($str)) + return false; + + return (QRinput::lookAnTable(ord($str[$pos])) >= 0); + } + + //---------------------------------------------------------------------- + public function identifyMode($pos) + { + if ($pos >= strlen($this->dataStr)) + return QR_MODE_NUL; + + $c = $this->dataStr[$pos]; + + if(self::isdigitat($this->dataStr, $pos)) { + return QR_MODE_NUM; + } else if(self::isalnumat($this->dataStr, $pos)) { + return QR_MODE_AN; + } else if($this->modeHint == QR_MODE_KANJI) { + + if ($pos+1 < strlen($this->dataStr)) + { + $d = $this->dataStr[$pos+1]; + $word = (ord($c) << 8) | ord($d); + if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) { + return QR_MODE_KANJI; + } + } + } + + return QR_MODE_8; + } + + //---------------------------------------------------------------------- + public function eatNum() + { + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 0; + while(self::isdigitat($this->dataStr, $p)) { + $p++; + } + + $run = $p; + $mode = $this->identifyMode($p); + + if($mode == QR_MODE_8) { + $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln + + QRinput::estimateBitsMode8(1) // + 4 + l8 + - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 + if($dif > 0) { + return $this->eat8(); + } + } + if($mode == QR_MODE_AN) { + $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln + + QRinput::estimateBitsModeAn(1) // + 4 + la + - QRinput::estimateBitsModeAn($run + 1);// - 4 - la + if($dif > 0) { + return $this->eatAn(); + } + } + + $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eatAn() + { + $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 0; + + while(self::isalnumat($this->dataStr, $p)) { + if(self::isdigitat($this->dataStr, $p)) { + $q = $p; + while(self::isdigitat($this->dataStr, $q)) { + $q++; + } + + $dif = QRinput::estimateBitsModeAn($p) // + 4 + la + + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln + - QRinput::estimateBitsModeAn($q); // - 4 - la + + if($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + + $run = $p; + + if(!self::isalnumat($this->dataStr, $p)) { + $dif = QRinput::estimateBitsModeAn($run) + 4 + $la + + QRinput::estimateBitsMode8(1) // + 4 + l8 + - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 + if($dif > 0) { + return $this->eat8(); + } + } + + $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eatKanji() + { + $p = 0; + + while($this->identifyMode($p) == QR_MODE_KANJI) { + $p += 2; + } + + $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr)); + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function eat8() + { + $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); + $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); + + $p = 1; + $dataStrLen = strlen($this->dataStr); + + while($p < $dataStrLen) { + + $mode = $this->identifyMode($p); + if($mode == QR_MODE_KANJI) { + break; + } + if($mode == QR_MODE_NUM) { + $q = $p; + while(self::isdigitat($this->dataStr, $q)) { + $q++; + } + $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 + + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln + - QRinput::estimateBitsMode8($q); // - 4 - l8 + if($dif < 0) { + break; + } else { + $p = $q; + } + } else if($mode == QR_MODE_AN) { + $q = $p; + while(self::isalnumat($this->dataStr, $q)) { + $q++; + } + $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 + + QRinput::estimateBitsModeAn($q - $p) + 4 + $la + - QRinput::estimateBitsMode8($q); // - 4 - l8 + if($dif < 0) { + break; + } else { + $p = $q; + } + } else { + $p++; + } + } + + $run = $p; + $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr)); + + if($ret < 0) + return -1; + + return $run; + } + + //---------------------------------------------------------------------- + public function splitString() + { + while (strlen($this->dataStr) > 0) + { + if($this->dataStr == '') + return 0; + + $mode = $this->identifyMode(0); + + switch ($mode) { + case QR_MODE_NUM: $length = $this->eatNum(); break; + case QR_MODE_AN: $length = $this->eatAn(); break; + case QR_MODE_KANJI: + if ($hint == QR_MODE_KANJI) + $length = $this->eatKanji(); + else $length = $this->eat8(); + break; + default: $length = $this->eat8(); break; + + } + + if($length == 0) return 0; + if($length < 0) return -1; + + $this->dataStr = substr($this->dataStr, $length); + } + } + + //---------------------------------------------------------------------- + public function toUpper() + { + $stringLen = strlen($this->dataStr); + $p = 0; + + while ($p<$stringLen) { + $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint); + if($mode == QR_MODE_KANJI) { + $p += 2; + } else { + if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) { + $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); + } + $p++; + } + } + + return $this->dataStr; + } + + //---------------------------------------------------------------------- + public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true) + { + if(is_null($string) || $string == '\0' || $string == '') { + throw new Exception('empty string!!!'); + } + + $split = new QRsplit($string, $input, $modeHint); + + if(!$casesensitive) + $split->toUpper(); + + return $split->splitString(); + } + } \ No newline at end of file diff --git a/vendor/phpqrcode/qrtools.php b/vendor/phpqrcode/qrtools.php new file mode 100644 index 0000000..3012db4 --- /dev/null +++ b/vendor/phpqrcode/qrtools.php @@ -0,0 +1,172 @@ + + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + class QRtools { + + //---------------------------------------------------------------------- + public static function binarize($frame) + { + $len = count($frame); + foreach ($frame as &$frameLine) { + + for($i=0; $i<$len; $i++) { + $frameLine[$i] = (ord($frameLine[$i])&1)?'1':'0'; + } + } + + return $frame; + } + + //---------------------------------------------------------------------- + public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037') + { + $barcode_array = array(); + + if (!is_array($mode)) + $mode = explode(',', $mode); + + $eccLevel = 'L'; + + if (count($mode) > 1) { + $eccLevel = $mode[1]; + } + + $qrTab = QRcode::text($code, false, $eccLevel); + $size = count($qrTab); + + $barcode_array['num_rows'] = $size; + $barcode_array['num_cols'] = $size; + $barcode_array['bcode'] = array(); + + foreach ($qrTab as $line) { + $arrAdd = array(); + foreach(str_split($line) as $char) + $arrAdd[] = ($char=='1')?1:0; + $barcode_array['bcode'][] = $arrAdd; + } + + return $barcode_array; + } + + //---------------------------------------------------------------------- + public static function clearCache() + { + self::$frames = array(); + } + + //---------------------------------------------------------------------- + public static function buildCache() + { + QRtools::markTime('before_build_cache'); + + $mask = new QRmask(); + for ($a=1; $a <= QRSPEC_VERSION_MAX; $a++) { + $frame = QRspec::newFrame($a); + if (QR_IMAGE) { + $fileName = QR_CACHE_DIR.'frame_'.$a.'.png'; + QRimage::png(self::binarize($frame), $fileName, 1, 0); + } + + $width = count($frame); + $bitMask = array_fill(0, $width, array_fill(0, $width, 0)); + for ($maskNo=0; $maskNo<8; $maskNo++) + $mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true); + } + + QRtools::markTime('after_build_cache'); + } + + //---------------------------------------------------------------------- + public static function log($outfile, $err) + { + if (QR_LOG_DIR !== false) { + if ($err != '') { + if ($outfile !== false) { + file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); + } else { + file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND); + } + } + } + } + + //---------------------------------------------------------------------- + public static function dumpMask($frame) + { + $width = count($frame); + for($y=0;$y<$width;$y++) { + for($x=0;$x<$width;$x++) { + echo ord($frame[$y][$x]).','; + } + } + } + + //---------------------------------------------------------------------- + public static function markTime($markerId) + { + list($usec, $sec) = explode(" ", microtime()); + $time = ((float)$usec + (float)$sec); + + if (!isset($GLOBALS['qr_time_bench'])) + $GLOBALS['qr_time_bench'] = array(); + + $GLOBALS['qr_time_bench'][$markerId] = $time; + } + + //---------------------------------------------------------------------- + public static function timeBenchmark() + { + self::markTime('finish'); + + $lastTime = 0; + $startTime = 0; + $p = 0; + + echo ' + + '; + + foreach($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) { + if ($p > 0) { + echo ''; + } else { + $startTime = $thisTime; + } + + $p++; + $lastTime = $thisTime; + } + + echo ' + + +
BENCHMARK
till '.$markerId.': '.number_format($thisTime-$lastTime, 6).'s
TOTAL: '.number_format($lastTime-$startTime, 6).'s
'; + } + + } + + //########################################################################## + + QRtools::markTime('start'); + \ No newline at end of file diff --git a/vendor/phpqrcode/tools/merge.bat b/vendor/phpqrcode/tools/merge.bat new file mode 100644 index 0000000..b60a485 --- /dev/null +++ b/vendor/phpqrcode/tools/merge.bat @@ -0,0 +1,2 @@ +php ./merge.php +pause \ No newline at end of file diff --git a/vendor/phpqrcode/tools/merge.php b/vendor/phpqrcode/tools/merge.php new file mode 100644 index 0000000..19d338b --- /dev/null +++ b/vendor/phpqrcode/tools/merge.php @@ -0,0 +1,70 @@ + + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + $QR_BASEDIR = dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR; + $QR_TOOLSDIR = dirname(__FILE__).DIRECTORY_SEPARATOR; + + $outputFile = $QR_BASEDIR.'phpqrcode.php'; + + // Required libs + + $fileList = array( + $QR_BASEDIR.'qrconst.php', + $QR_TOOLSDIR.'merged_config.php', + $QR_BASEDIR.'qrtools.php', + $QR_BASEDIR.'qrspec.php', + $QR_BASEDIR.'qrimage.php', + $QR_BASEDIR.'qrinput.php', + $QR_BASEDIR.'qrbitstream.php', + $QR_BASEDIR.'qrsplit.php', + $QR_BASEDIR.'qrrscode.php', + $QR_BASEDIR.'qrmask.php', + $QR_BASEDIR.'qrencode.php' + ); + + $headerFile = $QR_TOOLSDIR.'merged_header.php'; + $versionFile = $QR_BASEDIR.'VERSION'; + + $outputCode = ''; + + foreach($fileList as $fileName) { + $outputCode .= "\n\n".'//---- '.basename($fileName).' -----------------------------'."\n\n"; + $anotherCode = file_get_contents($fileName); + $anotherCode = preg_replace ('/^<\?php/', '', $anotherCode); + $anotherCode = preg_replace ('/\?>\*$/', '', $anotherCode); + $outputCode .= "\n\n".$anotherCode."\n\n"; + } + + $versionDataEx = explode("\n", file_get_contents($versionFile)); + + $outputContents = file_get_contents($headerFile); + $outputContents .= "\n\n/*\n * Version: ".trim($versionDataEx[0])."\n * Build: ".trim($versionDataEx[1])."\n */\n\n"; + $outputContents .= $outputCode; + + file_put_contents($outputFile, $outputContents); + + \ No newline at end of file diff --git a/vendor/phpqrcode/tools/merge.sh b/vendor/phpqrcode/tools/merge.sh new file mode 100644 index 0000000..e4c2fbc --- /dev/null +++ b/vendor/phpqrcode/tools/merge.sh @@ -0,0 +1,2 @@ +#!/bin/sh +php ./merge.php \ No newline at end of file diff --git a/vendor/phpqrcode/tools/merged_config.php b/vendor/phpqrcode/tools/merged_config.php new file mode 100644 index 0000000..55ddb45 --- /dev/null +++ b/vendor/phpqrcode/tools/merged_config.php @@ -0,0 +1,17 @@ + + * + * 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 3 of the License, or 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + \ No newline at end of file