[SPIP] ~maj v3.2.9-->v3.2.11
authorLudovic CHEVALIER <ludovic@beurresarrasin.net>
Thu, 8 Apr 2021 09:36:41 +0000 (11:36 +0200)
committerLudovic CHEVALIER <ludovic@beurresarrasin.net>
Thu, 8 Apr 2021 09:36:41 +0000 (11:36 +0200)
134 files changed:
www/CHANGELOG.TXT
www/config/ecran_securite.php
www/ecrire/auth/sha256.inc.php
www/ecrire/balise/url_.php
www/ecrire/base/connect_sql.php
www/ecrire/base/upgrade.php
www/ecrire/genie/optimiser.php
www/ecrire/inc/charsets.php
www/ecrire/inc/config.php
www/ecrire/inc/filtres.php
www/ecrire/inc/filtres_images_lib_mini.php
www/ecrire/inc/idna_convert.class.php
www/ecrire/inc/math.php
www/ecrire/inc/plonger.php
www/ecrire/inc/plugin.php
www/ecrire/inc/session.php
www/ecrire/inc/utils.php
www/ecrire/inc/xml.php
www/ecrire/inc_version.php
www/ecrire/install/etape_chmod.php
www/ecrire/iterateur/data.php
www/ecrire/paquet.xml
www/ecrire/public/assembler.php
www/ecrire/public/balises.php
www/ecrire/public/compiler.php
www/ecrire/public/composer.php
www/ecrire/public/iterateur.php
www/ecrire/public/quete.php
www/ecrire/public/references.php
www/ecrire/req/mysql.php
www/ecrire/req/sqlite_generique.php
www/plugins-dist/breves/breves_pipelines.php
www/plugins-dist/compresseur/inc/compresseur_embarquer.php
www/plugins-dist/compresseur/lib/csstidy/NEWS [deleted file]
www/plugins-dist/compresseur/lib/csstidy/README.md
www/plugins-dist/compresseur/lib/csstidy/class.csstidy.php
www/plugins-dist/compresseur/lib/csstidy/class.csstidy_optimise.php
www/plugins-dist/compresseur/lib/csstidy/class.csstidy_print.php
www/plugins-dist/compresseur/lib/csstidy/data.inc.php
www/plugins-dist/compresseur/paquet.xml
www/plugins-dist/medias/action/editer_document.php
www/plugins-dist/medias/lib/getid3/extension.cache.dbm.php
www/plugins-dist/medias/lib/getid3/extension.cache.mysql.php
www/plugins-dist/medias/lib/getid3/extension.cache.mysqli.php
www/plugins-dist/medias/lib/getid3/extension.cache.sqlite3.php
www/plugins-dist/medias/lib/getid3/getid3.lib.php
www/plugins-dist/medias/lib/getid3/getid3.php
www/plugins-dist/medias/lib/getid3/module.archive.gzip.php
www/plugins-dist/medias/lib/getid3/module.archive.rar.php
www/plugins-dist/medias/lib/getid3/module.archive.szip.php
www/plugins-dist/medias/lib/getid3/module.archive.tar.php
www/plugins-dist/medias/lib/getid3/module.archive.zip.php
www/plugins-dist/medias/lib/getid3/module.audio-video.asf.php
www/plugins-dist/medias/lib/getid3/module.audio-video.bink.php
www/plugins-dist/medias/lib/getid3/module.audio-video.flv.php
www/plugins-dist/medias/lib/getid3/module.audio-video.matroska.php
www/plugins-dist/medias/lib/getid3/module.audio-video.mpeg.php
www/plugins-dist/medias/lib/getid3/module.audio-video.nsv.php
www/plugins-dist/medias/lib/getid3/module.audio-video.quicktime.php
www/plugins-dist/medias/lib/getid3/module.audio-video.real.php
www/plugins-dist/medias/lib/getid3/module.audio-video.riff.php
www/plugins-dist/medias/lib/getid3/module.audio-video.swf.php
www/plugins-dist/medias/lib/getid3/module.audio-video.ts.php
www/plugins-dist/medias/lib/getid3/module.audio.aa.php
www/plugins-dist/medias/lib/getid3/module.audio.aac.php
www/plugins-dist/medias/lib/getid3/module.audio.ac3.php
www/plugins-dist/medias/lib/getid3/module.audio.amr.php
www/plugins-dist/medias/lib/getid3/module.audio.au.php
www/plugins-dist/medias/lib/getid3/module.audio.avr.php
www/plugins-dist/medias/lib/getid3/module.audio.bonk.php
www/plugins-dist/medias/lib/getid3/module.audio.dsf.php
www/plugins-dist/medias/lib/getid3/module.audio.dss.php
www/plugins-dist/medias/lib/getid3/module.audio.dts.php
www/plugins-dist/medias/lib/getid3/module.audio.flac.php
www/plugins-dist/medias/lib/getid3/module.audio.la.php
www/plugins-dist/medias/lib/getid3/module.audio.lpac.php
www/plugins-dist/medias/lib/getid3/module.audio.midi.php
www/plugins-dist/medias/lib/getid3/module.audio.mod.php
www/plugins-dist/medias/lib/getid3/module.audio.monkey.php
www/plugins-dist/medias/lib/getid3/module.audio.mp3.php
www/plugins-dist/medias/lib/getid3/module.audio.mpc.php
www/plugins-dist/medias/lib/getid3/module.audio.ogg.php
www/plugins-dist/medias/lib/getid3/module.audio.optimfrog.php
www/plugins-dist/medias/lib/getid3/module.audio.rkau.php
www/plugins-dist/medias/lib/getid3/module.audio.shorten.php
www/plugins-dist/medias/lib/getid3/module.audio.tta.php
www/plugins-dist/medias/lib/getid3/module.audio.voc.php
www/plugins-dist/medias/lib/getid3/module.audio.vqf.php
www/plugins-dist/medias/lib/getid3/module.audio.wavpack.php
www/plugins-dist/medias/lib/getid3/module.graphic.bmp.php
www/plugins-dist/medias/lib/getid3/module.graphic.efax.php
www/plugins-dist/medias/lib/getid3/module.graphic.gif.php
www/plugins-dist/medias/lib/getid3/module.graphic.jpg.php
www/plugins-dist/medias/lib/getid3/module.graphic.pcd.php
www/plugins-dist/medias/lib/getid3/module.graphic.png.php
www/plugins-dist/medias/lib/getid3/module.graphic.svg.php
www/plugins-dist/medias/lib/getid3/module.graphic.tiff.php
www/plugins-dist/medias/lib/getid3/module.misc.cue.php
www/plugins-dist/medias/lib/getid3/module.misc.exe.php
www/plugins-dist/medias/lib/getid3/module.misc.iso.php
www/plugins-dist/medias/lib/getid3/module.misc.msoffice.php
www/plugins-dist/medias/lib/getid3/module.misc.par2.php
www/plugins-dist/medias/lib/getid3/module.misc.pdf.php
www/plugins-dist/medias/lib/getid3/module.tag.apetag.php
www/plugins-dist/medias/lib/getid3/module.tag.id3v1.php
www/plugins-dist/medias/lib/getid3/module.tag.id3v2.php
www/plugins-dist/medias/lib/getid3/module.tag.lyrics3.php
www/plugins-dist/medias/lib/getid3/module.tag.xmp.php
www/plugins-dist/medias/lib/getid3/write.apetag.php
www/plugins-dist/medias/lib/getid3/write.id3v1.php
www/plugins-dist/medias/lib/getid3/write.id3v2.php
www/plugins-dist/medias/lib/getid3/write.php
www/plugins-dist/medias/lib/mejs/package.js [changed mode: 0644->0755]
www/plugins-dist/medias/lib/mejs/package.json [changed mode: 0644->0755]
www/plugins-dist/medias/paquet.xml
www/plugins-dist/medias/prive/squelettes/inclure/portfolio-documents.html
www/plugins-dist/organiseur/inc/quete_calendrier.php
www/plugins-dist/revisions/inc/diff.php
www/plugins-dist/revisions/inc/revisions.php
www/plugins-dist/safehtml/lib/safehtml/classes/HTMLSax3.php
www/plugins-dist/safehtml/lib/safehtml/classes/safehtml.php
www/plugins-dist/svp/inc/svp_outiller.php
www/plugins-dist/svp/svp_fonctions.php
www/plugins-dist/textwheel/engine/textwheel.php
www/plugins-dist/textwheel/engine/textwheelrule.php
www/plugins-dist/textwheel/inc/texte.php
www/plugins-dist/textwheel/lib/yaml/sfYamlInline.php
www/plugins-dist/textwheel/paquet.xml
www/prive/formulaires/login.html
www/prive/formulaires/login.php
www/prive/javascript/js.cookie.js [changed mode: 0644->0755]
www/prive/objets/infos/auteur.html
www/prive/objets/liste/auteurs_fonctions.php
www/prive/squelettes/inclure/admin_vider_cache.html

index d9db953..f69be25 100644 (file)
- SPIP-Core v3.2.8 -> v3.2.9 (12 février 2021)
- ---------------------------------------------
-
- c965889bc | cedric        | 2021-02-10 | Fix #4316 : la PR a ete fermee sur github quand on est passe a git.spip.net je suppose
- c76c39a6e | cedric        | 2021-02-10 | nonsense code, copie colle surement, fix #4315
- 93a917a4d | cedric        | 2021-02-10 | Fix #4140 (deja fixe en 3.3)
- 7246f1966 | cedric        | 2021-02-08 | Fix #3869 (ou du moins on espere, sinon c'est pas si grave)
- 55bc9fd5d | erational     | 2021-02-08 | [bugfix] empecher warning sur le count de l'iterateur devrait resoudre le ticket https://core.spip.net/issues/4450 et ..
- 42898eb47 | rastapopoulos | 2021-02-05 | Corrige 4401 en améliorant la rustine déjà en place
- 24eda3678 | cedric        | 2021-02-05 | nettoyer l'adresse site qu'on enregistre fix #4629
- bb69f3466 | bruno         | 2021-02-05 | ne pas stocker le champ ldap_password dans les fichiers de session
- 2269d0a6a | cedric        | 2021-02-01 | appels a autoriser sur les formulaires editer, a minima quand on les utilise en modification d'un objet existant depui..
- 610c24f06 | cedric        | 2021-02-02 | Eviter d'utiliser une globale, gerer le flag en static avec operations de lecture+reset
- a8493a3ce | cedric        | 2021-02-01 | Eviter de donner sa langue au chat
- f9d9e5b1a | cedric        | 2021-02-01 | on accepte pas une fonction de config inconnue si elle vient d'un modele
- 962a95f44 | cedric        | 2021-02-01 | Utiliser contexte_compil pour reperer les appels a executer_balise_dynamique() venant d'un modele, et lever un flag le..
- c35edb769 | cedric        | 2021-02-01 | une fonction pour detecter qu'un formulaire a ete inclu via un modele et non directement via une balide #FORMULAIRE_xxx
- 577ad8d21 | bruno         | 2021-01-21 | Ã©viter d'afficher n'importe quoi dans le message d'édition concurrente
- f1f27e9f7 | bruno         | 2021-02-01 | attribut_html() sur les attributs renvoyés par env_to_params() & env_to_attributs()
- 6c6b6c6d4 | nicod         | 2021-01-06 | Stocker les contextes dans des fichiers en cache si la longueur de l’argument géneré est plus long que ce qui est tolé..
- 2be11db95 | bruno         | 2020-10-25 | fix undefined index sur l'action réparation de la base
-
-
-
- SPIP-plugins-dist v3.2.8 -> v3.2.9 (12 février 2021)
- -----------------------------------------------------
-
- breves                  | ba1e040 | cedric       | 2021-02-04 | verifier l'autorisation de modifier la breve passe en argument
- mediabox                | 9020d16 | cedric       | 2021-02-08 | #4625 : echapper les valeurs injectees dans le js via les parametres mediabox, c'est plus propre
- medias                  | 96bf7b2 | cedric       | 2021-02-04 | Verifier l'autorisation de modifier les documents passes en argument du formulaire
- medias                  | bfc3319 | cedric       | 2021-01-20 | Report de 049dee8 : Extraire la fonction de determination automatique du statut d'un document dans une fonction inc_de..
- medias                  | 9764525 | cedric       | 2021-01-19 | Normaliser le comportement de document_instituer() en appelant les pipelines pre_editon et post_edition avec action=in..
- medias                  | 2293b84 | tcharlss     | 2021-01-19 | Report de 890506eb99 : Pour le JS des modes d'affichages, cibler plus précisément l'élément, sinon les boutons peuvent..
- mots                    | 0955e0d | cedric       | 2021-02-04 | Verifier les autorisations de modifier les mots/groupes de mots passes en argument du formulaire d'edition
- revisions               | e573977 | bruno        | 2020-10-23 | Ã©viter un warning dans les révisions lors de la suppression d'un lien par une personne non identifiée
- sites                   | 28bdb59 | cedric       | 2021-02-10 | Fix #4296 : l'url peut etre dans le href meme si c'est pas un link autofermant...
- sites                   | 92994f3 | cedric       | 2021-02-04 | verifier l'autorisation de modifier le site passe en argument du formulaire d'edition
- sites                   | 638ceef | cedric       | 2020-12-18 | Fix le id_mot manquant sur les syndic_articles. Ce n'est pas un usage frequent, mais il existe et soyons homogene avec..
- textwheel               | 317b045 | rastapopoulos | 2021-02-05 | Correction de 4508 : on ne gère le caption/summary *réellement* qu'en première ligne, seulement si on n'a pas déjà gén..
+SPIP-Core v3.2.10 -> v3.2.11 (26 March 2021)
+--------------------------------------------
+
+b52a4a5b3 | cedric       | 2021-03-12 | twitterbot est aussi notre ami pour le laisser scraper l'url qu'on veut touitter (fil)
+58d5d6190 | cedric       | 2021-02-15 | Report de https://git.spip.net/spip-contrib-outils/securite/commit/e7b571681a92eb40eddabbbb24b45dc472e113c1 qui fix #4..
+6611fd50b | cedric       | 2021-02-15 | Report de https://git.spip.net/spip-contrib-outils/securite/commit/3eccaf41426d4f3c8f28b50d81e12fbe5f8af4c2
+62d33c975 | marcimat     | 2021-03-26 | Notice-- : Attribut sans ses quotes... (realet)
+
+
+
+SPIP-Core v3.2.9 -> v3.2.10 (26 mars 2021)
+-------------------------------------------
+
+0b1bd0542 | marcimat      | 2018-09-05 | Compat PHP 7.x : Scorie résiduelle du passage Ã  mysqli. Mais ces fonctions ne semblent plus utilisées.
+7621a660a | marcimat      | 2021-03-19 | Retour partiel sur 31df72005 pour compat PHP 5.4 ...
+4de4b3c34 | marcimat      | 2021-03-19 | Correction deprecated php 7.4 : ordre de join inversé.
+0ea620c9a | marcimat      | 2018-09-05 | Tickets #4059 et #4138 : meilleure compat PHP 7.2
+f69b39c9e | marcimat      | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+a54ab9a89 | rastapopoulos | 2021-03-14 | Backport de 2e55e3a60e Ã  la main car plus dans le même fichier en 3.3.
+bdc53dcc9 | marcimat      | 2021-03-11 | Lorsqu'on déclare un traitement Ã  un champ de rubrique, tel que `$table_des_traitements['DEMO']['rubriques'] = ...`, c..
+510983b09 | cedric        | 2021-03-09 | Fix https://core.spip.net/issues/4442 : le vieux parseur xml a la main (qu'il faudrait virer) ne tolerait pas l'utilis..
+31df72005 | marcimat      | 2021-03-05 | Suite de e11b28be4 : plus Ã©viter une fatale en PHP 8 si unicode2charset cherche Ã  utiliser un charset inexistant
+00c2038da | marcimat      | 2021-03-05 | Correction d'une Fatale Suite Ã  27e4f1bcc. C'est sport mais le commit ajoute des accents dans le squelettes prive/sque..
+e380b0afd | cy.altern     | 2021-03-04 | report a4cdf3b633
+916b67198 | marcimat      | 2021-03-04 | Ticket #4348 : Compat PHP 7.4 (deprecated curly braces array)
+910c245ea | marcimat      | 2020-03-26 | Compat PHP 7.4 : Ã©viter une notice lorsque la pagination ne trouve aucune entrée.
+1b5549e51 | marcimat      | 2019-08-26 | Ticket #4348 : Compat PHP 7.4 (notice).
+c5492ea3e | marcimat      | 2019-08-26 | Ticket #4348 : Compat PHP 7.4 (deprecated curly braces array)
+da6dfc068 | marcimat      | 2019-08-26 | Ticket #4348 : Compat PHP 7.4, Trying to access array offset on value of type null.
+db1814dc5 | marcimat      | 2019-08-25 | Compat PHP 7.4, Deprecated:  Array and string offset access syntax with curly braces (Francky)
+330eb930f | marcimat      | 2019-06-17 | Ticket #4348 : Correction pour PHP 7.4 (Left-associative ternary operator deprecation)
+130ada180 | marcimat      | 2018-02-09 | Compatibilité PHP 7.2 : create_function => function xxx each => key, current, next
+8075d79f2 | marcimat      | 2017-12-11 |  Ticket #4059 : Compat PHP 7.2, remplacer un create_function.
+061107f80 | marcimat      | 2017-12-11 | Ticket #4059 : Compat PHP 7.2, remplacer des create_function.
+af94fa5d9 | marcimat      | 2017-12-11 | Ticket #4059 : Compat PHP 7.2, remplacer des create_function. (encore un eval du coup).
+e7fe0d5aa | marcimat      | 2017-12-11 | Ticket #4059 : Compat PHP 7.2, remplacer des create_function.
+49f24e83b | marcimat      | 2017-12-11 | Ticket #4059 : Compat PHP 7.2. Un create_function de moins. Pour le coup, Ã§a semble obligé ici de conserver une Ã©valua..
+6555cb7b4 | marcimat      | 2021-03-04 | Report adapté de 5647069fb (Meilleure compat PHP 7.3)
+fcb3e1f5e | marcimat      | 2019-08-21 | Ticket #4348 : Notices/Warning en PHP 7.3+ : Ã©viter un appel Ã  time() avec un argument.
+31c614782 | bruno         | 2020-03-13 | report adapté de a0c24ecb6f8c1d70dce86b859eb448fb0415d869
+60d4d3d1f | cedric        | 2021-02-17 | Fix vraiment #4167 : _deja_loge peut contenir un js de redirection et doit donc etre non filtre par interdire_scripts()
+7046e391d | cedric        | 2021-02-17 | Fix #4387 : Revert "Fix #4167 : Ã©viter d'afficher le script de redirection js quand le form de login est utilisé en aj..
+03cc99fce | cedric        | 2021-02-17 | Fix l'utilisation du niveau de log 0 (maieul) cf https://git.spip.net/spip/spip/pulls/106
+62e4284fd | bruno         | 2021-02-10 | Ã©viter un plantage avec url_page quand on utilise une fonction perso pour generer_generer_url_XXX
+0281d90f2 | maieul        | 2021-02-10 | fix #4633, ne pas passer une date quotée au pipeline optimiser_base_disparus
+
+
+SPIP-plugins-dist v3.2.9 -> v3.2.10 (26 mars 2021)
+---------------------------------------------------
+
+aide                    | 329cfce | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+archiviste              | de3283f | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+breves                  | 668efb9 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+breves                  | 658f025 | maieul       | 2021-02-10 | Adaptation du code au fix du core https://core.spip.net/issues/4633
+compagnon               | d8aaa96 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+compresseur             | 08b96ff | marcimat     | 2021-03-24 | Mise Ã  jour de CSSTidy en version 1.7.3
+compresseur             | 30d1b1f | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+compresseur             | 827ba88 | marcimat     | 2018-09-05 | Tickets #4059 et #4138 : meilleure compat PHP 7.2
+dump                    | d767e27 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+filtres_images          | eb9ace8 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+forum                   | cb90b1a | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+jquery_ui               | b04572e | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+mediabox                | bcadf3d | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+medias                  | d096d93 | marcimat     | 2021-03-26 | Report de d1ca0c8c : Suite de 890506eb99 : Il faut ajouteur la classe .portfolios__titre aux autres blocs documents du..
+medias                  | 4e13bea | cedric       | 2021-03-25 | Fix regression (Maieul via https://git.spip.net/spip/medias/pulls/17)
+medias                  | 1d917cd | spip.franck  | 2020-07-12 | - Mise Ã  jour de la lib getid3 en 1.9.20, nous Ã©tions en 1.9.18 - Le changelog est dispo ici: https://github.com/James..
+medias                  | e019d3e | spip.franck  | 2019-09-20 | Mise Ã  jour de la lib getid3 en 1.9.18, nous Ã©tions en 1.9.16. Le changelog est dispo ici: https://github.com/JamesHei..
+medias                  | 2dc03d5 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+mots                    | 6a346ba | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+organiseur              | a7177ba | marcimat     | 2021-03-19 | Correction join Ã  l'envers.
+organiseur              | 7c665fc | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+petitions               | 2909a25 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+plan                    | e722c87 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+porte_plume             | 0003d09 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+revisions               | 1d88a68 | bruno        | 2018-09-15 | retour sur r111482 : Ã©viter une erreur Maximum execution time
+revisions               | 2f2d47c | marcimat     | 2018-09-05 | Tickets #4059 et #4138 : meilleure compat PHP 7.2
+revisions               | 535cb2f | marcimat     | 2018-09-15 | Correction sur r111486 (compat PHP 7.2, suppression each()) qui Ã©tait erronné.
+revisions               | aa56bf3 | marcimat     | 2018-09-05 | Ticket #4138 : Compatibilité PHP 7.2
+revisions               | df4b821 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+revisions               | 19c0b6c | marcimat     | 2019-08-21 | Ticket #4348 : Compat PHP 7.4+ Deprecated: The behavior of unparenthesized expressions containing both '.' and '+'/'-'
+safehtml                | b2853a1 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+safehtml                | 6e81e13 | marcimat     | 2019-08-26 | Tiket #4348 / Compat PHP 7.4 : Array and string offset access syntax with curly braces is deprecated
+sites                   | 622387c | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+squelettes_par_rubrique | 357b283 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+statistiques            | 291386b | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+svp                     | a3c6abf | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+svp                     | 9fd9349 | marcimat     | 2019-08-25 | Compat PHP 7.4, Deprecated:  Array and string offset access syntax with curly braces (Francky)
+textwheel               | 8f70594 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+textwheel               | 84d32c5 | cedric       | 2018-09-06 | create_function est deprecie en PHP 7.2, on reecrit donc l'optimisation des subwheels via une fonction anonyme de type..
+textwheel               | 1bf8732 | marcimat     | 2018-02-09 | Compat PHP 7.2 : create_function => function (les plus simples, mais il en reste !…)
+urls_etendues           | be9066b | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+vertebres               | a381bc9 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+squelettes-dist         | 6323be9 | marcimat     | 2021-03-18 | Suppression du fichier .gitattributes inutile.
+
+
+
+SPIP-Core v3.2.8 -> v3.2.9 (12 février 2021)
+---------------------------------------------
+
+c965889bc | cedric        | 2021-02-10 | Fix #4316 : la PR a ete fermee sur github quand on est passe a git.spip.net je suppose
+c76c39a6e | cedric        | 2021-02-10 | nonsense code, copie colle surement, fix #4315
+93a917a4d | cedric        | 2021-02-10 | Fix #4140 (deja fixe en 3.3)
+7246f1966 | cedric        | 2021-02-08 | Fix #3869 (ou du moins on espere, sinon c'est pas si grave)
+55bc9fd5d | erational     | 2021-02-08 | [bugfix] empecher warning sur le count de l'iterateur devrait resoudre le ticket https://core.spip.net/issues/4450 et ..
+42898eb47 | rastapopoulos | 2021-02-05 | Corrige 4401 en améliorant la rustine déjà en place
+24eda3678 | cedric        | 2021-02-05 | nettoyer l'adresse site qu'on enregistre fix #4629
+bb69f3466 | bruno         | 2021-02-05 | ne pas stocker le champ ldap_password dans les fichiers de session
+2269d0a6a | cedric        | 2021-02-01 | appels a autoriser sur les formulaires editer, a minima quand on les utilise en modification d'un objet existant depui..
+610c24f06 | cedric        | 2021-02-02 | Eviter d'utiliser une globale, gerer le flag en static avec operations de lecture+reset
+a8493a3ce | cedric        | 2021-02-01 | Eviter de donner sa langue au chat
+f9d9e5b1a | cedric        | 2021-02-01 | on accepte pas une fonction de config inconnue si elle vient d'un modele
+962a95f44 | cedric        | 2021-02-01 | Utiliser contexte_compil pour reperer les appels a executer_balise_dynamique() venant d'un modele, et lever un flag le..
+c35edb769 | cedric        | 2021-02-01 | une fonction pour detecter qu'un formulaire a ete inclu via un modele et non directement via une balide #FORMULAIRE_xxx
+577ad8d21 | bruno         | 2021-01-21 | Ã©viter d'afficher n'importe quoi dans le message d'édition concurrente
+f1f27e9f7 | bruno         | 2021-02-01 | attribut_html() sur les attributs renvoyés par env_to_params() & env_to_attributs()
+6c6b6c6d4 | nicod         | 2021-01-06 | Stocker les contextes dans des fichiers en cache si la longueur de l’argument géneré est plus long que ce qui est tolé..
+2be11db95 | bruno         | 2020-10-25 | fix undefined index sur l'action réparation de la base
+
+
+
+SPIP-plugins-dist v3.2.8 -> v3.2.9 (12 février 2021)
+-----------------------------------------------------
+
+breves                  | ba1e040 | cedric       | 2021-02-04 | verifier l'autorisation de modifier la breve passe en argument
+mediabox                | 9020d16 | cedric       | 2021-02-08 | #4625 : echapper les valeurs injectees dans le js via les parametres mediabox, c'est plus propre
+medias                  | 96bf7b2 | cedric       | 2021-02-04 | Verifier l'autorisation de modifier les documents passes en argument du formulaire
+medias                  | bfc3319 | cedric       | 2021-01-20 | Report de 049dee8 : Extraire la fonction de determination automatique du statut d'un document dans une fonction inc_de..
+medias                  | 9764525 | cedric       | 2021-01-19 | Normaliser le comportement de document_instituer() en appelant les pipelines pre_editon et post_edition avec action=in..
+medias                  | 2293b84 | tcharlss     | 2021-01-19 | Report de 890506eb99 : Pour le JS des modes d'affichages, cibler plus précisément l'élément, sinon les boutons peuvent..
+mots                    | 0955e0d | cedric       | 2021-02-04 | Verifier les autorisations de modifier les mots/groupes de mots passes en argument du formulaire d'edition
+revisions               | e573977 | bruno        | 2020-10-23 | Ã©viter un warning dans les révisions lors de la suppression d'un lien par une personne non identifiée
+sites                   | 28bdb59 | cedric       | 2021-02-10 | Fix #4296 : l'url peut etre dans le href meme si c'est pas un link autofermant...
+sites                   | 92994f3 | cedric       | 2021-02-04 | verifier l'autorisation de modifier le site passe en argument du formulaire d'edition
+sites                   | 638ceef | cedric       | 2020-12-18 | Fix le id_mot manquant sur les syndic_articles. Ce n'est pas un usage frequent, mais il existe et soyons homogene avec..
+textwheel               | 317b045 | rastapopoulos | 2021-02-05 | Correction de 4508 : on ne gère le caption/summary *réellement* qu'en première ligne, seulement si on n'a pas déjà gén..
 
 
 SPIP-Core v3.2.7 -> v3.2.8 (29 septembre 2020)
index b471156..773ae6c 100644 (file)
@@ -5,7 +5,7 @@
  * ------------------
  */
 
-define('_ECRAN_SECURITE', '1.3.13'); // 2019-12-04
+define('_ECRAN_SECURITE', '1.4.1'); // 2021-03-12
 
 /*
  * Documentation : http://www.spip.net/fr_article4200.html
@@ -17,6 +17,10 @@ define('_ECRAN_SECURITE', '1.3.13'); // 2019-12-04
 if (isset($_GET['test_ecran_securite']))
        $ecran_securite_raison = 'test '._ECRAN_SECURITE;
 
+if (file_exists($f = __DIR__ . DIRECTORY_SEPARATOR  . 'ecran_securite_options.php')) {
+       include ($f);
+}
+
 /*
  * Monitoring
  * var_isbot=0 peut etre utilise par un bot de monitoring pour surveiller la disponibilite d'un site vu par les users
@@ -226,12 +230,15 @@ if (!defined('_IS_BOT')){
 if (!defined('_IS_BOT_FRIEND')){
        define('_IS_BOT_FRIEND',
                isset($_SERVER['HTTP_USER_AGENT'])
-               and preg_match(',' . implode ('|', array(
-                       'facebookexternalhit',
-                       'flipboardproxy',
-                       'wordpress'
-               )) . ',i',
-               (string)$_SERVER['HTTP_USER_AGENT'])
+                       and preg_match(
+                               ',' . implode('|', array(
+                                       'facebookexternalhit',
+                                       'twitterbot',
+                                       'flipboardproxy',
+                                       'wordpress'
+                               )) . ',i',
+                               (string)$_SERVER['HTTP_USER_AGENT']
+                       )
        );
 }
 
@@ -544,6 +551,7 @@ if (isset($ecran_securite_raison)) {
        header("Cache-Control: no-cache, must-revalidate");
        header("Pragma: no-cache");
        header("Content-Type: text/html");
+       header("Connection: close");
        die("<html><title>Error 403: Forbidden</title><body><h1>Error 403</h1><p>You are not authorized to view this page ($ecran_securite_raison)</p></body></html>");
 }
 
@@ -598,5 +606,6 @@ if (
        header("Cache-Control: no-cache, must-revalidate");
        header("Pragma: no-cache");
        header("Content-Type: text/html");
+       header("Connection: close");
        die("<html><title>Status 429: Too Many Requests</title><body><h1>Status 429</h1><p>Too Many Requests (try again soon)</p></body></html>");
 }
index 3b9c49b..887bc49 100644 (file)
@@ -258,7 +258,7 @@ if (!class_exists('nanoSha2')) {
                                return false;
                        }
 
-                       $h = ord($c{$index});
+                       $h = ord($c[$index]);
 
                        if ($h <= 0x7F) {
                                $bytes = 1;
@@ -274,20 +274,20 @@ if (!class_exists('nanoSha2')) {
                                        if ($h <= 0xDF && $index < $len-1) {
                                                $bytes = 2;
 
-                                               return ($h & 0x1F) << 6 | (ord($c{$index+1}) & 0x3F);
+                                               return ($h & 0x1F) << 6 | (ord($c[$index+1]) & 0x3F);
                                        } else {
                                                if ($h <= 0xEF && $index < $len-2) {
                                                        $bytes = 3;
 
-                                                       return ($h & 0x0F) << 12 | (ord($c{$index+1}) & 0x3F) << 6
-                                                       | (ord($c{$index+2}) & 0x3F);
+                                                       return ($h & 0x0F) << 12 | (ord($c[$index+1]) & 0x3F) << 6
+                                                       | (ord($c[$index+2]) & 0x3F);
                                                } else {
                                                        if ($h <= 0xF4 && $index < $len-3) {
                                                                $bytes = 4;
 
-                                                               return ($h & 0x0F) << 18 | (ord($c{$index+1}) & 0x3F) << 12
-                                                               | (ord($c{$index+2}) & 0x3F) << 6
-                                                               | (ord($c{$index+3}) & 0x3F);
+                                                               return ($h & 0x0F) << 18 | (ord($c[$index+1]) & 0x3F) << 12
+                                                               | (ord($c[$index+2]) & 0x3F) << 6
+                                                               | (ord($c[$index+3]) & 0x3F);
                                                        } else {
                                                                // pas utf mais renvoyer quand meme ce qu'on a
                                                                $bytes = 1;
index 3f16b2c..a3bb55c 100644 (file)
@@ -277,7 +277,7 @@ function balise_URL_PAGE_dist($p) {
                                $code .= ", $args";
                        }
                        $code = $f('page', $code, $s);
-
+                       $p->code = $code;
                        return $p;
                }
                $s = 'connect=' . addslashes($s);
index 1ec79e6..ba1fa37 100644 (file)
@@ -525,6 +525,7 @@ function query_reinjecte_textes($query, $textes) {
  *     - indéfini sinon.
  **/
 function spip_query($query, $serveur = '') {
+
        $f = spip_connect_sql($GLOBALS['spip_sql_version'], 'query', $serveur, true);
 
        return function_exists($f) ? $f($query, $serveur) : false;
index 41ad958..72f8dd4 100644 (file)
@@ -92,7 +92,7 @@ function base_upgrade_dist($titre = '', $reprise = '') {
  * @param string $redirect
  * @return array|bool
  */
-function maj_base($version_cible = 0, $redirect = '') {
+function maj_base($version_cible = 0, $redirect = '', $debut_page = true) {
 
        $version_installee = @$GLOBALS['meta']['version_installee'];
        //
@@ -152,7 +152,7 @@ function maj_base($version_cible = 0, $redirect = '') {
 
        include_spip('maj/svn10000');
        ksort($GLOBALS['maj']);
-       $res = maj_while($version_installee, $cible, $GLOBALS['maj'], 'version_installee', 'meta', $redirect, true);
+       $res = maj_while($version_installee, $cible, $GLOBALS['maj'], 'version_installee', 'meta', $redirect, $debut_page);
        if ($res) {
                if (!is_array($res)) {
                        spip_log("Pb d'acces SQL a la mise a jour", 'maj.' . _LOG_INFO_ERREUR);
@@ -381,8 +381,7 @@ function maj_while($installee, $cible, $maj, $meta = '', $table = 'meta', $redir
                define('_TIME_OUT', $time + _UPGRADE_TIME_OUT);
        }
 
-       reset($maj);
-       while (list($v, ) = each($maj)) {
+       foreach ($maj as $v => $operations) {
                // si une maj pour cette version
                if ($v == 'init' or
                        (spip_version_compare($v, $installee, '>')
@@ -392,7 +391,7 @@ function maj_while($installee, $cible, $maj, $meta = '', $table = 'meta', $redir
                                maj_debut_page($v, $meta, $table);
                        }
                        echo "MAJ $v";
-                       $etape = serie_alter($v, $maj[$v], $meta, $table, $redirect);
+                       $etape = serie_alter($v, $operations, $meta, $table, $redirect);
                        $trouver_table(''); // vider le cache des descriptions de table
                        # echec sur une etape en cours ?
                        # on sort
index 639aad0..455d969 100644 (file)
@@ -155,12 +155,13 @@ function optimiser_sansref($table, $id, $sel, $and = '') {
 function optimiser_base_disparus($attente = 86400) {
 
        # format = 20060610110141, si on veut forcer une optimisation tout de suite
-       $mydate = sql_quote(date("Y-m-d H:i:s", time() - $attente));
+       $mydate = date("Y-m-d H:i:s", time() - $attente);
+       $mydate_quote = sql_quote($mydate);
 
        $n = 0;
 
        //
-       // Rubriques 
+       // Rubriques
        //
 
        # les articles qui sont dans une id_rubrique inexistante
@@ -173,12 +174,12 @@ function optimiser_base_disparus($attente = 86400) {
                          ON A.id_rubrique=R.id_rubrique",
                "A.id_rubrique > 0
                         AND R.id_rubrique IS NULL
-                        AND A.maj < $mydate");
+                        AND A.maj < $mydate_quote");
 
        $n += optimiser_sansref('spip_articles', 'id_article', $res);
 
        // les articles a la poubelle
-       sql_delete("spip_articles", "statut='poubelle' AND maj < $mydate");
+       sql_delete("spip_articles", "statut='poubelle' AND maj < $mydate_quote");
 
        //
        // Auteurs
@@ -195,7 +196,7 @@ function optimiser_base_disparus($attente = 86400) {
                        LEFT JOIN spip_auteurs_liens AS L
                          ON L.id_auteur=A.id_auteur",
                "L.id_auteur IS NULL
-                       AND A.statut='5poubelle' AND A.maj < $mydate");
+                       AND A.statut='5poubelle' AND A.maj < $mydate_quote");
 
        $n += optimiser_sansref('spip_auteurs', 'id_auteur', $res);
 
index 7dbd178..98036d6 100644 (file)
@@ -404,20 +404,26 @@ function charset2unicode($texte, $charset = 'AUTO' /* $forcer: obsolete*/) {
                default:
                        // mbstring presente ?
                        if (init_mb_string()) {
-                               if ($order = mb_detect_order() # mb_string connait-il $charset?
-                                       and mb_detect_order($charset)
-                               ) {
-                                       $s = mb_convert_encoding($texte, 'utf-8', $charset);
-                                       if ($s && $s != $texte) {
-                                               return utf_8_to_unicode($s);
+                               $order = mb_detect_order();
+                               try {
+                                       # mb_string connait-il $charset?
+                                       if ($order and mb_detect_order($charset)) {
+                                               $s = mb_convert_encoding($texte, 'utf-8', $charset);
+                                               if ($s && $s != $texte) {
+                                                       return utf_8_to_unicode($s);
+                                               }
                                        }
-                               }
+                                       
+                               } catch (\Exception $e) {
+                                       // Le charset n'existe probablement pas
+                               } 
                                mb_detect_order($order); # remettre comme precedemment
                        }
 
                        // Sinon, peut-etre connaissons-nous ce charset ?
                        if (!isset($trans[$charset])) {
-                               if ($cset = load_charset($charset)
+                               if (
+                                       $cset = load_charset($charset)
                                        and is_array($GLOBALS['CHARSET'][$cset])
                                ) {
                                        foreach ($GLOBALS['CHARSET'][$cset] as $key => $val) {
@@ -425,7 +431,7 @@ function charset2unicode($texte, $charset = 'AUTO' /* $forcer: obsolete*/) {
                                        }
                                }
                        }
-                       if (count($trans[$charset])) {
+                       if (isset($trans[$charset]) and count($trans[$charset])) {
                                return str_replace(array_keys($trans[$charset]), array_values($trans[$charset]), $texte);
                        }
 
@@ -831,7 +837,7 @@ function javascript_to_binary($texte) {
  * @return string
  */
 function translitteration_rapide($texte, $charset = 'AUTO', $complexe = '') {
-       static $trans;
+       static $trans = [];
        if ($charset == 'AUTO') {
                $charset = $GLOBALS['meta']['charset'];
        }
@@ -842,7 +848,8 @@ function translitteration_rapide($texte, $charset = 'AUTO', $complexe = '') {
        $table_translit = 'translit' . $complexe;
 
        // 2. Translitterer grace a la table predefinie
-       if (!$trans[$complexe]) {
+       if (!isset($trans[$complexe])) {
+               $trans[$complexe] = [];
                load_charset($table_translit);
                foreach ($GLOBALS['CHARSET'][$table_translit] as $key => $val) {
                        $trans[$complexe][caractere_utf_8($key)] = $val;
@@ -897,8 +904,11 @@ function translitteration_complexe($texte, $chiffres = false) {
        $texte = translitteration($texte, 'AUTO', 'complexe');
 
        if ($chiffres) {
-               $texte = preg_replace("/[aeiuoyd]['`?~.^+(-]{1,2}/eS",
-                       "translitteration_chiffree('\\0')", $texte);
+               $texte = preg_replace_callback(
+                       "/[aeiuoyd]['`?~.^+(-]{1,2}/S",
+                       function($m) { return translitteration_chiffree($m[0]); },
+                       $texte
+               );
        }
 
        return $texte;
@@ -994,34 +1004,29 @@ function transcoder_page($texte, $headers = '') {
                return $texte;
        }
 
-       // Reconnaitre le BOM utf-8 (0xEFBBBF)
        if (bom_utf8($texte)) {
+               // Reconnaitre le BOM utf-8 (0xEFBBBF)
                $charset = 'utf-8';
                $texte = substr($texte, 3);
-       } // charset precise par le contenu (xml)
-       else {
-               if (preg_match(
-                       ',<[?]xml[^>]*encoding[^>]*=[^>]*([-_a-z0-9]+?),UimsS', $texte, $regs)) {
-                       $charset = trim(strtolower($regs[1]));
-               } // charset precise par le contenu (html)
-               else {
-                       if (preg_match(
-                                       ',<(meta|html|body)[^>]*charset[^>]*=[^>]*([-_a-z0-9]+?),UimsS',
-                                       $texte, $regs)
-                               # eviter #CHARSET des squelettes
-                               and (($tmp = trim(strtolower($regs[2]))) != 'charset')
-                       ) {
-                               $charset = $tmp;
-                       } // charset de la reponse http
-                       else {
-                               if (preg_match(',charset=([-_a-z0-9]+),i', $headers, $regs)) {
-                                       $charset = trim(strtolower($regs[1]));
-                               } else {
-                                       $charset = '';
-                               }
-                       }
-               }
+       } elseif (preg_match(',<[?]xml[^>]*encoding[^>]*=[^>]*([-_a-z0-9]+?),UimsS', $texte, $regs)) {
+               // charset precise par le contenu (xml)
+               $charset = trim(strtolower($regs[1]));
+       } elseif (
+               // charset precise par le contenu (html)
+               preg_match(',<(meta|html|body)[^>]*charset[^>]*=[^>]*([#-_a-z0-9]+?),UimsS', $texte, $regs)
+               # eviter toute balise SPIP tel que #CHARSET ou #CONFIG d'un squelette
+               and false === strpos($regs[2], '#')
+               and $tmp = trim(strtolower($regs[2]))
+       ) {
+               $charset = $tmp;
+       } elseif (preg_match(',charset=([-_a-z0-9]+),i', $headers, $regs)) {
+               // charset de la reponse http
+               $charset = trim(strtolower($regs[1]));
+       } else {
+               $charset = '';
        }
+
+
        // normaliser les noms du shif-jis japonais
        if (preg_match(',^(x|shift)[_-]s?jis$,i', $charset)) {
                $charset = 'shift-jis';
index ede9c12..d5d4113 100644 (file)
@@ -544,8 +544,8 @@ function actualise_metas($liste_meta) {
        // verifier le impt=non
        sql_updateq('spip_meta', array('impt' => 'non'), sql_in('nom', $meta_serveur));
 
-       while (list($nom, $valeur) = each($liste_meta)) {
-               if (!isset($GLOBALS['meta'][$nom]) or !$GLOBALS['meta'][$nom]) {
+       foreach ($liste_meta as $nom => $valeur) {
+               if (empty($GLOBALS['meta'][$nom])) {
                        ecrire_meta($nom, $valeur);
                }
        }
index 3b37483..064a44e 100644 (file)
@@ -1916,11 +1916,13 @@ function alterner($i) {
  **/
 function extraire_attribut($balise, $attribut, $complet = false) {
        if (is_array($balise)) {
-               array_walk($balise,
-                       create_function('&$a,$key,$t',
-                               '$a = extraire_attribut($a,$t);'
-                       ),
-                       $attribut);
+               array_walk(
+                       $balise,
+                       function(&$a, $key, $t){
+                               $a = extraire_attribut($a, $t);
+                       },
+                       $attribut
+               );
 
                return $balise;
        }
@@ -2361,7 +2363,7 @@ function microformat2enclosure($tags) {
 function tags2dcsubject($tags) {
        $subjects = '';
        foreach (extraire_balises($tags, 'a') as $e) {
-               if (extraire_attribut($e, rel) == 'tag') {
+               if (extraire_attribut($e, 'rel') == 'tag') {
                        $subjects .= '<dc:subject>'
                                . texte_backend(textebrut($e))
                                . '</dc:subject>' . "\n";
@@ -2400,7 +2402,9 @@ function extraire_balise($texte, $tag = 'a') {
        if (is_array($texte)) {
                array_walk(
                        $texte,
-                       create_function('&$a,$key,$t', '$a = extraire_balise($a,$t);'),
+                       function(&$a, $key, $t){
+                               $a = extraire_balise($a, $t);
+                       },
                        $tag
                );
 
@@ -2442,7 +2446,9 @@ function extraire_balises($texte, $tag = 'a') {
        if (is_array($texte)) {
                array_walk(
                        $texte,
-                       create_function('&$a,$key,$t', '$a = extraire_balises($a,$t);'),
+                       function(&$a, $key, $t){
+                               $a = extraire_balises($a, $t);
+                       },
                        $tag
                );
 
@@ -2846,9 +2852,11 @@ function urls_absolues_css($contenu, $source) {
 
        return preg_replace_callback(
                ",url\s*\(\s*['\"]?([^'\"/#\s][^:]*)['\"]?\s*\),Uims",
-               create_function('$x',
-                       'return "url(\'".suivre_lien(\'' . $path . '\',$x[1])."\')";'
-               ), $contenu);
+               function($x) use ($path) {
+                       return "url('" . suivre_lien($path, $x[1]) . "')";
+               },
+               $contenu
+       );
 }
 
 
@@ -4273,12 +4281,16 @@ function bouton_action($libelle, $url, $class = "", $confirm = "", $title = "",
 /**
  * Proteger les champs passes dans l'url et utiliser dans {tri ...}
  * preserver l'espace pour interpreter ensuite num xxx et multi xxx
+ * on permet d'utiliser les noms de champ prefixes
+ * articles.titre
+ * et les propriete json
+ * properties.gis[0].ville
  *
  * @param string $t
  * @return string
  */
 function tri_protege_champ($t) {
-       return preg_replace(',[^\s\w.+],', '', $t);
+       return preg_replace(',[^\s\w.+\[\]],', '', $t);
 }
 
 /**
index d93acc1..b45889b 100644 (file)
@@ -853,7 +853,7 @@ function _image_tag_changer_taille($tag, $width, $height, $style = false) {
 
        // enlever le width et height du style
        $style = preg_replace(",(^|;)\s*(width|height)\s*:\s*[^;]+,ims", "", $style);
-       if ($style and $style{0} == ';') {
+       if ($style and $style[0] == ';') {
                $style = substr($style, 1);
        }
 
index 5407a99..5e4e4fd 100644 (file)
@@ -423,7 +423,7 @@ class idna_convert {
         $delim_pos = strrpos($encoded, '-');
         if ($delim_pos > self::byteLength($this->_punycode_prefix)) {
             for ($k = self::byteLength($this->_punycode_prefix); $k < $delim_pos; ++$k) {
-                $decoded[] = ord($encoded{$k});
+                $decoded[] = ord($encoded[$k]);
             }
         }
         $deco_len = count($decoded);
@@ -437,7 +437,7 @@ class idna_convert {
 
         for ($enco_idx = ($delim_pos) ? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len) {
             for ($old_idx = $idx, $w = 1, $k = $this->_base; 1; $k += $this->_base) {
-                $digit = $this->_decode_digit($encoded{$enco_idx++});
+                $digit = $this->_decode_digit($encoded[$enco_idx++]);
                 $idx += $digit * $w;
                 $t = ($k <= $bias) ? $this->_tmin :
                         (($k >= $bias + $this->_tmax) ? $this->_tmax : ($k - $bias));
@@ -864,7 +864,7 @@ class idna_convert {
         $mode = 'next';
         $test = 'none';
         for ($k = 0; $k < $inp_len; ++$k) {
-            $v = ord($input{$k}); // Extract byte from input string
+            $v = ord($input[$k]); // Extract byte from input string
             if ($v < 128) { // We found an ASCII char - put into stirng as is
                 $output[$out_len] = $v;
                 ++$out_len;
@@ -995,7 +995,7 @@ class idna_convert {
                 $out_len++;
                 $output[$out_len] = 0;
             }
-            $output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4) ) );
+            $output[$out_len] += ord($input[$i]) << (8 * (3 - ($i % 4) ) );
         }
         return $output;
     }
index a134c57..ce841dc 100644 (file)
@@ -60,7 +60,7 @@ function produire_image_math($tex) {
 
                // MathML
                if ($GLOBALS['traiter_math'] == 'mathml') {
-                       return join(file("$fichier"), "");
+                       return implode("", file($fichier));
                } // TeX
                else {
                        list(, , , $size) = @getimagesize($fichier);
index fc93da4..1f55eb4 100644 (file)
@@ -57,8 +57,8 @@ function inc_plonger_dist($id_rubrique, $idom = "", $list = array(), $col = 1, $
                $rec = generer_url_ecrire('plonger', "rac=$idom&exclus=$exclu&do=$do&col=" . ($col + 1));
                $info = generer_url_ecrire('informer', "type=rubrique&rac=$idom&do=$do&id=");
                $args = "'$idom',this,$col,'" . $GLOBALS['spip_lang_left'] . "','$info',event";
-               while (list($id, $titrebrut) = each($ordre)) {
 
+               foreach ($ordre as $id => $titrebrut) {
                        $titre = supprimer_numero($titrebrut);
 
                        $classe1 = $id_rubrique ? 'petite-rubrique' : "petit-secteur";
index 417cb9f..1da2f36 100644 (file)
@@ -209,7 +209,7 @@ function plugin_version_compatible($intervalle, $version, $avec_quoi = '') {
                // cas du plugin qui n'est compatible qu'avec cette nouvelle version
        }
 
-       $minimum_inc = $intervalle{0} == "[";
+       $minimum_inc = $intervalle[0] == "[";
        $maximum_inc = substr($intervalle, -1) == "]";
 
        if (strlen($minimum)) {
@@ -699,7 +699,7 @@ function plugin_message_incompatibilite($intervalle, $version, $nom, $balise) {
                $minimum = $regs[1];
                $maximum = $regs[2];
 
-               $minimum_inclus = $intervalle{0} == "[";
+               $minimum_inclus = $intervalle[0] == "[";
                $maximum_inclus = substr($intervalle, -1) == "]";
 
                if (strlen($minimum)) {
@@ -933,7 +933,7 @@ function plugins_precompile_chemin($plugin_valides, $ordre) {
                                                        $GLOBALS['spip_version_branche'], 'spip')
                                        ) {
                                                $dir = $chemin['path'];
-                                               if (strlen($dir) and $dir{0} == "/") {
+                                               if (strlen($dir) and $dir[0] == "/") {
                                                        $dir = substr($dir, 1);
                                                }
                                                if (strlen($dir) and $dir == "./") {
index a759650..2e331bf 100644 (file)
@@ -77,16 +77,26 @@ function inc_session_dist($auteur = false) {
  */
 function supprimer_sessions($id_auteur, $toutes = true, $actives = true) {
 
+       $nb_files = 0;
+       $nb_max_files = (defined('_MAX_NB_SESSIONS_OUVERTES') ? _MAX_NB_SESSIONS_OUVERTES : 1000);
        spip_log("supprimer sessions auteur $id_auteur", "session");
        if ($toutes or $id_auteur !== $GLOBALS['visiteur_session']['id_auteur']) {
                if ($dir = opendir(_DIR_SESSIONS)) {
+                       $t = $_SERVER['REQUEST_TIME']  - (4*_RENOUVELLE_ALEA); // 48h par defaut
+                       $t_short = $_SERVER['REQUEST_TIME']  - max(_RENOUVELLE_ALEA/4,3*3600); // 3h par defaut
                        $t = time() - (4 * _RENOUVELLE_ALEA);
                        while (($f = readdir($dir)) !== false) {
+                               $nb_files++;
                                if (preg_match(",^[^\d-]*(-?\d+)_\w{32}\.php[3]?$,", $f, $regs)) {
                                        $f = _DIR_SESSIONS . $f;
                                        if (($actives and $regs[1] == $id_auteur) or ($t > filemtime($f))) {
                                                spip_unlink($f);
                                        }
+                                       // si il y a trop de sessions ouvertes, on purge les sessions anonymes de plus de 3H
+                                       // cf http://core.spip.org/issues/3276
+                                       elseif ($nb_files>$nb_max_files and !intval($regs[1]) and ($t_short > filemtime($f))) {
+                                               spip_unlink($f);
+                                       }
                                }
                        }
                }
index a89658a..afc4fbc 100644 (file)
@@ -328,9 +328,12 @@ function spip_log($message = null, $name = null) {
        if (!isset($regs[1]) or !$logname = $regs[1]) {
                $logname = null;
        }
-       if (!isset($regs[2]) or !$niveau = $regs[2]) {
+       if (!isset($regs[2])) {
                $niveau = _LOG_INFO;
        }
+       else {
+               $niveau = intval($regs[2]);
+       }
 
        if ($niveau <= (defined('_LOG_FILTRE_GRAVITE') ? _LOG_FILTRE_GRAVITE : _LOG_INFO_IMPORTANTE)) {
                if (!$pre) {
@@ -2741,9 +2744,11 @@ function spip_initialisation_suite() {
        // les anciens IIS n'acceptent pas les POST sur ecrire/ (#419)
        // meme pb sur thttpd cf. http://forum.spip.net/fr_184153.html
        if (!defined('_SPIP_ECRIRE_SCRIPT')) {
-               define('_SPIP_ECRIRE_SCRIPT', (empty($_SERVER['SERVER_SOFTWARE']) ? '' :
-                       preg_match(',IIS|thttpd,', $_SERVER['SERVER_SOFTWARE']) ?
-                               'index.php' : ''));
+               if (!empty($_SERVER['SERVER_SOFTWARE']) and preg_match(',IIS|thttpd,', $_SERVER['SERVER_SOFTWARE'])) {
+                       define('_SPIP_ECRIRE_SCRIPT', 'index.php');
+               } else {
+                       define('_SPIP_ECRIRE_SCRIPT', '');
+               }
        }
 
 
index 26c8077..a9a55ee 100644 (file)
@@ -212,13 +212,12 @@ function spip_xml_tagname($tag) {
 function spip_xml_decompose_tag($tag) {
        $tagname = spip_xml_tagname($tag);
        $liste = array();
-       $p = strpos($tag, ' ');
-       $tag = substr($tag, $p);
+       $tag = ltrim(strpbrk($tag, " \n\t"));
        $p = strpos($tag, '=');
        while ($p !== false) {
                $attr = trim(substr($tag, 0, $p));
                $tag = ltrim(substr($tag, $p + 1));
-               $quote = $tag{0};
+               $quote = $tag[0];
                $p = strpos($tag, $quote, 1);
                $cont = substr($tag, 1, $p - 1);
                $liste[$attr] = $cont;
index 6d45f32..a4f5006 100644 (file)
@@ -374,8 +374,8 @@ $liste_des_authentifications = array(
 // ex : 2.0.0, 2.0.0-dev, 2.0.0-beta, 2.0.0-beta2
 // le _SPIP_VERSION_ID est un nombre entier représentant le numéro de version (2 chiffres pour chaque 03 + 02 + 06 = 30206
 // le _SPIP_EXTRA_VERSION sert Ã  repérer les version dev, beta etc. Pour une version stable il est vide.
-$spip_version_branche = "3.2.9";
-define('_SPIP_VERSION_ID', 30209);
+$spip_version_branche = "3.2.11";
+define('_SPIP_VERSION_ID', 30211);
 define('_SPIP_EXTRA_VERSION', '');
 
 // cette version dev accepte tous les plugins compatible avec la version ci-dessous
index 0021f74..15e7d76 100644 (file)
@@ -93,7 +93,7 @@ function install_etape_chmod_dist() {
        $bad_dirs = array();
        $absent_dirs = array();
 
-       while (list(, $my_dir) = each($GLOBALS['test_dirs'])) {
+       foreach ($GLOBALS['test_dirs'] as $i => $my_dir) {
                $test = test_ecrire($my_dir);
                if (!$test) {
                        $m = preg_replace(',^' . _DIR_RACINE . ',', '', $my_dir);
index 5536788..616bfc8 100644 (file)
@@ -127,7 +127,9 @@ class IterateurDATA implements Iterator {
         */
        public function rewind() {
                reset($this->tableau);
-               list($this->cle, $this->valeur) = each($this->tableau);
+               $this->cle = key($this->tableau);
+               $this->valeur = current($this->tableau);
+               next($this->tableau);
        }
 
        /**
@@ -433,7 +435,7 @@ class IterateurDATA implements Iterator {
         *
         **/
        protected function select_datapath() {
-               list(, $base) = each($this->command['datapath']);
+               $base = reset($this->command['datapath']);
                if (strlen($base = ltrim(trim($base), "/"))) {
                        $this->tableau = table_valeur($this->tableau, $base);
                        if (!is_array($this->tableau)) {
@@ -486,17 +488,17 @@ class IterateurDATA implements Iterator {
                                        $a = ' . sprintf($tv, '$aa') . ';
                                        $b = ' . sprintf($tv, '$bb') . ';
                                        if ($a <> $b)
-                                               return ($a ' . ((isset($r[2]) and $r[2]) ? '>' : '<') . ' $b) ? -1 : 1;';
+                                               return ($a ' . (!empty($r[2]) ? '>' : '<') . ' $b) ? -1 : 1;';
                                        }
                                }
                        }
                }
 
                if ($sortfunc) {
-                       uasort($this->tableau, create_function('$aa,$bb',
-                               $sortfunc . '
-                               return 0;'
-                       ));
+                       $sortfunc .= "\n return 0;";
+                       uasort($this->tableau, function($aa, $bb) use ($sortfunc) {
+                               return eval($sortfunc);
+                       });
                }
        }
 
@@ -556,7 +558,9 @@ class IterateurDATA implements Iterator {
         */
        public function next() {
                if ($this->valid()) {
-                       list($this->cle, $this->valeur) = each($this->tableau);
+                       $this->cle = key($this->tableau);
+                       $this->valeur = current($this->tableau);
+                       next($this->tableau);
                }
        }
 
index d62467f..b441cd0 100644 (file)
@@ -1,7 +1,7 @@
 <paquet
        prefix="spip"
        categorie="outil"
-       version="3.2.9"
+       version="3.2.11"
        etat="stable"
        compatibilite="];["
        schema="23375"
index bbe6ba0..8fc3f7a 100644 (file)
@@ -537,11 +537,10 @@ function inclure_modele($type, $id, $params, $lien, $connect = '', $env = array(
 
        $params = array_filter(explode('|', $params));
        if ($params) {
-               list(, $soustype) = each($params);
+               $soustype = current($params);
                $soustype = strtolower(trim($soustype));
-               if (in_array($soustype,
-                       array('left', 'right', 'center', 'ajax'))) {
-                       list(, $soustype) = each($params);
+               if (in_array($soustype, array('left', 'right', 'center', 'ajax'))) {
+                       $soustype = next($params);
                        $soustype = strtolower($soustype);
                }
 
index f1a0d7a..9e80959 100644 (file)
@@ -1158,7 +1158,7 @@ function balise_PAGINATION_dist($p, $liste = 'true') {
        // si true, les arguments simples (sans truc=chose) vont degager
        $_contexte = argumenter_inclure($p->param, true, $p, $p->boucles, $p->id_boucle, false, false);
        if (count($_contexte)) {
-               list($key, $val) = each($_contexte);
+               $key = key($_contexte);
                if (is_numeric($key)) {
                        array_shift($_contexte);
                        $__modele = interprete_argument_balise(1, $p);
index 42ab5da..47ac7eb 100644 (file)
@@ -1194,7 +1194,13 @@ function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect = '
                $i++;
        }
        $squelette = preg_replace_callback(',\\\\([#[()\]{}<>]),',
-               create_function('$a', "return '$inerte-'.ord(\$a[1]).'-';"), $squelette, -1, $esc);
+               function($a) use ($inerte) {
+                       return "$inerte-" . ord($a[1]) . '-';
+               },
+               $squelette,
+               -1,
+               $esc
+       );
 
        $descr = array(
                'nom' => $nom,
@@ -1215,11 +1221,20 @@ function public_compiler_dist($squelette, $nom, $gram, $sourcefile, $connect = '
        // restituer les echappements
        if ($esc) {
                foreach ($boucles as $i => $boucle) {
-                       $boucles[$i]->return = preg_replace_callback(",$inerte-(\d+)-,", create_function('$a', 'return chr($a[1]);'),
-                               $boucle->return);
-                       $boucles[$i]->descr['squelette'] = preg_replace_callback(",$inerte-(\d+)-,",
-                               create_function('$a', 'return "\\\\".chr($a[1]);'),
-                               $boucle->descr['squelette']);
+                       $boucles[$i]->return = preg_replace_callback(
+                               ",$inerte-(\d+)-,",
+                               function($a) {
+                                       return chr($a[1]);
+                               },
+                               $boucle->return
+                       );
+                       $boucles[$i]->descr['squelette'] = preg_replace_callback(
+                               ",$inerte-(\d+)-,",
+                               function($a) {
+                                       return "\\\\" . chr($a[1]);
+                               },
+                               $boucle->descr['squelette']
+                       );
                }
        }
 
index c3d1174..62b476f 100644 (file)
@@ -979,7 +979,8 @@ function calculer_select(
                // penser a regarder aussi la clause groubpy pour ne pas simplifier abusivement
                // <BOUCLE10(EVENEMENTS){id_rubrique} />#TOTAL_BOUCLE<//B10>
 
-               list($t, $c) = each($from);
+               $t = key($from);
+               $c = current($from);
                reset($from);
                $e = '/\b(' . "$t\\." . join("|" . $t . '\.', $equiv) . ')\b/';
                if (!(strpos($t, ' ') or // jointure des le depart cf boucle_doc
@@ -991,8 +992,8 @@ function calculer_select(
                                calculer_jointnul($t, $having, $e))
                        && count($afrom[$t])
                ) {
-                       reset($afrom[$t]);
-                       list($nt, $nfrom) = each($afrom[$t]);
+                       $nfrom = reset($afrom[$t]);
+                       $nt = key($afrom[$t]);
                        unset($from[$t]);
                        $from[$nt] = $nfrom[1];
                        unset($afrom[$t][$nt]);
index 1e274d5..b5c2e35 100644 (file)
@@ -300,7 +300,10 @@ class IterDecorator extends FilterIterator {
 
                // Creer la fonction de filtrage sur $this
                if ($this->filtre) {
-                       $this->func_filtre = create_function('$me', $b = 'return (' . join(') AND (', $this->filtre) . ');');
+                       $filtres = 'return (' . join(') AND (', $this->filtre) . ');';
+                       $this->func_filtre = function () use ($filtres) {
+                               return eval($filtres);
+                       };
                }
        }
 
@@ -320,7 +323,7 @@ class IterDecorator extends FilterIterator {
                # if (!in_array($cle, array('cle', 'valeur')))
                #       return;
 
-               $a = '$me->get_select(\'' . $cle . '\')';
+               $a = '$this->get_select(\'' . $cle . '\')';
 
                $filtre = '';
 
@@ -566,7 +569,7 @@ class IterDecorator extends FilterIterator {
         **/
        public function accept() {
                if ($f = $this->func_filtre) {
-                       return $f($this);
+                       return $f();
                }
 
                return true;
index 09a4b1d..f8f406d 100644 (file)
@@ -669,7 +669,7 @@ function quete_debut_pagination($primary, $valeur, $pas, $iter) {
                $pos++;
        }
        // si on a pas trouve
-       if ($row[$primary] != $valeur) {
+       if (!$row or $row[$primary] != $valeur) {
                return 0;
        }
 
index 218f290..6a6116a 100644 (file)
@@ -704,13 +704,18 @@ function champs_traitements($p) {
                $type_requete = isset($p->boucles[$idb]->type_requete) ? $p->boucles[$idb]->type_requete : false;
                $table_sql = isset($p->boucles[$idb]->show['table_sql']) ? $p->boucles[$idb]->show['table_sql'] : false;
 
+               // bien prendre en compte les alias de boucles (hierarchie => rubrique, syndication => syncdic, etc.)
+               if ($type_requete and isset($GLOBALS['table_des_tables'][$type_requete])) {
+                       $type_requete = $GLOBALS['table_des_tables'][$type_requete];
+               }
+
                // le traitement peut n'etre defini que pour une table en particulier "spip_articles"
                if ($table_sql and isset($ps[$table_sql])) {
                        $ps = $ps[$table_sql];
                } // ou pour une boucle en particulier "DATA","articles"
                elseif ($type_requete and isset($ps[$type_requete])) {
                        $ps = $ps[$type_requete];
-               } // ou pour indiferrement quelle que soit la boucle
+               } // ou pour indifféremment quelle que soit la boucle
                elseif (isset($ps[0])) {
                        $ps = $ps[0];
                } else {
index 5cd2c0d..4c78e1c 100644 (file)
@@ -243,7 +243,7 @@ function spip_mysql_query($query, $serveur = '', $requeter = true) {
        if (defined('_DEBUG_SLOW_QUERIES') and _DEBUG_SLOW_QUERIES) {
                if (isset($GLOBALS['debug']['aucasou'])) {
                        list(, $id, , $infos) = $GLOBALS['debug']['aucasou'];
-                       $debug .= "BOUCLE$id @ " . $infos[0] . " | ";
+                       $debug .= "BOUCLE$id @ " . (isset($infos[0]) ? $infos[0] : '') . " | ";
                }
                $debug .= $_SERVER['REQUEST_URI'] . ' + ' . $GLOBALS['ip'];
                $debug = ' /* ' . mysqli_real_escape_string($link, str_replace('*/', '@/', $debug)) . ' */';
@@ -1681,7 +1681,8 @@ function spip_get_lock($nom, $timeout = 0) {
        $nom = "$bd:$prefixe:$nom" . _LOCK_TIME;
 
        $connexion['last'] = $q = "SELECT GET_LOCK(" . _q($nom) . ", $timeout) AS n";
-       $q = @sql_fetch(mysql_query($q));
+
+       $q = @sql_fetch(mysqli_query(_mysql_link(), $q));
        if (!$q) {
                spip_log("pas de lock sql pour $nom", _LOG_ERREUR);
        }
index 64f5016..294df17 100644 (file)
@@ -2298,16 +2298,14 @@ function _sqlite_charger_version($version = '') {
 function _sqlite_modifier_table($table, $colonne, $opt = array(), $serveur = '') {
 
        if (is_array($table)) {
-               reset($table);
-               list($table_origine, $table_destination) = each($table);
+               list($table_origine, $table_destination) = reset($table);
        } else {
                $table_origine = $table_destination = $table;
        }
        // ne prend actuellement qu'un changement
        // mais pourra etre adapte pour changer plus qu'une colonne a la fois
        if (is_array($colonne)) {
-               reset($colonne);
-               list($colonne_origine, $colonne_destination) = each($colonne);
+               list($colonne_origine, $colonne_destination) = reset($colonne);
        } else {
                $colonne_origine = $colonne_destination = $colonne;
        }
index 4a29627..6286fd5 100644 (file)
@@ -285,8 +285,7 @@ function breves_accueil_encours($flux) {
  */
 function breves_optimiser_base_disparus($flux) {
        $n = &$flux['data'];
-       $mydate = $flux['args']['date'];
-
+       $mydate = sql_quote($flux['args']['date']);
 
        # les breves qui sont dans une id_rubrique inexistante
        $res = sql_select(
@@ -295,7 +294,7 @@ function breves_optimiser_base_disparus($flux) {
                        LEFT JOIN spip_rubriques AS R
                                ON B.id_rubrique=R.id_rubrique',
                'R.id_rubrique IS NULL
-                       AND B.maj < ' . sql_quote($mydate)
+                       AND B.maj < ' . $mydate
        );
 
        $n += optimiser_sansref('spip_breves', 'id_breve', $res);
index 85d940d..891c7b8 100644 (file)
@@ -47,10 +47,9 @@ function compresseur_embarquer_images_css($contenu, $source, $source_file = null
 
        return preg_replace_callback(
                ",url\s*\(\s*['\"]?([^'\"/][^:]*[.](png|gif|jpg))['\"]?\s*\),Uims",
-               create_function(
-                       '$x',
-                       'return "url(\"".' . $filtre_embarque_fichier . '($x[1],"' . $base . '",_CSS_EMBARQUE_FICHIER_MAX_SIZE)."\")";'
-               ),
+               function($x) use ($filtre_embarque_fichier, $base) {
+                       return "url(\"" . $filtre_embarque_fichier($x[1], $base, _CSS_EMBARQUE_FICHIER_MAX_SIZE) . "\");";
+               },
                $contenu
        );
 }
diff --git a/www/plugins-dist/compresseur/lib/csstidy/NEWS b/www/plugins-dist/compresseur/lib/csstidy/NEWS
deleted file mode 100644 (file)
index 4862c65..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-Changelog
-
-Key: # = backwards incompatible change, ! = new feature, - = bugfix.
-
-1.4, unknown release date
-# CSSTidy is now licensed under LGPL!
-! csstidy->set_cfg now accept a single parameter, an associative array, to
-  set all configuration options
-! Templates can now be loaded via set_cfg using the 'template' config
-  parameter
-! csstidy_print->formatted_page added, returns a full XHTML page based
-  off of csstidy_print->formatted
-! cssparsed.css created, contains just the CSS for formatted CSS output
-! New CSS 3 units "ch" and "turn" added
-! Unit tests added, requires Text_Diff (PEAR) and SimpleTest
-! Some invalid selectors are now removed during optimization, this can
-  be turned off by setting 'discard_invalid_selectors' to false
-- Added localizations for css_optimiser.php
-- Fixed bug with cookie setting for custom templates
-- Minor security problem in css_optimiser.php fixed
-- Fixed bug with float handling in exotic locales
-- Fixed bug with non-functioning getenv in ASAPI
-- Fixed bug with bad hexadecimal syntax recovery
-- At-selectors optimized by removing unnecessary url()
-- Fixed optimisation: 1.0 was not optimised to 1
-- Fixed incorrect parsing of !imporant close to numbers
-- Allowed Copy to Clipboard for Firefox if preference set (if not, gives 
-  instructions on how to add and warning re: security)
\ No newline at end of file
index 31d0675..3e780f8 100644 (file)
@@ -2,20 +2,58 @@
 
 CSSTidy is a CSS minifier 
 
+* css_optimiser.php is the web-interface
+* class.csstidy.php is the parser
+* bin/pcsstidy is the standalone command line executable
+
+This class represents a CSS parser which reads CSS code and saves it in an array.
+In opposite to most other CSS parsers, it does not use regular expressions and
+thus has full CSS3 support and a higher reliability. The downside of not using regular expressions
+is a lower speed though.
+Additional to that it applies some optimisations and fixes to the CSS code.
+
+
+## Usage
+
+```
+include('class.csstidy.php');
+$csstidy = new csstidy();
+
+// Set some options :
+$csstidy->set_cfg('optimise_shorthands', 2);
+$csstidy->set_cfg('template', 'high');
+
+// Parse the CSS
+$csstidy->parse($css_code);
+
+// Get back the optimized CSS Code
+$css_code_opt = $csstidy->print->plain();
+```
+
+
+## Changelog
+* v1.7.3 :
+  - fix bug and notice on reverse_left_and_right option
+* v1.7.1 :
+  - fix deprecated with PHP 7.4
+* v1.7.0 :
+  - provide bin/pcsstidy for command line usage
+  - support nested @media and @supports rules
 * v1.6.5 :
-  fix warnings with PHP 7.3
+  fix warnings with PHP 7.3
 * v1.6.4 :
-  preserve important comments (starting with !) in the minification /*! Credits/Licence */
+  preserve important comments (starting with !) in the minification /*! Credits/Licence */
 * v1.6.3 :
-  border-radius shorthands optimisation, reverse_left_and_right option
+  border-radius shorthands optimisation, reverse_left_and_right option
 * v1.5.7 :
-  PHP 7 compatibility, composer update, Travis CI integration
+  PHP 7 compatibility, composer update, Travis CI integration
 * v1.5.6 :
-  fixes minor bugs, mainly on CSS3 properties/units
+  fixes minor bugs, mainly on CSS3 properties/units
 * v1.5.2 :
-  is PHP 5.4+ compliant, removes use of GLOBALS, fixes some bugs, integrates CSS3 units
-  and now available on https://packagist.org/packages/cerdic/css-tidy
-* v1.4 : is the new version coming from master branch (corresponds to the initial trunk of svn repository) after beeing stabilized
+  - is PHP 5.4+ compliant, removes use of GLOBALS, fixes some bugs, integrates CSS3 units
+  - and now available on https://packagist.org/packages/cerdic/css-tidy
+* v1.4 :<br/>
+Is the new version coming from master branch (corresponds to the initial trunk of svn repository) after beeing stabilized
 * v1.3 branch corresponds to the last stable relase published by the author.<br/>
 It integrates some bugfixes and a 1.3.1 version has been taged
 Since the original project (http://csstidy.sourceforge.net/index.php) has been suspended
@@ -23,34 +61,26 @@ here is the import of https://csstidy.svn.sourceforge.net/svnroot/csstidy on 201
 
 Only PHP version is here maintained
 
----
+## Licence
 
-## CSSTidy
+       Copyright 2005-2007 Florian Schmitz
+       Copyright 2010-2019 Cedric Morin
 
-Original Tracker : 
-http://sourceforge.net/tracker/?group_id=148404&atid=771415
-
-css_optimiser.php is the web-interface, css_parser.php contains the PHP class (CSSTidy).
-
-This class represents a CSS parser which reads CSS code and saves it in an array.
-In opposite to most other CSS parsers, it does not use regular expressions and
-thus has full CSS2 support and a higher reliability. The downside of not using regular expressions
-is a lower speed though.
-Additional to that it applies some optimisations and fixes to the CSS code.
-An online version should be available here: http://cdburnerxp.se/cssparse/css_optimiser.php
+       CSSTidy is free software; you can redistribute it and/or modify
+       it under the terms of the GNU Lesser General Public License as published by
+       the Free Software Foundation; either version 2.1 of the License, or
+       (at your option) any later version.
+  
+       CSSTidy 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 program.  If not, see <http://www.gnu.org/licenses/>.
 
-       Copyright 2005, 2006, 2007 Florian Schmitz
 
-  CSSTidy is free software; you can redistribute it and/or modify
-  it under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-  
-  CSSTidy 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.
+## History
 
-  You should have received a copy of the GNU Lesser General Public License
-  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+Original Tracker : 
+http://sourceforge.net/tracker/?group_id=148404&atid=771415
index d29068a..b09373d 100644 (file)
  * @author Mark Scherer (remove $GLOBALS once and for all + PHP5.4 comp) 2012
  */
 
-/**
- * Defines ctype functions if required.
- *
- * @TODO: Make these methods of CSSTidy.
- * @since 1.0.0
- */
-if (!function_exists('ctype_space')){
-       /* ctype_space Check for whitespace character(s) */
-       function ctype_space($text){
-               return (1===preg_match("/^[ \r\n\t\f]+$/", $text));
-       }
-}
-if (!function_exists('ctype_alpha')){
-       /* ctype_alpha Check for alphabetic character(s) */
-       function ctype_alpha($text){
-               return (1===preg_match('/^[a-zA-Z]+$/', $text));
-       }
-}
-if (!function_exists('ctype_xdigit')){
-       /* ctype_xdigit Check for HEX character(s) */
-       function ctype_xdigit($text){
-               return (1===preg_match('/^[a-fA-F0-9]+$/', $text));
-       }
-}
-
 /**
  * Defines constants
  * @todo //TODO: make them class constants of csstidy
@@ -95,7 +70,7 @@ require('class.csstidy_optimise.php');
  * An online version should be available here: http://cdburnerxp.se/cssparse/css_optimiser.php
  * @package csstidy
  * @author Florian Schmitz (floele at gmail dot com) 2005-2006
- * @version 1.6.5
+ * @version 1.7.3
  */
 class csstidy {
 
@@ -148,7 +123,7 @@ class csstidy {
         * @var string
         * @access private
         */
-       public $version = '1.6.5';
+       public $version = '1.7.3';
        /**
         * Stores the settings
         * @var array
@@ -416,7 +391,17 @@ class csstidy {
         */
        public function _add_token($type, $data, $do = false) {
                if ($this->get_cfg('preserve_css') || $do) {
-                       $this->tokens[] = array($type, ($type == COMMENT or $type == IMPORTANT_COMMENT) ? $data : trim($data));
+                       // nested @... : if opening a new part we just closed, remove the previous closing instead of adding opening
+                       if ($type === AT_START
+                               and count($this->tokens)
+                               and $last = end($this->tokens)
+                               and $last[0] === AT_END
+                               and $last[1] === trim($data)) {
+                               array_pop($this->tokens);
+                       }
+                       else {
+                               $this->tokens[] = array($type, ($type == COMMENT or $type == IMPORTANT_COMMENT) ? $data : trim($data));
+                       }
                }
        }
 
@@ -452,10 +437,10 @@ class csstidy {
                $add = '';
                $replaced = false;
 
-               while ($i < strlen($string) && (ctype_xdigit($string{$i}) || ctype_space($string{$i})) && strlen($add) < 6) {
-                       $add .= $string{$i};
+               while ($i < strlen($string) && (ctype_xdigit($string[$i]) || ctype_space($string[$i])) && strlen($add) < 6) {
+                       $add .= $string[$i];
 
-                       if (ctype_space($string{$i})) {
+                       if (ctype_space($string[$i])) {
                                break;
                        }
                        $i++;
@@ -469,12 +454,12 @@ class csstidy {
                        $add = trim('\\' . $add);
                }
 
-               if (@ctype_xdigit($string{$i + 1}) && ctype_space($string{$i})
-                                               && !$replaced || !ctype_space($string{$i})) {
+               if (@ctype_xdigit($string[$i + 1]) && ctype_space($string[$i])
+                                               && !$replaced || !ctype_space($string[$i])) {
                        $i--;
                }
 
-               if ($add !== '\\' || !$this->get_cfg('remove_bslash') || strpos($this->tokens_list, $string{$i + 1}) !== false) {
+               if ($add !== '\\' || !$this->get_cfg('remove_bslash') || strpos($this->tokens_list, $string[$i + 1]) !== false) {
                        return $add;
                }
 
@@ -576,7 +561,7 @@ class csstidy {
         * @version 1.11
         */
        public function is_token(&$string, $i) {
-               return (strpos($this->tokens_list, $string{$i}) !== false && !$this->escaped($string, $i));
+               return (strpos($this->tokens_list, $string[$i]) !== false && !$this->escaped($string, $i));
        }
 
        /**
@@ -603,9 +588,10 @@ class csstidy {
                $this->print->input_css = $string;
                $string = str_replace("\r\n", "\n", $string) . ' ';
                $cur_comment = '';
+               $cur_at = '';
 
                for ($i = 0, $size = strlen($string); $i < $size; $i++) {
-                       if ($string{$i} === "\n" || $string{$i} === "\r") {
+                       if ($string[$i] === "\n" || $string[$i] === "\r") {
                                ++$this->line;
                        }
 
@@ -613,27 +599,27 @@ class csstidy {
                                /* Case in at-block */
                                case 'at':
                                        if ($this->is_token($string, $i)) {
-                                               if ($string{$i} === '/' && @$string{$i + 1} === '*') {
+                                               if ($string[$i] === '/' && @$string[$i + 1] === '*') {
                                                        $this->status = 'ic';
                                                        ++$i;
                                                        $this->from[] = 'at';
-                                               } elseif ($string{$i} === '{') {
+                                               } elseif ($string[$i] === '{') {
                                                        $this->status = 'is';
-                                                       $this->at = $this->css_new_media_section($this->at);
+                                                       $this->at = $this->css_new_media_section($this->at, $cur_at);
                                                        $this->_add_token(AT_START, $this->at);
-                                               } elseif ($string{$i} === ',') {
-                                                       $this->at = trim($this->at) . ',';
-                                               } elseif ($string{$i} === '\\') {
-                                                       $this->at .= $this->_unicode($string, $i);
+                                               } elseif ($string[$i] === ',') {
+                                                       $cur_at = trim($cur_at) . ',';
+                                               } elseif ($string[$i] === '\\') {
+                                                       $cur_at .= $this->_unicode($string, $i);
                                                }
                                                // fix for complicated media, i.e @media screen and (-webkit-min-device-pixel-ratio:1.5)
-                                               elseif (in_array($string{$i}, array('(', ')', ':', '.', '/'))) {
-                                                       $this->at .= $string{$i};
+                                               elseif (in_array($string[$i], array('(', ')', ':', '.', '/'))) {
+                                                       $cur_at .= $string[$i];
                                                }
                                        } else {
-                                               $lastpos = strlen($this->at) - 1;
-                                               if (!( (ctype_space($this->at{$lastpos}) || $this->is_token($this->at, $lastpos) && $this->at{$lastpos} === ',') && ctype_space($string{$i}))) {
-                                                       $this->at .= $string{$i};
+                                               $lastpos = strlen($cur_at) - 1;
+                                               if (!( (ctype_space($cur_at[$lastpos]) || $this->is_token($cur_at, $lastpos) && $cur_at[$lastpos] === ',') && ctype_space($string[$i]))) {
+                                                       $cur_at .= $string[$i];
                                                }
                                        }
                                        break;
@@ -641,24 +627,25 @@ class csstidy {
                                /* Case in-selector */
                                case 'is':
                                        if ($this->is_token($string, $i)) {
-                                               if ($string{$i} === '/' && @$string{$i + 1} === '*' && trim($this->selector) == '') {
+                                               if ($string[$i] === '/' && @$string[$i + 1] === '*' && trim($this->selector) == '') {
                                                        $this->status = 'ic';
                                                        ++$i;
                                                        $this->from[] = 'is';
-                                               } elseif ($string{$i} === '@' && trim($this->selector) == '') {
+                                               } elseif ($string[$i] === '@' && trim($this->selector) == '') {
                                                        // Check for at-rule
                                                        $this->invalid_at = true;
                                                        foreach ($at_rules as $name => $type) {
                                                                if (!strcasecmp(substr($string, $i + 1, strlen($name)), $name)) {
-                                                                       ($type === 'at') ? $this->at = '@' . $name : $this->selector = '@' . $name;
+                                                                       ($type === 'at') ? $cur_at = '@' . $name : $this->selector = '@' . $name;
                                                                        if ($type === 'atis') {
                                                                                $this->next_selector_at = ($this->next_selector_at?$this->next_selector_at:($this->at?$this->at:DEFAULT_AT));
-                                                                               $this->at = $this->css_new_media_section(' ');
+                                                                               $this->at = $this->css_new_media_section($this->at, ' ', true);
                                                                                $type = 'is';
                                                                        }
                                                                        $this->status = $type;
                                                                        $i += strlen($name);
                                                                        $this->invalid_at = false;
+                                                                       break;
                                                                }
                                                        }
 
@@ -666,54 +653,55 @@ class csstidy {
                                                                $this->selector = '@';
                                                                $invalid_at_name = '';
                                                                for ($j = $i + 1; $j < $size; ++$j) {
-                                                                       if (!ctype_alpha($string{$j})) {
+                                                                       if (!ctype_alpha($string[$j])) {
                                                                                break;
                                                                        }
-                                                                       $invalid_at_name .= $string{$j};
+                                                                       $invalid_at_name .= $string[$j];
                                                                }
                                                                $this->log('Invalid @-rule: ' . $invalid_at_name . ' (removed)', 'Warning');
                                                        }
-                                               } elseif (($string{$i} === '"' || $string{$i} === "'")) {
-                                                       $this->cur_string[] = $string{$i};
+                                               } elseif (($string[$i] === '"' || $string[$i] === "'")) {
+                                                       $this->cur_string[] = $string[$i];
                                                        $this->status = 'instr';
-                                                       $this->str_char[] = $string{$i};
+                                                       $this->str_char[] = $string[$i];
                                                        $this->from[] = 'is';
                                                        /* fixing CSS3 attribute selectors, i.e. a[href$=".mp3" */
-                                                       $this->quoted_string[] = ($string{$i - 1} === '=' );
-                                               } elseif ($this->invalid_at && $string{$i} === ';') {
+                                                       $this->quoted_string[] = ($string[$i - 1] === '=' );
+                                               } elseif ($this->invalid_at && $string[$i] === ';') {
                                                        $this->invalid_at = false;
                                                        $this->status = 'is';
                                                        if ($this->next_selector_at) {
-                                                               $this->at = $this->css_new_media_section($this->next_selector_at);
+                                                               $this->at = $this->css_close_media_section($this->at);
+                                                               $this->at = $this->css_new_media_section($this->at, $this->next_selector_at);
                                                                $this->next_selector_at = '';
                                                        }
-                                               } elseif ($string{$i} === '{') {
+                                               } elseif ($string[$i] === '{') {
                                                        $this->status = 'ip';
                                                        if ($this->at == '') {
-                                                               $this->at = $this->css_new_media_section(DEFAULT_AT);
+                                                               $this->at = $this->css_new_media_section($this->at, DEFAULT_AT);
                                                        }
                                                        $this->selector = $this->css_new_selector($this->at,$this->selector);
                                                        $this->_add_token(SEL_START, $this->selector);
                                                        $this->added = false;
-                                               } elseif ($string{$i} === '}') {
+                                               } elseif ($string[$i] === '}') {
                                                        $this->_add_token(AT_END, $this->at);
-                                                       $this->at = '';
+                                                       $this->at = $this->css_close_media_section($this->at);
                                                        $this->selector = '';
                                                        $this->sel_separate = array();
-                                               } elseif ($string{$i} === ',') {
+                                               } elseif ($string[$i] === ',') {
                                                        $this->selector = trim($this->selector) . ',';
                                                        $this->sel_separate[] = strlen($this->selector);
-                                               } elseif ($string{$i} === '\\') {
+                                               } elseif ($string[$i] === '\\') {
                                                        $this->selector .= $this->_unicode($string, $i);
-                                               } elseif ($string{$i} === '*' && @in_array($string{$i + 1}, array('.', '#', '[', ':')) && ($i==0 OR $string{$i - 1}!=='/')) {
+                                               } elseif ($string[$i] === '*' && @in_array($string[$i + 1], array('.', '#', '[', ':')) && ($i==0 OR $string[$i - 1]!=='/')) {
                                                        // remove unnecessary universal selector, FS#147, but not comment in selector
                                                } else {
-                                                       $this->selector .= $string{$i};
+                                                       $this->selector .= $string[$i];
                                                }
                                        } else {
                                                $lastpos = strlen($this->selector) - 1;
-                                               if ($lastpos == -1 || !( (ctype_space($this->selector{$lastpos}) || $this->is_token($this->selector, $lastpos) && $this->selector{$lastpos} === ',') && ctype_space($string{$i}))) {
-                                                       $this->selector .= $string{$i};
+                                               if ($lastpos == -1 || !( (ctype_space($this->selector[$lastpos]) || $this->is_token($this->selector, $lastpos) && $this->selector[$lastpos] === ',') && ctype_space($string[$i]))) {
+                                                       $this->selector .= $string[$i];
                                                }
                                        }
                                        break;
@@ -721,17 +709,17 @@ class csstidy {
                                /* Case in-property */
                                case 'ip':
                                        if ($this->is_token($string, $i)) {
-                                               if (($string{$i} === ':' || $string{$i} === '=') && $this->property != '') {
+                                               if (($string[$i] === ':' || $string[$i] === '=') && $this->property != '') {
                                                        $this->status = 'iv';
                                                        if (!$this->get_cfg('discard_invalid_properties') || $this->property_is_valid($this->property)) {
                                                                $this->property = $this->css_new_property($this->at,$this->selector,$this->property);
                                                                $this->_add_token(PROPERTY, $this->property);
                                                        }
-                                               } elseif ($string{$i} === '/' && @$string{$i + 1} === '*' && $this->property == '') {
+                                               } elseif ($string[$i] === '/' && @$string[$i + 1] === '*' && $this->property == '') {
                                                        $this->status = 'ic';
                                                        ++$i;
                                                        $this->from[] = 'ip';
-                                               } elseif ($string{$i} === '}') {
+                                               } elseif ($string[$i] === '}') {
                                                        $this->explode_selectors();
                                                        $this->status = 'is';
                                                        $this->invalid_at = false;
@@ -739,45 +727,46 @@ class csstidy {
                                                        $this->selector = '';
                                                        $this->property = '';
                                                        if ($this->next_selector_at) {
-                                                               $this->at = $this->css_new_media_section($this->next_selector_at);
+                                                               $this->at = $this->css_close_media_section($this->at);
+                                                               $this->at = $this->css_new_media_section($this->at, $this->next_selector_at);
                                                                $this->next_selector_at = '';
                                                        }
-                                               } elseif ($string{$i} === ';') {
+                                               } elseif ($string[$i] === ';') {
                                                        $this->property = '';
-                                               } elseif ($string{$i} === '\\') {
+                                               } elseif ($string[$i] === '\\') {
                                                        $this->property .= $this->_unicode($string, $i);
                                                }
                                                // else this is dumb IE a hack, keep it
                                                // including //
-                                               elseif (($this->property === '' && !ctype_space($string{$i}))
-                                                       || ($this->property === '/' || $string{$i} === '/')) {
-                                                       $this->property .= $string{$i};
+                                               elseif (($this->property === '' && !ctype_space($string[$i]))
+                                                       || ($this->property === '/' || $string[$i] === '/')) {
+                                                       $this->property .= $string[$i];
                                                }
-                                       } elseif (!ctype_space($string{$i})) {
-                                               $this->property .= $string{$i};
+                                       } elseif (!ctype_space($string[$i])) {
+                                               $this->property .= $string[$i];
                                        }
                                        break;
 
                                /* Case in-value */
                                case 'iv':
-                                       $pn = (($string{$i} === "\n" || $string{$i} === "\r") && $this->property_is_next($string, $i + 1) || $i == strlen($string) - 1);
+                                       $pn = (($string[$i] === "\n" || $string[$i] === "\r") && $this->property_is_next($string, $i + 1) || $i == strlen($string) - 1);
                                        if ($this->is_token($string, $i) || $pn) {
-                                               if ($string{$i} === '/' && @$string{$i + 1} === '*') {
+                                               if ($string[$i] === '/' && @$string[$i + 1] === '*') {
                                                        $this->status = 'ic';
                                                        ++$i;
                                                        $this->from[] = 'iv';
-                                               } elseif (($string{$i} === '"' || $string{$i} === "'" || $string{$i} === '(')) {
-                                                       $this->cur_string[] = $string{$i};
-                                                       $this->str_char[] = ($string{$i} === '(') ? ')' : $string{$i};
+                                               } elseif (($string[$i] === '"' || $string[$i] === "'" || $string[$i] === '(')) {
+                                                       $this->cur_string[] = $string[$i];
+                                                       $this->str_char[] = ($string[$i] === '(') ? ')' : $string[$i];
                                                        $this->status = 'instr';
                                                        $this->from[] = 'iv';
                                                        $this->quoted_string[] = in_array(strtolower($this->property), $quoted_string_properties);
-                                               } elseif ($string{$i} === ',') {
+                                               } elseif ($string[$i] === ',') {
                                                        $this->sub_value = trim($this->sub_value) . ',';
-                                               } elseif ($string{$i} === '\\') {
+                                               } elseif ($string[$i] === '\\') {
                                                        $this->sub_value .= $this->_unicode($string, $i);
-                                               } elseif ($string{$i} === ';' || $pn) {
-                                                       if ($this->selector{0} === '@' && isset($at_rules[substr($this->selector, 1)]) && $at_rules[substr($this->selector, 1)] === 'iv') {
+                                               } elseif ($string[$i] === ';' || $pn) {
+                                                       if ($this->selector[0] === '@' && isset($at_rules[substr($this->selector, 1)]) && $at_rules[substr($this->selector, 1)] === 'iv') {
                                                                /* Add quotes to charset, import, namespace */
                                                                $this->sub_value_arr[] = trim($this->sub_value);
 
@@ -799,12 +788,12 @@ class csstidy {
                                                        } else {
                                                                $this->status = 'ip';
                                                        }
-                                               } elseif ($string{$i} !== '}') {
-                                                       $this->sub_value .= $string{$i};
+                                               } elseif ($string[$i] !== '}') {
+                                                       $this->sub_value .= $string[$i];
                                                }
-                                               if (($string{$i} === '}' || $string{$i} === ';' || $pn) && !empty($this->selector)) {
+                                               if (($string[$i] === '}' || $string[$i] === ';' || $pn) && !empty($this->selector)) {
                                                        if ($this->at == '') {
-                                                               $this->at = $this->css_new_media_section(DEFAULT_AT);
+                                                               $this->at = $this->css_new_media_section($this->at,DEFAULT_AT);
                                                        }
 
                                                        // case settings
@@ -850,21 +839,22 @@ class csstidy {
                                                        $this->sub_value_arr = array();
                                                        $this->value = '';
                                                }
-                                               if ($string{$i} === '}') {
+                                               if ($string[$i] === '}') {
                                                        $this->explode_selectors();
                                                        $this->_add_token(SEL_END, $this->selector);
                                                        $this->status = 'is';
                                                        $this->invalid_at = false;
                                                        $this->selector = '';
                                                        if ($this->next_selector_at) {
-                                                               $this->at = $this->css_new_media_section($this->next_selector_at);
+                                                               $this->at = $this->css_close_media_section($this->at);
+                                                               $this->at = $this->css_new_media_section($this->at, $this->next_selector_at);
                                                                $this->next_selector_at = '';
                                                        }
                                                }
                                        } elseif (!$pn) {
-                                               $this->sub_value .= $string{$i};
+                                               $this->sub_value .= $string[$i];
 
-                                               if (ctype_space($string{$i})) {
+                                               if (ctype_space($string[$i])) {
                                                        $this->optimise->subvalue();
                                                        if ($this->sub_value != '') {
                                                                $this->sub_value_arr[] = $this->sub_value;
@@ -879,26 +869,26 @@ class csstidy {
                                        $_str_char = $this->str_char[count($this->str_char)-1];
                                        $_cur_string = $this->cur_string[count($this->cur_string)-1];
                                        $_quoted_string = $this->quoted_string[count($this->quoted_string)-1];
-                                       $temp_add = $string{$i};
+                                       $temp_add = $string[$i];
 
                                        // Add another string to the stack. Strings can't be nested inside of quotes, only parentheses, but
                                        // parentheticals can be nested more than once.
-                                       if ($_str_char === ")" && ($string{$i} === "(" || $string{$i} === '"' || $string{$i} === '\'') && !$this->escaped($string, $i)) {
-                                               $this->cur_string[] = $string{$i};
-                                               $this->str_char[] = $string{$i} === '(' ? ')' : $string{$i};
+                                       if ($_str_char === ")" && ($string[$i] === "(" || $string[$i] === '"' || $string[$i] === '\'') && !$this->escaped($string, $i)) {
+                                               $this->cur_string[] = $string[$i];
+                                               $this->str_char[] = $string[$i] === '(' ? ')' : $string[$i];
                                                $this->from[] = 'instr';
-                                               $this->quoted_string[] = ($_str_char === ')' && $string{$i} !== '(' && trim($_cur_string)==='(')?$_quoted_string:!($string{$i} === '(');
+                                               $this->quoted_string[] = ($_str_char === ')' && $string[$i] !== '(' && trim($_cur_string)==='(')?$_quoted_string:!($string[$i] === '(');
                                                continue 2;
                                        }
 
-                                       if ($_str_char !== ")" && ($string{$i} === "\n" || $string{$i} === "\r") && !($string{$i - 1} === '\\' && !$this->escaped($string, $i - 1))) {
+                                       if ($_str_char !== ")" && ($string[$i] === "\n" || $string[$i] === "\r") && !($string[$i - 1] === '\\' && !$this->escaped($string, $i - 1))) {
                                                $temp_add = "\\A";
                                                $this->log('Fixed incorrect newline in string', 'Warning');
                                        }
 
                                        $_cur_string .= $temp_add;
 
-                                       if ($string{$i} === $_str_char && !$this->escaped($string, $i)) {
+                                       if ($string[$i] === $_str_char && !$this->escaped($string, $i)) {
                                                $this->status = array_pop($this->from);
 
                                                if (!preg_match('|[' . implode('', $this->data['csstidy']['whitespace']) . ']|uis', $_cur_string) && $this->property !== 'content') {
@@ -949,7 +939,7 @@ class csstidy {
 
                                /* Case in-comment */
                                case 'ic':
-                                       if ($string{$i} === '*' && $string{$i + 1} === '/') {
+                                       if ($string[$i] === '*' && $string[$i + 1] === '/') {
                                                $this->status = array_pop($this->from);
                                                $i++;
                                                if (strlen($cur_comment) > 1 and strncmp($cur_comment, '!', 1) === 0) {
@@ -961,7 +951,7 @@ class csstidy {
                                                }
                                                $cur_comment = '';
                                        } else {
-                                               $cur_comment .= $string{$i};
+                                               $cur_comment .= $string[$i];
                                        }
                                        break;
                        }
@@ -1044,7 +1034,7 @@ class csstidy {
         * @version 1.02
         */
        static function escaped(&$string, $pos) {
-               return!(@($string{$pos - 1} !== '\\') || csstidy::escaped($string, $pos - 1));
+               return!(@($string[$pos - 1] !== '\\') || csstidy::escaped($string, $pos - 1));
        }
 
 
@@ -1091,29 +1081,27 @@ class csstidy {
        }
 
        /**
-        * Start a new media section.
-        * Check if the media is not already known,
-        * else rename it with extra spaces
-        * to avoid merging
+        * Check if a current media section is the continuation of the last one
+        * if not inc the name of the media section to avoid a merging
         *
-        * @param string $media
-        * @return string
+        * @param int|string $media
+        * @return int|string
         */
-       public function css_new_media_section($media) {
-               if ($this->get_cfg('preserve_css')) {
+       public function css_check_last_media_section_or_inc($media) {
+               // are we starting?
+               if (!$this->css || !is_array($this->css) || empty($this->css)) {
                        return $media;
                }
 
                // if the last @media is the same as this
                // keep it
-               if (!$this->css || !is_array($this->css) || empty($this->css)) {
-                       return $media;
-               }
                end($this->css);
                $at = key($this->css);
                if ($at == $media) {
                        return $media;
                }
+
+               // else inc the section in the array
                while (isset($this->css[$media]))
                        if (is_numeric($media))
                                $media++;
@@ -1122,6 +1110,56 @@ class csstidy {
                return $media;
        }
 
+       /**
+        * Start a new media section.
+        * Check if the media is not already known,
+        * else rename it with extra spaces
+        * to avoid merging
+        *
+        * @param string $current_media
+        * @param string $media
+        * @param bool $at_root
+        * @return string
+        */
+       public function css_new_media_section($current_media, $new_media, $at_root = false) {
+               if ($this->get_cfg('preserve_css')) {
+                       return $new_media;
+               }
+
+               // if we already are in a media and CSS level is 3, manage nested medias
+               if ($current_media
+                       && !$at_root
+                       // numeric $current_media means DEFAULT_AT or inc
+                       && !is_numeric($current_media)
+                       && strncmp($this->get_cfg('css_level'), 'CSS3', 4) == 0) {
+
+                       $new_media = rtrim($current_media) . "{" . rtrim($new_media);
+               }
+
+               return $this->css_check_last_media_section_or_inc($new_media);
+       }
+
+       /**
+        * Close a media section
+        * Find the parent media we were in before or the root
+        * @param $current_media
+        * @return string
+        */
+       public function css_close_media_section($current_media) {
+               if ($this->get_cfg('preserve_css')) {
+                       return '';
+               }
+
+               if (strpos($current_media, '{') !== false) {
+                       $current_media = explode('{', $current_media);
+                       array_pop($current_media);
+                       $current_media = implode('{', $current_media);
+                       return $current_media;
+               }
+
+               return '';
+       }
+
        /**
         * Start a new selector.
         * If already referenced in this media section,
@@ -1255,7 +1293,7 @@ class csstidy {
        /**
         * Checks if a property is valid
         * @param string $property
-        * @return bool;
+        * @return bool
         * @access public
         * @version 1.0
         */
@@ -1279,7 +1317,6 @@ class csstidy {
         * @param string
         * @return array
         */
-
        public function parse_string_list($value) {
                $value = trim($value);
 
@@ -1292,26 +1329,26 @@ class csstidy {
                $current_string = '';
 
                for ($i = 0, $_len = strlen($value); $i < $_len; $i++) {
-                       if (($value{$i} === ',' || $value{$i} === ' ') && $in_str === true) {
+                       if (($value[$i] === ',' || $value[$i] === ' ') && $in_str === true) {
                                $in_str = false;
                                $strings[] = $current_string;
                                $current_string = '';
-                       } elseif ($value{$i} === '"' || $value{$i} === "'") {
-                               if ($in_str === $value{$i}) {
+                       } elseif ($value[$i] === '"' || $value[$i] === "'") {
+                               if ($in_str === $value[$i]) {
                                        $strings[] = $current_string;
                                        $in_str = false;
                                        $current_string = '';
                                        continue;
                                } elseif (!$in_str) {
-                                       $in_str = $value{$i};
+                                       $in_str = $value[$i];
                                }
                        } else {
                                if ($in_str) {
-                                       $current_string .= $value{$i};
+                                       $current_string .= $value[$i];
                                } else {
-                                       if (!preg_match("/[\s,]/", $value{$i})) {
+                                       if (!preg_match("/[\s,]/", $value[$i])) {
                                                $in_str = true;
-                                               $current_string = $value{$i};
+                                               $current_string = $value[$i];
                                        }
                                }
                        }
index 4972436..e4971f6 100644 (file)
@@ -358,8 +358,8 @@ class csstidy_optimise {
                // #aabbcc -> #abc
                if (strlen($color) == 7) {
                        $color_temp = strtolower($color);
-                       if ($color_temp{0} === '#' && $color_temp{1} == $color_temp{2} && $color_temp{3} == $color_temp{4} && $color_temp{5} == $color_temp{6}) {
-                               $color = '#' . $color{1} . $color{3} . $color{5};
+                       if ($color_temp[0] === '#' && $color_temp[1] == $color_temp[2] && $color_temp[3] == $color_temp[4] && $color_temp[5] == $color_temp[6]) {
+                               $color = '#' . $color[1] . $color[3] . $color[5];
                        }
                }
 
@@ -438,7 +438,7 @@ class csstidy_optimise {
         */
        public function AnalyseCssNumber($string) {
                // most simple checks first
-               if (strlen($string) == 0 || ctype_alpha($string{0})) {
+               if (strlen($string) == 0 || ctype_alpha($string[0])) {
                        return false;
                }
 
@@ -647,22 +647,22 @@ class csstidy_optimise {
                for ($i = 0, $len = strlen($string); $i < $len; $i++) {
                        switch ($status) {
                                case 'st':
-                                       if ($string{$i} == $sep && !$this->parser->escaped($string, $i)) {
+                                       if ($string[$i] == $sep && !$this->parser->escaped($string, $i)) {
                                                ++$num;
-                                       } elseif ($string{$i} === '"' || $string{$i} === '\'' || (!$explode_in_parenthesis && $string{$i} === '(') && !$this->parser->escaped($string, $i)) {
+                                       } elseif ($string[$i] === '"' || $string[$i] === '\'' || (!$explode_in_parenthesis && $string[$i] === '(') && !$this->parser->escaped($string, $i)) {
                                                $status = 'str';
-                                               $to = ($string{$i} === '(') ? ')' : $string{$i};
-                                               (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
+                                               $to = ($string[$i] === '(') ? ')' : $string[$i];
+                                               (isset($output[$num])) ? $output[$num] .= $string[$i] : $output[$num] = $string[$i];
                                        } else {
-                                               (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
+                                               (isset($output[$num])) ? $output[$num] .= $string[$i] : $output[$num] = $string[$i];
                                        }
                                        break;
 
                                case 'str':
-                                       if ($string{$i} == $to && !$this->parser->escaped($string, $i)) {
+                                       if ($string[$i] == $to && !$this->parser->escaped($string, $i)) {
                                                $status = 'st';
                                        }
-                                       (isset($output[$num])) ? $output[$num] .= $string{$i} : $output[$num] = $string{$i};
+                                       (isset($output[$num])) ? $output[$num] .= $string[$i] : $output[$num] = $string[$i];
                                        break;
                        }
                }
@@ -797,9 +797,9 @@ class csstidy_optimise {
                                        $have['clip'] = true;
                                } elseif (in_array($str_value[$i][$j], $origin, true)) {
                                        $return['background-origin'] .= $str_value[$i][$j] . ',';
-                               } elseif ($str_value[$i][$j]{0} === '(') {
+                               } elseif ($str_value[$i][$j][0] === '(') {
                                        $return['background-size'] .= substr($str_value[$i][$j], 1, -1) . ',';
-                               } elseif (in_array($str_value[$i][$j], $pos, true) || is_numeric($str_value[$i][$j]{0}) || $str_value[$i][$j]{0} === null || $str_value[$i][$j]{0} === '-' || $str_value[$i][$j]{0} === '.') {
+                               } elseif (in_array($str_value[$i][$j], $pos, true) || is_numeric($str_value[$i][$j][0]) || $str_value[$i][$j][0] === null || $str_value[$i][$j][0] === '-' || $str_value[$i][$j][0] === '.') {
                                        $return['background-position'] .= $str_value[$i][$j];
                                        if (!$have['pos'])
                                                $return['background-position'] .= ' '; else
@@ -945,7 +945,7 @@ class csstidy_optimise {
                        } elseif ($have['style'] === false && in_array($str_value[0][$j], $font_style)) {
                                $return['font-style'] = $str_value[0][$j];
                                $have['style'] = true;
-                       } elseif ($have['size'] === false && (is_numeric($str_value[0][$j]{0}) || $str_value[0][$j]{0} === null || $str_value[0][$j]{0} === '.')) {
+                       } elseif ($have['size'] === false && (is_numeric($str_value[0][$j][0]) || $str_value[0][$j][0] === null || $str_value[0][$j][0] === '.')) {
                                $size = $this->explode_ws('/', trim($str_value[0][$j]));
                                $return['font-size'] = $size[0];
                                if (isset($size[1])) {
@@ -975,7 +975,7 @@ class csstidy_optimise {
 
                // Fix for 100 and more font-size
                if ($have['size'] === false && isset($return['font-weight']) &&
-                                               is_numeric($return['font-weight']{0})) {
+                                               is_numeric($return['font-weight'][0])) {
                        $return['font-size'] = $return['font-weight'];
                        unset($return['font-weight']);
                }
@@ -1011,8 +1011,8 @@ class csstidy_optimise {
                                        $family = trim($family);
                                        $len = strlen($family);
                                        if (strpos($family, ' ') &&
-                                                                       !(($family{0} === '"' && $family{$len - 1} === '"') ||
-                                                                       ($family{0} === "'" && $family{$len - 1} === "'"))) {
+                                                                       !(($family[0] === '"' && $family[$len - 1] === '"') ||
+                                                                       ($family[0] === "'" && $family[$len - 1] === "'"))) {
                                                $family = '"' . $family . '"';
                                        }
                                        $result_families[] = $family;
@@ -1278,16 +1278,25 @@ class csstidy_optimise {
                if (stripos($value, 'left') === false and stripos($value, 'right') === false) {
                        $values = $this->explode_ws(' ', trim($value));
                        $values = array_map('trim', $values);
-                       $values = array_filter($values);
+                       $values = array_filter($values, function ($v) { return strlen($v);});
                        $values = array_values($values);
                        if (count($values) == 1) {
+                               if (in_array($value, array('center', 'top', 'bottom', 'inherit', 'initial', 'unset'))) {
+                                       return $value;
+                               }
                                return "left $value";
                        }
                        if ($values[1] == 'top' or $values[1] == 'bottom') {
+                               if ($values[0] === 'center') {
+                                       return $value;
+                               }
                                return 'left ' . implode(' ', $values);
                        }
                        else {
                                $last = array_pop($values);
+                               if ($last === 'center') {
+                                       return $value;
+                               }
                                return implode(' ', $values) . ' left ' . $last;
                        }
                }
index f4ea07c..e501107 100644 (file)
@@ -219,20 +219,25 @@ class csstidy_print {
                        $output .= $template[0] . '@namespace ' . $template[5] . $this->namespace . $template[6] . $template[13];
                }
 
-               $in_at_out = '';
+               $in_at_out = [];
                $out = & $output;
+               $indent_level = 0;
 
                foreach ($this->tokens as $key => $token) {
                        switch ($token[0]) {
                                case AT_START:
                                        $out .= $template[0] . $this->_htmlsp($token[1], $plain) . $template[1];
-                                       $out = & $in_at_out;
+                                       $indent_level++;
+                                       if (!isset($in_at_out[$indent_level])) {
+                                               $in_at_out[$indent_level] = '';
+                                       }
+                                       $out = & $in_at_out[$indent_level];
                                        break;
 
                                case SEL_START:
                                        if ($this->parser->get_cfg('lowercase_s'))
                                                $token[1] = strtolower($token[1]);
-                                       $out .= ( $token[1]{0} !== '@') ? $template[2] . $this->_htmlsp($token[1], $plain) : $template[0] . $this->_htmlsp($token[1], $plain);
+                                       $out .= ( $token[1][0] !== '@') ? $template[2] . $this->_htmlsp($token[1], $plain) : $template[0] . $this->_htmlsp($token[1], $plain);
                                        $out .= $template[3];
                                        break;
 
@@ -261,12 +266,28 @@ class csstidy_print {
                                        break;
 
                                case AT_END:
-                                       $out = & $output;
-                                       $in_at_out = str_replace("\n\n", "\r\n", $in_at_out); // don't fill empty lines
-                                       $in_at_out = str_replace("\n", "\n" . $template[10], $in_at_out);
-                                       $in_at_out = str_replace("\r\n", "\n\n", $in_at_out);
-                                       $out .= $template[10] . $in_at_out . $template[9];
-                                       $in_at_out = '';
+                                       if (strlen($template[10])) {
+                                               // indent the bloc we are closing
+                                               $out = str_replace("\n\n", "\r\n", $out); // don't fill empty lines
+                                               $out = str_replace("\n", "\n" . $template[10], $out);
+                                               $out = str_replace("\r\n", "\n\n", $out);
+                                       }
+                                       if ($indent_level > 1) {
+                                               $out = & $in_at_out[$indent_level-1];
+                                       }
+                                       else {
+                                               $out = & $output;
+                                       }
+                                       $out .= $template[10] . $in_at_out[$indent_level];
+                                       if ($this->_seeknocomment($key, 1) != AT_END) {
+                                               $out .= $template[9];
+                                       }
+                                       else {
+                                               $out .= rtrim($template[9]);
+                                       }
+
+                                       unset($in_at_out[$indent_level]);
+                                       $indent_level--;
                                        break;
 
                                case IMPORTANT_COMMENT:
@@ -332,7 +353,10 @@ class csstidy_print {
                        if (intval($medium) < DEFAULT_AT) {
                                // un medium vide (contenant @font-face ou autre @) ne produit aucun conteneur
                                if (strlen(trim($medium))) {
-                                       $this->parser->_add_token(AT_START, $medium, true);
+                                       $parts_to_open = explode('{', $medium);
+                                       foreach ($parts_to_open as $part) {
+                                               $this->parser->_add_token(AT_START, $part, true);
+                                       }
                                }
                        } elseif ($default_media) {
                                $this->parser->_add_token(AT_START, $default_media, true);
@@ -372,7 +396,10 @@ class csstidy_print {
                        if (intval($medium) < DEFAULT_AT) {
                                // un medium vide (contenant @font-face ou autre @) ne produit aucun conteneur
                                if (strlen(trim($medium))) {
-                                       $this->parser->_add_token(AT_END, $medium, true);
+                                       $parts_to_close = explode('{', $medium);
+                                       foreach (array_reverse($parts_to_close) as $part) {
+                                               $this->parser->_add_token(AT_END, $part, true);
+                                       }
                                }
                        } elseif ($default_media) {
                                $this->parser->_add_token(AT_END, $default_media, true);
index 5bbc2ae..63eeae8 100644 (file)
@@ -55,7 +55,7 @@ $data['csstidy']['units'] = array('in','cm','mm','pt','pc','px','rem','em','%','
  * @global array $data['csstidy']['at_rules']
  * @version 1.1
  */
-$data['csstidy']['at_rules'] = array('page' => 'is','font-face' => 'atis','charset' => 'iv', 'import' => 'iv','namespace' => 'iv','media' => 'at','keyframes' => 'at','-moz-keyframes' => 'at','-o-keyframes' => 'at','-webkit-keyframes' => 'at','-ms-keyframes' => 'at');
+$data['csstidy']['at_rules'] = array('page' => 'is','font-face' => 'atis','charset' => 'iv', 'import' => 'iv','namespace' => 'iv','media' => 'at', 'supports' => 'at', 'keyframes' => 'at','-moz-keyframes' => 'at','-o-keyframes' => 'at','-webkit-keyframes' => 'at','-ms-keyframes' => 'at');
 
  /**
  * Properties that need a value with unit
@@ -588,20 +588,20 @@ $data['csstidy']['multiple_properties'] = array('background', 'background-image'
  * @version 1.0
  * @see csstidy::load_template()
  */
-$data['csstidy']['predefined_templates']['default'][] = '<span class="at">'; //string before @rule
-$data['csstidy']['predefined_templates']['default'][] = '</span> <span class="format">{</span>'."\n"; //bracket after @-rule
-$data['csstidy']['predefined_templates']['default'][] = '<span class="selector">'; //string before selector
-$data['csstidy']['predefined_templates']['default'][] = '</span> <span class="format">{</span>'."\n"; //bracket after selector
-$data['csstidy']['predefined_templates']['default'][] = '<span class="property">'; //string before property
-$data['csstidy']['predefined_templates']['default'][] = '</span><span class="value">'; //string after property+before value
-$data['csstidy']['predefined_templates']['default'][] = '</span><span class="format">;</span>'."\n"; //string after value
-$data['csstidy']['predefined_templates']['default'][] = '<span class="format">}</span>'; //closing bracket - selector
-$data['csstidy']['predefined_templates']['default'][] = "\n\n"; //space between blocks {...}
-$data['csstidy']['predefined_templates']['default'][] = "\n".'<span class="format">}</span>'. "\n\n"; //closing bracket @-rule
-$data['csstidy']['predefined_templates']['default'][] = ''; //indent in @-rule
-$data['csstidy']['predefined_templates']['default'][] = '<span class="comment">'; // before comment
-$data['csstidy']['predefined_templates']['default'][] = '</span>'."\n"; // after comment
-$data['csstidy']['predefined_templates']['default'][] = "\n"; // after each line @-rule
+$data['csstidy']['predefined_templates']['default'][0]  = '<span class="at">'; //string before @rule
+$data['csstidy']['predefined_templates']['default'][1]  = '</span> <span class="format">{</span>'."\n"; //bracket after @-rule
+$data['csstidy']['predefined_templates']['default'][2]  = '<span class="selector">'; //string before selector
+$data['csstidy']['predefined_templates']['default'][3]  = '</span> <span class="format">{</span>'."\n"; //bracket after selector
+$data['csstidy']['predefined_templates']['default'][4]  = '<span class="property">'; //string before property
+$data['csstidy']['predefined_templates']['default'][5]  = '</span><span class="value">'; //string after property+before value
+$data['csstidy']['predefined_templates']['default'][6]  = '</span><span class="format">;</span>'."\n"; //string after value
+$data['csstidy']['predefined_templates']['default'][7]  = '<span class="format">}</span>'; //closing bracket - selector
+$data['csstidy']['predefined_templates']['default'][8]  = "\n\n"; //space between blocks {...}
+$data['csstidy']['predefined_templates']['default'][9]  = "\n".'<span class="format">}</span>'. "\n\n"; //closing bracket @-rule
+$data['csstidy']['predefined_templates']['default'][10] = ''; //indent in @-rule
+$data['csstidy']['predefined_templates']['default'][11] = '<span class="comment">'; // before comment
+$data['csstidy']['predefined_templates']['default'][12] = '</span>'."\n"; // after comment
+$data['csstidy']['predefined_templates']['default'][13] = "\n"; // after each line @-rule
 
 $data['csstidy']['predefined_templates']['high_compression'][] = '<span class="at">';
 $data['csstidy']['predefined_templates']['high_compression'][] = '</span> <span class="format">{</span>'."\n";
index 151e8e9..36eea2e 100644 (file)
@@ -12,6 +12,8 @@
 
        <auteur>Collectif SPIP</auteur>
 
+       <credit lien="https://github.com/Cerdic/CSSTidy">Cerdic/CSSTidy</credit>
+
        <licence lien="http://www.gnu.org/licenses/gpl-3.0.html">GPL</licence>
 
        <traduire module="compresseur" reference="fr" gestionnaire="salvatore" />
@@ -24,4 +26,6 @@
        <pipeline nom="ieconfig_metas" inclure="compresseur_ieconfig.php" />
 
        <utilise nom="porte_plume" compatibilite="[1.18.1;]" />
+
+       <procure nom="csstidy" version="1.7.3" />
 </paquet>
index e39986c..fd1f758 100644 (file)
@@ -233,7 +233,7 @@ function document_instituer($id_document, $champs = array()) {
        }
 
        sql_updateq('spip_documents', $champs, 'id_document=' . intval($id_document));
-       if ($statut !== $statut_ancien) {
+       if (!empty($champs['statut'])) {
                $publier_rubriques = sql_allfetsel(
                        'id_objet',
                        'spip_documents_liens',
@@ -242,7 +242,7 @@ function document_instituer($id_document, $champs = array()) {
                if (count($publier_rubriques)) {
                        include_spip('inc/rubriques');
                        foreach ($publier_rubriques as $r) {
-                               calculer_rubriques_if($r['id_objet'], array('statut' => $statut), $statut_ancien, false);
+                               calculer_rubriques_if($r['id_objet'], array('statut' => $champs['statut']), $statut_ancien, false);
                        }
                }
        }
index 2d72d95..010af10 100644 (file)
@@ -215,13 +215,14 @@ class getID3_cached_dbm extends getID3
        /**
         * clear cache
         *
-        * @param string $filename
-        * @param int    $filesize
-        * @param string $original_filename
+        * @param string   $filename
+        * @param int      $filesize
+        * @param string   $original_filename
+        * @param resource $fp
         *
         * @return mixed
         */
-       public function analyze($filename, $filesize=null, $original_filename='') {
+       public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
 
                if (file_exists($filename)) {
 
@@ -238,7 +239,7 @@ class getID3_cached_dbm extends getID3
                }
 
                // Miss
-               $result = parent::analyze($filename);
+               $result = parent::analyze($filename, $filesize, $original_filename, $fp);
 
                // Save result
                if (isset($key) && file_exists($filename)) {
index 2dd2b12..6444bcd 100644 (file)
@@ -159,15 +159,16 @@ class getID3_cached_mysql extends getID3
        /**
         * analyze file
         *
-        * @param string $filename
-        * @param int    $filesize
-        * @param string $original_filename
+        * @param string   $filename
+        * @param int      $filesize
+        * @param string   $original_filename
+        * @param resource $fp
         *
         * @return mixed
         */
-       public function analyze($filename, $filesize=null, $original_filename='') {
+       public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
 
-        $filetime = 0;
+               $filetime = 0;
                if (file_exists($filename)) {
 
                        // Short-hands
@@ -189,7 +190,7 @@ class getID3_cached_mysql extends getID3
                }
 
                // Miss
-               $analysis = parent::analyze($filename, $filesize, $original_filename);
+               $analysis = parent::analyze($filename, $filesize, $original_filename, $fp);
 
                // Save result
                if (file_exists($filename)) {
index 44ea694..cee2c53 100644 (file)
@@ -87,6 +87,11 @@ class getID3_cached_mysqli extends getID3
         */
        private $table;
 
+       /**
+        * @var bool
+        */
+       private $db_structure_check;
+
 
        /**
         * constructor - see top of this file for cache type and cache_options
@@ -109,8 +114,8 @@ class getID3_cached_mysqli extends getID3
 
                // Connect to database
                $this->mysqli = new mysqli($host, $username, $password);
-               if (!$this->mysqli) {
-                       throw new Exception('mysqli_connect() failed - check permissions and spelling.');
+               if ($this->mysqli->connect_error) {
+                       throw new Exception('Connect Error (' . $this->mysqli->connect_errno . ') ' . $this->mysqli->connect_error);
                }
 
                // Select database
@@ -124,14 +129,15 @@ class getID3_cached_mysqli extends getID3
                // Create cache table if not exists
                $this->create_table();
 
+               $this->db_structure_check = true; // set to false if you know your table structure has already been migrated to use `hash` as the primary key to avoid
+               $this->migrate_db_structure();
+
                // Check version number and clear cache if changed
                $version = '';
                $SQLquery  = 'SELECT `value`';
                $SQLquery .= ' FROM `'.$this->mysqli->real_escape_string($this->table).'`';
                $SQLquery .= ' WHERE (`filename` = \''.$this->mysqli->real_escape_string(getID3::VERSION).'\')';
-               $SQLquery .= ' AND (`filesize` = -1)';
-               $SQLquery .= ' AND (`filetime` = -1)';
-               $SQLquery .= ' AND (`analyzetime` = -1)';
+               $SQLquery .= ' AND (`hash` = \'getID3::VERSION\')';
                if ($this->cursor = $this->mysqli->query($SQLquery)) {
                        list($version) = $this->cursor->fetch_array();
                }
@@ -147,23 +153,55 @@ class getID3_cached_mysqli extends getID3
         * clear cache
         */
        public function clear_cache() {
-               $this->mysqli->query('DELETE FROM `'.$this->mysqli->real_escape_string($this->table).'`');
-               $this->mysqli->query('INSERT INTO `'.$this->mysqli->real_escape_string($this->table).'` (`filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES (\''.getID3::VERSION.'\', -1, -1, -1, \''.getID3::VERSION.'\')');
+               $this->mysqli->query('TRUNCATE TABLE `'.$this->mysqli->real_escape_string($this->table).'`');
+               $this->mysqli->query('INSERT INTO `'.$this->mysqli->real_escape_string($this->table).'` (`hash`, `filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES (\'getID3::VERSION\', \''.getID3::VERSION.'\', -1, -1, -1, \''.getID3::VERSION.'\')');
+       }
+
+
+       /**
+        * migrate database structure if needed
+        */
+       public function migrate_db_structure() {
+               // Check for table structure
+               if ($this->db_structure_check) {
+                       $SQLquery  = 'SHOW COLUMNS';
+                       $SQLquery .= ' FROM `'.$this->mysqli->real_escape_string($this->table).'`';
+                       $SQLquery .= ' LIKE \'hash\'';
+                       $this->cursor = $this->mysqli->query($SQLquery);
+                       if ($this->cursor->num_rows == 0) {
+                               // table has not been migrated, add column, add hashes, change index
+                               $SQLquery  = 'ALTER TABLE `getid3_cache` DROP PRIMARY KEY, ADD `hash` CHAR(32) NOT NULL DEFAULT \'\' FIRST, ADD PRIMARY KEY(`hash`)';
+                               $this->mysqli->query($SQLquery);
+
+                               $SQLquery  = 'UPDATE `getid3_cache` SET';
+                               $SQLquery .= ' `hash` = MD5(`filename`, `filesize`, `filetime`)';
+                               $SQLquery .= ' WHERE (`filesize` > -1)';
+                               $this->mysqli->query($SQLquery);
+
+                               $SQLquery  = 'UPDATE `getid3_cache` SET';
+                               $SQLquery .= ' `hash` = \'getID3::VERSION\'';
+                               $SQLquery .= ' WHERE (`filesize` = -1)';
+                               $SQLquery .= '   AND (`filetime` = -1)';
+                               $SQLquery .= '   AND (`filetime` = -1)';
+                               $this->mysqli->query($SQLquery);
+                       }
+               }
        }
 
 
        /**
         * analyze file
         *
-        * @param string $filename
-        * @param int    $filesize
-        * @param string $original_filename
+        * @param string   $filename
+        * @param int      $filesize
+        * @param string   $original_filename
+        * @param resource $fp
         *
         * @return mixed
         */
-       public function analyze($filename, $filesize=null, $original_filename='') {
+       public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
 
-        $filetime = 0;
+               $filetime = 0;
                if (file_exists($filename)) {
 
                        // Short-hands
@@ -173,9 +211,7 @@ class getID3_cached_mysqli extends getID3
                        // Lookup file
                        $SQLquery  = 'SELECT `value`';
                        $SQLquery .= ' FROM `'.$this->mysqli->real_escape_string($this->table).'`';
-                       $SQLquery .= ' WHERE (`filename` = \''.$this->mysqli->real_escape_string($filename).'\')';
-                       $SQLquery .= '   AND (`filesize` = \''.$this->mysqli->real_escape_string($filesize).'\')';
-                       $SQLquery .= '   AND (`filetime` = \''.$this->mysqli->real_escape_string($filetime).'\')';
+                       $SQLquery .= ' WHERE (`hash` = \''.$this->mysqli->real_escape_string(md5($filename.$filesize.$filetime)).'\')';
                        $this->cursor = $this->mysqli->query($SQLquery);
                        if ($this->cursor->num_rows > 0) {
                                // Hit
@@ -185,16 +221,18 @@ class getID3_cached_mysqli extends getID3
                }
 
                // Miss
-               $analysis = parent::analyze($filename, $filesize, $original_filename);
+               $analysis = parent::analyze($filename, $filesize, $original_filename, $fp);
 
                // Save result
                if (file_exists($filename)) {
-                       $SQLquery  = 'INSERT INTO `'.$this->mysqli->real_escape_string($this->table).'` (`filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES (';
-                       $SQLquery .=   '\''.$this->mysqli->real_escape_string($filename).'\'';
+                       $SQLquery  = 'INSERT INTO `'.$this->mysqli->real_escape_string($this->table).'` (`hash`, `filename`, `filesize`, `filetime`, `analyzetime`, `value`) VALUES (';
+                       $SQLquery .=   '\''.$this->mysqli->real_escape_string(md5($filename.$filesize.$filetime)).'\'';
+                       $SQLquery .= ', \''.$this->mysqli->real_escape_string($filename).'\'';
                        $SQLquery .= ', \''.$this->mysqli->real_escape_string($filesize).'\'';
                        $SQLquery .= ', \''.$this->mysqli->real_escape_string($filetime).'\'';
-                       $SQLquery .= ', \''.$this->mysqli->real_escape_string(time()   ).'\'';
-                       $SQLquery .= ', \''.$this->mysqli->real_escape_string(base64_encode(serialize($analysis))).'\')';
+                       $SQLquery .= ', UNIX_TIMESTAMP()';
+                       $SQLquery .= ', \''.$this->mysqli->real_escape_string(base64_encode(serialize($analysis))).'\'';
+                       $SQLquery .= ')';
                        $this->cursor = $this->mysqli->query($SQLquery);
                }
                return $analysis;
@@ -207,13 +245,18 @@ class getID3_cached_mysqli extends getID3
         * @param bool $drop
         */
        private function create_table($drop=false) {
+               if ($drop) {
+                       $SQLquery  = 'DROP TABLE IF EXISTS `'.$this->mysqli->real_escape_string($this->table).'`';
+                       $this->mysqli->query($SQLquery);
+               }
                $SQLquery  = 'CREATE TABLE IF NOT EXISTS `'.$this->mysqli->real_escape_string($this->table).'` (';
-               $SQLquery .=   '`filename` VARCHAR(990) NOT NULL DEFAULT \'\'';
+               $SQLquery .=   '`hash` CHAR(32) NOT NULL DEFAULT \'\'';
+               $SQLquery .= ', `filename` VARCHAR(1000) NOT NULL DEFAULT \'\'';
                $SQLquery .= ', `filesize` INT(11) NOT NULL DEFAULT \'0\'';
                $SQLquery .= ', `filetime` INT(11) NOT NULL DEFAULT \'0\'';
                $SQLquery .= ', `analyzetime` INT(11) NOT NULL DEFAULT \'0\'';
                $SQLquery .= ', `value` LONGTEXT NOT NULL';
-               $SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`))';
+               $SQLquery .= ', PRIMARY KEY (`hash`))';
                $this->cursor = $this->mysqli->query($SQLquery);
                echo $this->mysqli->error;
        }
index 9e4a843..dbcc72a 100644 (file)
@@ -172,13 +172,14 @@ class getID3_cached_sqlite3 extends getID3
        /**
         * analyze file and cache them, if cached pull from the db
         *
-        * @param string  $filename
-        * @param integer $filesize
-        * @param string  $original_filename
+        * @param string   $filename
+        * @param integer  $filesize
+        * @param string   $original_filename
+        * @param resource $fp
         *
         * @return mixed|false
         */
-       public function analyze($filename, $filesize=null, $original_filename='') {
+       public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
                if (!file_exists($filename)) {
                        return false;
                }
@@ -201,7 +202,7 @@ class getID3_cached_sqlite3 extends getID3
                        return unserialize(base64_decode($result));
                }
                // if it hasn't been analyzed before, then do it now
-               $analysis = parent::analyze($filename, $filesize, $original_filename);
+               $analysis = parent::analyze($filename, $filesize, $original_filename, $fp);
                // Save result
                $sql = $this->getQuery('cache_file');
                $stmt = $db->prepare($sql);
@@ -262,25 +263,18 @@ class getID3_cached_sqlite3 extends getID3
                switch ($name) {
                        case 'version_check':
                                return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'";
-                               break;
                        case 'delete_cache':
                                return "DELETE FROM $this->table";
-                               break;
                        case 'set_version':
                                return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, -1, -1, -1, :val)";
-                               break;
                        case 'get_id3_data':
                                return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = :filesize AND filetime = :filetime";
-                               break;
                        case 'cache_file':
                                return "INSERT INTO $this->table (filename, dirname, filesize, filetime, analyzetime, val) VALUES (:filename, :dirname, :filesize, :filetime, :atime, :val)";
-                               break;
                        case 'make_table':
                                return "CREATE TABLE IF NOT EXISTS $this->table (filename VARCHAR(255) DEFAULT '', dirname VARCHAR(255) DEFAULT '', filesize INT(11) DEFAULT '0', filetime INT(11) DEFAULT '0', analyzetime INT(11) DEFAULT '0', val text, PRIMARY KEY (filename, filesize, filetime))";
-                               break;
                        case 'get_cached_dir':
                                return "SELECT val FROM $this->table WHERE dirname = :dirname";
-                               break;
                        default:
                                return null;
                }
index 5c5a5df..916c430 100644 (file)
 class getid3_lib
 {
        /**
-        * @param string $string
-        * @param bool   $hex
-        * @param bool   $spaces
-        * @param string $htmlencoding
+        * @param string      $string
+        * @param bool        $hex
+        * @param bool        $spaces
+        * @param string|bool $htmlencoding
         *
         * @return string
         */
@@ -26,9 +26,9 @@ class getid3_lib
                $returnstring = '';
                for ($i = 0; $i < strlen($string); $i++) {
                        if ($hex) {
-                               $returnstring .= str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT);
+                               $returnstring .= str_pad(dechex(ord($string[$i])), 2, '0', STR_PAD_LEFT);
                        } else {
-                               $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string{$i}) ? $string{$i} : '¤');
+                               $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string[$i]) ? $string[$i] : '¤');
                        }
                        if ($spaces) {
                                $returnstring .= ' ';
@@ -152,11 +152,11 @@ class getid3_lib
        public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
                if (strpos($binarypointnumber, '.') === false) {
                        $binarypointnumber = '0.'.$binarypointnumber;
-               } elseif ($binarypointnumber{0} == '.') {
+               } elseif ($binarypointnumber[0] == '.') {
                        $binarypointnumber = '0'.$binarypointnumber;
                }
                $exponent = 0;
-               while (($binarypointnumber{0} != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
+               while (($binarypointnumber[0] != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
                        if (substr($binarypointnumber, 1, 1) == '.') {
                                $exponent--;
                                $binarypointnumber = substr($binarypointnumber, 2, 1).'.'.substr($binarypointnumber, 3);
@@ -164,7 +164,7 @@ class getid3_lib
                                $pointpos = strpos($binarypointnumber, '.');
                                $exponent += ($pointpos - 1);
                                $binarypointnumber = str_replace('.', '', $binarypointnumber);
-                               $binarypointnumber = $binarypointnumber{0}.'.'.substr($binarypointnumber, 1);
+                               $binarypointnumber = $binarypointnumber[0].'.'.substr($binarypointnumber, 1);
                        }
                }
                $binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT);
@@ -216,7 +216,6 @@ class getid3_lib
 
                        default:
                                return false;
-                               break;
                }
                if ($floatvalue >= 0) {
                        $signbit = '0';
@@ -255,7 +254,7 @@ class getid3_lib
                if (!$bitword) {
                        return 0;
                }
-               $signbit = $bitword{0};
+               $signbit = $bitword[0];
                $floatvalue = 0;
                $exponentbits = 0;
                $fractionbits = 0;
@@ -275,7 +274,7 @@ class getid3_lib
                                // 80-bit Apple SANE format
                                // http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
                                $exponentstring = substr($bitword, 1, 15);
-                               $isnormalized = intval($bitword{16});
+                               $isnormalized = intval($bitword[16]);
                                $fractionstring = substr($bitword, 17, 63);
                                $exponent = pow(2, self::Bin2Dec($exponentstring) - 16383);
                                $fraction = $isnormalized + self::DecimalBinary2Float($fractionstring);
@@ -284,11 +283,9 @@ class getid3_lib
                                        $floatvalue *= -1;
                                }
                                return $floatvalue;
-                               break;
 
                        default:
                                return false;
-                               break;
                }
                $exponentstring = substr($bitword, 1, $exponentbits);
                $fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
@@ -343,9 +340,9 @@ class getid3_lib
                for ($i = 0; $i < $bytewordlen; $i++) {
                        if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
                                //$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7); // faster, but runs into problems past 2^31 on 32-bit systems
-                               $intvalue += (ord($byteword{$i}) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7);
+                               $intvalue += (ord($byteword[$i]) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7);
                        } else {
-                               $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i));
+                               $intvalue += ord($byteword[$i]) * pow(256, ($bytewordlen - 1 - $i));
                        }
                }
                if ($signed && !$synchsafe) {
@@ -390,7 +387,7 @@ class getid3_lib
                $binvalue = '';
                $bytewordlen = strlen($byteword);
                for ($i = 0; $i < $bytewordlen; $i++) {
-                       $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT);
+                       $binvalue .= str_pad(decbin(ord($byteword[$i])), 8, '0', STR_PAD_LEFT);
                }
                return $binvalue;
        }
@@ -451,7 +448,7 @@ class getid3_lib
        public static function Bin2Dec($binstring, $signed=false) {
                $signmult = 1;
                if ($signed) {
-                       if ($binstring{0} == '1') {
+                       if ($binstring[0] == '1') {
                                $signmult = -1;
                        }
                        $binstring = substr($binstring, 1);
@@ -500,8 +497,8 @@ class getid3_lib
        }
 
        /**
-        * @param array $array1
-        * @param array $array2
+        * @param mixed $array1
+        * @param mixed $array2
         *
         * @return array|false
         */
@@ -523,8 +520,8 @@ class getid3_lib
        }
 
        /**
-        * @param array $array1
-        * @param array $array2
+        * @param mixed $array1
+        * @param mixed $array2
         *
         * @return array|false
         */
@@ -544,8 +541,8 @@ class getid3_lib
        }
 
        /**
-        * @param array $array1
-        * @param array $array2
+        * @param mixed $array1
+        * @param mixed $array2
         *
         * @return array|false|null
         */
@@ -684,10 +681,10 @@ class getid3_lib
         */
        public static function array_max($arraydata, $returnkey=false) {
                $maxvalue = false;
-               $maxkey = false;
+               $maxkey   = false;
                foreach ($arraydata as $key => $value) {
                        if (!is_array($value)) {
-                               if ($value > $maxvalue) {
+                               if (($maxvalue === false) || ($value > $maxvalue)) {
                                        $maxvalue = $value;
                                        $maxkey = $key;
                                }
@@ -704,10 +701,10 @@ class getid3_lib
         */
        public static function array_min($arraydata, $returnkey=false) {
                $minvalue = false;
-               $minkey = false;
+               $minkey   = false;
                foreach ($arraydata as $key => $value) {
                        if (!is_array($value)) {
-                               if ($value > $minvalue) {
+                               if (($minvalue === false) || ($value < $minvalue)) {
                                        $minvalue = $value;
                                        $minkey = $key;
                                }
@@ -735,9 +732,9 @@ class getid3_lib
        }
 
        /**
-       * @param SimpleXMLElement|array $XMLobject
+       * @param SimpleXMLElement|array|mixed $XMLobject
        *
-       * @return array
+       * @return mixed
        */
        public static function SimpleXMLelement2array($XMLobject) {
                if (!is_object($XMLobject) && !is_array($XMLobject)) {
@@ -751,9 +748,7 @@ class getid3_lib
        }
 
        /**
-        * self::md5_data() - returns md5sum for a file from startuing position to absolute end position
-        *
-        * @author Allan Hansen <ahØartemis*dk>
+        * Returns checksum for a file from starting position to absolute end position.
         *
         * @param string $file
         * @param int    $offset
@@ -761,97 +756,30 @@ class getid3_lib
         * @param string $algorithm
         *
         * @return string|false
-        * @throws Exception
         * @throws getid3_exception
         */
        public static function hash_data($file, $offset, $end, $algorithm) {
-               static $tempdir = '';
-               $windows_call = null;
-               $unix_call = null;
-               $hash_length = null;
-               $hash_function = null;
                if (!self::intValueSupported($end)) {
                        return false;
                }
-               switch ($algorithm) {
-                       case 'md5':
-                               $hash_function = 'md5_file';
-                               $unix_call     = 'md5sum';
-                               $windows_call  = 'md5sum.exe';
-                               $hash_length   = 32;
-                               break;
-
-                       case 'sha1':
-                               $hash_function = 'sha1_file';
-                               $unix_call     = 'sha1sum';
-                               $windows_call  = 'sha1sum.exe';
-                               $hash_length   = 40;
-                               break;
-
-                       default:
-                               throw new Exception('Invalid algorithm ('.$algorithm.') in self::hash_data()');
-                               break;
+               if (!in_array($algorithm, array('md5', 'sha1'))) {
+                       throw new getid3_exception('Invalid algorithm ('.$algorithm.') in self::hash_data()');
                }
-               $size = $end - $offset;
-               while (true) {
-                       if (GETID3_OS_ISWINDOWS) {
 
-                               // It seems that sha1sum.exe for Windows only works on physical files, does not accept piped data
-                               // Fall back to create-temp-file method:
-                               if ($algorithm == 'sha1') {
-                                       break;
-                               }
-
-                               $RequiredFiles = array('cygwin1.dll', 'head.exe', 'tail.exe', $windows_call);
-                               foreach ($RequiredFiles as $required_file) {
-                                       if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
-                                               // helper apps not available - fall back to old method
-                                               break 2;
-                                       }
-                               }
-                               $commandline  = GETID3_HELPERAPPSDIR.'head.exe -c '.$end.' '.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, $file)).' | ';
-                               $commandline .= GETID3_HELPERAPPSDIR.'tail.exe -c '.$size.' | ';
-                               $commandline .= GETID3_HELPERAPPSDIR.$windows_call;
-
-                       } else {
-
-                               $commandline  = 'head -c'.$end.' '.escapeshellarg($file).' | ';
-                               $commandline .= 'tail -c'.$size.' | ';
-                               $commandline .= $unix_call;
+               $size = $end - $offset;
 
-                       }
-                       if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
-                               //throw new Exception('PHP running in Safe Mode - backtick operator not available, using slower non-system-call '.$algorithm.' algorithm');
-                               break;
-                       }
-                       return substr(`$commandline`, 0, $hash_length);
+               $fp = fopen($file, 'rb');
+               fseek($fp, $offset);
+               $ctx = hash_init($algorithm);
+               while ($size > 0) {
+                       $buffer = fread($fp, min($size, getID3::FREAD_BUFFER_SIZE));
+                       hash_update($ctx, $buffer);
+                       $size -= getID3::FREAD_BUFFER_SIZE;
                }
+               $hash = hash_final($ctx);
+               fclose($fp);
 
-               if (empty($tempdir)) {
-                       // yes this is ugly, feel free to suggest a better way
-                       require_once(dirname(__FILE__).'/getid3.php');
-                       $getid3_temp = new getID3();
-                       $tempdir = $getid3_temp->tempdir;
-                       unset($getid3_temp);
-               }
-               // try to create a temporary file in the system temp directory - invalid dirname should force to system temp dir
-               if (($data_filename = tempnam($tempdir, 'gI3')) === false) {
-                       // can't find anywhere to create a temp file, just fail
-                       return false;
-               }
-
-               // Init
-               $result = false;
-
-               // copy parts of file
-               try {
-                       self::CopyFileParts($file, $data_filename, $offset, $end - $offset);
-                       $result = $hash_function($data_filename);
-               } catch (Exception $e) {
-                       throw new Exception('self::CopyFileParts() failed in getid_lib::hash_data(): '.$e->getMessage());
-               }
-               unlink($data_filename);
-               return $result;
+               return $hash;
        }
 
        /**
@@ -862,6 +790,8 @@ class getid3_lib
         *
         * @return bool
         * @throws Exception
+        *
+        * @deprecated Unused, may be removed in future versions of getID3
         */
        public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) {
                if (!self::intValueSupported($offset + $length)) {
@@ -935,7 +865,7 @@ class getid3_lib
                        $newcharstring .= "\xEF\xBB\xBF";
                }
                for ($i = 0; $i < strlen($string); $i++) {
-                       $charval = ord($string{$i});
+                       $charval = ord($string[$i]);
                        $newcharstring .= self::iconv_fallback_int_utf8($charval);
                }
                return $newcharstring;
@@ -955,7 +885,7 @@ class getid3_lib
                        $newcharstring .= "\xFE\xFF";
                }
                for ($i = 0; $i < strlen($string); $i++) {
-                       $newcharstring .= "\x00".$string{$i};
+                       $newcharstring .= "\x00".$string[$i];
                }
                return $newcharstring;
        }
@@ -974,7 +904,7 @@ class getid3_lib
                        $newcharstring .= "\xFF\xFE";
                }
                for ($i = 0; $i < strlen($string); $i++) {
-                       $newcharstring .= $string{$i}."\x00";
+                       $newcharstring .= $string[$i]."\x00";
                }
                return $newcharstring;
        }
@@ -1006,27 +936,27 @@ class getid3_lib
                $offset = 0;
                $stringlength = strlen($string);
                while ($offset < $stringlength) {
-                       if ((ord($string{$offset}) | 0x07) == 0xF7) {
+                       if ((ord($string[$offset]) | 0x07) == 0xF7) {
                                // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
-                               $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) << 12) &
-                                                  ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 3)}) & 0x3F);
+                               $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) << 12) &
+                                                  ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 3)]) & 0x3F);
                                $offset += 4;
-                       } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
+                       } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
                                // 1110bbbb 10bbbbbb 10bbbbbb
-                               $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 2)}) & 0x3F);
+                               $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 2)]) & 0x3F);
                                $offset += 3;
-                       } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
+                       } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
                                // 110bbbbb 10bbbbbb
-                               $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
-                                                       (ord($string{($offset + 1)}) & 0x3F);
+                               $charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
+                                                       (ord($string[($offset + 1)]) & 0x3F);
                                $offset += 2;
-                       } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
+                       } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
                                // 0bbbbbbb
-                               $charval = ord($string{$offset});
+                               $charval = ord($string[$offset]);
                                $offset += 1;
                        } else {
                                // error? throw some kind of warning here?
@@ -1056,27 +986,27 @@ class getid3_lib
                $offset = 0;
                $stringlength = strlen($string);
                while ($offset < $stringlength) {
-                       if ((ord($string{$offset}) | 0x07) == 0xF7) {
+                       if ((ord($string[$offset]) | 0x07) == 0xF7) {
                                // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
-                               $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) << 12) &
-                                                  ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 3)}) & 0x3F);
+                               $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) << 12) &
+                                                  ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 3)]) & 0x3F);
                                $offset += 4;
-                       } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
+                       } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
                                // 1110bbbb 10bbbbbb 10bbbbbb
-                               $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 2)}) & 0x3F);
+                               $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 2)]) & 0x3F);
                                $offset += 3;
-                       } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
+                       } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
                                // 110bbbbb 10bbbbbb
-                               $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
-                                                       (ord($string{($offset + 1)}) & 0x3F);
+                               $charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
+                                                       (ord($string[($offset + 1)]) & 0x3F);
                                $offset += 2;
-                       } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
+                       } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
                                // 0bbbbbbb
-                               $charval = ord($string{$offset});
+                               $charval = ord($string[$offset]);
                                $offset += 1;
                        } else {
                                // error? throw some kind of warning here?
@@ -1106,27 +1036,27 @@ class getid3_lib
                $offset = 0;
                $stringlength = strlen($string);
                while ($offset < $stringlength) {
-                       if ((ord($string{$offset}) | 0x07) == 0xF7) {
+                       if ((ord($string[$offset]) | 0x07) == 0xF7) {
                                // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
-                               $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) << 12) &
-                                                  ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 3)}) & 0x3F);
+                               $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) << 12) &
+                                                  ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 3)]) & 0x3F);
                                $offset += 4;
-                       } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
+                       } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
                                // 1110bbbb 10bbbbbb 10bbbbbb
-                               $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
-                                                  ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
-                                                       (ord($string{($offset + 2)}) & 0x3F);
+                               $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
+                                                  ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
+                                                       (ord($string[($offset + 2)]) & 0x3F);
                                $offset += 3;
-                       } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
+                       } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
                                // 110bbbbb 10bbbbbb
-                               $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
-                                                       (ord($string{($offset + 1)}) & 0x3F);
+                               $charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
+                                                       (ord($string[($offset + 1)]) & 0x3F);
                                $offset += 2;
-                       } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
+                       } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
                                // 0bbbbbbb
-                               $charval = ord($string{$offset});
+                               $charval = ord($string[$offset]);
                                $offset += 1;
                        } else {
                                // error? maybe throw some warning here?
@@ -1281,6 +1211,16 @@ class getid3_lib
 
                // mb_convert_encoding() available
                if (function_exists('mb_convert_encoding')) {
+                       if ((strtoupper($in_charset) == 'UTF-16') && (substr($string, 0, 2) != "\xFE\xFF") && (substr($string, 0, 2) != "\xFF\xFE")) {
+                               // if BOM missing, mb_convert_encoding will mishandle the conversion, assume UTF-16BE and prepend appropriate BOM
+                               $string = "\xFF\xFE".$string;
+                       }
+                       if ((strtoupper($in_charset) == 'UTF-16') && (strtoupper($out_charset) == 'UTF-8')) {
+                               if (($string == "\xFF\xFE") || ($string == "\xFE\xFF")) {
+                                       // if string consists of only BOM, mb_convert_encoding will return the BOM unmodified
+                                       return '';
+                               }
+                       }
                        if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) {
                                switch ($out_charset) {
                                        case 'ISO-8859-1':
@@ -1290,9 +1230,9 @@ class getid3_lib
                                return $converted_string;
                        }
                        return $string;
-               }
+
                // iconv() available
-               else if (function_exists('iconv')) {
+               } elseif (function_exists('iconv')) {
                        if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
                                switch ($out_charset) {
                                        case 'ISO-8859-1':
@@ -1397,22 +1337,22 @@ class getid3_lib
                        case 'utf-8':
                                $strlen = strlen($string);
                                for ($i = 0; $i < $strlen; $i++) {
-                                       $char_ord_val = ord($string{$i});
+                                       $char_ord_val = ord($string[$i]);
                                        $charval = 0;
                                        if ($char_ord_val < 0x80) {
                                                $charval = $char_ord_val;
                                        } elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F  &&  $i+3 < $strlen) {
                                                $charval  = (($char_ord_val & 0x07) << 18);
-                                               $charval += ((ord($string{++$i}) & 0x3F) << 12);
-                                               $charval += ((ord($string{++$i}) & 0x3F) << 6);
-                                               $charval +=  (ord($string{++$i}) & 0x3F);
+                                               $charval += ((ord($string[++$i]) & 0x3F) << 12);
+                                               $charval += ((ord($string[++$i]) & 0x3F) << 6);
+                                               $charval +=  (ord($string[++$i]) & 0x3F);
                                        } elseif ((($char_ord_val & 0xE0) >> 5) == 0x07  &&  $i+2 < $strlen) {
                                                $charval  = (($char_ord_val & 0x0F) << 12);
-                                               $charval += ((ord($string{++$i}) & 0x3F) << 6);
-                                               $charval +=  (ord($string{++$i}) & 0x3F);
+                                               $charval += ((ord($string[++$i]) & 0x3F) << 6);
+                                               $charval +=  (ord($string[++$i]) & 0x3F);
                                        } elseif ((($char_ord_val & 0xC0) >> 6) == 0x03  &&  $i+1 < $strlen) {
                                                $charval  = (($char_ord_val & 0x1F) << 6);
-                                               $charval += (ord($string{++$i}) & 0x3F);
+                                               $charval += (ord($string[++$i]) & 0x3F);
                                        }
                                        if (($charval >= 32) && ($charval <= 127)) {
                                                $HTMLstring .= htmlentities(chr($charval));
@@ -1536,6 +1476,15 @@ class getid3_lib
         * @return array|false
         */
        public static function GetDataImageSize($imgData, &$imageinfo=array()) {
+               if (PHP_VERSION_ID >= 50400) {
+                       $GetDataImageSize = @getimagesizefromstring($imgData, $imageinfo);
+                       if ($GetDataImageSize === false || !isset($GetDataImageSize[0], $GetDataImageSize[1])) {
+                               return false;
+                       }
+                       $GetDataImageSize['height'] = $GetDataImageSize[0];
+                       $GetDataImageSize['width'] = $GetDataImageSize[1];
+                       return $GetDataImageSize;
+               }
                static $tempdir = '';
                if (empty($tempdir)) {
                        if (function_exists('sys_get_temp_dir')) {
@@ -1544,12 +1493,11 @@ class getid3_lib
 
                        // yes this is ugly, feel free to suggest a better way
                        if (include_once(dirname(__FILE__).'/getid3.php')) {
-                               if ($getid3_temp = new getID3()) {
-                                       if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
-                                               $tempdir = $getid3_temp_tempdir;
-                                       }
-                                       unset($getid3_temp, $getid3_temp_tempdir);
+                               $getid3_temp = new getID3();
+                               if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
+                                       $tempdir = $getid3_temp_tempdir;
                                }
+                               unset($getid3_temp, $getid3_temp_tempdir);
                        }
                }
                $GetDataImageSize = false;
@@ -1581,13 +1529,20 @@ class getid3_lib
 
        /**
         * @param array $ThisFileInfo
+        * @param bool  $option_tags_html default true (just as in the main getID3 class)
         *
         * @return bool
         */
-       public static function CopyTagsToComments(&$ThisFileInfo) {
-
+       public static function CopyTagsToComments(&$ThisFileInfo, $option_tags_html=true) {
                // Copy all entries from ['tags'] into common ['comments']
                if (!empty($ThisFileInfo['tags'])) {
+                       if (isset($ThisFileInfo['tags']['id3v1'])) {
+                               // bubble ID3v1 to the end, if present to aid in detecting bad ID3v1 encodings
+                               $ID3v1 = $ThisFileInfo['tags']['id3v1'];
+                               unset($ThisFileInfo['tags']['id3v1']);
+                               $ThisFileInfo['tags']['id3v1'] = $ID3v1;
+                               unset($ID3v1);
+                       }
                        foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) {
                                foreach ($tagarray as $tagname => $tagdata) {
                                        foreach ($tagdata as $key => $value) {
@@ -1606,6 +1561,13 @@ class getid3_lib
                                                                                break 2;
                                                                        }
                                                                }
+                                                               if (function_exists('mb_convert_encoding')) {
+                                                                       if (trim($value) == trim(substr(mb_convert_encoding($existingvalue, $ThisFileInfo['id3v1']['encoding'], $ThisFileInfo['encoding']), 0, 30))) {
+                                                                               // value stored in ID3v1 appears to be probably the multibyte value transliterated (badly) into ISO-8859-1 in ID3v1.
+                                                                               // As an example, Foobar2000 will do this if you tag a file with Chinese or Arabic or Cyrillic or something that doesn't fit into ISO-8859-1 the ID3v1 will consist of mostly "?" characters, one per multibyte unrepresentable character
+                                                                               break 2;
+                                                                       }
+                                                               }
 
                                                        } elseif (!is_array($value)) {
 
@@ -1614,7 +1576,6 @@ class getid3_lib
                                                                        $oldvaluelength = strlen(trim($existingvalue));
                                                                        if ((strlen($existingvalue) > 10) && ($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) {
                                                                                $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
-                                                                               //break 2;
                                                                                break;
                                                                        }
                                                                }
@@ -1625,7 +1586,7 @@ class getid3_lib
                                                                if (!is_int($key) && !ctype_digit($key)) {
                                                                        $ThisFileInfo['comments'][$tagname][$key] = $value;
                                                                } else {
-                                                                       if (isset($ThisFileInfo['comments'][$tagname])) {
+                                                                       if (!isset($ThisFileInfo['comments'][$tagname])) {
                                                                                $ThisFileInfo['comments'][$tagname] = array($value);
                                                                        } else {
                                                                                $ThisFileInfo['comments'][$tagname][] = $value;
@@ -1649,19 +1610,21 @@ class getid3_lib
                                }
                        }
 
-                       // Copy to ['comments_html']
-                       if (!empty($ThisFileInfo['comments'])) {
-                               foreach ($ThisFileInfo['comments'] as $field => $values) {
-                                       if ($field == 'picture') {
-                                               // pictures can take up a lot of space, and we don't need multiple copies of them
-                                               // let there be a single copy in [comments][picture], and not elsewhere
-                                               continue;
-                                       }
-                                       foreach ($values as $index => $value) {
-                                               if (is_array($value)) {
-                                                       $ThisFileInfo['comments_html'][$field][$index] = $value;
-                                               } else {
-                                                       $ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
+                       if ($option_tags_html) {
+                               // Copy ['comments'] to ['comments_html']
+                               if (!empty($ThisFileInfo['comments'])) {
+                                       foreach ($ThisFileInfo['comments'] as $field => $values) {
+                                               if ($field == 'picture') {
+                                                       // pictures can take up a lot of space, and we don't need multiple copies of them
+                                                       // let there be a single copy in [comments][picture], and not elsewhere
+                                                       continue;
+                                               }
+                                               foreach ($values as $index => $value) {
+                                                       if (is_array($value)) {
+                                                               $ThisFileInfo['comments_html'][$field][$index] = $value;
+                                                       } else {
+                                                               $ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
+                                                       }
                                                }
                                        }
                                }
index 90d7c9c..bce97fb 100644 (file)
@@ -1,5 +1,4 @@
 <?php
-
 /////////////////////////////////////////////////////////////////
 /// getID3() by James Heinrich <info@getid3.org>               //
 //  available at https://github.com/JamesHeinrich/getID3       //
@@ -100,6 +99,13 @@ class getID3
         */
        public $encoding_id3v1  = 'ISO-8859-1';
 
+       /**
+        * ID3v1 should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'Windows-1251' or 'KOI8-R'. If true attempt to detect these encodings, but may return incorrect values for some tags actually in ISO-8859-1 encoding
+        *
+        * @var bool
+        */
+       public $encoding_id3v1_autodetect  = false;
+
        /*
         * Optional tag checks - disable for speed.
         */
@@ -251,7 +257,7 @@ class getID3
         */
        protected $startup_warning = '';
 
-       const VERSION           = '1.9.16-201810171314';
+       const VERSION           = '1.9.20-202006061653';
        const FREAD_BUFFER_SIZE = 32768;
 
        const ATTACHMENTS_NONE   = false;
@@ -267,14 +273,16 @@ class getID3
                }
 
                // Check memory
-               $this->memory_limit = ini_get('memory_limit');
-               if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $matches)) {
+               $memoryLimit = ini_get('memory_limit');
+               if (preg_match('#([0-9]+) ?M#i', $memoryLimit, $matches)) {
                        // could be stored as "16M" rather than 16777216 for example
-                       $this->memory_limit = $matches[1] * 1048576;
-               } elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
+                       $memoryLimit = $matches[1] * 1048576;
+               } elseif (preg_match('#([0-9]+) ?G#i', $memoryLimit, $matches)) { // The 'G' modifier is available since PHP 5.1.0
                        // could be stored as "2G" rather than 2147483648 for example
-                       $this->memory_limit = $matches[1] * 1073741824;
+                       $memoryLimit = $matches[1] * 1073741824;
                }
+               $this->memory_limit = $memoryLimit;
+
                if ($this->memory_limit <= 0) {
                        // memory limits probably disabled
                } elseif ($this->memory_limit <= 4194304) {
@@ -288,24 +296,26 @@ class getID3
                        $this->warning('WARNING: Safe mode is on, shorten support disabled, md5data/sha1data for ogg vorbis disabled, ogg vorbos/flac tag writing disabled.');
                }
 
-               if (($mbstring_func_overload = ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) {
+               if (($mbstring_func_overload = (int) ini_get('mbstring.func_overload')) && ($mbstring_func_overload & 0x02)) {
                        // http://php.net/manual/en/mbstring.overload.php
                        // "mbstring.func_overload in php.ini is a positive value that represents a combination of bitmasks specifying the categories of functions to be overloaded. It should be set to 1 to overload the mail() function. 2 for string functions, 4 for regular expression functions"
                        // getID3 cannot run when string functions are overloaded. It doesn't matter if mail() or ereg* functions are overloaded since getID3 does not use those.
                        $this->startup_error .= 'WARNING: php.ini contains "mbstring.func_overload = '.ini_get('mbstring.func_overload').'", getID3 cannot run with this setting (bitmask 2 (string functions) cannot be set). Recommended to disable entirely.'."\n";
                }
 
-               // Check for magic_quotes_runtime
-               if (function_exists('get_magic_quotes_runtime')) {
-                       if (get_magic_quotes_runtime()) {
-                               $this->startup_error .= 'magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'."\n";
+               // check for magic quotes in PHP < 7.4.0 (when these functions became deprecated)
+               if (version_compare(PHP_VERSION, '7.4.0', '<')) {
+                       // Check for magic_quotes_runtime
+                       if (function_exists('get_magic_quotes_runtime')) {
+                               if (get_magic_quotes_runtime()) {
+                                       $this->startup_error .= 'magic_quotes_runtime must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_runtime(0) and set_magic_quotes_runtime(1).'."\n";
+                               }
                        }
-               }
-
-               // Check for magic_quotes_gpc
-               if (function_exists('magic_quotes_gpc')) {
-                       if (get_magic_quotes_gpc()) {
-                               $this->startup_error .= 'magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'."\n";
+                       // Check for magic_quotes_gpc
+                       if (function_exists('get_magic_quotes_gpc')) {
+                               if (get_magic_quotes_gpc()) {
+                                       $this->startup_error .= 'magic_quotes_gpc must be disabled before running getID3(). Surround getid3 block by set_magic_quotes_gpc(0) and set_magic_quotes_gpc(1).'."\n";
+                               }
                        }
                }
 
@@ -321,7 +331,7 @@ class getID3
 
                // Needed for Windows only:
                // Define locations of helper applications for Shorten, VorbisComment, MetaFLAC
-               //   as well as other helper functions such as head, tail, md5sum, etc
+               //   as well as other helper functions such as head, etc
                // This path cannot contain spaces, but the below code will attempt to get the
                //   8.3-equivalent path automatically
                // IMPORTANT: This path must include the trailing slash
@@ -399,14 +409,15 @@ class getID3
        }
 
        /**
-        * @param string $filename
-        * @param int    $filesize
+        * @param string   $filename
+        * @param int      $filesize
+        * @param resource $fp
         *
         * @return bool
         *
         * @throws getid3_exception
         */
-       public function openfile($filename, $filesize=null) {
+       public function openfile($filename, $filesize=null, $fp=null) {
                try {
                        if (!empty($this->startup_error)) {
                                throw new getid3_exception($this->startup_error);
@@ -433,7 +444,9 @@ class getID3
 
                        // open local file
                        //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see https://www.getid3.org/phpBB3/viewtopic.php?t=1720
-                       if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
+                       if (($fp != null) && ((get_resource_type($fp) == 'file') || (get_resource_type($fp) == 'stream'))) {
+                               $this->fp = $fp;
+                       } elseif ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) {
                                // great
                        } else {
                                $errormessagelist = array();
@@ -508,15 +521,16 @@ class getID3
        /**
         * analyze file
         *
-        * @param string $filename
-        * @param int    $filesize
-        * @param string $original_filename
+        * @param string   $filename
+        * @param int      $filesize
+        * @param string   $original_filename
+        * @param resource $fp
         *
         * @return array
         */
-       public function analyze($filename, $filesize=null, $original_filename='') {
+       public function analyze($filename, $filesize=null, $original_filename='', $fp=null) {
                try {
-                       if (!$this->openfile($filename, $filesize)) {
+                       if (!$this->openfile($filename, $filesize, $fp)) {
                                return $this->info;
                        }
 
@@ -550,8 +564,8 @@ class getID3
                                $header = fread($this->fp, 10);
                                if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) {
                                        $this->info['id3v2']['header']        = true;
-                                       $this->info['id3v2']['majorversion']  = ord($header{3});
-                                       $this->info['id3v2']['minorversion']  = ord($header{4});
+                                       $this->info['id3v2']['majorversion']  = ord($header[3]);
+                                       $this->info['id3v2']['minorversion']  = ord($header[4]);
                                        $this->info['avdataoffset']          += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length
                                }
                        }
@@ -833,12 +847,20 @@ class getID3
 
                                // DSS  - audio       - Digital Speech Standard
                                'dss'  => array(
-                                                       'pattern'   => '^[\\x02-\\x06]ds[s2]',
+                                                       'pattern'   => '^[\\x02-\\x08]ds[s2]',
                                                        'group'     => 'audio',
                                                        'module'    => 'dss',
                                                        'mime_type' => 'application/octet-stream',
                                                ),
 
+                               // DSDIFF - audio     - Direct Stream Digital Interchange File Format
+                               'dsdiff' => array(
+                                                       'pattern'   => '^FRM8',
+                                                       'group'     => 'audio',
+                                                       'module'    => 'dsdiff',
+                                                       'mime_type' => 'audio/dsd',
+                                               ),
+
                                // DTS  - audio       - Dolby Theatre System
                                'dts'  => array(
                                                        'pattern'   => '^\\x7F\\xFE\\x80\\x01',
@@ -966,6 +988,14 @@ class getID3
                                                        'fail_ape'  => 'ERROR',
                                                ),
 
+                               // TAK  - audio       - Tom's lossless Audio Kompressor
+                               'tak'  => array(
+                                                       'pattern'   => '^tBaK',
+                                                       'group'     => 'audio',
+                                                       'module'    => 'tak',
+                                                       'mime_type' => 'application/octet-stream',
+                                               ),
+
                                // TTA  - audio       - TTA Lossless Audio Compressor (http://tta.corecodec.org)
                                'tta'  => array(
                                                        'pattern'   => '^TTA',  // could also be '^TTA(\\x01|\\x02|\\x03|2|1)'
@@ -1026,6 +1056,14 @@ class getID3
                                                        'mime_type' => 'video/x-flv',
                                                ),
 
+                               // IVF - audio/video - IVF
+                               'ivf' => array(
+                                                       'pattern'   => '^DKIF',
+                                                       'group'     => 'audio-video',
+                                                       'module'    => 'ivf',
+                                                       'mime_type' => 'video/x-ivf',
+                                               ),
+
                                // MKAV - audio/video - Mastroka
                                'matroska' => array(
                                                        'pattern'   => '^\\x1A\\x45\\xDF\\xA3',
@@ -1101,6 +1139,14 @@ class getID3
                                                        'mime_type' => 'video/MP2T',
                                                ),
 
+                               // WTV - audio/video - Windows Recorded TV Show
+                               'wtv' => array(
+                                                       'pattern'   => '^\\xB7\\xD8\\x00\\x20\\x37\\x49\\xDA\\x11\\xA6\\x4E\\x00\\x07\\xE9\\x5E\\xAD\\x8D',
+                                                       'group'     => 'audio-video',
+                                                       'module'    => 'wtv',
+                                                       'mime_type' => 'video/x-ms-wtv',
+                                               ),
+
 
                                // Still-Image formats
 
@@ -1202,12 +1248,22 @@ class getID3
                                                        'iconv_req' => false,
                                                ),
 
+                               // HPK  - data        - HPK compressed data
+                               'hpk'  => array(
+                                                       'pattern'   => '^BPUL',
+                                                       'group'     => 'archive',
+                                                       'module'    => 'hpk',
+                                                       'mime_type' => 'application/octet-stream',
+                                                       'fail_id3'  => 'ERROR',
+                                                       'fail_ape'  => 'ERROR',
+                                               ),
+
                                // RAR  - data        - RAR compressed data
                                'rar'  => array(
                                                        'pattern'   => '^Rar\\!',
                                                        'group'     => 'archive',
                                                        'module'    => 'rar',
-                                                       'mime_type' => 'application/octet-stream',
+                                                       'mime_type' => 'application/vnd.rar',
                                                        'fail_id3'  => 'ERROR',
                                                        'fail_ape'  => 'ERROR',
                                                ),
@@ -1252,6 +1308,16 @@ class getID3
                                                        'fail_ape'  => 'ERROR',
                                                ),
 
+                               // XZ   - data         - XZ compressed data
+                               'xz'  => array(
+                                                       'pattern'   => '^\\xFD7zXZ\\x00',
+                                                       'group'     => 'archive',
+                                                       'module'    => 'xz',
+                                                       'mime_type' => 'application/x-xz',
+                                                       'fail_id3'  => 'ERROR',
+                                                       'fail_ape'  => 'ERROR',
+                                               ),
+
 
                                // Misc other formats
 
@@ -1323,7 +1389,7 @@ class getID3
 
 
                if (preg_match('#\\.mp[123a]$#i', $filename)) {
-                       // Too many mp3 encoders on the market put gabage in front of mpeg files
+                       // Too many mp3 encoders on the market put garbage in front of mpeg files
                        // use assume format on these if format detection failed
                        $GetFileFormatArray = $this->GetFileFormatArray();
                        $info = $GetFileFormatArray['mp3'];
@@ -1399,6 +1465,7 @@ class getID3
                                'flac'      => array('vorbiscomment' , 'UTF-8'),
                                'divxtag'   => array('divx'          , 'ISO-8859-1'),
                                'iptc'      => array('iptc'          , 'ISO-8859-1'),
+                               'dsdiff'    => array('dsdiff'        , 'ISO-8859-1'),
                        );
                }
 
@@ -1427,6 +1494,7 @@ class getID3
                                                }
                                        }
                                        if ($tag_key == 'picture') {
+                                               // pictures can take up a lot of space, and we don't need multiple copies of them; let there be a single copy in [comments][picture], and not elsewhere
                                                unset($this->info[$comment_name]['comments'][$tag_key]);
                                        }
                                }
@@ -1440,6 +1508,11 @@ class getID3
 
                                if ($this->option_tags_html) {
                                        foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) {
+                                               if ($tag_key == 'picture') {
+                                                       // Do not to try to convert binary picture data to HTML
+                                                       // https://github.com/JamesHeinrich/getID3/issues/178
+                                                       continue;
+                                               }
                                                $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']);
                                        }
                                }
@@ -1448,8 +1521,7 @@ class getID3
 
                }
 
-               // pictures can take up a lot of space, and we don't need multiple copies of them
-               // let there be a single copy in [comments][picture], and not elsewhere
+               // pictures can take up a lot of space, and we don't need multiple copies of them; let there be a single copy in [comments][picture], and not elsewhere
                if (!empty($this->info['tags'])) {
                        $unset_keys = array('tags', 'tags_html');
                        foreach ($this->info['tags'] as $tagtype => $tagarray) {
@@ -1495,6 +1567,17 @@ class getID3
                return true;
        }
 
+       /**
+        * Calls getid3_lib::CopyTagsToComments() but passes in the option_tags_html setting from this instance of getID3
+        *
+        * @param array $ThisFileInfo
+        *
+        * @return bool
+        */
+       public function CopyTagsToComments(&$ThisFileInfo) {
+           return getid3_lib::CopyTagsToComments($ThisFileInfo, $this->option_tags_html);
+       }
+
        /**
         * @param string $algorithm
         *
@@ -1508,7 +1591,6 @@ class getID3
 
                        default:
                                return $this->error('bad algorithm "'.$algorithm.'" in getHashdata()');
-                               break;
                }
 
                if (!empty($this->info['fileformat']) && !empty($this->info['dataformat']) && ($this->info['fileformat'] == 'ogg') && ($this->info['audio']['dataformat'] == 'vorbis')) {
@@ -1824,16 +1906,14 @@ class getID3
         *
         * @return bool
         */
-    public static function is_writable ($filename) {
-        $ret = is_writable($filename);
-
-        if (!$ret) {
-            $perms = fileperms($filename);
-            $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002);
-        }
-
-        return $ret;
-    }
+       public static function is_writable ($filename) {
+               $ret = is_writable($filename);
+               if (!$ret) {
+                       $perms = fileperms($filename);
+                       $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002);
+               }
+               return $ret;
+       }
 
 }
 
@@ -1976,7 +2056,8 @@ abstract class getid3_handler
                */
                $contents = '';
                do {
-                       if (($this->getid3->memory_limit > 0) && ($bytes > $this->getid3->memory_limit)) {
+                       //if (($this->getid3->memory_limit > 0) && ($bytes > $this->getid3->memory_limit)) {
+                       if (($this->getid3->memory_limit > 0) && (($bytes / $this->getid3->memory_limit) > 0.99)) { // enable a more-fuzzy match to prevent close misses generating errors like "PHP Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 33554464 bytes)"
                                throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') that is more than available PHP memory ('.$this->getid3->memory_limit.')', 10);
                        }
                        $part = fread($this->getid3->fp, $bytes);
@@ -2025,6 +2106,61 @@ abstract class getid3_handler
                return fseek($this->getid3->fp, $bytes, $whence);
        }
 
+       /**
+        * @return string|false
+        *
+        * @throws getid3_exception
+        */
+       protected function fgets() {
+               // must be able to handle CR/LF/CRLF but not read more than one lineend
+               $buffer   = ''; // final string we will return
+               $prevchar = ''; // save previously-read character for end-of-line checking
+               if ($this->data_string_flag) {
+                       while (true) {
+                               $thischar = substr($this->data_string, $this->data_string_position++, 1);
+                               if (($prevchar == "\r") && ($thischar != "\n")) {
+                                       // read one byte too many, back up
+                                       $this->data_string_position--;
+                                       break;
+                               }
+                               $buffer .= $thischar;
+                               if ($thischar == "\n") {
+                                       break;
+                               }
+                               if ($this->data_string_position >= $this->data_string_length) {
+                                       // EOF
+                                       break;
+                               }
+                               $prevchar = $thischar;
+                       }
+
+               } else {
+
+                       // Ideally we would just use PHP's fgets() function, however...
+                       // it does not behave consistently with regards to mixed line endings, may be system-dependent
+                       // and breaks entirely when given a file with mixed \r vs \n vs \r\n line endings (e.g. some PDFs)
+                       //return fgets($this->getid3->fp);
+                       while (true) {
+                               $thischar = fgetc($this->getid3->fp);
+                               if (($prevchar == "\r") && ($thischar != "\n")) {
+                                       // read one byte too many, back up
+                                       fseek($this->getid3->fp, -1, SEEK_CUR);
+                                       break;
+                               }
+                               $buffer .= $thischar;
+                               if ($thischar == "\n") {
+                                       break;
+                               }
+                               if (feof($this->getid3->fp)) {
+                                       break;
+                               }
+                               $prevchar = $thischar;
+                       }
+
+               }
+               return $buffer;
+       }
+
        /**
         * @return bool
         */
index 5d730be..18d49f3 100644 (file)
@@ -19,6 +19,9 @@
 //                                                             //
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_gzip extends getid3_handler
 {
index c8f2678..4d40160 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_rar extends getid3_handler
 {
index 5b0601b..8647967 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_szip extends getid3_handler
 {
index 952a626..5b4aa56 100644 (file)
@@ -19,6 +19,9 @@
 //                                                             //
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_tar extends getid3_handler
 {
@@ -44,13 +47,13 @@ class getid3_tar extends getid3_handler
                        // check the block
                        $checksum = 0;
                        for ($i = 0; $i < 148; $i++) {
-                               $checksum += ord($buffer{$i});
+                               $checksum += ord($buffer[$i]);
                        }
                        for ($i = 148; $i < 156; $i++) {
                                $checksum += ord(' ');
                        }
                        for ($i = 156; $i < 512; $i++) {
-                               $checksum += ord($buffer{$i});
+                               $checksum += ord($buffer[$i]);
                        }
                        $attr    = unpack($unpack_header, $buffer);
                        $name    =       (isset($attr['fname']  ) ? trim($attr['fname']  ) : '');
index 7cb8719..1ce3fb7 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_zip extends getid3_handler
 {
@@ -92,19 +95,39 @@ class getid3_zip extends getid3_handler
                                                }
                                        }
 
+                                       // check for EPUB files
+                                       if (!empty($info['zip']['entries'][0]['filename']) &&
+                                               ($info['zip']['entries'][0]['filename'] == 'mimetype') &&
+                                               ($info['zip']['entries'][0]['compression_method'] == 'store') &&
+                                               ($info['zip']['entries'][0]['uncompressed_size'] == 20) &&
+                                               isset($info['zip']['entries'][0]['data_offset'])) {
+                                                       // http://idpf.org/epub/30/spec/epub30-ocf.html
+                                                       // "3.3 OCF ZIP Container Media Type Identification
+                                                       //  OCF ZIP Containers must include a mimetype file as the first file in the Container, and the contents of this file must be the MIME type string application/epub+zip.
+                                                       //  The contents of the mimetype file must not contain any leading padding or whitespace, must not begin with the Unicode signature (or Byte Order Mark),
+                                                       //  and the case of the MIME type string must be exactly as presented above. The mimetype file additionally must be neither compressed nor encrypted,
+                                                       //  and there must not be an extra field in its ZIP header."
+                                                       $this->fseek($info['zip']['entries'][0]['data_offset']);
+                                                       if ($this->fread(20) == 'application/epub+zip') {
+                                                               $info['fileformat'] = 'zip.epub';
+                                                               $info['mime_type'] = 'application/epub+zip';
+                                                       }
+                                       }
+
+                                       // check for Office Open XML files (e.g. .docx, .xlsx)
                                        if (!empty($info['zip']['files']['[Content_Types].xml']) &&
                                            !empty($info['zip']['files']['_rels']['.rels'])      &&
                                            !empty($info['zip']['files']['docProps']['app.xml']) &&
                                            !empty($info['zip']['files']['docProps']['core.xml'])) {
-                                                  // http://technet.microsoft.com/en-us/library/cc179224.aspx
-                                                  $info['fileformat'] = 'zip.msoffice';
-                                                  if (!empty($ThisFileInfo['zip']['files']['ppt'])) {
-                                                     $info['mime_type'] = 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
-                                                  } elseif (!empty($ThisFileInfo['zip']['files']['xl'])) {
-                                                     $info['mime_type'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
-                                                  } elseif (!empty($ThisFileInfo['zip']['files']['word'])) {
-                                                     $info['mime_type'] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
-                                                  }
+                                                       // http://technet.microsoft.com/en-us/library/cc179224.aspx
+                                                       $info['fileformat'] = 'zip.msoffice';
+                                                       if (!empty($ThisFileInfo['zip']['files']['ppt'])) {
+                                                               $info['mime_type'] = 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
+                                                       } elseif (!empty($ThisFileInfo['zip']['files']['xl'])) {
+                                                               $info['mime_type'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
+                                                       } elseif (!empty($ThisFileInfo['zip']['files']['word'])) {
+                                                               $info['mime_type'] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
+                                                       }
                                        }
 
                                        return true;
index d42607e..fce923c 100644 (file)
@@ -13,6 +13,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
 
 class getid3_asf extends getid3_handler
@@ -363,7 +366,7 @@ class getid3_asf extends getid3_handler
                                                                $thisfile_audio['codec'] = $this->TrimConvert($thisfile_asf_codeclistobject_codecentries_current['name']);
 
                                                                if (!isset($thisfile_audio['bitrate']) && strstr($AudioCodecBitrate, 'kbps')) {
-                                                                       $thisfile_audio['bitrate'] = (int) (trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000);
+                                                                       $thisfile_audio['bitrate'] = (int) trim(str_replace('kbps', '', $AudioCodecBitrate)) * 1000;
                                                                }
                                                                //if (!isset($thisfile_video['bitrate']) && isset($thisfile_audio['bitrate']) && isset($thisfile_asf['file_properties_object']['max_bitrate']) && ($thisfile_asf_codeclistobject['codec_entries_count'] > 1)) {
                                                                if (empty($thisfile_video['bitrate']) && !empty($thisfile_audio['bitrate']) && !empty($info['bitrate'])) {
@@ -797,17 +800,17 @@ class getid3_asf extends getid3_handler
                                                        case 'wm/tracknumber':
                                                        case 'tracknumber':
                                                                // be careful casting to int: casting unicode strings to int gives unexpected results (stops parsing at first non-numeric character)
-                                                               $thisfile_asf_comments['track'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
-                                                               foreach ($thisfile_asf_comments['track'] as $key => $value) {
+                                                               $thisfile_asf_comments['track_number'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
+                                                               foreach ($thisfile_asf_comments['track_number'] as $key => $value) {
                                                                        if (preg_match('/^[0-9\x00]+$/', $value)) {
-                                                                               $thisfile_asf_comments['track'][$key] = intval(str_replace("\x00", '', $value));
+                                                                               $thisfile_asf_comments['track_number'][$key] = intval(str_replace("\x00", '', $value));
                                                                        }
                                                                }
                                                                break;
 
                                                        case 'wm/track':
-                                                               if (empty($thisfile_asf_comments['track'])) {
-                                                                       $thisfile_asf_comments['track'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
+                                                               if (empty($thisfile_asf_comments['track_number'])) {
+                                                                       $thisfile_asf_comments['track_number'] = array(1 + (int) $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));
                                                                }
                                                                break;
 
@@ -1653,26 +1656,26 @@ class getid3_asf extends getid3_handler
         * @return string
         */
        public static function BytestringToGUID($Bytestring) {
-               $GUIDstring  = str_pad(dechex(ord($Bytestring{3})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{2})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{1})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{0})),  2, '0', STR_PAD_LEFT);
+               $GUIDstring  = str_pad(dechex(ord($Bytestring[3])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[2])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[1])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[0])),  2, '0', STR_PAD_LEFT);
                $GUIDstring .= '-';
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{5})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{4})),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[5])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[4])),  2, '0', STR_PAD_LEFT);
                $GUIDstring .= '-';
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{7})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{6})),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[7])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[6])),  2, '0', STR_PAD_LEFT);
                $GUIDstring .= '-';
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{8})),  2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{9})),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[8])),  2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[9])),  2, '0', STR_PAD_LEFT);
                $GUIDstring .= '-';
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{10})), 2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{11})), 2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{12})), 2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{13})), 2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{14})), 2, '0', STR_PAD_LEFT);
-               $GUIDstring .= str_pad(dechex(ord($Bytestring{15})), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[10])), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[11])), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[12])), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[13])), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[14])), 2, '0', STR_PAD_LEFT);
+               $GUIDstring .= str_pad(dechex(ord($Bytestring[15])), 2, '0', STR_PAD_LEFT);
 
                return strtoupper($GUIDstring);
        }
index bd38e33..b59ec67 100644 (file)
@@ -13,6 +13,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_bink extends getid3_handler
 {
@@ -29,20 +32,14 @@ class getid3_bink extends getid3_handler
                switch ($fileTypeID) {
                        case 'BIK':
                                return $this->ParseBink();
-                               break;
 
                        case 'SMK':
                                return $this->ParseSmacker();
-                               break;
 
                        default:
                                $this->error('Expecting "BIK" or "SMK" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($fileTypeID).'"');
                                return false;
-                               break;
                }
-
-               return true;
-
        }
 
        /**
index eb292c6..7e68407 100644 (file)
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
+
 define('GETID3_FLV_TAG_AUDIO',          8);
 define('GETID3_FLV_TAG_VIDEO',          9);
 define('GETID3_FLV_TAG_META',          18);
@@ -597,7 +601,6 @@ class AMFReader
                        // null
                        case 6:
                                return null;
-                               break;
 
                        // Mixed array
                        case 8:
index b2b187b..a285108 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 define('EBML_ID_CHAPTERS',                  0x0043A770); // [10][43][A7][70] -- A system to define basic menus and partition data. For more detailed information, look at the Chapters Explanation.
 define('EBML_ID_SEEKHEAD',                  0x014D9B74); // [11][4D][9B][74] -- Contains the position of other level 1 elements.
@@ -329,7 +332,7 @@ class getid3_matroska extends getid3_handler
                                                                break;*/
                                                }
 
-                                               $info['video']['streams'][] = $track_info;
+                                               $info['video']['streams'][$trackarray['TrackUID']] = $track_info;
                                                break;
 
                                        case 2: // Audio
@@ -342,7 +345,7 @@ class getid3_matroska extends getid3_handler
                                                switch ($trackarray['CodecID']) {
                                                        case 'A_PCM/INT/LIT':
                                                        case 'A_PCM/INT/BIG':
-                                                               $track_info['bitrate'] = $trackarray['SamplingFrequency'] * $trackarray['Channels'] * $trackarray['BitDepth'];
+                                                               $track_info['bitrate'] = $track_info['sample_rate'] * $track_info['channels'] * $trackarray['BitDepth'];
                                                                break;
 
                                                        case 'A_AC3':
@@ -362,7 +365,7 @@ class getid3_matroska extends getid3_handler
                                                                // create temp instance
                                                                $getid3_temp = new getID3();
                                                                if ($track_info['dataformat'] != 'flac') {
-                                                                       $getid3_temp->openfile($this->getid3->filename);
+                                                                       $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
                                                                }
                                                                $getid3_temp->info['avdataoffset'] = $info['matroska']['track_data_offsets'][$trackarray['TrackNumber']]['offset'];
                                                                if ($track_info['dataformat'][0] == 'm' || $track_info['dataformat'] == 'flac') {
@@ -478,7 +481,7 @@ class getid3_matroska extends getid3_handler
                                                                break;
                                                }
 
-                                               $info['audio']['streams'][] = $track_info;
+                                               $info['audio']['streams'][$trackarray['TrackUID']] = $track_info;
                                                break;
                                }
                        }
@@ -509,6 +512,30 @@ class getid3_matroska extends getid3_handler
                        unset($info['mime_type']);
                }
 
+               // use _STATISTICS_TAGS if available to set audio/video bitrates
+               if (!empty($info['matroska']['tags'])) {
+                       $_STATISTICS_byTrackUID = array();
+                       foreach ($info['matroska']['tags'] as $key1 => $value1) {
+                               if (!empty($value1['Targets']['TagTrackUID'][0]) && !empty($value1['SimpleTag'])) {
+                                       foreach ($value1['SimpleTag'] as $key2 => $value2) {
+                                               if (!empty($value2['TagName']) && isset($value2['TagString'])) {
+                                                       $_STATISTICS_byTrackUID[$value1['Targets']['TagTrackUID'][0]][$value2['TagName']] = $value2['TagString'];
+                                               }
+                                       }
+                               }
+                       }
+                       foreach (array('audio','video') as $avtype) {
+                               if (!empty($info[$avtype]['streams'])) {
+                                       foreach ($info[$avtype]['streams'] as $trackUID => $trackdata) {
+                                               if (!isset($trackdata['bitrate']) && !empty($_STATISTICS_byTrackUID[$trackUID]['BPS'])) {
+                                                       $info[$avtype]['streams'][$trackUID]['bitrate'] = (int) $_STATISTICS_byTrackUID[$trackUID]['BPS'];
+                                                       @$info[$avtype]['bitrate'] += $info[$avtype]['streams'][$trackUID]['bitrate'];
+                                               }
+                                       }
+                               }
+                       }
+               }
+
                return true;
        }
 
@@ -614,8 +641,10 @@ class getid3_matroska extends getid3_handler
                                                                                        while ($this->getEBMLelement($subelement, $track_entry['end'], array(EBML_ID_VIDEO, EBML_ID_AUDIO, EBML_ID_CONTENTENCODINGS, EBML_ID_CODECPRIVATE))) {
                                                                                                switch ($subelement['id']) {
 
-                                                                                                       case EBML_ID_TRACKNUMBER:
                                                                                                        case EBML_ID_TRACKUID:
+                                                                                                               $track_entry[$subelement['id_name']] = getid3_lib::PrintHexBytes($subelement['data'], true, false);
+                                                                                                               break;
+                                                                                                       case EBML_ID_TRACKNUMBER:
                                                                                                        case EBML_ID_TRACKTYPE:
                                                                                                        case EBML_ID_MINCACHE:
                                                                                                        case EBML_ID_MAXCACHE:
@@ -963,7 +992,7 @@ class getid3_matroska extends getid3_handler
                                                                                                                                case EBML_ID_TAGEDITIONUID:
                                                                                                                                case EBML_ID_TAGCHAPTERUID:
                                                                                                                                case EBML_ID_TAGATTACHMENTUID:
-                                                                                                                                       $targets_entry[$sub_sub_subelement['id_name']][] = getid3_lib::BigEndian2Int($sub_sub_subelement['data']);
+                                                                                                                                       $targets_entry[$sub_sub_subelement['id_name']][] = getid3_lib::PrintHexBytes($sub_sub_subelement['data'], true, false);
                                                                                                                                        break;
 
                                                                                                                                default:
index f27cd4b..5ca4120 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
 
 class getid3_mpeg extends getid3_handler
@@ -90,11 +93,9 @@ class getid3_mpeg extends getid3_handler
                                        break;
 
                                case 0xB3: // sequence_header_code
-                                       /*
-                                       Note: purposely doing the less-pretty (and probably a bit slower) method of using string of bits rather than bitwise operations.
-                                             Mostly because PHP 32-bit doesn't handle unsigned integers well for bitwise operation.
-                                             Also the MPEG stream is designed as a bitstream and often doesn't align nicely with byte boundaries.
-                                       */
+                                       // Note: purposely doing the less-pretty (and probably a bit slower) method of using string of bits rather than bitwise operations.
+                                       // Mostly because PHP 32-bit doesn't handle unsigned integers well for bitwise operation.
+                                       // Also the MPEG stream is designed as a bitstream and often doesn't align nicely with byte boundaries.
                                        $info['video']['codec'] = 'MPEG-1'; // will be updated if extension_start_code found
 
                                        $bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 4, 8));
@@ -393,7 +394,7 @@ $PackedElementaryStream['additional_header_bytes'] = $additional_header_bytes;
                                        $info['mpeg']['packed_elementary_streams'][$PackedElementaryStream['stream_type']][$PackedElementaryStream['stream_id']][] = $PackedElementaryStream;
 */
                                        $getid3_temp = new getID3();
-                                       $getid3_temp->openfile($this->getid3->filename);
+                                       $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
                                        $getid3_temp->info = $info;
                                        $getid3_mp3 = new getid3_mp3($getid3_temp);
                                        for ($i = 0; $i <= 7; $i++) {
@@ -521,7 +522,7 @@ echo 'average_File_bitrate = '.number_format(array_sum($vbr_bitrates) / count($v
         * @param int    $bits_to_read
         * @param bool $return_singlebit_as_boolean
         *
-        * @return bool|float|int
+        * @return bool|int
         */
        private function readBitsFromStream(&$bitstream, &$bitstreamoffset, $bits_to_read, $return_singlebit_as_boolean=true) {
                $return = bindec(substr($bitstream, $bitstreamoffset, $bits_to_read));
@@ -622,7 +623,7 @@ echo 'average_File_bitrate = '.number_format(array_sum($vbr_bitrates) / count($v
 
        /**
         * @param int $rawaspectratio
-     * @param int $mpeg_version
+        * @param int $mpeg_version
         *
         * @return string
         */
index 68a2ca1..043cdfc 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_nsv extends getid3_handler
 {
@@ -51,7 +54,6 @@ class getid3_nsv extends getid3_handler
                        default:
                                $this->error('Expecting "NSVs" or "NSVf" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($NSVheader).'"');
                                return false;
-                               break;
                }
 
                if (!isset($info['nsv']['NSVf'])) {
index 5c791e3..c176e5a 100644 (file)
@@ -15,6 +15,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); // needed for ISO 639-2 language code lookup
 
@@ -38,7 +41,7 @@ class getid3_quicktime extends getid3_handler
 
                $offset      = 0;
                $atomcounter = 0;
-               $atom_data_read_buffer_size = max($this->getid3->option_fread_buffer_size * 1024, ($info['php_memory_limit'] ? round($info['php_memory_limit'] / 4) : 1024)); // set read buffer to 25% of PHP memory limit (if one is specified), otherwise use option_fread_buffer_size [default: 32MB]
+               $atom_data_read_buffer_size = $info['php_memory_limit'] ? round($info['php_memory_limit'] / 4) : $this->getid3->option_fread_buffer_size * 1024; // set read buffer to 25% of PHP memory limit (if one is specified), otherwise use option_fread_buffer_size [default: 32MB]
                while ($offset < $info['avdataend']) {
                        if (!getid3_lib::intValueSupported($offset)) {
                                $this->error('Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions');
@@ -55,23 +58,33 @@ class getid3_quicktime extends getid3_handler
                                $atomsize = getid3_lib::BigEndian2Int($this->fread(8));
                        }
 
-                       $info['quicktime'][$atomname]['name']   = $atomname;
-                       $info['quicktime'][$atomname]['size']   = $atomsize;
-                       $info['quicktime'][$atomname]['offset'] = $offset;
-
                        if (($offset + $atomsize) > $info['avdataend']) {
+                               $info['quicktime'][$atomname]['name']   = $atomname;
+                               $info['quicktime'][$atomname]['size']   = $atomsize;
+                               $info['quicktime'][$atomname]['offset'] = $offset;
                                $this->error('Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)');
                                return false;
                        }
-
                        if ($atomsize == 0) {
                                // Furthermore, for historical reasons the list of atoms is optionally
                                // terminated by a 32-bit integer set to 0. If you are writing a program
                                // to read user data atoms, you should allow for the terminating 0.
+                               $info['quicktime'][$atomname]['name']   = $atomname;
+                               $info['quicktime'][$atomname]['size']   = $atomsize;
+                               $info['quicktime'][$atomname]['offset'] = $offset;
                                break;
                        }
+
                        $atomHierarchy = array();
-                       $info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, $atom_data_read_buffer_size)), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
+                       $parsedAtomData = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, $atom_data_read_buffer_size)), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
+                       $parsedAtomData['name']   = $atomname;
+                       $parsedAtomData['size']   = $atomsize;
+                       $parsedAtomData['offset'] = $offset;
+                       if (in_array($atomname, array('uuid'))) {
+                               @$info['quicktime'][$atomname][] = $parsedAtomData;
+                       } else {
+                               $info['quicktime'][$atomname] = $parsedAtomData;
+                       }
 
                        $offset += $atomsize;
                        $atomcounter++;
@@ -112,47 +125,44 @@ class getid3_quicktime extends getid3_handler
                if (!empty($info['quicktime']['comments']['location.ISO6709'])) {
                        // https://en.wikipedia.org/wiki/ISO_6709
                        foreach ($info['quicktime']['comments']['location.ISO6709'] as $ISO6709string) {
-                               $latitude  = false;
-                               $longitude = false;
-                               $altitude  = false;
+                               $ISO6709parsed = array('latitude'=>false, 'longitude'=>false, 'altitude'=>false);
                                if (preg_match('#^([\\+\\-])([0-9]{2}|[0-9]{4}|[0-9]{6})(\\.[0-9]+)?([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?(([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?)?/$#', $ISO6709string, $matches)) {
                                        @list($dummy, $lat_sign, $lat_deg, $lat_deg_dec, $lon_sign, $lon_deg, $lon_deg_dec, $dummy, $alt_sign, $alt_deg, $alt_deg_dec) = $matches;
 
                                        if (strlen($lat_deg) == 2) {        // [+-]DD.D
-                                               $latitude = floatval(ltrim($lat_deg, '0').$lat_deg_dec);
+                                               $ISO6709parsed['latitude'] = (($lat_sign == '-') ? -1 : 1) * floatval(ltrim($lat_deg, '0').$lat_deg_dec);
                                        } elseif (strlen($lat_deg) == 4) {  // [+-]DDMM.M
-                                               $latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0').$lat_deg_dec / 60);
+                                               $ISO6709parsed['latitude'] = (($lat_sign == '-') ? -1 : 1) * floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0').$lat_deg_dec / 60);
                                        } elseif (strlen($lat_deg) == 6) {  // [+-]DDMMSS.S
-                                               $latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lat_deg, 4, 2), '0').$lat_deg_dec / 3600);
+                                               $ISO6709parsed['latitude'] = (($lat_sign == '-') ? -1 : 1) * floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lat_deg, 4, 2), '0').$lat_deg_dec / 3600);
                                        }
 
                                        if (strlen($lon_deg) == 3) {        // [+-]DDD.D
-                                               $longitude = floatval(ltrim($lon_deg, '0').$lon_deg_dec);
+                                               $ISO6709parsed['longitude'] = (($lon_sign == '-') ? -1 : 1) * floatval(ltrim($lon_deg, '0').$lon_deg_dec);
                                        } elseif (strlen($lon_deg) == 5) {  // [+-]DDDMM.M
-                                               $longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0').$lon_deg_dec / 60);
+                                               $ISO6709parsed['longitude'] = (($lon_sign == '-') ? -1 : 1) * floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0').$lon_deg_dec / 60);
                                        } elseif (strlen($lon_deg) == 7) {  // [+-]DDDMMSS.S
-                                               $longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lon_deg, 4, 2), '0').$lon_deg_dec / 3600);
+                                               $ISO6709parsed['longitude'] = (($lon_sign == '-') ? -1 : 1) * floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lon_deg, 4, 2), '0').$lon_deg_dec / 3600);
                                        }
 
                                        if (strlen($alt_deg) == 3) {        // [+-]DDD.D
-                                               $altitude = floatval(ltrim($alt_deg, '0').$alt_deg_dec);
+                                               $ISO6709parsed['altitude'] = (($alt_sign == '-') ? -1 : 1) * floatval(ltrim($alt_deg, '0').$alt_deg_dec);
                                        } elseif (strlen($alt_deg) == 5) {  // [+-]DDDMM.M
-                                               $altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0').$alt_deg_dec / 60);
+                                               $ISO6709parsed['altitude'] = (($alt_sign == '-') ? -1 : 1) * floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0').$alt_deg_dec / 60);
                                        } elseif (strlen($alt_deg) == 7) {  // [+-]DDDMMSS.S
-                                               $altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600);
+                                               $ISO6709parsed['altitude'] = (($alt_sign == '-') ? -1 : 1) * floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600);
                                        }
 
-                                       if ($latitude !== false) {
-                                               $info['quicktime']['comments']['gps_latitude'][]  = (($lat_sign == '-') ? -1 : 1) * floatval($latitude);
-                                       }
-                                       if ($longitude !== false) {
-                                               $info['quicktime']['comments']['gps_longitude'][] = (($lon_sign == '-') ? -1 : 1) * floatval($longitude);
-                                       }
-                                       if ($altitude !== false) {
-                                               $info['quicktime']['comments']['gps_altitude'][]  = (($alt_sign == '-') ? -1 : 1) * floatval($altitude);
+                                       foreach (array('latitude', 'longitude', 'altitude') as $key) {
+                                               if ($ISO6709parsed[$key] !== false) {
+                                                       $value = (($lat_sign == '-') ? -1 : 1) * floatval($ISO6709parsed[$key]);
+                                                       if (!isset($info['quicktime']['comments']['gps_'.$key]) || !in_array($value, $info['quicktime']['comments']['gps_'.$key])) {
+                                                               @$info['quicktime']['comments']['gps_'.$key][] = (($lat_sign == '-') ? -1 : 1) * floatval($ISO6709parsed[$key]);
+                                                       }
+                                               }
                                        }
                                }
-                               if ($latitude === false) {
+                               if ($ISO6709parsed['latitude'] === false) {
                                        $this->warning('location.ISO6709 string not parsed correctly: "'.$ISO6709string.'", please submit as a bug');
                                }
                                break;
@@ -224,6 +234,7 @@ class getid3_quicktime extends getid3_handler
 
                $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see https://www.getid3.org/phpBB3/viewtopic.php?t=1717
                array_push($atomHierarchy, $atomname);
+               $atom_structure              = array();
                $atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
                $atom_structure['name']      = $atomname;
                $atom_structure['size']      = $atomsize;
@@ -244,6 +255,7 @@ class getid3_quicktime extends getid3_handler
                                case 'mdia': // MeDIA container atom
                                case 'minf': // Media INFormation container atom
                                case 'dinf': // Data INFormation container atom
+                               case 'nmhd': // Null Media HeaDer container atom
                                case 'udta': // User DaTA container atom
                                case 'cmov': // Compressed MOVie container atom
                                case 'rmra': // Reference Movie Record Atom
@@ -528,6 +540,7 @@ class getid3_quicktime extends getid3_handler
                                                                                                                } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
                                                                                                                        $atom_structure['image_mime'] = 'image/gif';
                                                                                                                }
+                                                                                                               $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_structure['data'], 'description'=>'cover');
                                                                                                                break;
 
                                                                                                        case 'atID':
@@ -554,6 +567,7 @@ class getid3_quicktime extends getid3_handler
                                                                                                        } elseif (preg_match('#^GIF#', $atom_structure['data'])) {
                                                                                                                $atom_structure['image_mime'] = 'image/gif';
                                                                                                        }
+                                                                                                       $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_structure['data'], 'description'=>'cover');
                                                                                                }
                                                                                                break;
 
@@ -568,8 +582,8 @@ class getid3_quicktime extends getid3_handler
                                                        }
                                                }
                                        }
-                                               $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']);
-                                               break;
+                                       $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']);
+                                       break;
 
 
                                case 'play': // auto-PLAY atom
@@ -757,6 +771,15 @@ class getid3_quicktime extends getid3_handler
                                                $atom_structure['sample_description_table'][$i]['data']             =                           substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2));
                                                $stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2);
 
+                                               if (substr($atom_structure['sample_description_table'][$i]['data'],  1, 54) == 'application/octet-stream;type=com.parrot.videometadata') {
+                                                       // special handling for apparently-malformed (TextMetaDataSampleEntry?) data for some version of Parrot drones
+                                                       $atom_structure['sample_description_table'][$i]['parrot_frame_metadata']['mime_type']        =       substr($atom_structure['sample_description_table'][$i]['data'],  1, 55);
+                                                       $atom_structure['sample_description_table'][$i]['parrot_frame_metadata']['metadata_version'] = (int) substr($atom_structure['sample_description_table'][$i]['data'], 55,  1);
+                                                       unset($atom_structure['sample_description_table'][$i]['data']);
+$this->warning('incomplete/incorrect handling of "stsd" with Parrot metadata in this version of getID3() ['.$this->getid3->version().']');
+                                                       continue;
+                                               }
+
                                                $atom_structure['sample_description_table'][$i]['encoder_version']  = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  0, 2));
                                                $atom_structure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  2, 2));
                                                $atom_structure['sample_description_table'][$i]['encoder_vendor']   =                           substr($atom_structure['sample_description_table'][$i]['data'],  4, 4);
@@ -1044,6 +1067,7 @@ class getid3_quicktime extends getid3_handler
 
 
                                case 'stco': // Sample Table Chunk Offset atom
+//                                     if (true) {
                                        if ($ParseAllPossibleAtoms) {
                                                $atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
                                                $atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
@@ -1133,7 +1157,7 @@ class getid3_quicktime extends getid3_handler
                                        $atom_structure['component_manufacturer'] =                           substr($atom_data, 12, 4);
                                        $atom_structure['component_flags_raw']    = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
                                        $atom_structure['component_flags_mask']   = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
-                                       $atom_structure['component_name']         =      $this->Pascal2String(substr($atom_data, 24));
+                                       $atom_structure['component_name']         = $this->MaybePascal2String(substr($atom_data, 24));
 
                                        if (($atom_structure['component_subtype'] == 'STpn') && ($atom_structure['component_manufacturer'] == 'zzzz')) {
                                                $info['video']['dataformat'] = 'quicktimevr';
@@ -1164,6 +1188,8 @@ class getid3_quicktime extends getid3_handler
                                        if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
                                                $info['comments']['language'][] = $atom_structure['language'];
                                        }
+                                       $info['quicktime']['timestamps_unix']['create'][$atom_structure['hierarchy']] = $atom_structure['creation_time_unix'];
+                                       $info['quicktime']['timestamps_unix']['modify'][$atom_structure['hierarchy']] = $atom_structure['modify_time_unix'];
                                        break;
 
 
@@ -1174,6 +1200,7 @@ class getid3_quicktime extends getid3_handler
                                        $atom_structure['atom_index']             = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
 
                                        $atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
+                                       $info['quicktime']['timestamps_unix']['modify'][$atom_structure['hierarchy']] = $atom_structure['modification_date_unix'];
                                        break;
 
 
@@ -1271,6 +1298,8 @@ class getid3_quicktime extends getid3_handler
                                        }
                                        $atom_structure['creation_time_unix']        = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
                                        $atom_structure['modify_time_unix']          = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
+                                       $info['quicktime']['timestamps_unix']['create'][$atom_structure['hierarchy']] = $atom_structure['creation_time_unix'];
+                                       $info['quicktime']['timestamps_unix']['modify'][$atom_structure['hierarchy']] = $atom_structure['modify_time_unix'];
                                        $info['quicktime']['time_scale']    = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
                                        $info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
                                        $info['playtime_seconds']           = $atom_structure['duration'] / $atom_structure['time_scale'];
@@ -1309,6 +1338,8 @@ class getid3_quicktime extends getid3_handler
                                        $atom_structure['flags']['in_poster']  = (bool) ($atom_structure['flags_raw'] & 0x0008);
                                        $atom_structure['creation_time_unix']  = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
                                        $atom_structure['modify_time_unix']    = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
+                                       $info['quicktime']['timestamps_unix']['create'][$atom_structure['hierarchy']] = $atom_structure['creation_time_unix'];
+                                       $info['quicktime']['timestamps_unix']['modify'][$atom_structure['hierarchy']] = $atom_structure['modify_time_unix'];
 
                                        // https://www.getid3.org/phpBB3/viewtopic.php?t=1908
                                        // attempt to compute rotation from matrix values
@@ -1450,7 +1481,7 @@ class getid3_quicktime extends getid3_handler
                                                $info['avdataend']    = $atom_structure['offset'] + $atom_structure['size']; // $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size'];
 
                                                $getid3_temp = new getID3();
-                                               $getid3_temp->openfile($this->getid3->filename);
+                                               $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
                                                $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
                                                $getid3_temp->info['avdataend']    = $info['avdataend'];
                                                $getid3_mp3 = new getid3_mp3($getid3_temp);
@@ -1639,6 +1670,146 @@ class getid3_quicktime extends getid3_handler
                                        }
                                        break;
 
+                               case 'uuid': // user-defined atom often seen containing XML data, also used for potentially many other purposes, only a few specifically handled by getID3 (e.g. 360fly spatial data)
+                                       //Get the UUID ID in first 16 bytes
+                                       $uuid_bytes_read = unpack('H8time_low/H4time_mid/H4time_hi/H4clock_seq_hi/H12clock_seq_low', substr($atom_data, 0, 16));
+                                       $atom_structure['uuid_field_id'] = implode('-', $uuid_bytes_read);
+
+                                       switch ($atom_structure['uuid_field_id']) {   // http://fileformats.archiveteam.org/wiki/Boxes/atoms_format#UUID_boxes
+
+                                               case '0537cdab-9d0c-4431-a72a-fa561f2a113e': // Exif                                       - http://fileformats.archiveteam.org/wiki/Exif
+                                               case '2c4c0100-8504-40b9-a03e-562148d6dfeb': // Photoshop Image Resources                  - http://fileformats.archiveteam.org/wiki/Photoshop_Image_Resources
+                                               case '33c7a4d2-b81d-4723-a0ba-f1a3e097ad38': // IPTC-IIM                                   - http://fileformats.archiveteam.org/wiki/IPTC-IIM
+                                               case '8974dbce-7be7-4c51-84f9-7148f9882554': // PIFF Track Encryption Box                  - http://fileformats.archiveteam.org/wiki/Protected_Interoperable_File_Format
+                                               case '96a9f1f1-dc98-402d-a7ae-d68e34451809': // GeoJP2 World File Box                      - http://fileformats.archiveteam.org/wiki/GeoJP2
+                                               case 'a2394f52-5a9b-4f14-a244-6c427c648df4': // PIFF Sample Encryption Box                 - http://fileformats.archiveteam.org/wiki/Protected_Interoperable_File_Format
+                                               case 'b14bf8bd-083d-4b43-a5ae-8cd7d5a6ce03': // GeoJP2 GeoTIFF Box                         - http://fileformats.archiveteam.org/wiki/GeoJP2
+                                               case 'd08a4f18-10f3-4a82-b6c8-32d8aba183d3': // PIFF Protection System Specific Header Box - http://fileformats.archiveteam.org/wiki/Protected_Interoperable_File_Format
+                                                       $this->warning('Unhandled (but recognized) "uuid" atom identified by "'.$atom_structure['uuid_field_id'].'" at offset '.$atom_structure['offset'].' ('.strlen($atom_data).' bytes)');
+                                                       break;
+
+                                               case 'be7acfcb-97a9-42e8-9c71-999491e3afac': // XMP data (in XML format)
+                                                       $atom_structure['xml'] = substr($atom_data, 16, strlen($atom_data) - 16 - 8); // 16 bytes for UUID, 8 bytes header(?)
+                                                       break;
+
+                                               case 'efe1589a-bb77-49ef-8095-27759eb1dc6f': // 360fly data
+                                                       /* 360fly code in this block by Paul Lewis 2019-Oct-31 */
+                                                       /*      Sensor Timestamps need to be calculated using the recordings base time at ['quicktime']['moov']['subatoms'][0]['creation_time_unix']. */
+                                                       $atom_structure['title'] = '360Fly Sensor Data';
+
+                                                       //Get the UUID HEADER data
+                                                       $uuid_bytes_read = unpack('vheader_size/vheader_version/vtimescale/vhardware_version/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/x/', substr($atom_data, 16, 32));
+                                                       $atom_structure['uuid_header'] = $uuid_bytes_read;
+
+                                                       $start_byte = 48;
+                                                       $atom_SENSOR_data = substr($atom_data, $start_byte);
+                                                       $atom_structure['sensor_data']['data_type'] = array(
+                                                                       'fusion_count'   => 0,       // ID 250
+                                                                       'fusion_data'    => array(),
+                                                                       'accel_count'    => 0,       // ID 1
+                                                                       'accel_data'     => array(),
+                                                                       'gyro_count'     => 0,       // ID 2
+                                                                       'gyro_data'      => array(),
+                                                                       'magno_count'    => 0,       // ID 3
+                                                                       'magno_data'     => array(),
+                                                                       'gps_count'      => 0,       // ID 5
+                                                                       'gps_data'       => array(),
+                                                                       'rotation_count' => 0,       // ID 6
+                                                                       'rotation_data'  => array(),
+                                                                       'unknown_count'  => 0,       // ID ??
+                                                                       'unknown_data'   => array(),
+                                                                       'debug_list'     => '',      // Used to debug variables stored as comma delimited strings
+                                                       );
+                                                       $debug_structure['debug_items'] = array();
+                                                       // Can start loop here to decode all sensor data in 32 Byte chunks:
+                                                       foreach (str_split($atom_SENSOR_data, 32) as $sensor_key => $sensor_data) {
+                                                               // This gets me a data_type code to work out what data is in the next 31 bytes.
+                                                               $sensor_data_type = substr($sensor_data, 0, 1);
+                                                               $sensor_data_content = substr($sensor_data, 1);
+                                                               $uuid_bytes_read = unpack('C*', $sensor_data_type);
+                                                               $sensor_data_array = array();
+                                                               switch ($uuid_bytes_read[1]) {
+                                                                       case 250:
+                                                                               $atom_structure['sensor_data']['data_type']['fusion_count']++;
+                                                                               $uuid_bytes_read = unpack('cmode/Jtimestamp/Gyaw/Gpitch/Groll/x*', $sensor_data_content);
+                                                                               $sensor_data_array['mode']      = $uuid_bytes_read['mode'];
+                                                                               $sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
+                                                                               $sensor_data_array['yaw']       = $uuid_bytes_read['yaw'];
+                                                                               $sensor_data_array['pitch']     = $uuid_bytes_read['pitch'];
+                                                                               $sensor_data_array['roll']      = $uuid_bytes_read['roll'];
+                                                                               array_push($atom_structure['sensor_data']['data_type']['fusion_data'], $sensor_data_array);
+                                                                               break;
+                                                                       case 1:
+                                                                               $atom_structure['sensor_data']['data_type']['accel_count']++;
+                                                                               $uuid_bytes_read = unpack('cmode/Jtimestamp/Gyaw/Gpitch/Groll/x*', $sensor_data_content);
+                                                                               $sensor_data_array['mode']      = $uuid_bytes_read['mode'];
+                                                                               $sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
+                                                                               $sensor_data_array['yaw']       = $uuid_bytes_read['yaw'];
+                                                                               $sensor_data_array['pitch']     = $uuid_bytes_read['pitch'];
+                                                                               $sensor_data_array['roll']      = $uuid_bytes_read['roll'];
+                                                                               array_push($atom_structure['sensor_data']['data_type']['accel_data'], $sensor_data_array);
+                                                                               break;
+                                                                       case 2:
+                                                                               $atom_structure['sensor_data']['data_type']['gyro_count']++;
+                                                                               $uuid_bytes_read = unpack('cmode/Jtimestamp/Gyaw/Gpitch/Groll/x*', $sensor_data_content);
+                                                                               $sensor_data_array['mode']      = $uuid_bytes_read['mode'];
+                                                                               $sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
+                                                                               $sensor_data_array['yaw']       = $uuid_bytes_read['yaw'];
+                                                                               $sensor_data_array['pitch']     = $uuid_bytes_read['pitch'];
+                                                                               $sensor_data_array['roll']      = $uuid_bytes_read['roll'];
+                                                                               array_push($atom_structure['sensor_data']['data_type']['gyro_data'], $sensor_data_array);
+                                                                               break;
+                                                                       case 3:
+                                                                               $atom_structure['sensor_data']['data_type']['magno_count']++;
+                                                                               $uuid_bytes_read = unpack('cmode/Jtimestamp/Gmagx/Gmagy/Gmagz/x*', $sensor_data_content);
+                                                                               $sensor_data_array['mode']      = $uuid_bytes_read['mode'];
+                                                                               $sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
+                                                                               $sensor_data_array['magx']      = $uuid_bytes_read['magx'];
+                                                                               $sensor_data_array['magy']      = $uuid_bytes_read['magy'];
+                                                                               $sensor_data_array['magz']      = $uuid_bytes_read['magz'];
+                                                                               array_push($atom_structure['sensor_data']['data_type']['magno_data'], $sensor_data_array);
+                                                                               break;
+                                                                       case 5:
+                                                                               $atom_structure['sensor_data']['data_type']['gps_count']++;
+                                                                               $uuid_bytes_read = unpack('cmode/Jtimestamp/Glat/Glon/Galt/Gspeed/nbearing/nacc/x*', $sensor_data_content);
+                                                                               $sensor_data_array['mode']      = $uuid_bytes_read['mode'];
+                                                                               $sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
+                                                                               $sensor_data_array['lat']       = $uuid_bytes_read['lat'];
+                                                                               $sensor_data_array['lon']       = $uuid_bytes_read['lon'];
+                                                                               $sensor_data_array['alt']       = $uuid_bytes_read['alt'];
+                                                                               $sensor_data_array['speed']     = $uuid_bytes_read['speed'];
+                                                                               $sensor_data_array['bearing']   = $uuid_bytes_read['bearing'];
+                                                                               $sensor_data_array['acc']       = $uuid_bytes_read['acc'];
+                                                                               array_push($atom_structure['sensor_data']['data_type']['gps_data'], $sensor_data_array);
+                                                                               //array_push($debug_structure['debug_items'], $uuid_bytes_read['timestamp']);
+                                                                               break;
+                                                                       case 6:
+                                                                               $atom_structure['sensor_data']['data_type']['rotation_count']++;
+                                                                               $uuid_bytes_read = unpack('cmode/Jtimestamp/Grotx/Groty/Grotz/x*', $sensor_data_content);
+                                                                               $sensor_data_array['mode']      = $uuid_bytes_read['mode'];
+                                                                               $sensor_data_array['timestamp'] = $uuid_bytes_read['timestamp'];
+                                                                               $sensor_data_array['rotx']      = $uuid_bytes_read['rotx'];
+                                                                               $sensor_data_array['roty']      = $uuid_bytes_read['roty'];
+                                                                               $sensor_data_array['rotz']      = $uuid_bytes_read['rotz'];
+                                                                               array_push($atom_structure['sensor_data']['data_type']['rotation_data'], $sensor_data_array);
+                                                                               break;
+                                                                       default:
+                                                                               $atom_structure['sensor_data']['data_type']['unknown_count']++;
+                                                                               break;
+                                                               }
+                                                       }
+                                                       //if (isset($debug_structure['debug_items']) && count($debug_structure['debug_items']) > 0) {
+                                                       //      $atom_structure['sensor_data']['data_type']['debug_list'] = implode(',', $debug_structure['debug_items']);
+                                                       //} else {
+                                                               $atom_structure['sensor_data']['data_type']['debug_list'] = 'No debug items in list!';
+                                                       //}
+                                                       break;
+
+                                               default:
+                                                       $this->warning('Unhandled "uuid" atom identified by "'.$atom_structure['uuid_field_id'].'" at offset '.$atom_structure['offset'].' ('.strlen($atom_data).' bytes)');
+                                       }
+                                       break;
+
                                case 'gps ':
                                        // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
                                        // The 'gps ' contains simple look up table made up of 8byte rows, that point to the 'free' atoms that contains the actual GPS data.
@@ -1683,22 +1854,24 @@ class getid3_quicktime extends getid3_handler
                                                                // $GPRMC,094347.000,A,5342.0061,N,00737.9908,W,0.01,156.75,140217,,,A*7D
                                                                if (preg_match('#\\$GPRMC,([0-9\\.]*),([AV]),([0-9\\.]*),([NS]),([0-9\\.]*),([EW]),([0-9\\.]*),([0-9\\.]*),([0-9]*),([0-9\\.]*),([EW]?)(,[A])?(\\*[0-9A-F]{2})#', $GPS_free_data, $matches)) {
                                                                        $GPS_this_GPRMC = array();
+                                                                       $GPS_this_GPRMC_raw = array();
                                                                        list(
-                                                                               $GPS_this_GPRMC['raw']['gprmc'],
-                                                                               $GPS_this_GPRMC['raw']['timestamp'],
-                                                                               $GPS_this_GPRMC['raw']['status'],
-                                                                               $GPS_this_GPRMC['raw']['latitude'],
-                                                                               $GPS_this_GPRMC['raw']['latitude_direction'],
-                                                                               $GPS_this_GPRMC['raw']['longitude'],
-                                                                               $GPS_this_GPRMC['raw']['longitude_direction'],
-                                                                               $GPS_this_GPRMC['raw']['knots'],
-                                                                               $GPS_this_GPRMC['raw']['angle'],
-                                                                               $GPS_this_GPRMC['raw']['datestamp'],
-                                                                               $GPS_this_GPRMC['raw']['variation'],
-                                                                               $GPS_this_GPRMC['raw']['variation_direction'],
+                                                                               $GPS_this_GPRMC_raw['gprmc'],
+                                                                               $GPS_this_GPRMC_raw['timestamp'],
+                                                                               $GPS_this_GPRMC_raw['status'],
+                                                                               $GPS_this_GPRMC_raw['latitude'],
+                                                                               $GPS_this_GPRMC_raw['latitude_direction'],
+                                                                               $GPS_this_GPRMC_raw['longitude'],
+                                                                               $GPS_this_GPRMC_raw['longitude_direction'],
+                                                                               $GPS_this_GPRMC_raw['knots'],
+                                                                               $GPS_this_GPRMC_raw['angle'],
+                                                                               $GPS_this_GPRMC_raw['datestamp'],
+                                                                               $GPS_this_GPRMC_raw['variation'],
+                                                                               $GPS_this_GPRMC_raw['variation_direction'],
                                                                                $dummy,
-                                                                               $GPS_this_GPRMC['raw']['checksum'],
+                                                                               $GPS_this_GPRMC_raw['checksum'],
                                                                        ) = $matches;
+                                                                       $GPS_this_GPRMC['raw'] = $GPS_this_GPRMC_raw;
 
                                                                        $hour   = substr($GPS_this_GPRMC['raw']['timestamp'], 0, 2);
                                                                        $minute = substr($GPS_this_GPRMC['raw']['timestamp'], 2, 2);
@@ -1706,7 +1879,7 @@ class getid3_quicktime extends getid3_handler
                                                                        $ms     = substr($GPS_this_GPRMC['raw']['timestamp'], 6);    // may contain decimal seconds
                                                                        $day    = substr($GPS_this_GPRMC['raw']['datestamp'], 0, 2);
                                                                        $month  = substr($GPS_this_GPRMC['raw']['datestamp'], 2, 2);
-                                                                       $year   = substr($GPS_this_GPRMC['raw']['datestamp'], 4, 2);
+                                                                       $year   = (int) substr($GPS_this_GPRMC['raw']['datestamp'], 4, 2);
                                                                        $year += (($year > 90) ? 1900 : 2000); // complete lack of foresight: datestamps are stored with 2-digit years, take best guess
                                                                        $GPS_this_GPRMC['timestamp'] = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second.$ms;
 
@@ -1829,17 +2002,22 @@ class getid3_quicktime extends getid3_handler
                                case 'thma': // subatom to "frea" -- "ThumbnailImage"
                                        // https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Kodak.html#frea
                                        if (strlen($atom_data) > 0) {
-                                               $info['quicktime']['comments']['picture'][] = array('data'=>$atom_data, 'image_mime'=>'image/jpeg');
+                                               $info['quicktime']['comments']['picture'][] = array('data'=>$atom_data, 'image_mime'=>'image/jpeg', 'description'=>'ThumbnailImage');
                                        }
                                        break;
                                case 'scra': // subatom to "frea" -- "PreviewImage"
                                        // https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Kodak.html#frea
                                        // but the only sample file I've seen has no useful data here
                                        if (strlen($atom_data) > 0) {
-                                               $info['quicktime']['comments']['picture'][] = array('data'=>$atom_data, 'image_mime'=>'image/jpeg');
+                                               $info['quicktime']['comments']['picture'][] = array('data'=>$atom_data, 'image_mime'=>'image/jpeg', 'description'=>'PreviewImage');
                                        }
                                        break;
 
+                               case 'cdsc': // timed metadata reference
+                                       // A QuickTime movie can contain none, one, or several timed metadata tracks. Timed metadata tracks can refer to multiple tracks.
+                                       // Metadata tracks are linked to the tracks they describe using a track-reference of type 'cdsc'. The metadata track holds the 'cdsc' track reference.
+                                       $atom_structure['track_number'] = getid3_lib::BigEndian2Int($atom_data);
+                                       break;
 
                                default:
                                        $this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).'), '.$atomsize.' bytes at offset '.$baseoffset);
@@ -1880,6 +2058,12 @@ class getid3_quicktime extends getid3_handler
                                }
                                return $atom_structure;
                        }
+                       if (strlen($subatomdata) < ($subatomsize - 8)) {
+                           // we don't have enough data to decode the subatom.
+                           // this may be because we are refusing to parse large subatoms, or it may be because this atom had its size set too large
+                           // so we passed in the start of a following atom incorrectly?
+                           return $atom_structure;
+                       }
                        $atom_structure[$subatomcounter++] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms);
                        $subatomoffset += $subatomsize;
                }
@@ -2654,7 +2838,7 @@ class getid3_quicktime extends getid3_handler
                        $handyatomtranslatorarray["\xA9".'src'] = 'source_credit';
                        $handyatomtranslatorarray["\xA9".'swr'] = 'software';
                        $handyatomtranslatorarray["\xA9".'too'] = 'encoding_tool';       // iTunes 4.0
-                       $handyatomtranslatorarray["\xA9".'trk'] = 'track';
+                       $handyatomtranslatorarray["\xA9".'trk'] = 'track_number';
                        $handyatomtranslatorarray["\xA9".'url'] = 'url';
                        $handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
                        $handyatomtranslatorarray["\xA9".'wrt'] = 'composer';
@@ -2720,19 +2904,8 @@ class getid3_quicktime extends getid3_handler
                }
                if ($comment_key) {
                        if ($comment_key == 'picture') {
-                               if (!is_array($data)) {
-                                       $image_mime = '';
-                                       if (preg_match('#^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $data)) {
-                                               $image_mime = 'image/png';
-                                       } elseif (preg_match('#^\xFF\xD8\xFF#', $data)) {
-                                               $image_mime = 'image/jpeg';
-                                       } elseif (preg_match('#^GIF#', $data)) {
-                                               $image_mime = 'image/gif';
-                                       } elseif (preg_match('#^BM#', $data)) {
-                                               $image_mime = 'image/bmp';
-                                       }
-                                       $data = array('data'=>$data, 'image_mime'=>$image_mime);
-                               }
+                               // already copied directly into [comments][picture] elsewhere, do not re-copy here
+                               return true;
                        }
                        $gooddata = array($data);
                        if ($comment_key == 'genre') {
@@ -2740,6 +2913,10 @@ class getid3_quicktime extends getid3_handler
                                $gooddata = explode(';', $data);
                        }
                        foreach ($gooddata as $data) {
+                               if (!empty($info['quicktime']['comments'][$comment_key]) && in_array($data, $info['quicktime']['comments'][$comment_key], true)) {
+                                       // avoid duplicate copies of identical data
+                                       continue;
+                               }
                                $info['quicktime']['comments'][$comment_key][] = $data;
                        }
                }
@@ -2752,38 +2929,35 @@ class getid3_quicktime extends getid3_handler
         *
         * @return string
         */
-    public function LociString($lstring, &$count) {
-            // Loci strings are UTF-8 or UTF-16 and null (x00/x0000) terminated. UTF-16 has a BOM
-            // Also need to return the number of bytes the string occupied so additional fields can be extracted
-            $len = strlen($lstring);
-            if ($len == 0) {
-                $count = 0;
-                return '';
-            }
-            if ($lstring[0] == "\x00") {
-                $count = 1;
-                return '';
-            }
-            //check for BOM
-            if ($len > 2 && (($lstring[0] == "\xFE" && $lstring[1] == "\xFF") || ($lstring[0] == "\xFF" && $lstring[1] == "\xFE"))) {
-                //UTF-16
-                if (preg_match('/(.*)\x00/', $lstring, $lmatches)){
-                     $count = strlen($lmatches[1]) * 2 + 2; //account for 2 byte characters and trailing \x0000
-                    return getid3_lib::iconv_fallback_utf16_utf8($lmatches[1]);
-                } else {
-                    return '';
-                }
-            } else {
-                //UTF-8
-                if (preg_match('/(.*)\x00/', $lstring, $lmatches)){
-                    $count = strlen($lmatches[1]) + 1; //account for trailing \x00
-                    return $lmatches[1];
-                }else {
-                    return '';
-                }
-
-            }
-        }
+       public function LociString($lstring, &$count) {
+               // Loci strings are UTF-8 or UTF-16 and null (x00/x0000) terminated. UTF-16 has a BOM
+               // Also need to return the number of bytes the string occupied so additional fields can be extracted
+               $len = strlen($lstring);
+               if ($len == 0) {
+                       $count = 0;
+                       return '';
+               }
+               if ($lstring[0] == "\x00") {
+                       $count = 1;
+                       return '';
+               }
+               // check for BOM
+               if (($len > 2) && ((($lstring[0] == "\xFE") && ($lstring[1] == "\xFF")) || (($lstring[0] == "\xFF") && ($lstring[1] == "\xFE")))) {
+                       // UTF-16
+                       if (preg_match('/(.*)\x00/', $lstring, $lmatches)) {
+                               $count = strlen($lmatches[1]) * 2 + 2; //account for 2 byte characters and trailing \x0000
+                               return getid3_lib::iconv_fallback_utf16_utf8($lmatches[1]);
+                       } else {
+                               return '';
+                       }
+               }
+               // UTF-8
+               if (preg_match('/(.*)\x00/', $lstring, $lmatches)) {
+                       $count = strlen($lmatches[1]) + 1; //account for trailing \x00
+                       return $lmatches[1];
+               }
+               return '';
+       }
 
        /**
         * @param string $nullterminatedstring
@@ -2808,6 +2982,23 @@ class getid3_quicktime extends getid3_handler
                return substr($pascalstring, 1);
        }
 
+       /**
+        * @param string $pascalstring
+        *
+        * @return string
+        */
+       public function MaybePascal2String($pascalstring) {
+               // Pascal strings have 1 unsigned byte at the beginning saying how many chars (1-255) are in the string
+               // Check if string actually is in this format or written incorrectly, straight string, or null-terminated string
+               if (ord(substr($pascalstring, 0, 1)) == (strlen($pascalstring) - 1)) {
+                       return substr($pascalstring, 1);
+               } elseif (substr($pascalstring, -1, 1) == "\x00") {
+                       // appears to be null-terminated instead of Pascal-style
+                       return substr($pascalstring, 0, -1);
+               }
+               return $pascalstring;
+       }
+
 
        /**
         * Helper functions for m4b audiobook chapters
index f5d2ce7..990379e 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
 
 class getid3_real extends getid3_handler
@@ -483,8 +486,9 @@ class getid3_real extends getid3_handler
                        $ParsedArray['fourcc'] = $ParsedArray['fourcc3'];
 
                }
+               /** @var string[]|false[] $value */
                foreach ($ParsedArray['comments'] as $key => $value) {
-                       if ($ParsedArray['comments'][$key][0] === false) {
+                       if ($value[0] === false) {
                                $ParsedArray['comments'][$key][0] = '';
                        }
                }
index 8992ad7..cdf5533 100644 (file)
@@ -23,6 +23,9 @@
 * @todo Rewrite RIFF parser totally
 */
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true);
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true);
@@ -51,7 +54,7 @@ class getid3_riff extends getid3_handler
                $thisfile_audio_dataformat = &$thisfile_audio['dataformat'];
                $thisfile_riff_audio       = &$thisfile_riff['audio'];
                $thisfile_riff_video       = &$thisfile_riff['video'];
-        $thisfile_riff_WAVE        = array();
+               $thisfile_riff_WAVE        = array();
 
                $Original['avdataoffset'] = $info['avdataoffset'];
                $Original['avdataend']    = $info['avdataend'];
@@ -203,7 +206,7 @@ class getid3_riff extends getid3_handler
                                        unset($thisfile_riff_audio[$streamindex]['raw']);
                                        $thisfile_audio['streams'][$streamindex] = $thisfile_riff_audio[$streamindex];
 
-                                       $thisfile_audio = getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
+                                       $thisfile_audio = (array) getid3_lib::array_merge_noclobber($thisfile_audio, $thisfile_riff_audio[$streamindex]);
                                        if (substr($thisfile_audio['codec'], 0, strlen('unknown: 0x')) == 'unknown: 0x') {
                                                $this->warning('Audio codec = '.$thisfile_audio['codec']);
                                        }
@@ -703,13 +706,13 @@ class getid3_riff extends getid3_handler
                                                'capturedfile' => 0x00010000,
                                                'copyrighted'  => 0x00020010,
                                        );
-                    foreach ($flags as $flag => $value) {
+                                       foreach ($flags as $flag => $value) {
                                                $thisfile_riff_raw_avih['flags'][$flag] = (bool) ($thisfile_riff_raw_avih['dwFlags'] & $value);
                                        }
 
                                        // shortcut
                                        $thisfile_riff_video[$streamindex] = array();
-                    /** @var array $thisfile_riff_video_current */
+                                       /** @var array $thisfile_riff_video_current */
                                        $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex];
 
                                        if ($thisfile_riff_raw_avih['dwWidth'] > 0) {
@@ -923,7 +926,7 @@ class getid3_riff extends getid3_handler
                        // http://en.wikipedia.org/wiki/CD-DA
                        case 'CDDA':
                                $info['fileformat'] = 'cda';
-                           unset($info['mime_type']);
+                               unset($info['mime_type']);
 
                                $thisfile_audio_dataformat      = 'cda';
 
@@ -943,7 +946,7 @@ class getid3_riff extends getid3_handler
 
                                        $thisfile_riff_CDDA_fmt_0['start_offset_seconds'] = (float) $thisfile_riff_CDDA_fmt_0['start_offset_frame'] / 75;
                                        $thisfile_riff_CDDA_fmt_0['playtime_seconds']     = (float) $thisfile_riff_CDDA_fmt_0['playtime_frames'] / 75;
-                                       $info['comments']['track']                = $thisfile_riff_CDDA_fmt_0['track_num'];
+                                       $info['comments']['track_number']         = $thisfile_riff_CDDA_fmt_0['track_num'];
                                        $info['playtime_seconds']                 = $thisfile_riff_CDDA_fmt_0['playtime_seconds'];
 
                                        // hardcoded data for CD-audio
@@ -956,7 +959,7 @@ class getid3_riff extends getid3_handler
                                }
                                break;
 
-            // http://en.wikipedia.org/wiki/AIFF
+                       // http://en.wikipedia.org/wiki/AIFF
                        case 'AIFF':
                        case 'AIFC':
                                $info['fileformat'] = 'aiff';
@@ -1066,7 +1069,7 @@ class getid3_riff extends getid3_handler
                                if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
                                        getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
                                        $getid3_temp = new getID3();
-                                       $getid3_temp->openfile($this->getid3->filename);
+                                       $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
                                        $getid3_id3v2 = new getid3_id3v2($getid3_temp);
                                        $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
                                        if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
@@ -1169,7 +1172,7 @@ class getid3_riff extends getid3_handler
                                        getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true);
 
                                        $getid3_temp = new getID3();
-                                       $getid3_temp->openfile($this->getid3->filename);
+                                       $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
                                        $getid3_mpeg = new getid3_mpeg($getid3_temp);
                                        $getid3_mpeg->Analyze();
                                        if (empty($getid3_temp->info['error'])) {
@@ -1255,7 +1258,7 @@ class getid3_riff extends getid3_handler
                                        getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
 
                                        $getid3_temp = new getID3();
-                                       $getid3_temp->openfile($this->getid3->filename);
+                                       $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
                                        $getid3_id3v2 = new getid3_id3v2($getid3_temp);
                                        $getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
                                        if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
@@ -1554,7 +1557,7 @@ class getid3_riff extends getid3_handler
                                                                                // MP3
                                                                                if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
                                                                                        $getid3_temp = new getID3();
-                                                                                       $getid3_temp->openfile($this->getid3->filename);
+                                                                                       $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
                                                                                        $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
                                                                                        $getid3_temp->info['avdataend']    = $this->ftell() + $AudioChunkSize;
                                                                                        $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
@@ -1576,7 +1579,7 @@ class getid3_riff extends getid3_handler
 
                                                                                // AC3
                                                                                $getid3_temp = new getID3();
-                                                                               $getid3_temp->openfile($this->getid3->filename);
+                                                                               $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
                                                                                $getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
                                                                                $getid3_temp->info['avdataend']    = $this->ftell() + $AudioChunkSize;
                                                                                $getid3_ac3 = new getid3_ac3($getid3_temp);
@@ -1637,7 +1640,7 @@ class getid3_riff extends getid3_handler
                                                                        // Probably is MP3 data
                                                                        if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
                                                                                $getid3_temp = new getID3();
-                                                                               $getid3_temp->openfile($this->getid3->filename);
+                                                                               $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
                                                                                $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
                                                                                $getid3_temp->info['avdataend']    = $info['avdataend'];
                                                                                $getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
@@ -1654,7 +1657,7 @@ class getid3_riff extends getid3_handler
                                                                        // This is probably AC-3 data
                                                                        $getid3_temp = new getID3();
                                                                        if ($isRegularAC3) {
-                                                                               $getid3_temp->openfile($this->getid3->filename);
+                                                                               $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
                                                                                $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
                                                                                $getid3_temp->info['avdataend']    = $info['avdataend'];
                                                                        }
@@ -1688,7 +1691,7 @@ class getid3_riff extends getid3_handler
 
                                                                        // This is probably DTS data
                                                                        $getid3_temp = new getID3();
-                                                                       $getid3_temp->openfile($this->getid3->filename);
+                                                                       $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
                                                                        $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
                                                                        $getid3_dts = new getid3_dts($getid3_temp);
                                                                        $getid3_dts->Analyze();
@@ -1756,6 +1759,75 @@ class getid3_riff extends getid3_handler
                                                        //      $info['divxtag']['comments'] = self::ParseDIVXTAG($this->fread($chunksize));
                                                        //      break;
 
+                                                       case 'scot':
+                                                               // https://cmsdk.com/node-js/adding-scot-chunk-to-wav-file.html
+                                                               $RIFFchunk[$chunkname][$thisindex]['data'] = $this->fread($chunksize);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['alter']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],   0,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib']          =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],   1,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['artnum']          = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],   2,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['title']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],   4,  43);  // "name" in other documentation
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['copy']            =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  47,   4);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['padd']            =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  51,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['asclen']          =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  52,   5);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['startseconds']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  57,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['starthundredths'] = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  59,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['endseconds']      = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  61,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['endhundreths']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  63,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['sdate']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  65,   6);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['kdate']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  71,   6);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['start_hr']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  77,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['kill_hr']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  78,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['digital']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  79,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['sample_rate']     = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  80,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['stereo']          =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  82,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['compress']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  83,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['eomstrt']         = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  84,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['eomlen']          = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  88,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['attrib2']         = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'],  90,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['future1']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'],  94,  12);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['catfontcolor']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 106,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['catcolor']        = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 110,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['segeompos']       = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 114,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_startsecs']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 118,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['vt_starthunds']   = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 120,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcat']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 122,   3);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['priorcopy']       =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 125,   4);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['priorpadd']       =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 129,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['postcat']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 130,   3);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['postcopy']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 133,   4);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['postpadd']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 137,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['hrcanplay']       =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 138,  21);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['future2']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 159, 108);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['artist']          =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 267,  34);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['comment']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 301,  34); // "trivia" in other documentation
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['intro']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 335,   2);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['end']             =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 337,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['year']            =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 338,   4);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['obsolete2']       =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 342,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['rec_hr']          =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 343,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['rdate']           =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 344,   6);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['mpeg_bitrate']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 350,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['pitch']           = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 352,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['playlevel']       = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 354,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['lenvalid']        =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 356,   1);
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['filelength']      = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 357,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['newplaylevel']    = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 361,   2));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['chopsize']        = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 363,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['vteomovr']        = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 367,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['desiredlen']      = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 371,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['triggers']        = getid3_lib::LittleEndian2Int(substr($RIFFchunk[$chunkname][$thisindex]['data'], 375,   4));
+                                                               $RIFFchunk[$chunkname][$thisindex]['parsed']['fillout']         =                              substr($RIFFchunk[$chunkname][$thisindex]['data'], 379,   33);
+
+                                                               foreach (array('title', 'artist', 'comment') as $key) {
+                                                                       if (trim($RIFFchunk[$chunkname][$thisindex]['parsed'][$key])) {
+                                                                               $info['riff']['comments'][$key] = array($RIFFchunk[$chunkname][$thisindex]['parsed'][$key]);
+                                                                       }
+                                                               }
+                                                               if ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] && !empty($info['filesize']) && ($RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'] != $info['filesize'])) {
+                                                                       $this->warning('RIFF.WAVE.scot.filelength ('.$RIFFchunk[$chunkname][$thisindex]['parsed']['filelength'].') different from actual filesize ('.$info['filesize'].')');
+                                                               }
+                                                               break;
+
                                                        default:
                                                                if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) {
                                                                        $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset'];
index e1151f3..fc4a5c5 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_swf extends getid3_handler
 {
@@ -49,7 +52,6 @@ class getid3_swf extends getid3_handler
                                unset($info['swf']);
                                unset($info['fileformat']);
                                return false;
-                               break;
                }
                $info['swf']['header']['version'] = getid3_lib::LittleEndian2Int(substr($SWFfileData, 3, 1));
                $info['swf']['header']['length']  = getid3_lib::LittleEndian2Int(substr($SWFfileData, 4, 4));
index 24679bc..474503a 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_ts extends getid3_handler
 {
index 1eec54e..171e72d 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_aa extends getid3_handler
 {
index 846850c..d4f04b8 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_aac extends getid3_handler
 {
index d4e4e4b..636ff8f 100644 (file)
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_ac3 extends getid3_handler
 {
        /**
         * @var array
         */
-    private $AC3header = array();
+       private $AC3header = array();
 
        /**
         * @var int
         */
-    private $BSIoffset = 0;
+       private $BSIoffset = 0;
 
-    const syncword = 0x0B77;
+       const syncword = 0x0B77;
 
        /**
         * @return bool
@@ -422,7 +425,7 @@ class getid3_ac3 extends getid3_handler
                } else {
 
                        $this->error('Bit stream identification is version '.$thisfile_ac3_raw_bsi['bsid'].', but getID3() only understands up to version 16. Please submit a support ticket with a sample file.');
-                   unset($info['ac3']);
+                       unset($info['ac3']);
                        return false;
 
                }
@@ -485,7 +488,7 @@ class getid3_ac3 extends getid3_handler
        /**
         * @param int $length
         *
-        * @return float|int
+        * @return int
         */
        private function readHeaderBSI($length) {
                $data = substr($this->AC3header['bsi'], $this->BSIoffset, $length);
@@ -687,7 +690,7 @@ class getid3_ac3 extends getid3_handler
                // -8    -42.14 dB
 
                $fourbit = str_pad(decbin(($compre & 0xF0) >> 4), 4, '0', STR_PAD_LEFT);
-               if ($fourbit{0} == '1') {
+               if ($fourbit[0] == '1') {
                        $log_gain = -8 + bindec(substr($fourbit, 1));
                } else {
                        $log_gain = bindec(substr($fourbit, 1));
@@ -758,11 +761,13 @@ class getid3_ac3 extends getid3_handler
                                18 => array(2560, 2786, 3840)   // 640 kbps
                        );
                }
+               $paddingBytes = 0;
                if (($fscod == 1) && $padding) {
                        // frame lengths are padded by 1 word (16 bits) at 44100
-                       $frameSizeLookup[$frmsizecod] += 2;
+                       // (fscode==1) means 44100Hz (see sampleRateCodeLookup)
+                       $paddingBytes = 2;
                }
-               return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false);
+               return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] + $paddingBytes : false);
        }
 
        /**
index 42ebd14..e2e4531 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_amr extends getid3_handler
 {
index a99d05d..73df103 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_au extends getid3_handler
 {
index 50e2994..69a2605 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_avr extends getid3_handler
 {
index 5398391..c6cf9ac 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_bonk extends getid3_handler
 {
@@ -44,7 +47,7 @@ class getid3_bonk extends getid3_handler
                                $this->fseek(0 - $BonkTagSize, SEEK_CUR);
                                $BonkTagOffset = $this->ftell();
                                $TagHeaderTest = $this->fread(5);
-                               if (($TagHeaderTest{0} != "\x00") || (substr($PossibleBonkTag, 4, 4) != strtolower(substr($PossibleBonkTag, 4, 4)))) {
+                               if (($TagHeaderTest[0] != "\x00") || (substr($PossibleBonkTag, 4, 4) != strtolower(substr($PossibleBonkTag, 4, 4)))) {
                                        $this->error('Expecting "'.getid3_lib::PrintHexBytes("\x00".strtoupper(substr($PossibleBonkTag, 4, 4))).'" at offset '.$BonkTagOffset.', found "'.getid3_lib::PrintHexBytes($TagHeaderTest).'"');
                                        return false;
                                }
@@ -201,7 +204,7 @@ class getid3_bonk extends getid3_handler
                                // ID3v2 checking is optional
                                if (class_exists('getid3_id3v2')) {
                                        $getid3_temp = new getID3();
-                                       $getid3_temp->openfile($this->getid3->filename);
+                                       $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
                                        $getid3_id3v2 = new getid3_id3v2($getid3_temp);
                                        $getid3_id3v2->StartingOffset = $info['bonk'][' ID3']['offset'] + 2;
                                        $info['bonk'][' ID3']['valid'] = $getid3_id3v2->Analyze();
index bbcee76..cd059c9 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
 
 class getid3_dsf extends getid3_handler
index 492393a..dd2a56b 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_dss extends getid3_handler
 {
@@ -26,8 +29,8 @@ class getid3_dss extends getid3_handler
                $this->fseek($info['avdataoffset']);
                $DSSheader  = $this->fread(1540);
 
-               if (!preg_match('#^[\\x02-\\x06]ds[s2]#', $DSSheader)) {
-                       $this->error('Expecting "[02-06] 64 73 [73|32]" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($DSSheader, 0, 4)).'"');
+               if (!preg_match('#^[\\x02-\\x08]ds[s2]#', $DSSheader)) {
+                       $this->error('Expecting "[02-08] 64 73 [73|32]" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes(substr($DSSheader, 0, 4)).'"');
                        return false;
                }
 
@@ -46,7 +49,7 @@ class getid3_dss extends getid3_handler
                // 32-37 = "FE FF FE FF F7 FF" in all the sample files I've seen
                $info['dss']['date_create_unix']   = $this->DSSdateStringToUnixDate(substr($DSSheader,   38,  12));
                $info['dss']['date_complete_unix'] = $this->DSSdateStringToUnixDate(substr($DSSheader,   50,  12));
-               $info['dss']['playtime_sec']       = intval((substr($DSSheader,  62, 2) * 3600) + (substr($DSSheader,  64, 2) * 60) + substr($DSSheader,  66, 2)); // approximate file playtime in HHMMSS
+               $info['dss']['playtime_sec']       = ((int) substr($DSSheader, 62, 2) * 3600) + ((int) substr($DSSheader, 64, 2) * 60) + (int) substr($DSSheader, 66, 2); // approximate file playtime in HHMMSS
                if ($info['dss']['version'] <= 3) {
                        $info['dss']['playtime_ms']        =   getid3_lib::LittleEndian2Int(substr($DSSheader,  512,   4)); // exact file playtime in milliseconds. Has also been observed at offset 530 in one sample file, with something else (unknown) at offset 512
                        $info['dss']['priority']           =                            ord(substr($DSSheader,  793,   1));
@@ -79,7 +82,7 @@ class getid3_dss extends getid3_handler
         * @return int|false
         */
        public function DSSdateStringToUnixDate($datestring) {
-               $y = substr($datestring,  0, 2);
+               $y = (int) substr($datestring,  0, 2);
                $m = substr($datestring,  2, 2);
                $d = substr($datestring,  4, 2);
                $h = substr($datestring,  6, 2);
index 2dd44e9..ff1a88f 100644 (file)
@@ -14,6 +14,9 @@
 //                                                             //
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 /**
 * @tutorial http://wiki.multimedia.cx/index.php?title=DTS
@@ -51,18 +54,18 @@ class getid3_dts extends getid3_handler
 
                // check syncword
                $sync = substr($DTSheader, 0, 4);
-        if (($encoding = array_search($sync, self::$syncwords)) !== false) {
+               if (($encoding = array_search($sync, self::$syncwords)) !== false) {
 
-               $info['dts']['raw']['magic'] = $sync;
+                       $info['dts']['raw']['magic'] = $sync;
                        $this->readBinDataOffset = 32;
 
-        } elseif ($this->isDependencyFor('matroska')) {
+               } elseif ($this->isDependencyFor('matroska')) {
 
                        // Matroska contains DTS without syncword encoded as raw big-endian format
                        $encoding = 0;
                        $this->readBinDataOffset = 0;
 
-        } else {
+               } else {
 
                        unset($info['fileformat']);
                        return $this->error('Expecting "'.implode('| ', array_map('getid3_lib::PrintHexBytes', self::$syncwords)).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($sync).'"');
@@ -149,7 +152,7 @@ class getid3_dts extends getid3_handler
         * @param string $bin
         * @param int $length
         *
-        * @return float|int
+        * @return int
         */
        private function readBinData($bin, $length) {
                $data = substr($bin, $this->readBinDataOffset, $length);
@@ -252,36 +255,28 @@ class getid3_dts extends getid3_handler
                switch ($index) {
                        case 0:
                                return 1;
-                               break;
                        case 1:
                        case 2:
                        case 3:
                        case 4:
                                return 2;
-                               break;
                        case 5:
                        case 6:
                                return 3;
-                               break;
                        case 7:
                        case 8:
                                return 4;
-                               break;
                        case 9:
                                return 5;
-                               break;
                        case 10:
                        case 11:
                        case 12:
                                return 6;
-                               break;
                        case 13:
                                return 7;
-                               break;
                        case 14:
                        case 15:
                                return 8;
-                               break;
                }
                return false;
        }
@@ -323,10 +318,8 @@ class getid3_dts extends getid3_handler
                switch ($version) {
                        case 7:
                                return 0 - $index;
-                               break;
                        case 6:
                                return 0 - 16 - $index;
-                               break;
                }
                return false;
        }
index 4edf587..1cea436 100644 (file)
@@ -14,7 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
-
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, true);
 
 /**
@@ -178,7 +180,7 @@ class getid3_flac extends getid3_handler
                if (isset($info['flac']['STREAMINFO']['audio_signature'])) {
 
                        if ($info['flac']['STREAMINFO']['audio_signature'] === str_repeat("\x00", 16)) {
-                $this->warning('FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)');
+                               $this->warning('FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)');
                        }
                        else {
                                $info['md5_data_source'] = '';
index 3fee9d3..27a4679 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
 
 class getid3_la extends getid3_handler
@@ -215,7 +218,6 @@ class getid3_la extends getid3_handler
                                        $this->error('Not a LA (Lossless-Audio) file');
                                }
                                return false;
-                               break;
                }
 
                $info['audio']['channels']    = $info['la']['channels'];
index 375ba20..f49e244 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
 
 class getid3_lpac extends getid3_handler
@@ -80,7 +83,7 @@ class getid3_lpac extends getid3_handler
                }
 
                $getid3_temp = new getID3();
-               $getid3_temp->openfile($this->getid3->filename);
+               $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
                $getid3_temp->info = $info;
                $getid3_riff = new getid3_riff($getid3_temp);
                $getid3_riff->Analyze();
index 770481c..eaef9cb 100644 (file)
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
+
 define('GETID3_MIDI_MAGIC_MTHD', 'MThd'); // MIDI file header magic
 define('GETID3_MIDI_MAGIC_MTRK', 'MTrk'); // MIDI track header magic
 
@@ -243,9 +247,9 @@ class getid3_midi extends getid3_handler
                                                                break;
 
                                                        case 0x58: // Time signature
-                                                               $timesig_numerator   = getid3_lib::BigEndian2Int($METAeventData{0});
-                                                               $timesig_denominator = pow(2, getid3_lib::BigEndian2Int($METAeventData{1})); // $02 -> x/4, $03 -> x/8, etc
-                                                               $timesig_32inqnote   = getid3_lib::BigEndian2Int($METAeventData{2});         // number of 32nd notes to the quarter note
+                                                               $timesig_numerator   = getid3_lib::BigEndian2Int($METAeventData[0]);
+                                                               $timesig_denominator = pow(2, getid3_lib::BigEndian2Int($METAeventData[1])); // $02 -> x/4, $03 -> x/8, etc
+                                                               $timesig_32inqnote   = getid3_lib::BigEndian2Int($METAeventData[2]);         // number of 32nd notes to the quarter note
                                                                //$thisfile_midi_raw['events'][$tracknumber][$eventid]['timesig_32inqnote']   = $timesig_32inqnote;
                                                                //$thisfile_midi_raw['events'][$tracknumber][$eventid]['timesig_numerator']   = $timesig_numerator;
                                                                //$thisfile_midi_raw['events'][$tracknumber][$eventid]['timesig_denominator'] = $timesig_denominator;
@@ -254,13 +258,13 @@ class getid3_midi extends getid3_handler
                                                                break;
 
                                                        case 0x59: // Keysignature
-                                                               $keysig_sharpsflats = getid3_lib::BigEndian2Int($METAeventData{0});
+                                                               $keysig_sharpsflats = getid3_lib::BigEndian2Int($METAeventData[0]);
                                                                if ($keysig_sharpsflats & 0x80) {
                                                                        // (-7 -> 7 flats, 0 ->key of C, 7 -> 7 sharps)
                                                                        $keysig_sharpsflats -= 256;
                                                                }
 
-                                                               $keysig_majorminor  = getid3_lib::BigEndian2Int($METAeventData{1}); // 0 -> major, 1 -> minor
+                                                               $keysig_majorminor  = getid3_lib::BigEndian2Int($METAeventData[1]); // 0 -> major, 1 -> minor
                                                                $keysigs = array(-7=>'Cb', -6=>'Gb', -5=>'Db', -4=>'Ab', -3=>'Eb', -2=>'Bb', -1=>'F', 0=>'C', 1=>'G', 2=>'D', 3=>'A', 4=>'E', 5=>'B', 6=>'F#', 7=>'C#');
                                                                //$thisfile_midi_raw['events'][$tracknumber][$eventid]['keysig_sharps'] = (($keysig_sharpsflats > 0) ? abs($keysig_sharpsflats) : 0);
                                                                //$thisfile_midi_raw['events'][$tracknumber][$eventid]['keysig_flats']  = (($keysig_sharpsflats < 0) ? abs($keysig_sharpsflats) : 0);
index 708d213..bf8be33 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_mod extends getid3_handler
 {
index 3317a93..beaca8c 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_monkey extends getid3_handler
 {
@@ -162,7 +165,7 @@ class getid3_monkey extends getid3_handler
                                $info['md5_data_source'] = '';
                                $md5 = $thisfile_monkeysaudio_raw['cFileMD5'];
                                for ($i = 0; $i < strlen($md5); $i++) {
-                                       $info['md5_data_source'] .= str_pad(dechex(ord($md5{$i})), 2, '00', STR_PAD_LEFT);
+                                       $info['md5_data_source'] .= str_pad(dechex(ord($md5[$i])), 2, '00', STR_PAD_LEFT);
                                }
                                if (!preg_match('/^[0-9a-f]{32}$/', $info['md5_data_source'])) {
                                        unset($info['md5_data_source']);
index 4434380..26b2806 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 // number of frames to scan to determine if MPEG-audio sequence is valid
 // Lower this number to 5-20 for faster scanning
@@ -701,7 +704,7 @@ class getid3_mp3 extends getid3_handler
                                if ($thisfile_mpeg_audio['xing_flags']['toc']) {
                                        $LAMEtocData = substr($headerstring, $VBRidOffset + 16, 100);
                                        for ($i = 0; $i < 100; $i++) {
-                                               $thisfile_mpeg_audio['toc'][$i] = ord($LAMEtocData{$i});
+                                               $thisfile_mpeg_audio['toc'][$i] = ord($LAMEtocData[$i]);
                                        }
                                }
                                if ($thisfile_mpeg_audio['xing_flags']['vbr_scale']) {
@@ -719,8 +722,17 @@ class getid3_mp3 extends getid3_handler
 
                                        $thisfile_mpeg_audio_lame['long_version']  = substr($headerstring, $VBRidOffset + 120, 20);
                                        $thisfile_mpeg_audio_lame['short_version'] = substr($thisfile_mpeg_audio_lame['long_version'], 0, 9);
+                                       $thisfile_mpeg_audio_lame['numeric_version'] = str_replace('LAME', '', $thisfile_mpeg_audio_lame['short_version']);
+                                       if (preg_match('#^LAME([0-9\\.a-z]+)#', $thisfile_mpeg_audio_lame['long_version'], $matches)) {
+                                               $thisfile_mpeg_audio_lame['short_version']   = $matches[0];
+                                               $thisfile_mpeg_audio_lame['numeric_version'] = $matches[1];
+                                       }
+                                       foreach (explode('.', $thisfile_mpeg_audio_lame['numeric_version']) as $key => $number) {
+                                               $thisfile_mpeg_audio_lame['integer_version'][$key] = intval($number);
+                                       }
 
-                                       if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') {
+                                       //if ($thisfile_mpeg_audio_lame['short_version'] >= 'LAME3.90') {
+                                       if ((($thisfile_mpeg_audio_lame['integer_version'][0] * 1000) + $thisfile_mpeg_audio_lame['integer_version'][1]) >= 3090) { // cannot use string version compare, may have "LAME3.90" or "LAME3.100" -- see https://github.com/JamesHeinrich/getID3/issues/207
 
                                                // extra 11 chars are not part of version string when LAMEtag present
                                                unset($thisfile_mpeg_audio_lame['long_version']);
@@ -1173,9 +1185,9 @@ class getid3_mp3 extends getid3_handler
 
                $SyncPattern1 = substr($MPEGaudioData, 0, 4);
                // may be different pattern due to padding
-               $SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) | 0x02).$SyncPattern1{3};
+               $SyncPattern2 = $SyncPattern1[0].$SyncPattern1[1].chr(ord($SyncPattern1[2]) | 0x02).$SyncPattern1[3];
                if ($SyncPattern2 === $SyncPattern1) {
-                       $SyncPattern2 = $SyncPattern1{0}.$SyncPattern1{1}.chr(ord($SyncPattern1{2}) & 0xFD).$SyncPattern1{3};
+                       $SyncPattern2 = $SyncPattern1[0].$SyncPattern1[1].chr(ord($SyncPattern1[2]) & 0xFD).$SyncPattern1[3];
                }
 
                $framelength = false;
@@ -1280,9 +1292,9 @@ class getid3_mp3 extends getid3_handler
                        if (strlen($head4) < 4) {
                                break;
                        }
-                       if ($head4{0} != "\xFF") {
+                       if ($head4[0] != "\xFF") {
                                for ($i = 1; $i < 4; $i++) {
-                                       if ($head4{$i} == "\xFF") {
+                                       if ($head4[$i] == "\xFF") {
                                                $this->fseek($i - 4, SEEK_CUR);
                                                continue 2;
                                        }
@@ -1314,7 +1326,7 @@ class getid3_mp3 extends getid3_handler
                                        $WhereWeWere = $this->ftell();
                                        $this->fseek($MPEGaudioHeaderLengthCache[$head4] - 4, SEEK_CUR);
                                        $next4 = $this->fread(4);
-                                       if ($next4{0} == "\xFF") {
+                                       if ($next4[0] == "\xFF") {
                                                if (!isset($MPEGaudioHeaderDecodeCache[$next4])) {
                                                        $MPEGaudioHeaderDecodeCache[$next4] = self::MPEGaudioHeaderDecode($next4);
                                                }
@@ -1324,12 +1336,12 @@ class getid3_mp3 extends getid3_handler
                                                if ($MPEGaudioHeaderValidCache[$next4]) {
                                                        $this->fseek(-4, SEEK_CUR);
 
-                                                       getid3_lib::safe_inc($Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]]);
-                                                       getid3_lib::safe_inc($Distribution['layer'][$LongMPEGlayerLookup[$head4]]);
-                                                       getid3_lib::safe_inc($Distribution['version'][$LongMPEGversionLookup[$head4]]);
-                                                       getid3_lib::safe_inc($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]);
-                                                       getid3_lib::safe_inc($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]);
-                                                       if ($max_frames_scan && (++$frames_scanned >= $max_frames_scan)) {
+                                                       $Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]] = isset($Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]]) ? ++$Distribution['bitrate'][$LongMPEGbitrateLookup[$head4]] : 1;
+                                                       $Distribution['layer'][$LongMPEGlayerLookup[$head4]] = isset($Distribution['layer'][$LongMPEGlayerLookup[$head4]]) ? ++$Distribution['layer'][$LongMPEGlayerLookup[$head4]] : 1;
+                                                       $Distribution['version'][$LongMPEGversionLookup[$head4]] = isset($Distribution['version'][$LongMPEGversionLookup[$head4]]) ? ++$Distribution['version'][$LongMPEGversionLookup[$head4]] : 1;
+                                                       $Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] = isset($Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])]) ? ++$Distribution['padding'][intval($LongMPEGpaddingLookup[$head4])] : 1;
+                                                       $Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] = isset($Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]]) ? ++$Distribution['frequency'][$LongMPEGfrequencyLookup[$head4]] : 1;
+                                                       if (++$frames_scanned >= $max_frames_scan) {
                                                                $pct_data_scanned = ($this->ftell() - $info['avdataoffset']) / ($info['avdataend'] - $info['avdataoffset']);
                                                                $this->warning('too many MPEG audio frames to scan, only scanned first '.$max_frames_scan.' frames ('.number_format($pct_data_scanned * 100, 1).'% of file) and extrapolated distribution, playtime and bitrate may be incorrect.');
                                                                foreach ($Distribution as $key1 => $value1) {
@@ -1407,10 +1419,9 @@ class getid3_mp3 extends getid3_handler
                static $MPEGaudioLayerLookup;
                static $MPEGaudioBitrateLookup;
                if (empty($MPEGaudioVersionLookup)) {
-                  $MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
-                  $MPEGaudioLayerLookup   = self::MPEGaudioLayerArray();
-                  $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
-
+                       $MPEGaudioVersionLookup = self::MPEGaudioVersionArray();
+                       $MPEGaudioLayerLookup   = self::MPEGaudioLayerArray();
+                       $MPEGaudioBitrateLookup = self::MPEGaudioBitrateArray();
                }
 
                $this->fseek($avdataoffset);
@@ -1460,7 +1471,7 @@ class getid3_mp3 extends getid3_handler
                                return false;
                        }
 
-                       if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected
+                       if (($header[$SynchSeekOffset] == "\xFF") && ($header[($SynchSeekOffset + 1)] > "\xE0")) { // synch detected
                                $FirstFrameAVDataOffset = null;
                                if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) {
                                        $FirstFrameThisfileInfo = $info;
@@ -1555,7 +1566,7 @@ class getid3_mp3 extends getid3_handler
                                                                $this->fseek($scan_start_offset[$current_segment]);
                                                                $buffer_4k = $this->fread(4096);
                                                                for ($j = 0; $j < (strlen($buffer_4k) - 4); $j++) {
-                                                                       if (($buffer_4k{$j} == "\xFF") && ($buffer_4k{($j + 1)} > "\xE0")) { // synch detected
+                                                                       if (($buffer_4k[$j] == "\xFF") && ($buffer_4k[($j + 1)] > "\xE0")) { // synch detected
                                                                                if ($this->decodeMPEGaudioHeader($scan_start_offset[$current_segment] + $j, $dummy, false, false, $FastMode)) {
                                                                                        $calculated_next_offset = $scan_start_offset[$current_segment] + $j + $dummy['mpeg']['audio']['framelength'];
                                                                                        if ($this->decodeMPEGaudioHeader($calculated_next_offset, $dummy, false, false, $FastMode)) {
@@ -1780,7 +1791,7 @@ class getid3_mp3 extends getid3_handler
         * @return bool
         */
        public static function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) {
-               if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
+               if (!isset($rawarray['synch']) || ($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
                        return false;
                }
 
@@ -1877,18 +1888,18 @@ class getid3_mp3 extends getid3_handler
                }
 
                $MPEGrawHeader['synch']         = (getid3_lib::BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4;
-               $MPEGrawHeader['version']       = (ord($Header4Bytes{1}) & 0x18) >> 3; //    BB
-               $MPEGrawHeader['layer']         = (ord($Header4Bytes{1}) & 0x06) >> 1; //      CC
-               $MPEGrawHeader['protection']    = (ord($Header4Bytes{1}) & 0x01);      //        D
-               $MPEGrawHeader['bitrate']       = (ord($Header4Bytes{2}) & 0xF0) >> 4; // EEEE
-               $MPEGrawHeader['sample_rate']   = (ord($Header4Bytes{2}) & 0x0C) >> 2; //     FF
-               $MPEGrawHeader['padding']       = (ord($Header4Bytes{2}) & 0x02) >> 1; //       G
-               $MPEGrawHeader['private']       = (ord($Header4Bytes{2}) & 0x01);      //        H
-               $MPEGrawHeader['channelmode']   = (ord($Header4Bytes{3}) & 0xC0) >> 6; // II
-               $MPEGrawHeader['modeextension'] = (ord($Header4Bytes{3}) & 0x30) >> 4; //   JJ
-               $MPEGrawHeader['copyright']     = (ord($Header4Bytes{3}) & 0x08) >> 3; //     K
-               $MPEGrawHeader['original']      = (ord($Header4Bytes{3}) & 0x04) >> 2; //      L
-               $MPEGrawHeader['emphasis']      = (ord($Header4Bytes{3}) & 0x03);      //       MM
+               $MPEGrawHeader['version']       = (ord($Header4Bytes[1]) & 0x18) >> 3; //    BB
+               $MPEGrawHeader['layer']         = (ord($Header4Bytes[1]) & 0x06) >> 1; //      CC
+               $MPEGrawHeader['protection']    = (ord($Header4Bytes[1]) & 0x01);      //        D
+               $MPEGrawHeader['bitrate']       = (ord($Header4Bytes[2]) & 0xF0) >> 4; // EEEE
+               $MPEGrawHeader['sample_rate']   = (ord($Header4Bytes[2]) & 0x0C) >> 2; //     FF
+               $MPEGrawHeader['padding']       = (ord($Header4Bytes[2]) & 0x02) >> 1; //       G
+               $MPEGrawHeader['private']       = (ord($Header4Bytes[2]) & 0x01);      //        H
+               $MPEGrawHeader['channelmode']   = (ord($Header4Bytes[3]) & 0xC0) >> 6; // II
+               $MPEGrawHeader['modeextension'] = (ord($Header4Bytes[3]) & 0x30) >> 4; //   JJ
+               $MPEGrawHeader['copyright']     = (ord($Header4Bytes[3]) & 0x08) >> 3; //     K
+               $MPEGrawHeader['original']      = (ord($Header4Bytes[3]) & 0x04) >> 2; //      L
+               $MPEGrawHeader['emphasis']      = (ord($Header4Bytes[3]) & 0x03);      //       MM
 
                return $MPEGrawHeader;
        }
@@ -1997,7 +2008,7 @@ class getid3_mp3 extends getid3_handler
        public static function XingVBRidOffset($version, $channelmode) {
                static $XingVBRidOffsetCache = array();
                if (empty($XingVBRidOffsetCache)) {
-            $XingVBRidOffsetCache = array (
+                       $XingVBRidOffsetCache = array (
                                '1'   => array ('mono'          => 0x15, // 4 + 17 = 21
                                                                'stereo'        => 0x24, // 4 + 32 = 36
                                                                'joint stereo'  => 0x24,
index 6d7c851..4f6f5c8 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_mpc extends getid3_handler
 {
@@ -200,7 +203,6 @@ class getid3_mpc extends getid3_handler
                                default:
                                        $this->error('Found unhandled key type "'.$thisPacket['key'].'" at offset '.$thisPacket['offset']);
                                        return false;
-                                       break;
                        }
                        if (!empty($thisPacket)) {
                                $info['mpc']['packets'][] = $thisPacket;
@@ -382,7 +384,6 @@ class getid3_mpc extends getid3_handler
                                $info['error'] = 'Expecting 4, 5 or 6 in version field, found '.$thisfile_mpc_header['stream_version_major'].' instead';
                                unset($info['mpc']);
                                return false;
-                               break;
                }
 
                if (($thisfile_mpc_header['stream_version_major'] > 4) && ($thisfile_mpc_header['block_size'] != 1)) {
index 51fee3e..fe092d9 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.flac.php', __FILE__, true);
 
 class getid3_ogg extends getid3_handler
@@ -615,7 +618,6 @@ class getid3_ogg extends getid3_handler
 
                        default:
                                return false;
-                               break;
                }
 
                $VendorSize = getid3_lib::LittleEndian2Int(substr($commentdata, $commentdataoffset, 4));
index 1c12230..7e888cc 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
 
 class getid3_optimfrog extends getid3_handler
@@ -76,7 +79,7 @@ class getid3_optimfrog extends getid3_handler
                $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8);
 
                $getid3_temp = new getID3();
-               $getid3_temp->openfile($this->getid3->filename);
+               $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
                $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
                $getid3_temp->info['avdataend']    = $info['avdataend'];
                $getid3_riff = new getid3_riff($getid3_temp);
@@ -307,7 +310,7 @@ class getid3_optimfrog extends getid3_handler
                $RIFFdata = substr($RIFFdata, 0, 36).substr($RIFFdata, 44).substr($RIFFdata, 36, 8);
 
                $getid3_temp = new getID3();
-               $getid3_temp->openfile($this->getid3->filename);
+               $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
                $getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
                $getid3_temp->info['avdataend']    = $info['avdataend'];
                $getid3_riff = new getid3_riff($getid3_temp);
index 7e1c810..8bbacd4 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_rkau extends getid3_handler
 {
index f5e2a57..533208f 100644 (file)
@@ -14,7 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
-
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 class getid3_shorten extends getid3_handler
 {
        /**
@@ -150,6 +152,9 @@ class getid3_shorten extends getid3_handler
 
                if (!empty($output) && (substr($output, 12, 4) == 'fmt ')) {
 
+                       if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+                               exit;
+                       }
                        getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true);
 
                        $fmt_size = getid3_lib::LittleEndian2Int(substr($output, 16, 4));
index 13d8fe2..700cd05 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_tta extends getid3_handler
 {
@@ -41,7 +44,7 @@ class getid3_tta extends getid3_handler
                        return false;
                }
 
-               switch ($ttaheader{3}) {
+               switch ($ttaheader[3]) {
                        case "\x01": // TTA v1.x
                        case "\x02": // TTA v1.x
                        case "\x03": // TTA v1.x
@@ -49,7 +52,7 @@ class getid3_tta extends getid3_handler
                                $info['tta']['major_version'] = 1;
                                $info['avdataoffset'] += 16;
 
-                               $info['tta']['compression_level']   = ord($ttaheader{3});
+                               $info['tta']['compression_level']   = ord($ttaheader[3]);
                                $info['tta']['channels']            = getid3_lib::LittleEndian2Int(substr($ttaheader,  4,  2));
                                $info['tta']['bits_per_sample']     = getid3_lib::LittleEndian2Int(substr($ttaheader,  6,  2));
                                $info['tta']['sample_rate']         = getid3_lib::LittleEndian2Int(substr($ttaheader,  8,  4));
@@ -92,9 +95,8 @@ class getid3_tta extends getid3_handler
                                break;
 
                        default:
-                               $this->error('This version of getID3() ['.$this->getid3->version().'] only knows how to handle TTA v1 and v2 - it may not work correctly with this file which appears to be TTA v'.$ttaheader{3});
+                               $this->error('This version of getID3() ['.$this->getid3->version().'] only knows how to handle TTA v1 and v2 - it may not work correctly with this file which appears to be TTA v'.$ttaheader[3]);
                                return false;
-                               break;
                }
 
                $info['audio']['encoder']         = 'TTA v'.$info['tta']['major_version'];
index 4483158..f765719 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_voc extends getid3_handler
 {
@@ -61,7 +64,7 @@ class getid3_voc extends getid3_handler
 
                        $BlockOffset    = $this->ftell();
                        $BlockData      = $this->fread(4);
-                       $BlockType      = ord($BlockData{0});
+                       $BlockType      = ord($BlockData[0]);
                        $BlockSize      = getid3_lib::LittleEndian2Int(substr($BlockData, 1, 3));
                        $ThisBlock      = array();
 
index 9ab821e..55c7881 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_vqf extends getid3_handler
 {
index a6e57fd..acb0d3e 100644 (file)
@@ -14,7 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
-
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 class getid3_wavpack extends getid3_handler
 {
        /**
@@ -102,8 +104,8 @@ class getid3_wavpack extends getid3_handler
                                        return false;
                                }
 
-                               $info['wavpack']['blockheader']['minor_version'] = ord($wavpackheader{8});
-                               $info['wavpack']['blockheader']['major_version'] = ord($wavpackheader{9});
+                               $info['wavpack']['blockheader']['minor_version'] = ord($wavpackheader[8]);
+                               $info['wavpack']['blockheader']['major_version'] = ord($wavpackheader[9]);
 
                                if (($info['wavpack']['blockheader']['major_version'] != 4) ||
                                        (($info['wavpack']['blockheader']['minor_version'] < 4) &&
@@ -122,8 +124,8 @@ class getid3_wavpack extends getid3_handler
                                                return false;
                                }
 
-                               $info['wavpack']['blockheader']['track_number']  = ord($wavpackheader{10}); // unused
-                               $info['wavpack']['blockheader']['index_number']  = ord($wavpackheader{11}); // unused
+                               $info['wavpack']['blockheader']['track_number']  = ord($wavpackheader[10]); // unused
+                               $info['wavpack']['blockheader']['index_number']  = ord($wavpackheader[11]); // unused
                                $info['wavpack']['blockheader']['total_samples'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 12,  4));
                                $info['wavpack']['blockheader']['block_index']   = getid3_lib::LittleEndian2Int(substr($wavpackheader, 16,  4));
                                $info['wavpack']['blockheader']['block_samples'] = getid3_lib::LittleEndian2Int(substr($wavpackheader, 20,  4));
@@ -153,7 +155,7 @@ class getid3_wavpack extends getid3_handler
                                if (feof($this->getid3->fp)) {
                                        break;
                                }
-                               $metablock['id'] = ord($metablockheader{0});
+                               $metablock['id'] = ord($metablockheader[0]);
                                $metablock['function_id'] = ($metablock['id'] & 0x3F);
                                $metablock['function_name'] = $this->WavPackMetablockNameLookup($metablock['function_id']);
 
@@ -173,6 +175,7 @@ class getid3_wavpack extends getid3_handler
                                }
                                $metablock['size'] = getid3_lib::LittleEndian2Int(substr($metablockheader, 1)) * 2; // size is stored in words
                                $metablock['data'] = null;
+                               $metablock['comments'] = array();
 
                                if ($metablock['size'] > 0) {
 
@@ -221,7 +224,7 @@ class getid3_wavpack extends getid3_handler
                                                        $original_wav_filesize = getid3_lib::LittleEndian2Int(substr($metablock['data'], 4, 4));
 
                                                        $getid3_temp = new getID3();
-                                                       $getid3_temp->openfile($this->getid3->filename);
+                                                       $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
                                                        $getid3_riff = new getid3_riff($getid3_temp);
                                                        $getid3_riff->ParseRIFFdata($metablock['data']);
                                                        $metablock['riff']            = $getid3_temp->info['riff'];
@@ -243,7 +246,7 @@ class getid3_wavpack extends getid3_handler
 
                                                        $startoffset = $metablock['offset'] + ($metablock['large_block'] ? 4 : 2);
                                                        $getid3_temp = new getID3();
-                                                       $getid3_temp->openfile($this->getid3->filename);
+                                                       $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
                                                        $getid3_temp->info['avdataend']  = $info['avdataend'];
                                                        //$getid3_temp->info['fileformat'] = 'riff';
                                                        $getid3_riff = new getid3_riff($getid3_temp);
index dc7b30d..276688d 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_bmp extends getid3_handler
 {
@@ -334,7 +337,7 @@ class getid3_bmp extends getid3_handler
                                                case 1:
                                                        for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
                                                                for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) {
-                                                                       $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++});
+                                                                       $paletteindexbyte = ord($BMPpixelData[$pixeldataoffset++]);
                                                                        for ($i = 7; $i >= 0; $i--) {
                                                                                $paletteindex = ($paletteindexbyte & (0x01 << $i)) >> $i;
                                                                                $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex];
@@ -351,7 +354,7 @@ class getid3_bmp extends getid3_handler
                                                case 4:
                                                        for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
                                                                for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) {
-                                                                       $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++});
+                                                                       $paletteindexbyte = ord($BMPpixelData[$pixeldataoffset++]);
                                                                        for ($i = 1; $i >= 0; $i--) {
                                                                                $paletteindex = ($paletteindexbyte & (0x0F << (4 * $i))) >> (4 * $i);
                                                                                $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex];
@@ -368,7 +371,7 @@ class getid3_bmp extends getid3_handler
                                                case 8:
                                                        for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
                                                                for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) {
-                                                                       $paletteindex = ord($BMPpixelData{$pixeldataoffset++});
+                                                                       $paletteindex = ord($BMPpixelData[$pixeldataoffset++]);
                                                                        $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex];
                                                                }
                                                                while (($pixeldataoffset % 4) != 0) {
@@ -381,7 +384,7 @@ class getid3_bmp extends getid3_handler
                                                case 24:
                                                        for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
                                                                for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) {
-                                                                       $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset});
+                                                                       $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData[$pixeldataoffset+2]) << 16) | (ord($BMPpixelData[$pixeldataoffset+1]) << 8) | ord($BMPpixelData[$pixeldataoffset]);
                                                                        $pixeldataoffset += 3;
                                                                }
                                                                while (($pixeldataoffset % 4) != 0) {
@@ -394,7 +397,7 @@ class getid3_bmp extends getid3_handler
                                                case 32:
                                                        for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) {
                                                                for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) {
-                                                                       $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+3}) << 24) | (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset});
+                                                                       $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData[$pixeldataoffset+3]) << 24) | (ord($BMPpixelData[$pixeldataoffset+2]) << 16) | (ord($BMPpixelData[$pixeldataoffset+1]) << 8) | ord($BMPpixelData[$pixeldataoffset]);
                                                                        $pixeldataoffset += 4;
                                                                }
                                                                while (($pixeldataoffset % 4) != 0) {
index 426ef3e..82ea354 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_efax extends getid3_handler
 {
@@ -46,8 +49,6 @@ class getid3_efax extends getid3_handler
 
                $this->error('eFax parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
                return false;
-
-               return true;
        }
 
 }
index 4fb1247..0e463c8 100644 (file)
  * @link https://www.w3.org/Graphics/GIF/spec-gif89a.txt
  * @link http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
  */
+
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
+
 class getid3_gif extends getid3_handler
 {
        /**
@@ -46,6 +51,10 @@ class getid3_gif extends getid3_handler
                        return false;
                }
 
+               //if (!$this->getid3->option_extra_info) {
+               //      $this->warning('GIF Extensions and Global Color Table not returned due to !getid3->option_extra_info');
+               //}
+
                $info['gif']['header']['raw']['version']               =                              substr($GIFheader, $offset, 3);
                $offset += 3;
                $info['gif']['header']['raw']['width']                 = getid3_lib::LittleEndian2Int(substr($GIFheader, $offset, 2));
@@ -85,12 +94,15 @@ class getid3_gif extends getid3_handler
 
                if ($info['gif']['header']['flags']['global_color_table']) {
                        $GIFcolorTable = $this->fread(3 * $info['gif']['header']['global_color_size']);
-                       $offset = 0;
-                       for ($i = 0; $i < $info['gif']['header']['global_color_size']; $i++) {
-                               $red   = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
-                               $green = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
-                               $blue  = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
-                               $info['gif']['global_color_table'][$i] = (($red << 16) | ($green << 8) | ($blue));
+                       if ($this->getid3->option_extra_info) {
+                               $offset = 0;
+                               for ($i = 0; $i < $info['gif']['header']['global_color_size']; $i++) {
+                                       $red   = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
+                                       $green = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
+                                       $blue  = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
+                                       $info['gif']['global_color_table'][$i] = (($red << 16) | ($green << 8) | ($blue));
+                                       $info['gif']['global_color_table_rgb'][$i] = sprintf('%02X%02X%02X', $red, $green, $blue);
+                               }
                        }
                }
 
@@ -166,7 +178,9 @@ class getid3_gif extends getid3_handler
                                                }
                                        }
 
-                                       $info['gif']['extension_blocks'][] = $ExtensionBlock;
+                                       if ($this->getid3->option_extra_info) {
+                                               $info['gif']['extension_blocks'][] = $ExtensionBlock;
+                                       }
                                        break;
 
                                case ';':
index 3c874f3..5079119 100644 (file)
@@ -15,7 +15,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
-
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 class getid3_jpg extends getid3_handler
 {
        /**
index 8824479..85fb4c9 100644 (file)
@@ -14,7 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
-
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 class getid3_pcd extends getid3_handler
 {
        public $ExtractData = 0;
@@ -48,6 +50,7 @@ class getid3_pcd extends getid3_handler
                if ($this->ExtractData > 3) {
 
                        $this->error('Cannot extract PSD image data for detail levels above BASE (level-3) because encrypted with Kodak-proprietary compression/encryption.');
+                       return false;
 
                } elseif ($this->ExtractData > 0) {
 
@@ -76,11 +79,11 @@ class getid3_pcd extends getid3_handler
 
                                for ($x = 0; $x < $PCD_width; $x++) {
                                        if ($PCDisVertical) {
-                                               $info['pcd']['data'][$PCD_width - $x][$y]     = $this->YCbCr2RGB(ord($PCD_data_Y1{$x}), ord($PCD_data_Cb{(int) floor($x / 2)}), ord($PCD_data_Cr{(int) floor($x / 2)}));
-                                               $info['pcd']['data'][$PCD_width - $x][$y + 1] = $this->YCbCr2RGB(ord($PCD_data_Y2{$x}), ord($PCD_data_Cb{(int) floor($x / 2)}), ord($PCD_data_Cr{(int) floor($x / 2)}));
+                                               $info['pcd']['data'][$PCD_width - $x][$y]     = $this->YCbCr2RGB(ord($PCD_data_Y1[$x]), ord($PCD_data_Cb[(int) floor($x / 2)]), ord($PCD_data_Cr[(int) floor($x / 2)]));
+                                               $info['pcd']['data'][$PCD_width - $x][$y + 1] = $this->YCbCr2RGB(ord($PCD_data_Y2[$x]), ord($PCD_data_Cb[(int) floor($x / 2)]), ord($PCD_data_Cr[(int) floor($x / 2)]));
                                        } else {
-                                               $info['pcd']['data'][$y][$x]                  = $this->YCbCr2RGB(ord($PCD_data_Y1{$x}), ord($PCD_data_Cb{(int) floor($x / 2)}), ord($PCD_data_Cr{(int) floor($x / 2)}));
-                                               $info['pcd']['data'][$y + 1][$x]              = $this->YCbCr2RGB(ord($PCD_data_Y2{$x}), ord($PCD_data_Cb{(int) floor($x / 2)}), ord($PCD_data_Cr{(int) floor($x / 2)}));
+                                               $info['pcd']['data'][$y][$x]                  = $this->YCbCr2RGB(ord($PCD_data_Y1[$x]), ord($PCD_data_Cb[(int) floor($x / 2)]), ord($PCD_data_Cr[(int) floor($x / 2)]));
+                                               $info['pcd']['data'][$y + 1][$x]              = $this->YCbCr2RGB(ord($PCD_data_Y2[$x]), ord($PCD_data_Cb[(int) floor($x / 2)]), ord($PCD_data_Cr[(int) floor($x / 2)]));
                                        }
                                }
                        }
@@ -100,6 +103,7 @@ class getid3_pcd extends getid3_handler
 
                }
 
+               return false;
        }
 
        /**
index a9827f2..018062c 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_png extends getid3_handler
 {
@@ -593,23 +596,18 @@ class getid3_png extends getid3_handler
                switch ($color_type) {
                        case 0: // Each pixel is a grayscale sample.
                                return $bit_depth;
-                               break;
 
                        case 2: // Each pixel is an R,G,B triple
                                return 3 * $bit_depth;
-                               break;
 
                        case 3: // Each pixel is a palette index; a PLTE chunk must appear.
                                return $bit_depth;
-                               break;
 
                        case 4: // Each pixel is a grayscale sample, followed by an alpha sample.
                                return 2 * $bit_depth;
-                               break;
 
                        case 6: // Each pixel is an R,G,B triple, followed by an alpha sample.
                                return 4 * $bit_depth;
-                               break;
                }
                return false;
        }
index 73b9d84..8bb577b 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_svg extends getid3_handler
 {
index 57d500f..5d40494 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_tiff extends getid3_handler
 {
@@ -36,14 +39,13 @@ class getid3_tiff extends getid3_handler
                        default:
                                $this->error('Invalid TIFF byte order identifier ('.substr($TIFFheader, 0, 2).') at offset '.$info['avdataoffset']);
                                return false;
-                               break;
                }
 
                $info['fileformat']          = 'tiff';
                $info['video']['dataformat'] = 'tiff';
                $info['video']['lossless']   = true;
                $info['tiff']['ifd']         = array();
-               $CurrentIFD                          = array();
+               $CurrentIFD                  = array();
 
                $FieldTypeByteLength = array(1=>1, 2=>1, 3=>2, 4=>4, 5=>8);
 
@@ -57,47 +59,61 @@ class getid3_tiff extends getid3_handler
                        $CurrentIFD['fieldcount'] = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']);
 
                        for ($i = 0; $i < $CurrentIFD['fieldcount']; $i++) {
-                               $CurrentIFD['fields'][$i]['raw']['tag']    = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']);
-                               $CurrentIFD['fields'][$i]['raw']['type']   = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']);
-                               $CurrentIFD['fields'][$i]['raw']['length'] = $this->TIFFendian2Int($this->fread(4), $info['tiff']['byte_order']);
-                               $CurrentIFD['fields'][$i]['raw']['offset'] =                       $this->fread(4);
-
+                               $CurrentIFD['fields'][$i]['raw']['tag']      = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']);
+                               $CurrentIFD['fields'][$i]['raw']['type']     = $this->TIFFendian2Int($this->fread(2), $info['tiff']['byte_order']);
+                               $CurrentIFD['fields'][$i]['raw']['length']   = $this->TIFFendian2Int($this->fread(4), $info['tiff']['byte_order']);
+                               $CurrentIFD['fields'][$i]['raw']['valoff']   =                       $this->fread(4); // To save time and space the Value Offset contains the Value instead of pointing to the Value if and only if the Value fits into 4 bytes. If the Value is shorter than 4 bytes, it is left-justified within the 4-byte Value Offset, i.e., stored in the lowernumbered bytes. Whether the Value fits within 4 bytes is determined by the Type and Count of the field.
                                $CurrentIFD['fields'][$i]['raw']['tag_name'] = $this->TIFFcommentName($CurrentIFD['fields'][$i]['raw']['tag']);
 
                                switch ($CurrentIFD['fields'][$i]['raw']['type']) {
                                        case 1: // BYTE  An 8-bit unsigned integer.
                                                if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) {
-                                                       $CurrentIFD['fields'][$i]['value']  = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['offset'], 0, 1), $info['tiff']['byte_order']);
+                                                       $CurrentIFD['fields'][$i]['value']  = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['valoff'], 0, 1), $info['tiff']['byte_order']);
                                                } else {
-                                                       $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $info['tiff']['byte_order']);
+                                                       $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
                                                }
                                                break;
 
                                        case 2: // ASCII 8-bit bytes  that store ASCII codes; the last byte must be null.
                                                if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) {
-                                                       $CurrentIFD['fields'][$i]['value']  = substr($CurrentIFD['fields'][$i]['raw']['offset'], 3);
+                                                       $CurrentIFD['fields'][$i]['value']  = substr($CurrentIFD['fields'][$i]['raw']['valoff'], 3);
                                                } else {
-                                                       $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $info['tiff']['byte_order']);
+                                                       $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
                                                }
                                                break;
 
                                        case 3: // SHORT A 16-bit (2-byte) unsigned integer.
                                                if ($CurrentIFD['fields'][$i]['raw']['length'] <= 2) {
-                                                       $CurrentIFD['fields'][$i]['value']  = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['offset'], 0, 2), $info['tiff']['byte_order']);
+                                                       $CurrentIFD['fields'][$i]['value']  = $this->TIFFendian2Int(substr($CurrentIFD['fields'][$i]['raw']['valoff'], 0, 2), $info['tiff']['byte_order']);
                                                } else {
-                                                       $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $info['tiff']['byte_order']);
+                                                       $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
                                                }
                                                break;
 
                                        case 4: // LONG  A 32-bit (4-byte) unsigned integer.
-                                               if ($CurrentIFD['fields'][$i]['raw']['length'] <= 1) {
-                                                       $CurrentIFD['fields'][$i]['value']  = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $info['tiff']['byte_order']);
+                                               if ($CurrentIFD['fields'][$i]['raw']['length'] <= 4) {
+                                                       $CurrentIFD['fields'][$i]['value']  = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
                                                } else {
-                                                       $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['offset'], $info['tiff']['byte_order']);
+                                                       $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
                                                }
                                                break;
 
                                        case 5: // RATIONAL   Two LONG_s:  the first represents the numerator of a fraction, the second the denominator.
+                                       case 7: // UNDEFINED An 8-bit byte that may contain anything, depending on the definition of the field.
+                                               $CurrentIFD['fields'][$i]['offset'] = $this->TIFFendian2Int($CurrentIFD['fields'][$i]['raw']['valoff'], $info['tiff']['byte_order']);
+                                               break;
+
+                                       // Warning: It is possible that other TIFF field types will be added in the future. Readers should skip over fields containing an unexpected field type.
+                                       // In TIFF 6.0, some new field types have been defined:
+                                       // These new field types are also governed by the byte order (II or MM) in the TIFF header.
+                                       case 6: // SBYTE An 8-bit signed (twos-complement) integer.
+                                       case 8: // SSHORT A 16-bit (2-byte) signed (twos-complement) integer.
+                                       case 9: // SLONG A 32-bit (4-byte) signed (twos-complement) integer.
+                                       case 10: // SRATIONAL Two SLONGs: the first represents the numerator of a fraction, the second the denominator.
+                                       case 11: // FLOAT Single precision (4-byte) IEEE format
+                                       case 12: // DOUBLE Double precision (8-byte) IEEE format
+                                       default:
+                                               $this->warning('unhandled IFD field type '.$CurrentIFD['fields'][$i]['raw']['type'].' for IFD entry '.$i);
                                                break;
                                }
                        }
@@ -137,6 +153,16 @@ class getid3_tiff extends getid3_handler
 
                                                }
                                                break;
+                                       case 700:
+                                               $XMPmagic = '<?xpacket';
+                                               $this->fseek($fieldarray['offset']);
+                                               $xmpkey = (isset($info['tiff']['XMP']) ? count($info['tiff']['XMP']) : 0);
+                                               $info['tiff']['XMP'][$xmpkey]['raw'] = $this->fread($fieldarray['raw']['length']);
+                                               if (substr($info['tiff']['XMP'][$xmpkey]['raw'], 0, strlen($XMPmagic)) != $XMPmagic) {
+                                                       $this->warning('did not find expected XMP data at offset '.$fieldarray['offset']);
+                                                       unset($info['tiff']['XMP'][$xmpkey]['raw']);
+                                               }
+                                               break;
                                }
                                switch ($fieldarray['raw']['tag']) {
                                        case 256: // ImageWidth
@@ -207,14 +233,33 @@ class getid3_tiff extends getid3_handler
         * @return string
         */
        public function TIFFcompressionMethod($id) {
+               // https://en.wikipedia.org/wiki/TIFF#TIFF_Compression_Tag
                static $TIFFcompressionMethod = array();
                if (empty($TIFFcompressionMethod)) {
                        $TIFFcompressionMethod = array(
-                               1     => 'Uncompressed',
-                               2     => 'Huffman',
-                               3     => 'Fax - CCITT 3',
-                               5     => 'LZW',
-                               32773 => 'PackBits',
+                               0x0001 => 'Uncompressed',
+                               0x0002 => 'Huffman',
+                               0x0003 => 'CCITT T.4',
+                               0x0004 => 'CCITT T.6',
+                               0x0005 => 'LZW',
+                               0x0006 => 'JPEG-old',
+                               0x0007 => 'JPEG',
+                               0x0008 => 'deflate',
+                               0x0009 => 'JBIG ITU-T T.85',
+                               0x000A => 'JBIG ITU-T T.43',
+                               0x7FFE => 'NeXT RLE 2-bit',
+                               0x8005 => 'PackBits',
+                               0x8029 => 'ThunderScan RLE 4-bit',
+                               0x807F => 'RasterPadding',
+                               0x8080 => 'RLE-LW',
+                               0x8081 => 'RLE-CT',
+                               0x8082 => 'RLE-BL',
+                               0x80B2 => 'deflate-PK',
+                               0x80B3 => 'Kodak-DCS',
+                               0x8765 => 'JBIG',
+                               0x8798 => 'JPEG2000',
+                               0x8799 => 'Nikon NEF',
+                               0x879B => 'JBIG2',
                        );
                }
                return (isset($TIFFcompressionMethod[$id]) ? $TIFFcompressionMethod[$id] : 'unknown/invalid ('.$id.')');
index 4602cde..a66e2eb 100644 (file)
  * A CueSheet class used to open and parse cuesheets.
  *
  */
+
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
+
 class getid3_cue extends getid3_handler
 {
        public $cuesheet = array();
index 57bea05..9064fed 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_exe extends getid3_handler
 {
index 231a32a..efca73a 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_iso extends getid3_handler
 {
@@ -29,7 +32,7 @@ class getid3_iso extends getid3_handler
                        $this->fseek(2048 * $i);
                        $ISOheader = $this->fread(2048);
                        if (substr($ISOheader, 1, 5) == 'CD001') {
-                               switch (ord($ISOheader{0})) {
+                               switch (ord($ISOheader[0])) {
                                        case 1:
                                                $info['iso']['primary_volume_descriptor']['offset'] = 2048 * $i;
                                                $this->ParsePrimaryVolumeDescriptor($ISOheader);
@@ -296,9 +299,9 @@ class getid3_iso extends getid3_handler
                $DirectoryRecordData = $this->fread(1);
                $DirectoryRecord = array();
 
-               while (ord($DirectoryRecordData{0}) > 33) {
+               while (ord($DirectoryRecordData[0]) > 33) {
 
-                       $DirectoryRecordData .= $this->fread(ord($DirectoryRecordData{0}) - 1);
+                       $DirectoryRecordData .= $this->fread(ord($DirectoryRecordData[0]) - 1);
 
                        $ThisDirectoryRecord = array();
 
@@ -389,13 +392,13 @@ class getid3_iso extends getid3_handler
                // 6: second of the minute from 0 to 59
                // 7: Offset from Greenwich Mean Time in number of 15 minute intervals from -48 (West) to +52 (East)
 
-               $UNIXyear   = ord($ISOtime{0}) + 1900;
-               $UNIXmonth  = ord($ISOtime{1});
-               $UNIXday    = ord($ISOtime{2});
-               $UNIXhour   = ord($ISOtime{3});
-               $UNIXminute = ord($ISOtime{4});
-               $UNIXsecond = ord($ISOtime{5});
-               $GMToffset  = $this->TwosCompliment2Decimal(ord($ISOtime{5}));
+               $UNIXyear   = ord($ISOtime[0]) + 1900;
+               $UNIXmonth  = ord($ISOtime[1]);
+               $UNIXday    = ord($ISOtime[2]);
+               $UNIXhour   = ord($ISOtime[3]);
+               $UNIXminute = ord($ISOtime[4]);
+               $UNIXsecond = ord($ISOtime[5]);
+               $GMToffset  = $this->TwosCompliment2Decimal(ord($ISOtime[5]));
 
                return gmmktime($UNIXhour, $UNIXminute, $UNIXsecond, $UNIXmonth, $UNIXday, $UNIXyear);
        }
index 9a60aa0..56d07f0 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_msoffice extends getid3_handler
 {
index f5da193..b6c493b 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_par2 extends getid3_handler
 {
index c6896a6..1aca6ae 100644 (file)
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_pdf extends getid3_handler
 {
+       public $returnXREF = false; // return full details of PDF Cross-Reference Table (XREF)
+
        /**
         * @return bool
         */
        public function Analyze() {
                $info = &$this->getid3->info;
 
-               $info['fileformat'] = 'pdf';
+               $this->fseek(0);
+               if (preg_match('#^%PDF-([0-9\\.]+)$#', rtrim($this->fgets()), $matches)) {
+                       $info['pdf']['header']['version'] = floatval($matches[1]);
+                       $info['fileformat'] = 'pdf';
+
+                       // the PDF Cross-Reference Table (XREF) is located near the end of the file
+                       // the starting offset is specified in the penultimate section, on the two lines just before "%%EOF"
+                       // the first line is "startxref", the second line is the byte offset of the XREF.
+                       // We know the length of "%%EOF" and "startxref", but the offset could be 2-10 bytes,
+                       // and we're not sure if the line ends are one or two bytes, so we might find "startxref" as little as 18(?) bytes
+                       // from EOF, but it could 30 bytes, so we start 40 bytes back just to be safe and do a search for the data we want.
+                       $this->fseek(-40, SEEK_END);
+                       if (preg_match('#[\r\n]startxref[ \r\n]+([0-9]+)[ \r\n]+#', $this->fread(40), $matches)) {
+                               $info['pdf']['trailer']['startxref'] = intval($matches[1]);
+                               $this->parseXREF($info['pdf']['trailer']['startxref']);
+                               if (!empty($info['pdf']['xref']['offset'])) {
+                                       while (!$this->feof() && (max(array_keys($info['pdf']['xref']['offset'])) > $info['pdf']['xref']['count'])) {
+                                               // suspect that there may be another XREF entry somewhere in the file, brute-force scan for it
+                                               /*
+                                               // starting at last known entry of main XREF table
+                                               $this->fseek(max($info['pdf']['xref']['offset']));
+                                               */
+                                               // starting at the beginning of the file
+                                               $this->fseek(0);
+                                               while (!$this->feof()) {
+                                                       $XREFoffset = $this->ftell();
+                                                       if (rtrim($this->fgets()) == 'xref') {
+                                                               if (empty($info['pdf']['xref']['xref_offsets']) || !in_array($XREFoffset, $info['pdf']['xref']['xref_offsets'])) {
+                                                                       $this->parseXREF($XREFoffset);
+                                                                       break;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                                       foreach ($info['pdf']['xref']['offset'] as $objectNumber => $offset) {
+                                               if ($info['pdf']['xref']['entry'][$objectNumber] == 'f') {
+                                                       // "free" object means "deleted", ignore
+                                                       continue;
+                                               }
+                                               $this->fseek($offset);
+                                               $line = rtrim($this->fgets());
+                                               if (preg_match('#^'.$objectNumber.' ([0-9]+) obj#', $line, $matches)) {
+                                                       if (strlen($line) > strlen($matches[0])) {
+                                                               // object header line not actually on its own line, rewind file pointer to start reading data
+                                                               $this->fseek($offset + strlen($matches[0]));
+                                                       }
+                                                       $objectData  = '';
+                                                       while (true) {
+                                                               $line = $this->fgets();
+                                                               if (rtrim($line) == 'endobj') {
+                                                                       break;
+                                                               }
+                                                               $objectData .= $line;
+                                                       }
+                                                       if (preg_match('#^<<[\r\n\s]*(/Type|/Pages|/Parent [0-9]+ [0-9]+ [A-Z]|/Count [0-9]+|/Kids *\\[[0-9A-Z ]+\\]|[\r\n\s])+[\r\n\s]*>>#', $objectData, $matches)) {
+                                                               if (preg_match('#/Count ([0-9]+)#', $objectData, $matches)) {
+                                                                       $info['pdf']['pages'] = (int) $matches[1];
+                                                                       break; // for now this is the only data we're looking for in the PDF not need to loop through every object in the file (and a large PDF may contain MANY objects). And it MAY be possible that there are other objects elsewhere in the file that define additional (or removed?) pages
+                                                               }
+                                                       }
+                                               } else {
+                                                       $this->error('Unexpected structure "'.$line.'" at offset '.$offset);
+                                                       break;
+                                               }
+                                       }
+                                       if (!$this->returnXREF) {
+                                               unset($info['pdf']['xref']['offset'], $info['pdf']['xref']['generation'], $info['pdf']['xref']['entry']);
+                                       }
+
+                               } else {
+                                       $this->error('Did not find "xref" at offset '.$info['pdf']['trailer']['startxref']);
+                               }
+                       } else {
+                               $this->error('Did not find "startxref" in the last 40 bytes of the PDF');
+                       }
 
-               $this->error('PDF parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
+                       $this->warning('PDF parsing incomplete in this version of getID3() ['.$this->getid3->version().']');
+                       return true;
+               }
+               $this->error('Did not find "%PDF" at the beginning of the PDF');
                return false;
 
        }
 
+       /**
+        * @return bool
+        */
+       private function parseXREF($XREFoffset) {
+               $info = &$this->getid3->info;
+
+               $this->fseek($XREFoffset);
+               if (rtrim($this->fgets()) == 'xref') {
+
+                       $info['pdf']['xref']['xref_offsets'][$XREFoffset] = $XREFoffset;
+                       list($firstObjectNumber, $XREFcount) = explode(' ', rtrim($this->fgets()));
+                       $XREFcount = (int) $XREFcount;
+                       $info['pdf']['xref']['count'] = $XREFcount + (!empty($info['pdf']['xref']['count']) ? $info['pdf']['xref']['count'] : 0);
+                       for ($i = 0; $i < $XREFcount; $i++) {
+                               $line = rtrim($this->fgets());
+                               if (preg_match('#^([0-9]+) ([0-9]+) ([nf])$#', $line, $matches)) {
+                                       $info['pdf']['xref']['offset'][($firstObjectNumber + $i)]     = (int) $matches[1];
+                                       $info['pdf']['xref']['generation'][($firstObjectNumber + $i)] = (int) $matches[2];
+                                       $info['pdf']['xref']['entry'][($firstObjectNumber + $i)]      =       $matches[3];
+                               } else {
+                                       $this->error('failed to parse XREF entry #'.$i.' in XREF table at offset '.$XREFoffset);
+                                       return false;
+                               }
+                       }
+                       sort($info['pdf']['xref']['xref_offsets']);
+                       return true;
+
+               }
+               $this->warning('failed to find expected XREF structure at offset '.$XREFoffset);
+               return false;
+       }
+
 }
index 37971a6..26be982 100644 (file)
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
+
 class getid3_apetag extends getid3_handler
 {
        /**
@@ -162,8 +166,8 @@ class getid3_apetag extends getid3_handler
                        switch (strtolower($item_key)) {
                                // http://wiki.hydrogenaud.io/index.php?title=ReplayGain#MP3Gain
                                case 'replaygain_track_gain':
-                                       if (preg_match('#^[\\-\\+][0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
-                                               $thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
+                                       if (preg_match('#^([\\-\\+][0-9\\.,]{8})( dB)?$#', $thisfile_ape_items_current['data'][0], $matches)) {
+                                               $thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
                                                $thisfile_replaygain['track']['originator'] = 'unspecified';
                                        } else {
                                                $this->warning('MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
@@ -171,8 +175,8 @@ class getid3_apetag extends getid3_handler
                                        break;
 
                                case 'replaygain_track_peak':
-                                       if (preg_match('#^[0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
-                                               $thisfile_replaygain['track']['peak']       = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
+                                       if (preg_match('#^([0-9\\.,]{8})$#', $thisfile_ape_items_current['data'][0], $matches)) {
+                                               $thisfile_replaygain['track']['peak']       = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
                                                $thisfile_replaygain['track']['originator'] = 'unspecified';
                                                if ($thisfile_replaygain['track']['peak'] <= 0) {
                                                        $this->warning('ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
@@ -183,8 +187,8 @@ class getid3_apetag extends getid3_handler
                                        break;
 
                                case 'replaygain_album_gain':
-                                       if (preg_match('#^[\\-\\+][0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
-                                               $thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
+                                       if (preg_match('#^([\\-\\+][0-9\\.,]{8})( dB)?$#', $thisfile_ape_items_current['data'][0], $matches)) {
+                                               $thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
                                                $thisfile_replaygain['album']['originator'] = 'unspecified';
                                        } else {
                                                $this->warning('MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
@@ -192,8 +196,8 @@ class getid3_apetag extends getid3_handler
                                        break;
 
                                case 'replaygain_album_peak':
-                                       if (preg_match('#^[0-9\\.,]{8}$#', $thisfile_ape_items_current['data'][0])) {
-                                               $thisfile_replaygain['album']['peak']       = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
+                                       if (preg_match('#^([0-9\\.,]{8})$#', $thisfile_ape_items_current['data'][0], $matches)) {
+                                               $thisfile_replaygain['album']['peak']       = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
                                                $thisfile_replaygain['album']['originator'] = 'unspecified';
                                                if ($thisfile_replaygain['album']['peak'] <= 0) {
                                                        $this->warning('ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
@@ -237,7 +241,7 @@ class getid3_apetag extends getid3_handler
                                case 'tracknumber':
                                        if (is_array($thisfile_ape_items_current['data'])) {
                                                foreach ($thisfile_ape_items_current['data'] as $comment) {
-                                                       $thisfile_ape['comments']['track'][] = $comment;
+                                                       $thisfile_ape['comments']['track_number'][] = $comment;
                                                }
                                        }
                                        break;
index cafc3fb..16dcf25 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 
 class getid3_id3v1 extends getid3_handler
 {
@@ -45,9 +48,9 @@ class getid3_id3v1 extends getid3_handler
 
                        // If second-last byte of comment field is null and last byte of comment field is non-null
                        // then this is ID3v1.1 and the comment field is 28 bytes long and the 30th byte is the track number
-                       if (($id3v1tag{125} === "\x00") && ($id3v1tag{126} !== "\x00")) {
-                               $ParsedID3v1['track']   = ord(substr($ParsedID3v1['comment'], 29,  1));
-                               $ParsedID3v1['comment'] =     substr($ParsedID3v1['comment'],  0, 28);
+                       if (($id3v1tag[125] === "\x00") && ($id3v1tag[126] !== "\x00")) {
+                               $ParsedID3v1['track_number'] = ord(substr($ParsedID3v1['comment'], 29,  1));
+                               $ParsedID3v1['comment']      =     substr($ParsedID3v1['comment'],  0, 28);
                        }
                        $ParsedID3v1['comment'] = $this->cutfield($ParsedID3v1['comment']);
 
@@ -62,26 +65,30 @@ class getid3_id3v1 extends getid3_handler
                        foreach ($ParsedID3v1 as $key => $value) {
                                $ParsedID3v1['comments'][$key][0] = $value;
                        }
-                       // ID3v1 encoding detection hack START
-                       // ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets
-                       // Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess
-                       $ID3v1encoding = 'ISO-8859-1';
-                       foreach ($ParsedID3v1['comments'] as $tag_key => $valuearray) {
-                               foreach ($valuearray as $key => $value) {
-                                       if (preg_match('#^[\\x00-\\x40\\xA8\\B8\\x80-\\xFF]+$#', $value)) {
-                                               foreach (array('Windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
-                                                       if (function_exists('mb_convert_encoding') && @mb_convert_encoding($value, $id3v1_bad_encoding, $id3v1_bad_encoding) === $value) {
-                                                               $ID3v1encoding = $id3v1_bad_encoding;
-                                                               break 3;
-                                                       } elseif (function_exists('iconv') && @iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
-                                                               $ID3v1encoding = $id3v1_bad_encoding;
-                                                               break 3;
+                       $ID3v1encoding = $this->getid3->encoding_id3v1;
+                       if ($this->getid3->encoding_id3v1_autodetect) {
+                               // ID3v1 encoding detection hack START
+                               // ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets
+                               // Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess
+                               foreach ($ParsedID3v1['comments'] as $tag_key => $valuearray) {
+                                       foreach ($valuearray as $key => $value) {
+                                               if (preg_match('#^[\\x00-\\x40\\x80-\\xFF]+$#', $value) && !ctype_digit((string) $value)) { // check for strings with only characters above chr(128) and punctuation/numbers, but not just numeric strings (e.g. track numbers or years)
+                                                       foreach (array('Windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
+                                                               if (function_exists('mb_convert_encoding') && @mb_convert_encoding($value, $id3v1_bad_encoding, $id3v1_bad_encoding) === $value) {
+                                                                       $ID3v1encoding = $id3v1_bad_encoding;
+                                                                       $this->warning('ID3v1 detected as '.$id3v1_bad_encoding.' text encoding in '.$tag_key);
+                                                                       break 3;
+                                                               } elseif (function_exists('iconv') && @iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
+                                                                       $ID3v1encoding = $id3v1_bad_encoding;
+                                                                       $this->warning('ID3v1 detected as '.$id3v1_bad_encoding.' text encoding in '.$tag_key);
+                                                                       break 3;
+                                                               }
                                                        }
                                                }
                                        }
                                }
+                               // ID3v1 encoding detection hack END
                        }
-                       // ID3v1 encoding detection hack END
 
                        // ID3v1 data is supposed to be padded with NULL characters, but some taggers pad with spaces
                        $GoodFormatID3v1tag = $this->GenerateID3v1Tag(
@@ -91,7 +98,7 @@ class getid3_id3v1 extends getid3_handler
                                                                                        $ParsedID3v1['year'],
                                                                                        (isset($ParsedID3v1['genre']) ? $this->LookupGenreID($ParsedID3v1['genre']) : false),
                                                                                        $ParsedID3v1['comment'],
-                                                                                       (!empty($ParsedID3v1['track']) ? $ParsedID3v1['track'] : ''));
+                                                                                       (!empty($ParsedID3v1['track_number']) ? $ParsedID3v1['track_number'] : ''));
                        $ParsedID3v1['padding_valid'] = true;
                        if ($id3v1tag !== $GoodFormatID3v1tag) {
                                $ParsedID3v1['padding_valid'] = false;
index c51dedb..85dd7a1 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v1.php', __FILE__, true);
 
 class getid3_id3v2 extends getid3_handler
@@ -59,8 +62,8 @@ class getid3_id3v2 extends getid3_handler
                $header = $this->fread(10);
                if (substr($header, 0, 3) == 'ID3'  &&  strlen($header) == 10) {
 
-                       $thisfile_id3v2['majorversion'] = ord($header{3});
-                       $thisfile_id3v2['minorversion'] = ord($header{4});
+                       $thisfile_id3v2['majorversion'] = ord($header[3]);
+                       $thisfile_id3v2['minorversion'] = ord($header[4]);
 
                        // shortcut
                        $id3v2_majorversion = &$thisfile_id3v2['majorversion'];
@@ -79,7 +82,7 @@ class getid3_id3v2 extends getid3_handler
 
                }
 
-               $id3_flags = ord($header{5});
+               $id3_flags = ord($header[5]);
                switch ($id3v2_majorversion) {
                        case 2:
                                // %ab000000 in v2.2
@@ -260,7 +263,7 @@ class getid3_id3v2 extends getid3_handler
                                        $thisfile_id3v2['padding']['length'] = strlen($framedata);
                                        $thisfile_id3v2['padding']['valid']  = true;
                                        for ($i = 0; $i < $thisfile_id3v2['padding']['length']; $i++) {
-                                               if ($framedata{$i} != "\x00") {
+                                               if ($framedata[$i] != "\x00") {
                                                        $thisfile_id3v2['padding']['valid'] = false;
                                                        $thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
                                                        $this->warning('Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)');
@@ -326,7 +329,7 @@ class getid3_id3v2 extends getid3_handler
 
                                        $len = strlen($framedata);
                                        for ($i = 0; $i < $len; $i++) {
-                                               if ($framedata{$i} != "\x00") {
+                                               if ($framedata[$i] != "\x00") {
                                                        $thisfile_id3v2['padding']['valid'] = false;
                                                        $thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;
                                                        $this->warning('Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)');
@@ -434,11 +437,11 @@ class getid3_id3v2 extends getid3_handler
                        $footer = $this->fread(10);
                        if (substr($footer, 0, 3) == '3DI') {
                                $thisfile_id3v2['footer'] = true;
-                               $thisfile_id3v2['majorversion_footer'] = ord($footer{3});
-                               $thisfile_id3v2['minorversion_footer'] = ord($footer{4});
+                               $thisfile_id3v2['majorversion_footer'] = ord($footer[3]);
+                               $thisfile_id3v2['minorversion_footer'] = ord($footer[4]);
                        }
                        if ($thisfile_id3v2['majorversion_footer'] <= 4) {
-                               $id3_flags = ord($footer{5});
+                               $id3_flags = ord($footer[5]);
                                $thisfile_id3v2_flags['unsynch_footer']  = (bool) ($id3_flags & 0x80);
                                $thisfile_id3v2_flags['extfoot_footer']  = (bool) ($id3_flags & 0x40);
                                $thisfile_id3v2_flags['experim_footer']  = (bool) ($id3_flags & 0x20);
@@ -459,10 +462,10 @@ class getid3_id3v2 extends getid3_handler
                        unset($key, $value, $genres, $genre);
                }
 
-               if (isset($thisfile_id3v2['comments']['track'])) {
-                       foreach ($thisfile_id3v2['comments']['track'] as $key => $value) {
+               if (isset($thisfile_id3v2['comments']['track_number'])) {
+                       foreach ($thisfile_id3v2['comments']['track_number'] as $key => $value) {
                                if (strstr($value, '/')) {
-                                       list($thisfile_id3v2['comments']['tracknum'][$key], $thisfile_id3v2['comments']['totaltracks'][$key]) = explode('/', $thisfile_id3v2['comments']['track'][$key]);
+                                       list($thisfile_id3v2['comments']['track_number'][$key], $thisfile_id3v2['comments']['totaltracks'][$key]) = explode('/', $thisfile_id3v2['comments']['track_number'][$key]);
                                }
                        }
                }
@@ -520,14 +523,21 @@ class getid3_id3v2 extends getid3_handler
                if (($this->getid3->info['id3v2']['majorversion'] == 3) && !preg_match('#[\x00]#', $genrestring)) {
                        // note: MusicBrainz Picard incorrectly stores plaintext genres separated by "/" when writing in ID3v2.3 mode, hack-fix here:
                        // replace / with NULL, then replace back the two ID3v1 genres that legitimately have "/" as part of the single genre name
-                       if (preg_match('#/#', $genrestring)) {
+                       if (strpos($genrestring, '/') !== false) {
+                               $LegitimateSlashedGenreList = array(  // https://github.com/JamesHeinrich/getID3/issues/223
+                                       'Pop/Funk',    // ID3v1 genre #62 - https://en.wikipedia.org/wiki/ID3#standard
+                                       'Cut-up/DJ',   // Discogs - https://www.discogs.com/style/cut-up/dj
+                                       'RnB/Swing',   // Discogs - https://www.discogs.com/style/rnb/swing
+                                       'Funk / Soul', // Discogs (note spaces) - https://www.discogs.com/genre/funk+%2F+soul
+                               );
                                $genrestring = str_replace('/', "\x00", $genrestring);
-                               $genrestring = str_replace('Pop'."\x00".'Funk', 'Pop/Funk', $genrestring);
-                               $genrestring = str_replace('Rock'."\x00".'Rock', 'Folk/Rock', $genrestring);
+                               foreach ($LegitimateSlashedGenreList as $SlashedGenre) {
+                                       $genrestring = str_ireplace(str_replace('/', "\x00", $SlashedGenre), $SlashedGenre, $genrestring);
+                               }
                        }
 
                        // some other taggers separate multiple genres with semicolon, e.g. "Heavy Metal;Thrash Metal;Metal"
-                       if (preg_match('#;#', $genrestring)) {
+                       if (strpos($genrestring, ';') !== false) {
                                $genrestring = str_replace(';', "\x00", $genrestring);
                        }
                }
@@ -672,16 +682,14 @@ class getid3_id3v2 extends getid3_handler
                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
                        }
-                       $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
+                       $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
                        $parsedFrame['encodingid']  = $frame_textencoding;
                        $parsedFrame['encoding']    = $this->TextEncodingNameLookup($frame_textencoding);
 
-                       $parsedFrame['description'] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $frame_description));
+                       $parsedFrame['description'] = trim(getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['description']));
                        $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
+                       $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator);
                        if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
                                $commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0));
                                if (!isset($info['id3v2']['comments'][$parsedFrame['framenameshort']]) || !array_key_exists($commentkey, $info['id3v2']['comments'][$parsedFrame['framenameshort']])) {
@@ -693,7 +701,7 @@ class getid3_id3v2 extends getid3_handler
                        //unset($parsedFrame['data']); do not unset, may be needed elsewhere, e.g. for replaygain
 
 
-               } elseif ($parsedFrame['frame_name']{0} == 'T') { // 4.2. T??[?] Text information frame
+               } elseif ($parsedFrame['frame_name'][0] == 'T') { // 4.2. T??[?] Text information frame
                        //   There may only be one text information frame of its kind in an tag.
                        // <Header for 'Text information frame', ID: 'T000' - 'TZZZ',
                        // excluding 'TXXX' described in 4.2.6.>
@@ -707,10 +715,10 @@ class getid3_id3v2 extends getid3_handler
                        }
 
                        $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
+                       $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding));
 
                        $parsedFrame['encodingid'] = $frame_textencoding;
                        $parsedFrame['encoding']   = $this->TextEncodingNameLookup($frame_textencoding);
-
                        if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
                                // ID3v2.3 specs say that TPE1 (and others) can contain multiple artist values separated with /
                                // This of course breaks when an artist name contains slash character, e.g. "AC/DC"
@@ -766,38 +774,20 @@ class getid3_id3v2 extends getid3_handler
                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
                        }
-                       $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
-                       $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
-
-                       $frame_terminatorpos = strpos($parsedFrame['data'], $frame_textencoding_terminator);
-                       if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
-                               $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
-                       }
-                       if ($frame_terminatorpos) {
-                               // there are null bytes after the data - this is not according to spec
-                               // only use data up to first null byte
-                               $frame_urldata = (string) substr($parsedFrame['data'], 0, $frame_terminatorpos);
-                       } else {
-                               // no null bytes following data, just use all data
-                               $frame_urldata = (string) $parsedFrame['data'];
-                       }
-
                        $parsedFrame['encodingid']  = $frame_textencoding;
                        $parsedFrame['encoding']    = $this->TextEncodingNameLookup($frame_textencoding);
+                       $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);           // according to the frame text encoding
+                       $parsedFrame['url']         = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator)); // always ISO-8859-1
+                       $parsedFrame['description'] = $this->RemoveStringTerminator($parsedFrame['description'], $frame_textencoding_terminator);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
 
-                       $parsedFrame['url']         = $frame_urldata;     // always ISO-8859-1
-                       $parsedFrame['description'] = $frame_description; // according to the frame text encoding
                        if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']);
                        }
                        unset($parsedFrame['data']);
 
 
-               } elseif ($parsedFrame['frame_name']{0} == 'W') { // 4.3. W??? URL link frames
+               } elseif ($parsedFrame['frame_name'][0] == 'W') { // 4.3. W??? URL link frames
                        //   There may only be one URL link frame of its kind in a tag,
                        //   except when stated otherwise in the frame description
                        // <Header for 'URL link frame', ID: 'W000' - 'WZZZ', excluding 'WXXX'
@@ -1010,19 +1000,16 @@ class getid3_id3v2 extends getid3_handler
                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
                        }
-                       $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
+                       $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
                        $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
+                       $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $frame_textencoding_terminator);
 
                        $parsedFrame['encodingid']   = $frame_textencoding;
                        $parsedFrame['encoding']     = $this->TextEncodingNameLookup($frame_textencoding);
 
                        $parsedFrame['language']     = $frame_language;
                        $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
-                       $parsedFrame['description']  = $frame_description;
                        if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
                        }
@@ -1077,7 +1064,7 @@ class getid3_id3v2 extends getid3_handler
                                        $parsedFrame['lyrics'][$timestampindex]['data'] = substr($frame_remainingdata, $frame_offset, $frame_terminatorpos - $frame_offset);
 
                                        $frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator));
-                                       if (($timestampindex == 0) && (ord($frame_remainingdata{0}) != 0)) {
+                                       if (($timestampindex == 0) && (ord($frame_remainingdata[0]) != 0)) {
                                                // timestamp probably omitted for first data item
                                        } else {
                                                $parsedFrame['lyrics'][$timestampindex]['timestamp'] = getid3_lib::BigEndian2Int(substr($frame_remainingdata, 0, 4));
@@ -1118,19 +1105,16 @@ class getid3_id3v2 extends getid3_handler
                                if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
                                        $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
                                }
-                               $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                               if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                                       // if description only contains a BOM or terminator then make it blank
-                                       $frame_description = '';
-                               }
+                               $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                               $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
                                $frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
+                               $frame_text = $this->RemoveStringTerminator($frame_text, $frame_textencoding_terminator);
 
                                $parsedFrame['encodingid']   = $frame_textencoding;
                                $parsedFrame['encoding']     = $this->TextEncodingNameLookup($frame_textencoding);
 
                                $parsedFrame['language']     = $frame_language;
                                $parsedFrame['languagename'] = $this->LanguageLookup($frame_language, false);
-                               $parsedFrame['description']  = $frame_description;
                                $parsedFrame['data']         = $frame_text;
                                if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
                                        $commentkey = ($parsedFrame['description'] ? $parsedFrame['description'] : (!empty($info['id3v2']['comments'][$parsedFrame['framenameshort']]) ? count($info['id3v2']['comments'][$parsedFrame['framenameshort']]) : 0));
@@ -1423,26 +1407,22 @@ class getid3_id3v2 extends getid3_handler
                                if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
                                        $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
                                }
-                               $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                               if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                                       // if description only contains a BOM or terminator then make it blank
-                                       $frame_description = '';
-                               }
-                               $parsedFrame['encodingid']       = $frame_textencoding;
-                               $parsedFrame['encoding']         = $this->TextEncodingNameLookup($frame_textencoding);
+                               $parsedFrame['description']   = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                               $parsedFrame['description']   = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
+                               $parsedFrame['encodingid']    = $frame_textencoding;
+                               $parsedFrame['encoding']      = $this->TextEncodingNameLookup($frame_textencoding);
 
                                if ($id3v2_majorversion == 2) {
-                                       $parsedFrame['imagetype']    = isset($frame_imagetype) ? $frame_imagetype : null;
+                                       $parsedFrame['imagetype'] = isset($frame_imagetype) ? $frame_imagetype : null;
                                } else {
-                                       $parsedFrame['mime']         = isset($frame_mimetype) ? $frame_mimetype : null;
+                                       $parsedFrame['mime']      = isset($frame_mimetype) ? $frame_mimetype : null;
                                }
-                               $parsedFrame['picturetypeid']    = $frame_picturetype;
-                               $parsedFrame['picturetype']      = $this->APICPictureTypeLookup($frame_picturetype);
-                               $parsedFrame['description']      = $frame_description;
-                               $parsedFrame['data']             = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
-                               $parsedFrame['datalength']       = strlen($parsedFrame['data']);
+                               $parsedFrame['picturetypeid'] = $frame_picturetype;
+                               $parsedFrame['picturetype']   = $this->APICPictureTypeLookup($frame_picturetype);
+                               $parsedFrame['data']          = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
+                               $parsedFrame['datalength']    = strlen($parsedFrame['data']);
 
-                               $parsedFrame['image_mime'] = '';
+                               $parsedFrame['image_mime']    = '';
                                $imageinfo = array();
                                if ($imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo)) {
                                        if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
@@ -1550,11 +1530,8 @@ class getid3_id3v2 extends getid3_handler
                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
                        }
-                       $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
+                       $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
                        $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
 
                        $parsedFrame['objectdata']  = (string) substr($parsedFrame['data'], $frame_offset);
@@ -1563,7 +1540,6 @@ class getid3_id3v2 extends getid3_handler
 
                        $parsedFrame['mime']        = $frame_mimetype;
                        $parsedFrame['filename']    = $frame_filename;
-                       $parsedFrame['description'] = $frame_description;
                        unset($parsedFrame['data']);
 
 
@@ -1633,16 +1609,12 @@ class getid3_id3v2 extends getid3_handler
                        $frame_offset = $frame_terminatorpos + strlen("\x00");
 
                        $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
-                       $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
+                       $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
                        $frame_offset = $frame_terminatorpos + strlen("\x00");
 
                        $parsedFrame['ownerid']     = $frame_ownerid;
                        $parsedFrame['data']        = (string) substr($parsedFrame['data'], $frame_offset);
-                       $parsedFrame['description'] = $frame_description;
                        unset($parsedFrame['data']);
 
 
@@ -1738,7 +1710,8 @@ class getid3_id3v2 extends getid3_handler
                        $parsedFrame['encodingid']   = $frame_textencoding;
                        $parsedFrame['encoding']     = $this->TextEncodingNameLookup($frame_textencoding);
 
-                       $parsedFrame['data']         = (string) substr($parsedFrame['data'], $frame_offset);
+                       $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
+                       $parsedFrame['data'] = $this->RemoveStringTerminator($parsedFrame['data'], $this->TextEncodingTerminatorLookup($frame_textencoding));
                        if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
                                $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['data']);
                        }
@@ -1776,6 +1749,7 @@ class getid3_id3v2 extends getid3_handler
                        $frame_offset += 8;
 
                        $parsedFrame['seller'] = (string) substr($parsedFrame['data'], $frame_offset);
+                       $parsedFrame['seller'] = $this->RemoveStringTerminator($parsedFrame['seller'], $this->TextEncodingTerminatorLookup($frame_textencoding));
                        unset($parsedFrame['data']);
 
 
@@ -1834,11 +1808,8 @@ class getid3_id3v2 extends getid3_handler
                        if (ord(substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
                                $frame_terminatorpos++; // strpos() fooled because 2nd byte of Unicode chars are often 0x00
                        }
-                       $frame_description = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
-                       if (in_array($frame_description, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
-                               // if description only contains a BOM or terminator then make it blank
-                               $frame_description = '';
-                       }
+                       $parsedFrame['description'] = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
+                       $parsedFrame['description'] = $this->MakeUTF16emptyStringEmpty($parsedFrame['description']);
                        $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
 
                        $frame_terminatorpos = strpos($parsedFrame['data'], "\x00", $frame_offset);
@@ -1855,7 +1826,6 @@ class getid3_id3v2 extends getid3_handler
                        $parsedFrame['receivedasid']      = $frame_receivedasid;
                        $parsedFrame['receivedas']        = $this->COMRReceivedAsLookup($frame_receivedasid);
                        $parsedFrame['sellername']        = $frame_sellername;
-                       $parsedFrame['description']       = $frame_description;
                        $parsedFrame['mime']              = $frame_mimetype;
                        $parsedFrame['logo']              = $frame_sellerlogo;
                        unset($parsedFrame['data']);
@@ -2019,9 +1989,9 @@ class getid3_id3v2 extends getid3_handler
                        // Element ID      <text string> $00
                        // Start time      $xx xx xx xx
                        // End time        $xx xx xx xx
-            // Start offset    $xx xx xx xx
-            // End offset      $xx xx xx xx
-            // <Optional embedded sub-frames>
+                       // Start offset    $xx xx xx xx
+                       // End offset      $xx xx xx xx
+                       // <Optional embedded sub-frames>
 
                        $frame_offset = 0;
                        @list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
@@ -2062,7 +2032,7 @@ class getid3_id3v2 extends getid3_handler
                                        $subframe['encodingid'] = ord(substr($subframe_rawdata, 0, 1));
                                        $subframe['text']       =     substr($subframe_rawdata, 1);
                                        $subframe['encoding']   = $this->TextEncodingNameLookup($subframe['encodingid']);
-                                       $encoding_converted_text = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe['text']));;
+                                       $encoding_converted_text = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe['text']));
                                        switch (substr($encoding_converted_text, 0, 2)) {
                                                case "\xFF\xFE":
                                                case "\xFE\xFF":
@@ -2082,22 +2052,51 @@ class getid3_id3v2 extends getid3_handler
                                                        break;
                                        }
 
-                                       if (($subframe['name'] == 'TIT2') || ($subframe['name'] == 'TIT3')) {
-                                               if ($subframe['name'] == 'TIT2') {
+                                       switch ($subframe['name']) {
+                                               case 'TIT2':
                                                        $parsedFrame['chapter_name']        = $encoding_converted_text;
-                                               } elseif ($subframe['name'] == 'TIT3') {
+                                                       $parsedFrame['subframes'][] = $subframe;
+                                                       break;
+                                               case 'TIT3':
                                                        $parsedFrame['chapter_description'] = $encoding_converted_text;
-                                               }
-                                               $parsedFrame['subframes'][] = $subframe;
-                                       } else {
-                                               $this->warning('ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (only TIT2 and TIT3)');
+                                                       $parsedFrame['subframes'][] = $subframe;
+                                                       break;
+                                               case 'WXXX':
+                                                       list($subframe['chapter_url_description'], $subframe['chapter_url']) = explode("\x00", $encoding_converted_text, 2);
+                                                       $parsedFrame['chapter_url'][$subframe['chapter_url_description']] = $subframe['chapter_url'];
+                                                       $parsedFrame['subframes'][] = $subframe;
+                                                       break;
+                                               case 'APIC':
+                                                       if (preg_match('#^([^\\x00]+)*\\x00(.)([^\\x00]+)*\\x00(.+)$#s', $subframe['text'], $matches)) {
+                                                               list($dummy, $subframe_apic_mime, $subframe_apic_picturetype, $subframe_apic_description, $subframe_apic_picturedata) = $matches;
+                                                               $subframe['image_mime']   = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe_apic_mime));
+                                                               $subframe['picture_type'] = $this->APICPictureTypeLookup($subframe_apic_picturetype);
+                                                               $subframe['description']  = trim(getid3_lib::iconv_fallback($subframe['encoding'], $info['encoding'], $subframe_apic_description));
+                                                               if (strlen($this->TextEncodingTerminatorLookup($subframe['encoding'])) == 2) {
+                                                                       // the null terminator between "description" and "picture data" could be either 1 byte (ISO-8859-1, UTF-8) or two bytes (UTF-16)
+                                                                       // the above regex assumes one byte, if it's actually two then strip the second one here
+                                                                       $subframe_apic_picturedata = substr($subframe_apic_picturedata, 1);
+                                                               }
+                                                               $subframe['data'] = $subframe_apic_picturedata;
+                                                               unset($dummy, $subframe_apic_mime, $subframe_apic_picturetype, $subframe_apic_description, $subframe_apic_picturedata);
+                                                               unset($subframe['text'], $parsedFrame['text']);
+                                                               $parsedFrame['subframes'][] = $subframe;
+                                                               $parsedFrame['picture_present'] = true;
+                                                       } else {
+                                                               $this->warning('ID3v2.CHAP subframe #'.(count($parsedFrame['subframes']) + 1).' "'.$subframe['name'].'" not in expected format');
+                                                       }
+                                                       break;
+                                               default:
+                                                       $this->warning('ID3v2.CHAP subframe "'.$subframe['name'].'" not handled (supported: TIT2, TIT3, WXXX, APIC)');
+                                                       break;
                                        }
                                }
                                unset($subframe_rawdata, $subframe, $encoding_converted_text);
+                               unset($parsedFrame['data']); // debatable whether this this be here, without it the returned structure may contain a large amount of duplicate data if chapters contain APIC
                        }
 
                        $id3v2_chapter_entry = array();
-                       foreach (array('id', 'time_begin', 'time_end', 'offset_begin', 'offset_end', 'chapter_name', 'chapter_description') as $id3v2_chapter_key) {
+                       foreach (array('id', 'time_begin', 'time_end', 'offset_begin', 'offset_end', 'chapter_name', 'chapter_description', 'chapter_url', 'picture_present') as $id3v2_chapter_key) {
                                if (isset($parsedFrame[$id3v2_chapter_key])) {
                                        $id3v2_chapter_entry[$id3v2_chapter_key] = $parsedFrame[$id3v2_chapter_key];
                                }
@@ -2116,7 +2115,7 @@ class getid3_id3v2 extends getid3_handler
                        // CTOC flags        %xx
                        // Entry count       $xx
                        // Child Element ID  <string>$00   /* zero or more child CHAP or CTOC entries */
-            // <Optional embedded sub-frames>
+                       // <Optional embedded sub-frames>
 
                        $frame_offset = 0;
                        @list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
@@ -3695,6 +3694,35 @@ class getid3_id3v2 extends getid3_handler
                return (isset($TextEncodingNameLookup[$encoding]) ? $TextEncodingNameLookup[$encoding] : 'ISO-8859-1');
        }
 
+       /**
+        * @param string $string
+        * @param string $terminator
+        *
+        * @return string
+        */
+       public static function RemoveStringTerminator($string, $terminator) {
+               // Null terminator at end of comment string is somewhat ambiguous in the specification, may or may not be implemented by various taggers. Remove terminator only if present.
+               // https://github.com/JamesHeinrich/getID3/issues/121
+               // https://community.mp3tag.de/t/x-trailing-nulls-in-id3v2-comments/19227
+               if (substr($string, -strlen($terminator), strlen($terminator)) === $terminator) {
+                       $string = substr($string, 0, -strlen($terminator));
+               }
+               return $string;
+       }
+
+       /**
+        * @param string $string
+        *
+        * @return string
+        */
+       public static function MakeUTF16emptyStringEmpty($string) {
+               if (in_array($string, array("\x00", "\x00\x00", "\xFF\xFE", "\xFE\xFF"))) {
+                       // if string only contains a BOM or terminator then make it actually an empty string
+                       $string = '';
+               }
+               return $string;
+       }
+
        /**
         * @param string $framename
         * @param int    $id3v2majorversion
@@ -3705,12 +3733,10 @@ class getid3_id3v2 extends getid3_handler
                switch ($id3v2majorversion) {
                        case 2:
                                return preg_match('#[A-Z][A-Z0-9]{2}#', $framename);
-                               break;
 
                        case 3:
                        case 4:
                                return preg_match('#[A-Z][A-Z0-9]{3}#', $framename);
-                               break;
                }
                return false;
        }
@@ -3724,10 +3750,10 @@ class getid3_id3v2 extends getid3_handler
         */
        public static function IsANumber($numberstring, $allowdecimal=false, $allownegative=false) {
                for ($i = 0; $i < strlen($numberstring); $i++) {
-                       if ((chr($numberstring{$i}) < chr('0')) || (chr($numberstring{$i}) > chr('9'))) {
-                               if (($numberstring{$i} == '.') && $allowdecimal) {
+                       if ((chr($numberstring[$i]) < chr('0')) || (chr($numberstring[$i]) > chr('9'))) {
+                               if (($numberstring[$i] == '.') && $allowdecimal) {
                                        // allowed
-                               } elseif (($numberstring{$i} == '-') && $allownegative && ($i == 0)) {
+                               } elseif (($numberstring[$i] == '-') && $allownegative && ($i == 0)) {
                                        // allowed
                                } else {
                                        return false;
index 80e8165..b237505 100644 (file)
@@ -14,7 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
-
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 class getid3_lyrics3 extends getid3_handler
 {
        /**
@@ -32,7 +34,7 @@ class getid3_lyrics3 extends getid3_handler
 
                $this->fseek((0 - 128 - 9 - 6), SEEK_END);          // end - ID3v1 - "LYRICSEND" - [Lyrics3size]
                $lyrics3_id3v1 = $this->fread(128 + 9 + 6);
-               $lyrics3lsz    = substr($lyrics3_id3v1,  0,   6); // Lyrics3size
+               $lyrics3lsz    = (int) substr($lyrics3_id3v1, 0, 6); // Lyrics3size
                $lyrics3end    = substr($lyrics3_id3v1,  6,   9); // LYRICSEND or LYRICS200
                $id3v1tag      = substr($lyrics3_id3v1, 15, 128); // ID3v1
 
@@ -107,7 +109,7 @@ class getid3_lyrics3 extends getid3_handler
                                        $GETID3_ERRORARRAY = &$info['warning'];
                                        getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE__, true);
                                        $getid3_temp = new getID3();
-                                       $getid3_temp->openfile($this->getid3->filename);
+                                       $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
                                        $getid3_apetag = new getid3_apetag($getid3_temp);
                                        $getid3_apetag->overrideendoffset = $info['lyrics3']['tag_offset_start'];
                                        $getid3_apetag->Analyze();
@@ -240,7 +242,6 @@ class getid3_lyrics3 extends getid3_handler
                        default:
                                $this->error('Cannot process Lyrics3 version '.$version.' (only v1 and v2)');
                                return false;
-                               break;
                }
 
 
index a976ef8..db29601 100644 (file)
@@ -114,7 +114,7 @@ class Image_XMP
                $data = fread($filehnd, 2);
 
                // Check that the third character is 0xFF (Start of first segment header)
-               if ($data{0} != "\xFF")
+               if ($data[0] != "\xFF")
                {
                        // NO FF found - close file and return - JPEG is probably corrupted
                        fclose($filehnd);
@@ -124,16 +124,16 @@ class Image_XMP
                // Flag that we havent yet hit the compressed image data
                $hit_compressed_image_data = false;
 
-        $headerdata = array();
+               $headerdata = array();
                // Cycle through the file until, one of: 1) an EOI (End of image) marker is hit,
                //                                       2) we have hit the compressed image data (no more headers are allowed after data)
                //                                       3) or end of file is hit
 
-               while (($data{1} != "\xD9") && (!$hit_compressed_image_data) && (!feof($filehnd)))
+               while (($data[1] != "\xD9") && (!$hit_compressed_image_data) && (!feof($filehnd)))
                {
                        // Found a segment to look at.
                        // Check that the segment marker is not a Restart marker - restart markers don't have size or data after them
-                       if ((ord($data{1}) < 0xD0) || (ord($data{1}) > 0xD7))
+                       if ((ord($data[1]) < 0xD0) || (ord($data[1]) > 0xD7))
                        {
                                // Segment isn't a Restart marker
                                // Read the next two bytes (size)
@@ -150,15 +150,15 @@ class Image_XMP
 
                                // Store the segment information in the output array
                                $headerdata[] = array(
-                                       'SegType'      => ord($data{1}),
-                                       'SegName'      => $GLOBALS['JPEG_Segment_Names'][ord($data{1})],
+                                       'SegType'      => ord($data[1]),
+                                       'SegName'      => $GLOBALS['JPEG_Segment_Names'][ord($data[1])],
                                        'SegDataStart' => $segdatastart,
                                        'SegData'      => $segdata,
                                );
                        }
 
                        // If this is a SOS (Start Of Scan) segment, then there is no more header data - the compressed image data follows
-                       if ($data{1} == "\xDA")
+                       if ($data[1] == "\xDA")
                        {
                                // Flag that we have hit the compressed image data - exit loop as no more headers available.
                                $hit_compressed_image_data = true;
@@ -169,7 +169,7 @@ class Image_XMP
                                $data = fread($filehnd, 2);
 
                                // Check that the first byte of the two is 0xFF as it should be for a marker
-                               if ($data{0} != "\xFF")
+                               if ($data[0] != "\xFF")
                                {
                                        // NO FF found - close file and return - JPEG is probably corrupted
                                        fclose($filehnd);
@@ -305,11 +305,11 @@ class Image_XMP
                                                                {
                                                                        // Check whether we want this details from this attribute
 //                                                                     if (in_array($key, $GLOBALS['XMP_tag_captions']))
-                                                                       if (true)
-                                                                       {
+//                                                                     if (true)
+//                                                                     {
                                                                                // Attribute wanted
                                                                                $xmp_array[$key] = $xml_elem['attributes'][$key];
-                                                                       }
+//                                                                     }
                                                                }
                                                        }
                                                        break;
@@ -365,8 +365,8 @@ class Image_XMP
                                default:
                                        // Check whether we want the details from this attribute
 //                                     if (in_array($xml_elem['tag'], $GLOBALS['XMP_tag_captions']))
-                                       if (true)
-                                       {
+//                                     if (true)
+//                                     {
                                                switch ($xml_elem['type'])
                                                {
                                                        case 'open':
@@ -388,7 +388,7 @@ class Image_XMP
                                                                // ignore
                                                                break;
                                                }
-                                       }
+//                                     }
                                        break;
                        }
 
index 7fc507c..a34beed 100644 (file)
@@ -14,7 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
-
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE__, true);
 
 class getid3_write_apetag
index 6f84867..22c4677 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v1.php', __FILE__, true);
 
 class getid3_write_id3v1
@@ -68,16 +71,16 @@ class getid3_write_id3v1
                                } else {
                                        fseek($fp_source, 0, SEEK_END);    // append new ID3v1 tag
                                }
-                               $this->tag_data['track'] = (isset($this->tag_data['track']) ? $this->tag_data['track'] : (isset($this->tag_data['track_number']) ? $this->tag_data['track_number'] : (isset($this->tag_data['tracknumber']) ? $this->tag_data['tracknumber'] : '')));
+                               $this->tag_data['track_number'] = (isset($this->tag_data['track_number']) ? $this->tag_data['track_number'] : '');
 
                                $new_id3v1_tag_data = getid3_id3v1::GenerateID3v1Tag(
-                                                                                                               (isset($this->tag_data['title']  ) ? $this->tag_data['title']   : ''),
-                                                                                                               (isset($this->tag_data['artist'] ) ? $this->tag_data['artist']  : ''),
-                                                                                                               (isset($this->tag_data['album']  ) ? $this->tag_data['album']   : ''),
-                                                                                                               (isset($this->tag_data['year']   ) ? $this->tag_data['year']    : ''),
-                                                                                                               (isset($this->tag_data['genreid']) ? $this->tag_data['genreid'] : ''),
-                                                                                                               (isset($this->tag_data['comment']) ? $this->tag_data['comment'] : ''),
-                                                                                                               (isset($this->tag_data['track']  ) ? $this->tag_data['track']   : ''));
+                                                                                                               (isset($this->tag_data['title']       ) ? $this->tag_data['title']        : ''),
+                                                                                                               (isset($this->tag_data['artist']      ) ? $this->tag_data['artist']       : ''),
+                                                                                                               (isset($this->tag_data['album']       ) ? $this->tag_data['album']        : ''),
+                                                                                                               (isset($this->tag_data['year']        ) ? $this->tag_data['year']         : ''),
+                                                                                                               (isset($this->tag_data['genreid']     ) ? $this->tag_data['genreid']      : ''),
+                                                                                                               (isset($this->tag_data['comment']     ) ? $this->tag_data['comment']      : ''),
+                                                                                                               (isset($this->tag_data['track_number']) ? $this->tag_data['track_number'] : ''));
                                fwrite($fp_source, $new_id3v1_tag_data, 128);
                                fclose($fp_source);
                                return true;
index fae45d2..ae2313e 100644 (file)
@@ -14,6 +14,9 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+       exit;
+}
 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
 
 class getid3_write_id3v2
@@ -24,7 +27,7 @@ class getid3_write_id3v2
        public $filename;
 
        /**
-        * @var array
+        * @var array|null
         */
        public $tag_data;
 
@@ -325,7 +328,6 @@ class getid3_write_id3v2
 
                        default:
                                return false;
-                               break;
                }
                return chr(bindec($flag));
        }
@@ -345,7 +347,7 @@ class getid3_write_id3v2
        public function GenerateID3v2FrameFlags($TagAlter=false, $FileAlter=false, $ReadOnly=false, $Compression=false, $Encryption=false, $GroupingIdentity=false, $Unsynchronisation=false, $DataLengthIndicator=false) {
                $flag1 = null;
                $flag2 = null;
-           switch ($this->majorversion) {
+               switch ($this->majorversion) {
                        case 4:
                                // %0abc0000 %0h00kmnp
                                $flag1  = '0';
@@ -378,7 +380,6 @@ class getid3_write_id3v2
 
                        default:
                                return false;
-                               break;
 
                }
                return chr(bindec($flag1)).chr(bindec($flag2));
@@ -852,7 +853,7 @@ class getid3_write_id3v2
                                                $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion;
                                        } elseif (!$this->ID3v2IsValidAPICpicturetype($source_data_array['picturetypeid'])) {
                                                $this->errors[] = 'Invalid Picture Type byte in '.$frame_name.' ('.$source_data_array['picturetypeid'].') for ID3v2.'.$this->majorversion;
-                                       } elseif (($this->majorversion >= 3) && (!$this->ID3v2IsValidAPICimageformat($source_data_array['mime']))) {
+                                       } elseif ((!$this->ID3v2IsValidAPICimageformat($source_data_array['mime']))) {
                                                $this->errors[] = 'Invalid MIME Type in '.$frame_name.' ('.$source_data_array['mime'].') for ID3v2.'.$this->majorversion;
                                        } elseif (($source_data_array['mime'] == '-->') && (!$this->IsValidURL($source_data_array['data'], false))) {
                                                //$this->errors[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')';
@@ -905,10 +906,14 @@ class getid3_write_id3v2
                                        // Email to user   <text string> $00
                                        // Rating          $xx
                                        // Counter         $xx xx xx xx (xx ...)
+                                       if (!$this->IsValidEmail($source_data_array['email'])) {
+                                               // https://github.com/JamesHeinrich/getID3/issues/216
+                                               // https://en.wikipedia.org/wiki/ID3#ID3v2_rating_tag_issue
+                                               // ID3v2 specs say it should be an email address, but Windows instead uses string like "Windows Media Player 9 Series"
+                                               $this->warnings[] = 'Invalid Email in '.$frame_name.' ('.$source_data_array['email'].')';
+                                       }
                                        if (!$this->IsWithinBitRange($source_data_array['rating'], 8, false)) {
                                                $this->errors[] = 'Invalid Rating byte in '.$frame_name.' ('.$source_data_array['rating'].') (range = 0 to 255)';
-                                       } elseif (!$this->IsValidEmail($source_data_array['email'])) {
-                                               $this->errors[] = 'Invalid Email in '.$frame_name.' ('.$source_data_array['email'].')';
                                        } else {
                                                $framedata .= str_replace("\x00", '', $source_data_array['email'])."\x00";
                                                $framedata .= chr($source_data_array['rating']);
@@ -1095,7 +1100,6 @@ class getid3_write_id3v2
                                                $this->errors[] = 'Invalid MIME Type in '.$frame_name.' ('.$source_data_array['mime'].')';
                                        } else {
                                                $framedata .= chr($source_data_array['encodingid']);
-                                               unset($pricestring);
                                                $pricestrings = array();
                                                foreach ($source_data_array['price'] as $key => $val) {
                                                        if ($this->ID3v2IsValidPriceString($key.$val['value'])) {
@@ -1233,9 +1237,9 @@ class getid3_write_id3v2
                                        break;
 
                                default:
-                                       if ((($this->majorversion == 2) && (strlen($frame_name) != 3)) || (($this->majorversion > 2) && (strlen($frame_name) != 4))) {
+                                       if (/*(($this->majorversion == 2) && (strlen($frame_name) != 3)) || (($this->majorversion > 2) && (*/strlen($frame_name) != 4/*))*/) {
                                                $this->errors[] = 'Invalid frame name "'.$frame_name.'" for ID3v2.'.$this->majorversion;
-                                       } elseif ($frame_name{0} == 'T') {
+                                       } elseif ($frame_name[0] == 'T') {
                                                // 4.2. T???  Text information frames
                                                // Text encoding                $xx
                                                // Information                  <text string(s) according to encoding>
@@ -1246,7 +1250,7 @@ class getid3_write_id3v2
                                                        $framedata .= chr($source_data_array['encodingid']);
                                                        $framedata .= $source_data_array['data'];
                                                }
-                                       } elseif ($frame_name{0} == 'W') {
+                                       } elseif ($frame_name[0] == 'W') {
                                                // 4.3. W???  URL link frames
                                                // URL              <text string>
                                                if (!$this->IsValidURL($source_data_array['data'], false)) {
@@ -1402,7 +1406,7 @@ class getid3_write_id3v2
                                        break;
 
                                default:
-                                       if (($frame_name{0} != 'T') && ($frame_name{0} != 'W')) {
+                                       if (($frame_name[0] != 'T') && ($frame_name[0] != 'W')) {
                                                $this->errors[] = 'Frame not allowed in ID3v2.'.$this->majorversion.': '.$frame_name;
                                        }
                                        break;
@@ -1525,7 +1529,7 @@ class getid3_write_id3v2
                                        break;
 
                                default:
-                                       if (($frame_name{0} != 'T') && ($frame_name{0} != 'W')) {
+                                       if (($frame_name[0] != 'T') && ($frame_name[0] != 'W')) {
                                                $this->errors[] = 'Frame not allowed in ID3v2.'.$this->majorversion.': '.$frame_name;
                                        }
                                        break;
@@ -1617,7 +1621,7 @@ class getid3_write_id3v2
                                        break;
 
                                default:
-                                       if (($frame_name{0} != 'T') && ($frame_name{0} != 'W')) {
+                                       if (($frame_name[0] != 'T') && ($frame_name[0] != 'W')) {
                                                $this->errors[] = 'Frame not allowed in ID3v2.'.$this->majorversion.': '.$frame_name;
                                        }
                                        break;
@@ -1688,18 +1692,18 @@ class getid3_write_id3v2
                                                        if ($noerrorsonly) {
                                                                return false;
                                                        } else {
-                                                               unset($frame_name);
+                                                               $frame_name = null;
                                                        }
                                                }
                                        } else {
                                                // ignore any invalid frame names, including 'title', 'header', etc
                                                $this->warnings[] = 'Ignoring invalid ID3v2 frame type: "'.$frame_name.'"';
-                                               unset($frame_name);
+                                               $frame_name = null;
                                                unset($frame_length);
                                                unset($frame_flags);
                                                unset($frame_data);
                                        }
-                                       if (isset($frame_name) && isset($frame_length) && isset($frame_flags) && isset($frame_data)) {
+                                       if (null !== $frame_name && isset($frame_length) && isset($frame_flags) && isset($frame_data)) {
                                                $tagstring .= $frame_name.$frame_length.$frame_flags.$frame_data;
                                        }
                                }
@@ -1723,7 +1727,7 @@ class getid3_write_id3v2
                        }
 
                        $footer = false; // ID3v2 footers not yet supported in getID3()
-                       if (!$footer && ($this->paddedlength > (strlen($tagstring) + getid3_id3v2::ID3v2HeaderLength($this->majorversion)))) {
+                       if (/*!$footer && */($this->paddedlength > (strlen($tagstring) + getid3_id3v2::ID3v2HeaderLength($this->majorversion)))) {
                                // pad up to $paddedlength bytes if unpadded tag is shorter than $paddedlength
                                // "Furthermore it MUST NOT have any padding when a tag footer is added to the tag."
                                if (($this->paddedlength - strlen($tagstring) - getid3_id3v2::ID3v2HeaderLength($this->majorversion)) > 0) {
@@ -1791,11 +1795,9 @@ class getid3_write_id3v2
                switch ($framename) {
                        case 'RGAD':
                                return false;
-                               break;
 
                        default:
                                return false;
-                               break;
                }
        }
 
@@ -1958,10 +1960,10 @@ class getid3_write_id3v2
                $unsyncheddata = '';
                $datalength = strlen($data);
                for ($i = 0; $i < $datalength; $i++) {
-                       $thischar = $data{$i};
+                       $thischar = $data[$i];
                        $unsyncheddata .= $thischar;
                        if ($thischar == "\xFF") {
-                               $nextchar = ord($data{$i + 1});
+                               $nextchar = ord($data[$i + 1]);
                                if (($nextchar & 0xE0) == 0xE0) {
                                        // previous byte = 11111111, this byte = 111?????
                                        $unsyncheddata .= "\x00";
@@ -2316,6 +2318,7 @@ class getid3_write_id3v2
                        $ID3v2ShortFrameNameLookup[4]['performer_sort_order']              = 'TSOP';
                        $ID3v2ShortFrameNameLookup[4]['title_sort_order']                  = 'TSOT';
                        $ID3v2ShortFrameNameLookup[4]['set_subtitle']                      = 'TSST';
+                       $ID3v2ShortFrameNameLookup[4]['year']                              = 'TDRC'; // subset of ISO 8601: valid timestamps are yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddTHH, yyyy-MM-ddTHH:mm and yyyy-MM-ddTHH:mm:ss. All time stamps are UTC
                }
                return (isset($ID3v2ShortFrameNameLookup[$majorversion][strtolower($long_description)]) ? $ID3v2ShortFrameNameLookup[$majorversion][strtolower($long_description)] : '');
 
index cc98e5d..73eea6d 100644 (file)
@@ -205,14 +205,12 @@ class getid3_writetags
                                                        //$AllowedTagFormats = array('metaflac');
                                                        $this->errors[] = 'metaflac is not (yet) compatible with OggFLAC files';
                                                        return false;
-                                                       break;
                                                case 'vorbis':
                                                        $AllowedTagFormats = array('vorbiscomment');
                                                        break;
                                                default:
                                                        $this->errors[] = 'metaflac is not (yet) compatible with Ogg files other than OggVorbis';
                                                        return false;
-                                                       break;
                                        }
                                        break;
 
@@ -282,7 +280,6 @@ class getid3_writetags
                                default:
                                        $this->errors[] = 'unknown tag format "'.$tagformat.'" in $tagformats in WriteTags()';
                                        return false;
-                                       break;
                        }
 
                }
@@ -311,9 +308,9 @@ class getid3_writetags
                        }
                }
 
-               // Convert "TRACK" to "TRACKNUMBER" (if needed) for compatability with all formats
-               if (isset($this->tag_data['TRACK']) && !isset($this->tag_data['TRACKNUMBER'])) {
-                       $this->tag_data['TRACKNUMBER'] = $this->tag_data['TRACK'];
+               // Convert "TRACK" to "TRACK_NUMBER" (if needed) for compatability with all formats
+               if (isset($this->tag_data['TRACK']) && !isset($this->tag_data['TRACK_NUMBER'])) {
+                       $this->tag_data['TRACK_NUMBER'] = $this->tag_data['TRACK'];
                        unset($this->tag_data['TRACK']);
                }
 
@@ -408,7 +405,6 @@ class getid3_writetags
                                default:
                                        $this->errors[] = 'Invalid tag format to write: "'.$tagformat.'"';
                                        return false;
-                                       break;
                        }
                        if (!$success) {
                                return false;
@@ -486,7 +482,6 @@ class getid3_writetags
                                default:
                                        $this->errors[] = 'Invalid tag format to delete: "'.$DeleteTagFormat.'"';
                                        return false;
-                                       break;
                        }
                        if (!$success) {
                                return false;
@@ -508,10 +503,10 @@ class getid3_writetags
                        // do nothing - ignore previous data
                } else {
                        throw new Exception('$this->overwrite_tags=false is known to be buggy in this version of getID3. Check http://github.com/JamesHeinrich/getID3 for a newer version.');
-                       if (!isset($this->ThisFileInfo['tags'][$TagFormat])) {
-                               return false;
-                       }
-                       $tag_data = array_merge_recursive($tag_data, $this->ThisFileInfo['tags'][$TagFormat]);
+//                     if (!isset($this->ThisFileInfo['tags'][$TagFormat])) {
+//                             return false;
+//                     }
+//                     $tag_data = array_merge_recursive($tag_data, $this->ThisFileInfo['tags'][$TagFormat]);
                }
                return true;
        }
@@ -559,14 +554,14 @@ class getid3_writetags
                                }
                        }
                }
-               $tag_data_id3v1['title']   =        getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['TITLE']      ) ? $this->tag_data['TITLE']       : array())));
-               $tag_data_id3v1['artist']  =        getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['ARTIST']     ) ? $this->tag_data['ARTIST']      : array())));
-               $tag_data_id3v1['album']   =        getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['ALBUM']      ) ? $this->tag_data['ALBUM']       : array())));
-               $tag_data_id3v1['year']    =        getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['YEAR']       ) ? $this->tag_data['YEAR']        : array())));
-               $tag_data_id3v1['comment'] =        getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['COMMENT']    ) ? $this->tag_data['COMMENT']     : array())));
-               $tag_data_id3v1['track']   = intval(getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['TRACKNUMBER']) ? $this->tag_data['TRACKNUMBER'] : array()))));
-               if ($tag_data_id3v1['track'] <= 0) {
-                       $tag_data_id3v1['track'] = '';
+               $tag_data_id3v1['title']        =        getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['TITLE']       ) ? $this->tag_data['TITLE']        : array())));
+               $tag_data_id3v1['artist']       =        getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['ARTIST']      ) ? $this->tag_data['ARTIST']       : array())));
+               $tag_data_id3v1['album']        =        getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['ALBUM']       ) ? $this->tag_data['ALBUM']        : array())));
+               $tag_data_id3v1['year']         =        getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['YEAR']        ) ? $this->tag_data['YEAR']         : array())));
+               $tag_data_id3v1['comment']      =        getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['COMMENT']     ) ? $this->tag_data['COMMENT']      : array())));
+               $tag_data_id3v1['track_number'] = intval(getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['TRACK_NUMBER']) ? $this->tag_data['TRACK_NUMBER'] : array()))));
+               if ($tag_data_id3v1['track_number'] <= 0) {
+                       $tag_data_id3v1['track_number'] = '';
                }
 
                $this->MergeExistingTagData('id3v1', $tag_data_id3v1);
@@ -665,7 +660,7 @@ class getid3_writetags
                                                                // note: some software, notably Windows Media Player and iTunes are broken and treat files tagged with UTF-16BE (with BOM) as corrupt
                                                                // therefore we force data to UTF-16LE and manually prepend the BOM
                                                                $ID3v2_tag_data_converted = false;
-                                                               if (!$ID3v2_tag_data_converted && ($this->tag_encoding == 'ISO-8859-1')) {
+                                                               if (/*!$ID3v2_tag_data_converted && */($this->tag_encoding == 'ISO-8859-1')) {
                                                                        // great, leave data as-is for minimum compatability problems
                                                                        $tag_data_id3v2[$ID3v2_framename][$key]['encodingid'] = 0;
                                                                        $tag_data_id3v2[$ID3v2_framename][$key]['data']       = $value;
@@ -675,7 +670,7 @@ class getid3_writetags
                                                                        do {
                                                                                // if UTF-8 string does not include any characters above chr(127) then it is identical to ISO-8859-1
                                                                                for ($i = 0; $i < strlen($value); $i++) {
-                                                                                       if (ord($value{$i}) > 127) {
+                                                                                       if (ord($value[$i]) > 127) {
                                                                                                break 2;
                                                                                        }
                                                                                }
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 6b09414..5a184a0 100644 (file)
@@ -1,7 +1,7 @@
 <paquet
        prefix="medias"
        categorie="multimedia"
-       version="2.20.34"
+       version="2.20.35"
        etat="stable"
        compatibilite="[3.2.0;3.2.*]"
        logo="prive/themes/spip/images/portfolio-32.png"
index 4a80ae9..2a877ec 100644 (file)
@@ -32,7 +32,7 @@
 
 [(#REM) puis les images du portfolio]
 <B_portfolio>
-<h3><:medias:info_portfolio:></h3>
+<h3 class="portfolios__titre"><:medias:info_portfolio:></h3>
 <div class="liste_items documents ordonner_rang_lien" id="portfolio#ENV{id_unique}" data-cookie-affichage="portfolio" data-lien="[(#OBJET|concat{'/',#ID_OBJET}|attribut_html)]">
 [<p class="pagination">(#PAGINATION{prive})</p>]
 <div class="sortable">
@@ -53,7 +53,7 @@
 
 [(#REM) puis les documents]
 <B_documents>
-<h3><:medias:info_documents:></h3>
+<h3 class="portfolios__titre"><:medias:info_documents:></h3>
 <div class="liste_items documents ordonner_rang_lien" id="documents#ENV{id_unique}" data-cookie-affichage="documents" data-lien="[(#OBJET|concat{'/',#ID_OBJET}|attribut_html)]">
 [<p class="pagination">(#PAGINATION{prive})</p>]
 <div class="sortable">
index c2b8cf7..1278f3e 100644 (file)
@@ -345,7 +345,7 @@ function quete_calendrier_interval_rv($avant, $apres) {
                                                'DESCRIPTION' => $row['texte'],
                                                'SUMMARY' => $row['titre'],
                                                'CATEGORIES' => $cat,
-                                               'ATTENDEE' => (count($auteurs) == 0) ? '' : join($auteurs, ', ')
+                                               'ATTENDEE' => (count($auteurs) == 0) ? '' : implode(', ', $auteurs)
                                        );
                        }
 
index 4fbec34..a159525 100644 (file)
@@ -194,7 +194,9 @@ class Diff {
                        if (!$fin_old) {
                                // Paragraphes supprimes jusqu'au paragraphe courant
                                if (!isset($i_old)) {
-                                       list($i_old, $p_old) = each($paras_old);
+                                       $i_old = key($paras_old);
+                                       $p_old = current($paras_old);
+                                       next($paras_old);
                                        if (!$p_old) {
                                                $fin_old = true;
                                        }
@@ -204,7 +206,9 @@ class Diff {
                                                $this->diff->supprimer($p_old);
                                        }
                                        unset($i_old);
-                                       list($i_old, $p_old) = each($paras_old);
+                                       $i_old = key($paras_old);
+                                       $p_old = current($paras_old);
+                                       next($paras_old);
                                        if (!$p_old) {
                                                $fin_old = true;
                                        }
@@ -216,7 +220,9 @@ class Diff {
                // Paragraphes supprimes a la fin du texte
                if (!$fin_old) {
                        if (!isset($i_old)) {
-                               list($i_old, $p_old) = each($paras_old);
+                               $i_old = key($paras_old);
+                               $p_old = current($paras_old);
+                               next($paras_old);
                                if (!strlen($p_old)) {
                                        $fin_old = true;
                                }
@@ -225,7 +231,9 @@ class Diff {
                                if (!isset($trans_rev[$i_old])) {
                                        $this->diff->supprimer($p_old);
                                }
-                               list($i_old, $p_old) = each($paras_old);
+                               $i_old = key($paras_old);
+                               $p_old = current($paras_old);
+                               next($paras_old);
                                if (!$p_old) {
                                        $fin_old = true;
                                }
index cb60ec8..cfe2a64 100644 (file)
@@ -561,8 +561,8 @@ function ajouter_version($id_objet, $objet, $champs, $titre_version = "", $id_au
        // distinctif (pour eviter la violation d'unicite)
        // et un titre contenant en fait le moment de l'insertion
        list($ms, $sec) = explode(' ', microtime());
-       $date = $sec . substr($ms, 1,
-                       4) - 20; // SQL ne ramene que 4 chiffres significatifs apres la virgule pour 0.0+titre_version
+       // SQL ne ramene que 4 chiffres significatifs apres la virgule pour 0.0+titre_version
+       $date = ($sec . substr($ms, 1, 4)) - 20;
        $datediff = ($sec - mktime(0, 0, 0, 9, 1, 2007)) * 1000000 + substr($ms, 2, strlen($ms) - 4);
 
        $valeurs = array(
@@ -653,7 +653,8 @@ function ajouter_version($id_objet, $objet, $champs, $titre_version = "", $id_au
 
                for ($i = 0; $i < $n; $i++) {
                        while ($i >= $paras_champ[$nom]) {
-                               list($nom, ) = each($champs);
+                               $nom = key($champs);
+                               next($champs);
                        }
                        // Lier au fragment existant si possible, sinon creer un nouveau fragment
                        $id_fragment = isset($trans[$i]) ? $trans[$i] : $next++;
index 8102868..2b71148 100644 (file)
@@ -68,7 +68,7 @@ class XML_HTMLSax3_StateParser {
 \r
  function scanCharacter() {\r
   if ($this->position < $this->length) {\r
-   return $this->rawtext{$this->position++};\r
+   return $this->rawtext[$this->position++];\r
   }\r
  }\r
 \r
@@ -166,7 +166,7 @@ class XML_HTMLSax3_StateParser_Lt430 extends XML_HTMLSax3_StateParser {
 \r
  function scanUntilCharacters($string) {\r
   $startpos = $this->position;\r
-  while ($this->position < $this->length && strpos($string, $this->rawtext{$this->position}) === FALSE) {\r
+  while ($this->position < $this->length && strpos($string, $this->rawtext[$this->position]) === FALSE) {\r
    $this->position++;\r
   }\r
   return substr($this->rawtext, $startpos, $this->position - $startpos);\r
@@ -174,7 +174,7 @@ class XML_HTMLSax3_StateParser_Lt430 extends XML_HTMLSax3_StateParser {
 \r
  function ignoreWhitespace() {\r
   while ($this->position < $this->length && \r
-   strpos(" \n\r\t", $this->rawtext{$this->position}) !== FALSE) {\r
+   strpos(" \n\r\t", $this->rawtext[$this->position]) !== FALSE) {\r
    $this->position++;\r
   }\r
  }\r
index ca88e8a..6959b1c 100644 (file)
@@ -285,7 +285,7 @@ class SafeHTML
         foreach ($this->blackProtocols as $proto) {
             $preg = "/[\s\x01-\x1F]*";
             for ($i=0; $i<strlen($proto); $i++) {
-                $preg .= $proto{$i} . "[\s\x01-\x1F]*";
+                $preg .= $proto[$i] . "[\s\x01-\x1F]*";
             }
             $preg .= ":/i";
             $this->protoRegexps[] = $preg;
index 9f74f5f..e3185d9 100644 (file)
@@ -196,7 +196,7 @@ function extraire_bornes($intervalle, $initialiser = false) {
        ) {
                if ($matches[1]) {
                        $bornes['min']['valeur'] = trim($matches[1]);
-                       $bornes['min']['incluse'] = ($intervalle{0} == "[");
+                       $bornes['min']['incluse'] = ($intervalle[0] == "[");
                }
                if ($matches[2]) {
                        $bornes['max']['valeur'] = trim($matches[2]);
index 9ab89f2..a0d9c02 100644 (file)
@@ -40,8 +40,9 @@ function svp_afficher_intervalle($intervalle, $logiciel) {
        }
 
        $mineure = $regs[1];
+
        $majeure = preg_replace(',\.99$,', '.*', $regs[2]);
-       $mineure_inc = $intervalle{0} == "[";
+       $mineure_inc = $intervalle[0] == "[";
        $majeure_inc = substr($intervalle, -1) == "]";
        if (strlen($mineure)) {
                if (!strlen($majeure)) {
index 3768e48..9cb9b64 100644 (file)
@@ -28,6 +28,8 @@ class TextWheel {
        protected $ruleset;
        protected static $subwheel = array();
 
+       // Experimental : projet de compilation PHP d'une wheel
+       // pour generation d'un fichier php execute a la place de ->text()
        protected $compiled = array();
 
        /**
@@ -83,13 +85,14 @@ class TextWheel {
                foreach ($rules as $name => $rule) {
                        $rule->name = $name;
                        $this->initRule($rule);
-                       if (is_string($rule->replace)
-                               and isset($this->compiled[$rule->replace])
-                               and $fun = $this->compiled[$rule->replace]
+                       if ($rule->replace
+                               and $compiledEntry = $this->ruleCompiledEntryName($rule->replace)
+                               and isset($this->compiled[$compiledEntry])
+                               and $fun = $this->compiled[$compiledEntry]
                        ) {
                                $pre[] = "\n###\n## $name\n###\n" . $fun;
                                preg_match(',function (\w+), ', $fun, $r);
-                               $rule->compilereplace = $r[1]; # ne pas modifier ->replace sinon on casse l'execution...
+                               $rule->compilereplace = "'".$r[1]."'"; # ne pas modifier ->replace sinon on casse l'execution...
                        }
 
                        $r = "\t/* $name */\n";
@@ -109,9 +112,18 @@ class TextWheel {
 
                        if ($rule->func_replace !== 'replace_identity') {
                                $fun = 'TextWheel::' . $rule->func_replace;
+                               $call = '';
                                switch ($fun) {
                                        case 'TextWheel::replace_all_cb':
-                                               $fun = $rule->replace; # trim()...
+                                               if (is_string($rule->replace)) {
+                                                       $fun = $rule->replace;
+                                               }
+                                               elseif ($rule->compilereplace) {
+                                                       $fun = trim($rule->compilereplace, "'");
+                                               };
+                                               if ($fun) {
+                                                       $call = "\$t = $fun(\$t);";
+                                               }
                                                break;
                                        case 'TextWheel::replace_preg':
                                                $fun = 'preg_replace';
@@ -125,7 +137,13 @@ class TextWheel {
                                        default:
                                                break;
                                }
-                               $r .= "\t" . '$t = ' . $fun . '(' . TextWheel::export($rule->match) . ', ' . TextWheel::export($rule->replace) . ', $t);' . "\n";
+                               if (!$call) {
+                                       if (empty($rule->compilereplace)) {
+                                               $rule->compilereplace = TextWheel::export($rule->replace);
+                                       }
+                                       $call = '$t = ' . $fun . '(' . TextWheel::export($rule->match) . ', ' . $rule->compilereplace . ', $t);';
+                               }
+                               $r .= "\t$call\n";
                        }
 
                        $comp[] = $r;
@@ -161,6 +179,20 @@ class TextWheel {
                return $tw;
        }
 
+       /**
+        * @param $replace
+        * @return string
+        */
+       protected function ruleCompiledEntryName($replace) {
+               if (is_array($replace)) {
+                       return serialize($replace);
+               }
+               elseif (is_object($replace)) {
+                       return get_class($replace) . ':' . spl_object_hash($replace);
+               }
+               return $replace;
+       }
+
        /**
         * Initializing a rule a first call
         * including file, creating function or wheel
@@ -183,25 +215,35 @@ class TextWheel {
                }
 
                if ($rule->create_replace) {
+                       // DEPRECATED : rule->create_replace, on ne peut rien faire de mieux ici
+                       // mais c'est voue a disparaitre
                        $compile = $rule->replace . '($t)';
                        $rule->replace = create_function('$m', $rule->replace);
-                       $this->compiled[$rule->replace] = $compile;
+                       $this->compiled[$this->ruleCompiledEntryName($rule->replace)] = $compile;
                        $rule->create_replace = false;
                        $rule->is_callback = true;
-               } elseif ($rule->is_wheel) {
-                       $n = count(TextWheel::$subwheel);
+               }
+               elseif ($rule->is_wheel) {
+                       $rule_number = count(TextWheel::$subwheel);
                        TextWheel::$subwheel[] = $this->createSubWheel($rule->replace);
-                       $var = '$m[' . intval($rule->pick_match) . ']';
+                       $cname = 'compiled_' . str_replace('-', '_', $rule->name) . '_' . substr(md5(spl_object_hash($rule)),0,7);
                        if ($rule->type == 'all' or $rule->type == 'str' or $rule->type == 'split' or !isset($rule->match)) {
-                               $var = '$m';
+                               $rule->replace = function ($m) use ($rule_number) {
+                                       return TextWheel::getSubWheel($rule_number)->text($m);
+                               };
+                               $rule->compilereplace = "'$cname'";
+                       }
+                       else {
+                               $pick_match = intval($rule->pick_match);
+                               $rule->replace = function ($m) use ($rule_number, $pick_match) {
+                                       return TextWheel::getSubWheel($rule_number)->text($m[$pick_match]);
+                               };
+                               $rule->compilereplace = 'function ($m) { return '.$cname.'($m['.$pick_match.']) }';
                        }
-                       $code = 'return TextWheel::getSubWheel(' . $n . ')->text(' . $var . ');';
-                       $rule->replace = create_function('$m', $code);
-                       $cname = 'compiled_' . str_replace('-', '_', $rule->name);
-                       $compile = TextWheel::getSubWheel($n)->compile($cname);
-                       $this->compiled[$rule->replace] = $compile;
                        $rule->is_wheel = false;
                        $rule->is_callback = true;
+                       $compile = TextWheel::getSubWheel($rule_number)->compile($cname);
+                       $this->compiled[$this->ruleCompiledEntryName($rule->replace)] = $compile;
                }
 
                # optimization
index a3cd6fd..2f0efc2 100644 (file)
@@ -65,10 +65,12 @@ class TextWheelRule {
        # optional
        # language specific
        public $require; # file to require_once
+       # DEPRECATED : create_function deprecated a partir de PHP 7.2, ne plus utiliser
        public $create_replace; # do create_function('$m', %) on $this->replace, $m is the matched array
 
        # optimizations
        public $func_replace;
+       public $compilereplace;
 
        /**
         * Rule constructor
index 71aa559..325bedb 100644 (file)
@@ -377,7 +377,6 @@ function traiter_tableau($bloc) {
        $lignes = array();
        $debut_table = $summary = '';
        $l = 0;
-       $numeric = true;
 
        // Traiter chaque ligne
        $reg_line1 = ',^(\|(' . _RACCOURCI_TH_SPAN . '))+$,sS';
index 6645dd7..b72d6ee 100644 (file)
@@ -110,7 +110,7 @@ class sfYamlInline
     if (
       (1 == count($keys) && '0' == $keys[0])
       ||
-      (count($keys) > 1 && array_reduce($keys, create_function('$v,$w', 'return (integer) $v + $w;'), 0) == count($keys) * (count($keys) - 1) / 2))
+      (count($keys) > 1 && array_reduce($keys, function($v,$w) { return (integer) $v + $w; }, 0) == count($keys) * (count($keys) - 1) / 2))
     {
       $output = array();
       foreach ($value as $val)
@@ -222,7 +222,7 @@ class sfYamlInline
       // evaluate the string
       $buffer = str_replace(array('\\n', '\\r'), array("\n", "\r"), $buffer);
                        if (strpos($buffer,'\\x')!==false){
-                               $buffer = preg_replace_callback(',\\\\x([0-9a-f]+),', create_function('$m', 'return chr(hexdec($m[1]));'), $buffer);
+                               $buffer = preg_replace_callback(',\\\\x([0-9a-f]+),', function($m) { return chr(hexdec($m[1])); }, $buffer);
                        }
     }
 
index 5a427bf..40d79d9 100644 (file)
@@ -1,7 +1,7 @@
 <paquet
        prefix="tw"
        categorie="edition"
-       version="1.5.5"
+       version="1.5.6"
        etat="stable"
        compatibilite="[3.2.0;3.2.*]"
        logo="textwheel-32.png"
index 705e952..c7148af 100644 (file)
@@ -2,7 +2,7 @@
 #HTTP_HEADER{"Pragma: no-cache"}
 
 <div class='formulaire_spip formulaire_login'>
-       [<p class="reponse_formulaire reponse_formulaire_ok">(#ENV*{_deja_loge})</p>]
+       [<p class="reponse_formulaire reponse_formulaire_ok">(#ENV**{_deja_loge})</p>]
        [<p class="reponse_formulaire reponse_formulaire_ok">(#ENV*{message_ok})</p>]
        [<p class='reponse_formulaire reponse_formulaire_erreur'>(#ENV*{message_erreur})</p>]
 
index 9ec45ac..393bb30 100644 (file)
@@ -121,7 +121,7 @@ function formulaires_login_charger_dist($cible = '', $login = '', $prive = null)
                if (isset($res['redirect']) and $res['redirect']) {
                        include_spip('inc/headers');
                        # preparer un lien pour quand redirige_formulaire ne fonctionne pas
-                       $m = redirige_formulaire($res['redirect'], '', 'ajaxform');
+                       $m = redirige_formulaire($res['redirect']);
                        $valeurs['_deja_loge'] = inserer_attribut(
                                '<a>' . _T('login_par_ici') . "</a>$m",
                                'href',
old mode 100644 (file)
new mode 100755 (executable)
index 6c0a0af..93f0714 100644 (file)
@@ -14,7 +14,7 @@
                <:info_webmestre_forces{file_options=#GET{options}}:>
        ]
        [(#VAL{_ID_WEBMESTRES}|defined|non)
-               [(#BOUTON_ACTION{<:info_admin_etre_webmestre:>,[(#URL_ACTION_AUTEUR{etre_webmestre,[(#REM|time)],#SELF})]})]
+               [(#BOUTON_ACTION{<:info_admin_etre_webmestre:>,[(#URL_ACTION_AUTEUR{etre_webmestre,[(#EVAL{'time()'})],#SELF})]})]
        ]
 ]
 <INCLURE{fond=prive/objets/infos/inc-auteur-rubriques,id_auteur,statut} />
index 3e4f837..99bb10a 100644 (file)
@@ -117,7 +117,8 @@ function afficher_initiale($url, $initiale, $compteur, $debut, $pas) {
                if (count($res) > 1) {
                        $out = implode(' ', $res);
                }
-               $memo = $res = null;
+               $memo = null;
+               $res = array();
        }
 
        return $out;
index 14877b7..08c09b1 100644 (file)
@@ -11,7 +11,7 @@
                <iframe src="#URL_ACTION_AUTEUR{calculer_taille_cache,skel}" style="width: 100%;height: 3em;overflow: hidden;"></iframe>
        </noscript>
 
-       #SET{cache_inhib,#CONFIG{cache_inhib}|sinon{0}|>{#REM|time}|oui}
+       #SET{cache_inhib,#CONFIG{cache_inhib}|sinon{0}|>{#EVAL{'time()'}}|oui}
 
        [(#GET{cache_inhib}|oui)
        <div><strong><:info_cache_desactive:></strong>