From 77a53a65e59f60f4d49b41f1b82d72830ba68987 Mon Sep 17 00:00:00 2001 From: Ludovic CHEVALIER Date: Mon, 11 Mar 2019 11:20:43 +0100 Subject: [PATCH] [SPIP] v3.2.1-->v3.2.3 --- www/CHANGELOG.TXT | 4 + www/ecrire/inc_version.php | 2 +- www/ecrire/paquet.xml | 2 +- www/plugins-dist/aide/inc/aide.php | 2 +- www/plugins-dist/archiviste/inc/archives.php | 2 +- .../breves/action/editer_breve.php | 2 +- www/plugins-dist/breves/base/breves.php | 2 +- .../breves/breves_administrations.php | 2 +- www/plugins-dist/breves/breves_autoriser.php | 2 +- www/plugins-dist/breves/breves_pipelines.php | 2 +- .../breves/formulaires/configurer_breves.php | 2 +- .../breves/formulaires/editer_breve.php | 2 +- .../prive/squelettes/contenu/breves.html | 2 +- .../compresseur/compresseur_fonctions.php | 2 +- .../compresseur/compresseur_pipeline.php | 2 +- .../formulaires/configurer_compresseur.php | 2 +- .../compresseur/inc/compresseur.php | 2 +- .../inc/compresseur_concatener.php | 2 +- .../compresseur/inc/compresseur_embarquer.php | 2 +- .../compresseur/inc/compresseur_minifier.php | 9 +- .../class.JavaScriptPacker.php | 20 +- .../lib/csstidy/{README => README.md} | 22 +- .../compresseur/lib/csstidy/class.csstidy.php | 60 +- .../lib/csstidy/class.csstidy_optimise.php | 391 +- .../lib/csstidy/class.csstidy_print.php | 7 + .../compresseur/lib/csstidy/data.inc.php | 7 +- www/plugins-dist/compresseur/paquet.xml | 4 +- www/plugins-dist/dump/action/restaurer.php | 2 +- www/plugins-dist/dump/action/sauvegarder.php | 2 +- .../dump/action/supprimer_dump.php | 2 +- .../dump/action/telecharger_dump.php | 2 +- www/plugins-dist/dump/base/restaurer.php | 2 +- www/plugins-dist/dump/connect/dump.php | 2 +- www/plugins-dist/dump/dump_autoriser.php | 4 +- www/plugins-dist/dump/exec/base_restaurer.php | 2 +- .../dump/formulaires/restaurer.html | 2 +- .../dump/formulaires/restaurer.php | 2 +- .../dump/formulaires/sauvegarder.php | 2 +- www/plugins-dist/dump/inc/dump.php | 2 +- www/plugins-dist/dump/inc/sauvegarder.php | 2 +- www/plugins-dist/dump/paquet.xml | 2 +- .../contenu/restaurer_fonctions.php | 2 +- .../contenu/sauvegarder_fonctions.php | 2 +- .../filtres_images/filtres/couleurs.php | 2 +- .../filtres_images/filtres/images_lib.php | 2 +- .../filtres/images_transforme.php | 2 +- .../filtres_images/filtres/images_typo.php | 2 +- .../filtres_images/images_fonctions.php | 2 +- .../forum/action/editer_forum.php | 2 +- .../forum/action/instituer_forum.php | 2 +- .../forum/action/instituer_lot_forum.php | 2 +- .../forum/balise/formulaire_forum.php | 2 +- .../forum/balise/formulaire_forum_prive.php | 2 +- www/plugins-dist/forum/base/forum.php | 2 +- .../formulaires/activer_forums_objet.php | 2 +- .../formulaires/configurer_forums_contenu.php | 2 +- .../configurer_forums_notifications.php | 2 +- .../configurer_forums_participants.php | 2 +- .../formulaires/configurer_forums_prives.php | 2 +- www/plugins-dist/forum/formulaires/forum.php | 2 +- .../forum/formulaires/forum_prive.php | 2 +- .../forum/forum_administrations.php | 2 +- www/plugins-dist/forum/forum_autoriser.php | 2 +- www/plugins-dist/forum/forum_fonctions.php | 2 +- www/plugins-dist/forum/forum_pipelines.php | 6 +- .../forum/inc/email_notification_forum.php | 2 +- www/plugins-dist/forum/inc/forum.php | 2 +- www/plugins-dist/forum/inc/forum_insert.php | 2 +- www/plugins-dist/forum/paquet.xml | 2 +- .../forum/prive/modeles/forum_fonctions.php | 2 +- www/plugins-dist/forum/public/forum.php | 2 +- .../forum/urls/generer_url_ecrire_forum.php | 2 +- .../forum/urls/generer_url_forum.php | 2 +- .../medias/action/acceder_document.php | 2 +- .../medias/action/ajouter_documents.php | 2 +- .../medias/action/changer_mode_document.php | 2 +- .../medias/action/copier_local.php | 2 +- .../action/desordonner_liens_documents.php | 2 +- .../medias/action/dissocier_document.php | 2 +- .../medias/action/editer_document.php | 2 +- .../medias/action/supprimer_document.php | 2 +- .../action/supprimer_tous_orphelins.php | 2 +- www/plugins-dist/medias/action/tourner.php | 2 +- .../action/verifier_documents_brises.php | 2 +- .../action/verifier_documents_liens.php | 2 +- www/plugins-dist/medias/base/medias.php | 2 +- www/plugins-dist/medias/base/typedoc.php | 2 +- .../formulaires/changer_fichier_document.php | 2 +- .../formulaires/configurer_documents.php | 2 +- .../medias/formulaires/editer_document.php | 2 +- .../medias/formulaires/illustrer_document.php | 2 +- .../formulaires/inc-upload_document.html | 7 +- .../medias/formulaires/joindre_document.php | 2 +- .../medias/inc/choisir_mode_document.php | 2 +- .../medias/inc/documenter_objet.php | 2 +- www/plugins-dist/medias/inc/documents.php | 2 +- www/plugins-dist/medias/inc/getdocument.php | 2 +- .../medias/inc/joindre_document.php | 8 +- .../medias/inc/marquer_doublons_doc.php | 2 +- .../medias/inc/renseigner_document.php | 2 +- .../inc/verifier_document_mode_image.php | 2 +- .../inc/verifier_document_mode_vignette.php | 2 +- www/plugins-dist/medias/inc/vignette.php | 2 +- .../medias/lib/getid3/extension.cache.dbm.php | 64 +- .../lib/getid3/extension.cache.mysql.php | 60 +- .../lib/getid3/extension.cache.mysqli.php | 65 +- .../lib/getid3/extension.cache.sqlite3.php | 183 +- .../medias/lib/getid3/getid3.lib.php | 595 +- www/plugins-dist/medias/lib/getid3/getid3.php | 486 +- .../medias/lib/getid3/module.archive.gzip.php | 48 +- .../medias/lib/getid3/module.archive.rar.php | 17 +- .../medias/lib/getid3/module.archive.szip.php | 18 +- .../medias/lib/getid3/module.archive.tar.php | 30 +- .../medias/lib/getid3/module.archive.zip.php | 64 +- .../lib/getid3/module.audio-video.asf.php | 103 +- .../lib/getid3/module.audio-video.bink.php | 21 +- .../lib/getid3/module.audio-video.flv.php | 211 +- .../getid3/module.audio-video.matroska.php | 139 +- .../lib/getid3/module.audio-video.mpeg.php | 117 +- .../lib/getid3/module.audio-video.nsv.php | 41 +- .../getid3/module.audio-video.quicktime.php | 2831 +- .../lib/getid3/module.audio-video.real.php | 27 +- .../lib/getid3/module.audio-video.riff.php | 156 +- .../lib/getid3/module.audio-video.swf.php | 13 +- .../lib/getid3/module.audio-video.ts.php | 24 +- .../medias/lib/getid3/module.audio.aa.php | 20 +- .../medias/lib/getid3/module.audio.aac.php | 49 +- .../medias/lib/getid3/module.audio.ac3.php | 129 +- .../medias/lib/getid3/module.audio.amr.php | 25 +- .../medias/lib/getid3/module.audio.au.php | 29 +- .../medias/lib/getid3/module.audio.avr.php | 14 +- .../medias/lib/getid3/module.audio.bonk.php | 22 +- .../medias/lib/getid3/module.audio.dsf.php | 20 +- .../medias/lib/getid3/module.audio.dss.php | 24 +- .../medias/lib/getid3/module.audio.dts.php | 75 +- .../medias/lib/getid3/module.audio.flac.php | 105 +- .../medias/lib/getid3/module.audio.la.php | 14 +- .../medias/lib/getid3/module.audio.lpac.php | 17 +- .../medias/lib/getid3/module.audio.midi.php | 32 +- .../medias/lib/getid3/module.audio.mod.php | 27 +- .../medias/lib/getid3/module.audio.monkey.php | 25 +- .../medias/lib/getid3/module.audio.mp3.php | 189 +- .../medias/lib/getid3/module.audio.mpc.php | 58 +- .../medias/lib/getid3/module.audio.ogg.php | 120 +- .../lib/getid3/module.audio.optimfrog.php | 59 +- .../medias/lib/getid3/module.audio.rkau.php | 22 +- .../lib/getid3/module.audio.shorten.php | 16 +- .../medias/lib/getid3/module.audio.tta.php | 14 +- .../medias/lib/getid3/module.audio.voc.php | 29 +- .../medias/lib/getid3/module.audio.vqf.php | 23 +- .../lib/getid3/module.audio.wavpack.php | 22 +- .../medias/lib/getid3/module.graphic.bmp.php | 42 +- .../medias/lib/getid3/module.graphic.efax.php | 18 +- .../medias/lib/getid3/module.graphic.gif.php | 207 +- .../medias/lib/getid3/module.graphic.jpg.php | 43 +- .../medias/lib/getid3/module.graphic.pcd.php | 28 +- .../medias/lib/getid3/module.graphic.png.php | 105 +- .../medias/lib/getid3/module.graphic.svg.php | 15 +- .../medias/lib/getid3/module.graphic.tiff.php | 276 +- .../medias/lib/getid3/module.misc.cue.php | 105 +- .../medias/lib/getid3/module.misc.exe.php | 18 +- .../medias/lib/getid3/module.misc.iso.php | 59 +- .../lib/getid3/module.misc.msoffice.php | 18 +- .../medias/lib/getid3/module.misc.par2.php | 14 +- .../medias/lib/getid3/module.misc.pdf.php | 14 +- .../medias/lib/getid3/module.tag.apetag.php | 48 +- .../medias/lib/getid3/module.tag.id3v1.php | 52 +- .../medias/lib/getid3/module.tag.id3v2.php | 187 +- .../medias/lib/getid3/module.tag.lyrics3.php | 43 +- .../medias/lib/getid3/module.tag.xmp.php | 38 +- .../medias/lib/getid3/write.apetag.php | 77 +- .../medias/lib/getid3/write.id3v1.php | 55 +- .../medias/lib/getid3/write.id3v2.php | 308 +- .../medias/lib/getid3/write.lyrics3.php | 43 +- .../medias/lib/getid3/write.metaflac.php | 106 +- www/plugins-dist/medias/lib/getid3/write.php | 247 +- .../medias/lib/getid3/write.real.php | 81 +- .../medias/lib/getid3/write.vorbiscomment.php | 47 +- .../medias/medias_administrations.php | 2 +- www/plugins-dist/medias/medias_autoriser.php | 2 +- www/plugins-dist/medias/medias_fonctions.php | 2 +- www/plugins-dist/medias/medias_pipelines.php | 8 +- www/plugins-dist/medias/metadata/audio.php | 1 - www/plugins-dist/medias/metadata/html.php | 2 +- www/plugins-dist/medias/metadata/image.php | 2 +- www/plugins-dist/medias/metadata/svg.php | 2 +- www/plugins-dist/medias/metadata/swf.php | 2 +- .../modeles/document_case_fonctions.php | 4 +- .../medias/modeles/document_desc.html | 4 +- www/plugins-dist/medias/modeles/video.html | 6 +- www/plugins-dist/medias/paquet.xml | 2 +- .../inclure/ajouter-documents_fonctions.php | 2 +- .../mediatheque-navigation_fonctions.php | 2 +- .../inclure/portfolio-documents.html | 6 +- .../medias/puce_statut/document.php | 2 +- .../medias/urls/generer_url_document.php | 2 +- .../urls/generer_url_ecrire_document.php | 2 +- .../mots/action/editer_groupe_mots.php | 2 +- www/plugins-dist/mots/action/editer_mot.php | 2 +- .../mots/action/supprimer_groupe_mots.php | 2 +- .../mots/action/supprimer_mot.php | 2 +- www/plugins-dist/mots/base/mots.php | 2 +- .../mots/formulaires/configurer_mots.php | 2 +- .../mots/formulaires/editer_groupe_mot.php | 2 +- .../mots/formulaires/editer_mot.php | 2 +- www/plugins-dist/mots/inc/mots.php | 2 +- .../mots/mots_administrations.php | 2 +- www/plugins-dist/mots/mots_autoriser.php | 2 +- www/plugins-dist/mots/mots_pipelines.php | 2 +- www/plugins-dist/mots/paquet.xml | 2 +- .../mots/prive/objets/infos/mot_fonctions.php | 2 +- .../objets/liste/mots-admin_fonctions.php | 2 +- .../objets/liste/mots_associer-recherche.html | 4 +- .../prive/objets/liste/mots_associer.html | 4 +- .../prive/squelettes/contenu/groupe_mots.html | 6 +- .../mots/prive/squelettes/contenu/mots.html | 2 +- www/plugins-dist/mots/puce_statut/mot.php | 2 +- .../organiseur/action/effacer_messagerecu.php | 2 +- .../organiseur/action/envoyer_message.php | 2 +- .../organiseur/action/quete_autocomplete.php | 2 +- .../action/quete_calendrier_prive.php | 2 +- .../organiseur/action/supprimer_message.php | 2 +- .../organiseur/base/organiseur.php | 2 +- .../configurer_messagerie_agenda.php | 2 +- .../organiseur/formulaires/editer_message.php | 2 +- .../organiseur/inc/date_gestion.php | 2 +- www/plugins-dist/organiseur/inc/messages.php | 2 +- .../organiseur/inc/quete_calendrier.php | 2 +- .../lib/fullcalendar/fullcalendar.css | 1593 +- .../lib/fullcalendar/fullcalendar.js | 32843 +++++++--------- .../lib/fullcalendar/fullcalendar.min.css | 6 +- .../lib/fullcalendar/fullcalendar.min.js | 17 +- .../lib/fullcalendar/fullcalendar.print.css | 156 +- .../fullcalendar/fullcalendar.print.min.css | 8 +- .../organiseur/lib/fullcalendar/gcal.js | 600 +- .../organiseur/lib/fullcalendar/gcal.min.js | 6 +- .../organiseur/lib/fullcalendar/locale-all.js | 11 +- .../organiseur/lib/fullcalendar/locale/af.js | 2 +- .../lib/fullcalendar/locale/ar-dz.js | 2 +- .../lib/fullcalendar/locale/ar-kw.js | 2 +- .../lib/fullcalendar/locale/ar-ly.js | 2 +- .../lib/fullcalendar/locale/ar-ma.js | 2 +- .../lib/fullcalendar/locale/ar-sa.js | 2 +- .../lib/fullcalendar/locale/ar-tn.js | 2 +- .../organiseur/lib/fullcalendar/locale/ar.js | 2 +- .../organiseur/lib/fullcalendar/locale/bg.js | 2 +- .../organiseur/lib/fullcalendar/locale/bs.js | 1 + .../organiseur/lib/fullcalendar/locale/ca.js | 2 +- .../organiseur/lib/fullcalendar/locale/cs.js | 2 +- .../organiseur/lib/fullcalendar/locale/da.js | 2 +- .../lib/fullcalendar/locale/de-at.js | 2 +- .../lib/fullcalendar/locale/de-ch.js | 2 +- .../organiseur/lib/fullcalendar/locale/de.js | 2 +- .../organiseur/lib/fullcalendar/locale/el.js | 2 +- .../lib/fullcalendar/locale/en-au.js | 2 +- .../lib/fullcalendar/locale/en-ca.js | 2 +- .../lib/fullcalendar/locale/en-gb.js | 2 +- .../lib/fullcalendar/locale/en-ie.js | 2 +- .../lib/fullcalendar/locale/en-nz.js | 2 +- .../lib/fullcalendar/locale/es-do.js | 2 +- .../lib/fullcalendar/locale/es-us.js | 1 + .../organiseur/lib/fullcalendar/locale/es.js | 2 +- .../organiseur/lib/fullcalendar/locale/et.js | 2 +- .../organiseur/lib/fullcalendar/locale/eu.js | 2 +- .../organiseur/lib/fullcalendar/locale/fa.js | 2 +- .../organiseur/lib/fullcalendar/locale/fi.js | 2 +- .../lib/fullcalendar/locale/fr-ca.js | 2 +- .../lib/fullcalendar/locale/fr-ch.js | 2 +- .../organiseur/lib/fullcalendar/locale/fr.js | 2 +- .../organiseur/lib/fullcalendar/locale/gl.js | 2 +- .../organiseur/lib/fullcalendar/locale/he.js | 2 +- .../organiseur/lib/fullcalendar/locale/hi.js | 2 +- .../organiseur/lib/fullcalendar/locale/hr.js | 2 +- .../organiseur/lib/fullcalendar/locale/hu.js | 2 +- .../organiseur/lib/fullcalendar/locale/id.js | 2 +- .../organiseur/lib/fullcalendar/locale/is.js | 2 +- .../organiseur/lib/fullcalendar/locale/it.js | 2 +- .../organiseur/lib/fullcalendar/locale/ja.js | 2 +- .../organiseur/lib/fullcalendar/locale/ka.js | 1 + .../organiseur/lib/fullcalendar/locale/kk.js | 2 +- .../organiseur/lib/fullcalendar/locale/ko.js | 2 +- .../organiseur/lib/fullcalendar/locale/lb.js | 2 +- .../organiseur/lib/fullcalendar/locale/lt.js | 2 +- .../organiseur/lib/fullcalendar/locale/lv.js | 2 +- .../organiseur/lib/fullcalendar/locale/mk.js | 2 +- .../lib/fullcalendar/locale/ms-my.js | 2 +- .../organiseur/lib/fullcalendar/locale/ms.js | 2 +- .../organiseur/lib/fullcalendar/locale/nb.js | 2 +- .../lib/fullcalendar/locale/nl-be.js | 2 +- .../organiseur/lib/fullcalendar/locale/nl.js | 2 +- .../organiseur/lib/fullcalendar/locale/nn.js | 2 +- .../organiseur/lib/fullcalendar/locale/pl.js | 2 +- .../lib/fullcalendar/locale/pt-br.js | 2 +- .../organiseur/lib/fullcalendar/locale/pt.js | 2 +- .../organiseur/lib/fullcalendar/locale/ro.js | 2 +- .../organiseur/lib/fullcalendar/locale/ru.js | 2 +- .../organiseur/lib/fullcalendar/locale/sk.js | 2 +- .../organiseur/lib/fullcalendar/locale/sl.js | 2 +- .../organiseur/lib/fullcalendar/locale/sq.js | 1 + .../lib/fullcalendar/locale/sr-cyrl.js | 2 +- .../organiseur/lib/fullcalendar/locale/sr.js | 2 +- .../organiseur/lib/fullcalendar/locale/sv.js | 2 +- .../organiseur/lib/fullcalendar/locale/th.js | 2 +- .../organiseur/lib/fullcalendar/locale/tr.js | 2 +- .../organiseur/lib/fullcalendar/locale/uk.js | 2 +- .../organiseur/lib/fullcalendar/locale/vi.js | 2 +- .../lib/fullcalendar/locale/zh-cn.js | 2 +- .../lib/fullcalendar/locale/zh-tw.js | 2 +- .../lib/moment/moment-with-locales.js | 26292 +++++++------ .../lib/moment/moment-with-locales.min.js | 506 +- .../organiseur/lib/moment/moment.js | 7497 ++-- .../organiseur/lib/moment/moment.min.js | 8 +- .../notifications/instituermessage.php | 2 +- .../organiseur/organiseur_administrations.php | 2 +- .../organiseur/organiseur_autoriser.php | 2 +- .../organiseur/organiseur_fonctions.php | 2 +- .../organiseur/organiseur_pipelines.php | 2 +- www/plugins-dist/organiseur/paquet.xml | 2 +- .../petitions/action/confirmer_signature.php | 2 +- .../petitions/action/editer_petition.php | 2 +- .../petitions/action/editer_signature.php | 2 +- .../petitions/action/relancer_signature.php | 2 +- .../petitions/action/supprimer_signature.php | 2 +- .../action/traiter_lot_signature.php | 2 +- .../petitions/action/valider_signature.php | 2 +- .../petitions/balise/formulaire_signature.php | 2 +- www/plugins-dist/petitions/base/petitions.php | 2 +- .../formulaires/activer_petition_article.php | 2 +- .../petitions/formulaires/signature.php | 2 +- .../petitions/petitions_administrations.php | 2 +- .../petitions/petitions_autoriser.php | 2 +- .../petitions/petitions_fonctions.php | 2 +- .../petitions/petitions_options.php | 2 +- .../petitions/petitions_pipelines.php | 2 +- .../porte_plume/javascript/jquery.markitup.js | 15 +- .../javascript/jquery.markitup_pour_spip.js | 22 +- www/plugins-dist/porte_plume/paquet.xml | 2 +- .../revisions/afficher_diff/champ.php | 2 +- .../revisions/afficher_diff/id_rubrique.php | 2 +- .../revisions/afficher_diff/jointure.php | 2 +- www/plugins-dist/revisions/base/revisions.php | 2 +- .../configurer_revisions_objets.php | 2 +- .../revisions/formulaires/reviser.php | 2 +- .../revisions/genie/optimiser_revisions.php | 2 +- www/plugins-dist/revisions/inc/diff.php | 2 +- www/plugins-dist/revisions/inc/revisions.php | 2 +- .../revisions/inc/revisions_autoriser.php | 2 +- .../revisions/inc/revisions_pipeline.php | 48 +- .../revisions/inc/suivi_versions.php | 2 +- www/plugins-dist/revisions/paquet.xml | 3 +- .../prive/rss/revisions_fonctions.php | 2 +- .../prive/squelettes/contenu/revision.html | 2 +- .../revisions/revisions_administrations.php | 2 +- .../revisions/revisions_autoriser.php | 4 +- www/plugins-dist/safehtml/inc/safehtml.php | 2 +- .../lib/safehtml/classes/safehtml.php | 372 +- .../safehtml/lib/safehtml/license.txt | 1 + .../safehtml/lib/safehtml/readme-SPIP.txt | 10 +- .../safehtml/lib/safehtml/readme.txt | 18 +- www/plugins-dist/safehtml/paquet.xml | 2 +- www/plugins-dist/sites/action/editer_site.php | 2 +- .../sites/action/exporter_bookmarks.php | 2 +- .../action/importer_bookmarks_netscape.php | 2 +- .../sites/action/importer_bookmarks_opml.php | 2 +- .../sites/action/instituer_syndic_article.php | 2 +- www/plugins-dist/sites/action/purger_site.php | 2 +- .../sites/action/syndiquer_site.php | 2 +- .../sites/balise/formulaire_site.php | 2 +- www/plugins-dist/sites/base/sites.php | 2 +- .../sites/formulaires/configurer_sites.php | 2 +- .../sites/formulaires/editer_site.php | 2 +- .../formulaires/editer_site_fonctions.php | 2 +- .../sites/formulaires/exporter_sites.php | 2 +- .../sites/formulaires/importer_sites.php | 2 +- .../formulaires/regler_moderation_site.php | 2 +- www/plugins-dist/sites/formulaires/site.php | 2 +- www/plugins-dist/sites/genie/syndic.php | 2 +- www/plugins-dist/sites/inc/site.php | 2 +- www/plugins-dist/sites/inc/syndic.php | 2 +- .../sites/liens/implicite_site.php | 2 +- .../liste/syndic_articles_fonctions.php | 2 +- www/plugins-dist/sites/puce_statut/site.php | 2 +- .../sites/sites_administrations.php | 2 +- www/plugins-dist/sites/sites_autoriser.php | 2 +- www/plugins-dist/sites/sites_fonctions.php | 2 +- www/plugins-dist/sites/sites_pipelines.php | 2 +- .../squelettes_par_rubrique_options.php | 2 +- .../action/statistiques_archiver.php | 2 +- .../statistiques/base/delete_referers.php | 2 +- .../statistiques/base/delete_stats.php | 2 +- www/plugins-dist/statistiques/base/stats.php | 2 +- .../statistiques/engines-list.txt | 37 + .../exec/base_delete_referers.php | 2 +- .../statistiques/exec/base_delete_stats.php | 2 +- .../formulaires/configurer_compteur.php | 2 +- .../statistiques/genie/popularites.php | 2 +- .../statistiques/genie/visites.php | 20 +- .../statistiques/inc/referenceurs.php | 4 +- .../statistiques/inc/statistiques.php | 2 +- .../inc/stats_referers_to_array.php | 2 +- .../inc/stats_visites_to_array.php | 2 +- www/plugins-dist/statistiques/paquet.xml | 2 +- .../contenu/stats_lang_fonctions.php | 2 +- .../squelettes/contenu/stats_referers.html | 4 +- .../contenu/stats_repartition_fonctions.php | 2 +- .../inclure/stats-visites-jours.html | 16 +- .../statistiques/prive/stats/visites.html | 17 +- .../prive/style_prive_plugin_stats.html | 13 +- .../statistiques/public/stats.php | 2 +- .../statistiques/stats_administrations.php | 2 +- www/plugins-dist/svp/action/editer_depot.php | 2 +- www/plugins-dist/svp/exec/admin_plugin.php | 6 +- www/plugins-dist/textwheel/inc/lien.php | 2 +- www/plugins-dist/textwheel/inc/notes.php | 2 +- www/plugins-dist/textwheel/inc/texte.php | 14 +- www/plugins-dist/textwheel/inc/textwheel.php | 2 +- www/plugins-dist/textwheel/paquet.xml | 2 +- www/plugins-dist/textwheel/typographie/en.php | 2 +- www/plugins-dist/textwheel/typographie/fr.php | 2 +- .../urls_etendues/action/editer_url.php | 2 +- .../urls_etendues/action/supprimer_url.php | 2 +- .../urls_etendues/action/urls_actualiser.php | 2 +- www/plugins-dist/urls_etendues/base/urls.php | 3 +- .../formulaires/configurer_urls.php | 2 +- .../formulaires/editer_url_objet.php | 2 +- www/plugins-dist/urls_etendues/paquet.xml | 4 +- .../squelettes/navigation/controler_urls.html | 2 +- www/plugins-dist/urls_etendues/urls/arbo.php | 2 +- www/plugins-dist/urls_etendues/urls/html.php | 2 +- .../urls_etendues/urls/libres.php | 2 +- .../urls_etendues/urls/propres.php | 2 +- .../urls_etendues/urls/propres2.php | 2 +- .../urls_etendues/urls/propres_qs.php | 2 +- .../urls_etendues/urls/simple.php | 2 +- .../urls_etendues/urls_administrations.php | 6 +- .../urls_etendues/urls_pipeline.php | 2 +- .../vertebres/public/vertebrer.php | 2 +- .../vertebres/vertebres_pipelines.php | 2 +- .../formulaires/ecrire_auteur.php | 2 +- .../formulaires/inscription.php | 2 +- .../formulaires/mot_de_passe.php | 2 +- www/squelettes-dist/formulaires/oubli.php | 2 +- www/squelettes-dist/formulaires/recherche.php | 2 +- www/svn.revision | 12 +- 444 files changed, 40931 insertions(+), 39259 deletions(-) rename www/plugins-dist/compresseur/lib/csstidy/{README => README.md} (74%) create mode 100644 www/plugins-dist/organiseur/lib/fullcalendar/locale/bs.js create mode 100644 www/plugins-dist/organiseur/lib/fullcalendar/locale/es-us.js create mode 100644 www/plugins-dist/organiseur/lib/fullcalendar/locale/ka.js create mode 100644 www/plugins-dist/organiseur/lib/fullcalendar/locale/sq.js diff --git a/www/CHANGELOG.TXT b/www/CHANGELOG.TXT index 19e94a9d..c3839e37 100644 --- a/www/CHANGELOG.TXT +++ b/www/CHANGELOG.TXT @@ -1,3 +1,7 @@ +SPIP-Core spip-3.2.2 -> spip-3.2.3 21 janvier 2019 +------------------------------------------------------------- +Oups : problème de génération du zip + SPIP-Core spip-3.2.1 -> spip-3.2.2 18 janvier 2019 ------------------------------------------------------------- diff --git a/www/ecrire/inc_version.php b/www/ecrire/inc_version.php index 97c06f18..16a24979 100644 --- a/www/ecrire/inc_version.php +++ b/www/ecrire/inc_version.php @@ -372,7 +372,7 @@ $liste_des_authentifications = array( // pour specifier les versions de SPIP necessaires // il faut s'en tenir a un nombre de decimales fixe // ex : 2.0.0, 2.0.0-dev, 2.0.0-beta, 2.0.0-beta2 -$spip_version_branche = "3.2.2"; +$spip_version_branche = "3.2.3"; // cette version dev accepte tous les plugins compatible avec la version ci-dessous // a supprimer en phase beta/rc/release #define('_DEV_VERSION_SPIP_COMPAT',"3.1.3"); diff --git a/www/ecrire/paquet.xml b/www/ecrire/paquet.xml index dc8848e1..c9bfbcad 100644 --- a/www/ecrire/paquet.xml +++ b/www/ecrire/paquet.xml @@ -1,7 +1,7 @@ buffer = $escapeChar; return preg_replace_callback( '/\\' . $escapeChar . '(.)' .'/', array(&$this, '_escapeBis'), @@ -737,16 +736,15 @@ class ParseMaster { } // https://code.spip.net/@_escapeBis function _escapeBis($match) { - $this->_escaped[] = $match[1]; - return $this->buffer; + $this->_escaped[] = $match[0]; + return "@@@@AVECDELACROUTE".(count($this->_escaped)-1)."@@@@"; } // decode escaped characters // https://code.spip.net/@_unescape function _unescape($string, $escapeChar) { if ($escapeChar) { - $regexp = '/'.'\\'.$escapeChar.'/'; - $this->buffer = array('escapeChar'=> $escapeChar, 'i' => 0); + $regexp = '/@@@@AVECDELACROUTE(\d+)@@@@/'; return preg_replace_callback ( $regexp, @@ -759,16 +757,8 @@ class ParseMaster { } } // https://code.spip.net/@_unescapeBis - function _unescapeBis() { - if (isset($this->_escaped[$this->buffer['i']]) - && $this->_escaped[$this->buffer['i']] != '') - { - $temp = $this->_escaped[$this->buffer['i']]; - } else { - $temp = ''; - } - $this->buffer['i']++; - return $this->buffer['escapeChar'] . $temp; + function _unescapeBis($r) { + return $this->_escaped[$r[1]]; } // https://code.spip.net/@_internalEscape diff --git a/www/plugins-dist/compresseur/lib/csstidy/README b/www/plugins-dist/compresseur/lib/csstidy/README.md similarity index 74% rename from www/plugins-dist/compresseur/lib/csstidy/README rename to www/plugins-dist/compresseur/lib/csstidy/README.md index b4405fdd..45ca70a9 100644 --- a/www/plugins-dist/compresseur/lib/csstidy/README +++ b/www/plugins-dist/compresseur/lib/csstidy/README.md @@ -1,18 +1,20 @@ -CSSTidy ---- +# CSSTidy [![Build Status](https://travis-ci.org/Cerdic/CSSTidy.svg?branch=master)](https://travis-ci.org/Cerdic/CSSTidy) CSSTidy is a CSS minifier -v1.5.6 +* v1.6.4 : + preserve important comments (starting with !) in the minification /*! Credits/Licence */ +* v1.6.3 : + border-radius shorthands optimisation, reverse_left_and_right option +* v1.5.7 : + PHP 7 compatibility, composer update, Travis CI integration +* v1.5.6 : fixes minor bugs, mainly on CSS3 properties/units - -v1.5.2 +* 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 - -v1.3 branch corresponds to the last stable relase published by the author. +* v1.4 : 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.
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 here is the import of https://csstidy.svn.sourceforge.net/svnroot/csstidy on 2010-11-14 @@ -21,7 +23,7 @@ Only PHP version is here maintained --- -CSSTidy +## CSSTidy Original Tracker : http://sourceforge.net/tracker/?group_id=148404&atid=771415 diff --git a/www/plugins-dist/compresseur/lib/csstidy/class.csstidy.php b/www/plugins-dist/compresseur/lib/csstidy/class.csstidy.php index 4410da71..3520279b 100644 --- a/www/plugins-dist/compresseur/lib/csstidy/class.csstidy.php +++ b/www/plugins-dist/compresseur/lib/csstidy/class.csstidy.php @@ -61,19 +61,20 @@ if (!function_exists('ctype_xdigit')){ * Defines constants * @todo //TODO: make them class constants of csstidy */ -define('AT_START', 1); -define('AT_END', 2); -define('SEL_START', 3); -define('SEL_END', 4); -define('PROPERTY', 5); -define('VALUE', 6); -define('COMMENT', 7); -define('DEFAULT_AT', 41); +define('AT_START', 1); +define('AT_END', 2); +define('SEL_START', 3); +define('SEL_END', 4); +define('PROPERTY', 5); +define('VALUE', 6); +define('COMMENT', 7); +define('IMPORTANT_COMMENT',8); +define('DEFAULT_AT', 41); /** * Contains a class for printing CSS code * - * @version 1.0 + * @version 1.1.0 */ require('class.csstidy_print.php'); @@ -94,7 +95,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.5.6 + * @version 1.6.4 */ class csstidy { @@ -147,7 +148,7 @@ class csstidy { * @var string * @access private */ - public $version = '1.5.6'; + public $version = '1.6.4'; /** * Stores the settings * @var array @@ -318,6 +319,10 @@ class csstidy { /* is dangeroues to be used: CSS is broken sometimes */ $this->settings['merge_selectors'] = 0; /* preserve or not browser hacks */ + + /* Useful to produce a rtl css from a ltr one (or the opposite) */ + $this->settings['reverse_left_and_right'] = 0; + $this->settings['discard_invalid_selectors'] = false; $this->settings['discard_invalid_properties'] = false; $this->settings['css_level'] = 'CSS3.0'; @@ -411,7 +416,7 @@ class csstidy { */ public function _add_token($type, $data, $do = false) { if ($this->get_cfg('preserve_css') || $do) { - $this->tokens[] = array($type, ($type == COMMENT) ? $data : trim($data)); + $this->tokens[] = array($type, ($type == COMMENT or $type == IMPORTANT_COMMENT) ? $data : trim($data)); } } @@ -947,7 +952,13 @@ class csstidy { if ($string{$i} === '*' && $string{$i + 1} === '/') { $this->status = array_pop($this->from); $i++; - $this->_add_token(COMMENT, $cur_comment); + if (strlen($cur_comment) > 1 and strncmp($cur_comment, '!', 1) === 0) { + $this->_add_token(IMPORTANT_COMMENT, $cur_comment); + $this->css_add_important_comment($cur_comment); + } + else { + $this->_add_token(COMMENT, $cur_comment); + } $cur_comment = ''; } else { $cur_comment .= $string{$i}; @@ -1036,6 +1047,25 @@ class csstidy { return!(@($string{$pos - 1} !== '\\') || csstidy::escaped($string, $pos - 1)); } + + /** + * Add an important comment to the css code + * (one we want to keep) + * @param $comment + */ + public function css_add_important_comment($comment) { + if ($this->get_cfg('preserve_css') || trim($comment) == '') { + return; + } + if (!isset($this->css['!'])) { + $this->css['!'] = ''; + } + else { + $this->css['!'] .= "\n"; + } + $this->css['!'] .= $comment; + } + /** * Adds a property with value to the existing CSS code * @param string $media @@ -1080,7 +1110,7 @@ class csstidy { return $media; } end($this->css); - list($at,) = each($this->css); + $at = key($this->css); if ($at == $media) { return $media; } @@ -1119,7 +1149,7 @@ class csstidy { // if last is the same, keep it end($this->css[$media]); - list($sel,) = each($this->css[$media]); + $sel = key($this->css[$media]); if ($sel == $selector) { return $selector; } diff --git a/www/plugins-dist/compresseur/lib/csstidy/class.csstidy_optimise.php b/www/plugins-dist/compresseur/lib/csstidy/class.csstidy_optimise.php index bfa83729..49724369 100644 --- a/www/plugins-dist/compresseur/lib/csstidy/class.csstidy_optimise.php +++ b/www/plugins-dist/compresseur/lib/csstidy/class.csstidy_optimise.php @@ -70,40 +70,60 @@ class csstidy_optimise { * @version 1.0 */ public function postparse() { + + if ($this->parser->get_cfg('reverse_left_and_right') > 0) { + + foreach ($this->css as $medium => $selectors) { + if (is_array($selectors)) { + foreach ($selectors as $selector => $properties) { + $this->css[$medium][$selector] = $this->reverse_left_and_right($this->css[$medium][$selector]); + } + } + } + + } + if ($this->parser->get_cfg('preserve_css')) { return; } if ((int)$this->parser->get_cfg('merge_selectors') === 2) { foreach ($this->css as $medium => $value) { - $this->merge_selectors($this->css[$medium]); + if (is_array($value)) { + $this->merge_selectors($this->css[$medium]); + } } } if ($this->parser->get_cfg('discard_invalid_selectors')) { foreach ($this->css as $medium => $value) { - $this->discard_invalid_selectors($this->css[$medium]); + if (is_array($value)) { + $this->discard_invalid_selectors($this->css[$medium]); + } } } if ($this->parser->get_cfg('optimise_shorthands') > 0) { foreach ($this->css as $medium => $value) { - foreach ($value as $selector => $value1) { - $this->css[$medium][$selector] = $this->merge_4value_shorthands($this->css[$medium][$selector]); + if (is_array($value)) { + foreach ($value as $selector => $value1) { + $this->css[$medium][$selector] = $this->merge_4value_shorthands($this->css[$medium][$selector]); + $this->css[$medium][$selector] = $this->merge_4value_radius_shorthands($this->css[$medium][$selector]); - if ($this->parser->get_cfg('optimise_shorthands') < 2) { - continue; - } + if ($this->parser->get_cfg('optimise_shorthands') < 2) { + continue; + } - $this->css[$medium][$selector] = $this->merge_font($this->css[$medium][$selector]); + $this->css[$medium][$selector] = $this->merge_font($this->css[$medium][$selector]); - if ($this->parser->get_cfg('optimise_shorthands') < 3) { - continue; - } + if ($this->parser->get_cfg('optimise_shorthands') < 3) { + continue; + } - $this->css[$medium][$selector] = $this->merge_bg($this->css[$medium][$selector]); - if (empty($this->css[$medium][$selector])) { - unset($this->css[$medium][$selector]); + $this->css[$medium][$selector] = $this->merge_bg($this->css[$medium][$selector]); + if (empty($this->css[$medium][$selector])) { + unset($this->css[$medium][$selector]); + } } } } @@ -525,12 +545,15 @@ class csstidy_optimise { * Dissolves properties like padding:10px 10px 10px to padding-top:10px;padding-bottom:10px;... * @param string $property * @param string $value + * @param array|null $shorthands * @return array * @version 1.0 * @see merge_4value_shorthands() */ - public function dissolve_4value_shorthands($property, $value) { - $shorthands = & $this->parser->data['csstidy']['shorthands']; + public function dissolve_4value_shorthands($property, $value, $shorthands = null) { + if (is_null($shorthands)) { + $shorthands = & $this->parser->data['csstidy']['shorthands']; + } if (!is_array($shorthands[$property])) { $return[$property] = $value; return $return; @@ -567,25 +590,66 @@ class csstidy_optimise { return $return; } + /** + * Dissolves radius properties like + * border-radius:10px 10px 10px / 1px 2px + * to border-top-left:10px 1px;border-top-right:10px 2x;... + * @param string $property + * @param string $value + * @return array + * @version 1.0 + * @use dissolve_4value_shorthands() + * @see merge_4value_radius_shorthands() + */ + public function dissolve_4value_radius_shorthands($property, $value) { + $shorthands = & $this->parser->data['csstidy']['radius_shorthands']; + if (!is_array($shorthands[$property])) { + $return[$property] = $value; + return $return; + } + + if (strpos($value, '/') !== false) { + $values = $this->explode_ws('/', $value); + if (count($values) == 2) { + $r[0] = $this->dissolve_4value_shorthands($property, trim($values[0]), $shorthands); + $r[1] = $this->dissolve_4value_shorthands($property, trim($values[1]), $shorthands); + $return = array(); + foreach ($r[0] as $p=>$v) { + $return[$p] = $v; + if ($r[1][$p] !== $v) { + $return[$p] .= ' ' . $r[1][$p]; + } + } + return $return; + } + } + + $return = $this->dissolve_4value_shorthands($property, $value, $shorthands); + return $return; + } + /** * Explodes a string as explode() does, however, not if $sep is escaped or within a string. * @param string $sep seperator * @param string $string + * @param bool $explode_in_parenthesis * @return array * @version 1.0 */ - public function explode_ws($sep, $string) { + public function explode_ws($sep, $string, $explode_in_parenthesis = false) { $status = 'st'; $to = ''; - $output = array(); + $output = array( + 0 => '', + ); $num = 0; for ($i = 0, $len = strlen($string); $i < $len; $i++) { switch ($status) { case 'st': if ($string{$i} == $sep && !$this->parser->escaped($string, $i)) { ++$num; - } elseif ($string{$i} === '"' || $string{$i} === '\'' || $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}; @@ -603,27 +667,26 @@ class csstidy_optimise { } } - if (isset($output[0])) { - return $output; - } else { - return array($output); - } + return $output; } /** * Merges Shorthand properties again, the opposite of dissolve_4value_shorthands() * @param array $array + * @param array|null $shorthands * @return array * @version 1.2 * @see dissolve_4value_shorthands() */ - public function merge_4value_shorthands($array) { + public function merge_4value_shorthands($array, $shorthands = null) { $return = $array; - $shorthands = & $this->parser->data['csstidy']['shorthands']; + if (is_null($shorthands)) { + $shorthands = & $this->parser->data['csstidy']['shorthands']; + } foreach ($shorthands as $key => $value) { - if (isset($array[$value[0]]) && isset($array[$value[1]]) - && isset($array[$value[2]]) && isset($array[$value[3]]) && $value !== 0) { + if ($value !== 0 && isset($array[$value[0]]) && isset($array[$value[1]]) + && isset($array[$value[2]]) && isset($array[$value[3]])) { $return[$key] = ''; $important = ''; @@ -643,6 +706,45 @@ class csstidy_optimise { return $return; } + /** + * Merges Shorthand properties again, the opposite of dissolve_4value_shorthands() + * @param array $array + * @return array + * @version 1.2 + * @use merge_4value_shorthands() + * @see dissolve_4value_radius_shorthands() + */ + public function merge_4value_radius_shorthands($array) { + $return = $array; + $shorthands = & $this->parser->data['csstidy']['radius_shorthands']; + + foreach ($shorthands as $key => $value) { + if (isset($array[$value[0]]) && isset($array[$value[1]]) + && isset($array[$value[2]]) && isset($array[$value[3]]) && $value !== 0) { + $return[$key] = ''; + $a = array(); + for ($i = 0; $i < 4; $i++) { + $v = $this->explode_ws(' ', trim($array[$value[$i]])); + $a[0][$value[$i]] = reset($v); + $a[1][$value[$i]] = end($v); + } + $r = array(); + $r[0] = $this->merge_4value_shorthands($a[0], $shorthands); + $r[1] = $this->merge_4value_shorthands($a[1], $shorthands); + + if (isset($r[0][$key]) and isset($r[1][$key])) { + $return[$key] = $r[0][$key]; + if ($r[1][$key] !== $r[0][$key]) { + $return[$key] .= ' / ' . $r[1][$key]; + } + for ($i = 0; $i < 4; $i++) { + unset($return[$value[$i]]); + } + } + } + } + return $return; + } /** * Dissolve background property * @param string $str_value @@ -960,4 +1062,237 @@ class csstidy_optimise { return $input_css; } + /** + * Reverse left vs right in a list of properties/values + * @param array $array + * @return array + */ + public function reverse_left_and_right($array) { + $return = array(); + + // change left <-> right in properties name and values + foreach ($array as $propertie => $value) { + + if (method_exists($this, $m = 'reverse_left_and_right_' . str_replace('-','_',trim($propertie)))) { + $value = $this->$m($value); + } + + // simple replacement for properties + $propertie = str_ireplace(array('left', 'right' ,"\x1"), array("\x1", 'left', 'right') , $propertie); + // be careful for values, not modifying protected or quoted valued + foreach (array('left' => "\x1", 'right' => 'left', "\x1" => 'right') as $v => $r) { + if (strpos($value, $v) !== false) { + // attraper les left et right separes du reste (pas au milieu d'un mot) + if (in_array($v, array('left', 'right') )) { + $value = preg_replace(",\\b$v\\b,", "\x0" , $value); + } + else { + $value = str_replace($v, "\x0" , $value); + } + $value = $this->explode_ws("\x0", $value . ' ', true); + $value = rtrim(implode($r, $value)); + $value = str_replace("\x0" , $v, $value); + } + } + $return[$propertie] = $value; + } + + return $return; + } + + /** + * Reversing 4 values shorthands properties + * @param string $value + * @return string + */ + public function reverse_left_and_right_4value_shorthands($property, $value) { + $shorthands = & $this->parser->data['csstidy']['shorthands']; + if (isset($shorthands[$property])) { + $property_right = $shorthands[$property][1]; + $property_left = $shorthands[$property][3]; + $v = $this->dissolve_4value_shorthands($property, $value); + if ($v[$property_left] !== $v[$property_right]) { + $r = $v[$property_right]; + $v[$property_right] = $v[$property_left]; + $v[$property_left] = $r; + $v = $this->merge_4value_shorthands($v); + if (isset($v[$property])) { + return $v[$property]; + } + } + } + return $value; + } + + /** + * Reversing 4 values radius shorthands properties + * @param string $value + * @return string + */ + public function reverse_left_and_right_4value_radius_shorthands($property, $value) { + $shorthands = & $this->parser->data['csstidy']['radius_shorthands']; + if (isset($shorthands[$property])) { + $v = $this->dissolve_4value_radius_shorthands($property, $value); + if ($v[$shorthands[$property][0]] !== $v[$shorthands[$property][1]] + or $v[$shorthands[$property][2]] !== $v[$shorthands[$property][3]]) { + $r = array( + $shorthands[$property][0] => $v[$shorthands[$property][1]], + $shorthands[$property][1] => $v[$shorthands[$property][0]], + $shorthands[$property][2] => $v[$shorthands[$property][3]], + $shorthands[$property][3] => $v[$shorthands[$property][2]], + ); + $v = $this->merge_4value_radius_shorthands($r); + if (isset($v[$property])) { + return $v[$property]; + } + } + } + return $value; + } + + /** + * Reversing margin shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right_margin($value) { + return $this->reverse_left_and_right_4value_shorthands('margin', $value); + } + + /** + * Reversing padding shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right_padding($value) { + return $this->reverse_left_and_right_4value_shorthands('padding', $value); + } + + /** + * Reversing border-color shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right_border_color($value) { + return $this->reverse_left_and_right_4value_shorthands('border-color', $value); + } + + /** + * Reversing border-style shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right_border_style($value) { + return $this->reverse_left_and_right_4value_shorthands('border-style', $value); + } + + /** + * Reversing border-width shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right_border_width($value) { + return $this->reverse_left_and_right_4value_shorthands('border-width', $value); + } + + /** + * Reversing border-radius shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right_border_radius($value) { + return $this->reverse_left_and_right_4value_radius_shorthands('border-radius', $value); + } + + /** + * Reversing border-radius shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right__moz_border_radius($value) { + return $this->reverse_left_and_right_4value_radius_shorthands('border-radius', $value); + } + + /** + * Reversing border-radius shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right__webkit_border_radius($value) { + return $this->reverse_left_and_right_4value_radius_shorthands('border-radius', $value); + } + + + /** + * Reversing background shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right_background($value) { + $values = $this->dissolve_short_bg($value); + if (isset($values['background-position']) and $values['background-position']) { + $v = $this->reverse_left_and_right_background_position($values['background-position']); + if ($v !== $values['background-position']) { + if ($value == $values['background-position']) { + return $v; + } + else { + $values['background-position'] = $v; + $x = $this->merge_bg($values); + if (isset($x['background'])) { + return $x['background']; + } + } + } + } + return $value; + } + + /** + * Reversing background position shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right_background_position_x($value) { + return $this->reverse_left_and_right_background_position($value); + } + + /** + * Reversing background position shorthands + * @param string $value + * @return string + */ + public function reverse_left_and_right_background_position($value) { + // multiple background case + if (strpos($value, ',') !== false) { + $values = $this->explode_ws(',', $value); + if (count($values) > 1) { + foreach ($values as $k=>$v) { + $values[$k] = $this->reverse_left_and_right_background_position($v); + } + return implode(',', $values); + } + } + + // if no explicit left or right value + 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_values($values); + if (count($values) == 1) { + return "left $value"; + } + if ($values[1] == 'top' or $values[1] == 'bottom') { + return 'left ' . implode(' ', $values); + } + else { + $last = array_pop($values); + return implode(' ', $values) . ' left ' . $last; + } + } + + return $value; + } + } diff --git a/www/plugins-dist/compresseur/lib/csstidy/class.csstidy_print.php b/www/plugins-dist/compresseur/lib/csstidy/class.csstidy_print.php index 762b26ee..f4ea07c7 100644 --- a/www/plugins-dist/compresseur/lib/csstidy/class.csstidy_print.php +++ b/www/plugins-dist/compresseur/lib/csstidy/class.csstidy_print.php @@ -269,6 +269,7 @@ class csstidy_print { $in_at_out = ''; break; + case IMPORTANT_COMMENT: case COMMENT: $out .= $template[11] . '/*' . $this->_htmlsp($token[1], $plain) . '*/' . $template[12]; break; @@ -319,6 +320,12 @@ class csstidy_print { $sort_selectors = $this->parser->get_cfg('sort_selectors'); $sort_properties = $this->parser->get_cfg('sort_properties'); + // important comment section ? + if (isset($this->css['!'])) { + $this->parser->_add_token(IMPORTANT_COMMENT, rtrim($this->css['!']), true); + unset($this->css['!']); + } + foreach ($this->css as $medium => $val) { if ($sort_selectors) ksort($val); diff --git a/www/plugins-dist/compresseur/lib/csstidy/data.inc.php b/www/plugins-dist/compresseur/lib/csstidy/data.inc.php index ec1322ed..5bbc2ae5 100644 --- a/www/plugins-dist/compresseur/lib/csstidy/data.inc.php +++ b/www/plugins-dist/compresseur/lib/csstidy/data.inc.php @@ -274,7 +274,10 @@ $data['csstidy']['shorthands']['border-style'] = array('border-top-style','borde $data['csstidy']['shorthands']['border-width'] = array('border-top-width','border-right-width','border-bottom-width','border-left-width'); $data['csstidy']['shorthands']['margin'] = array('margin-top','margin-right','margin-bottom','margin-left'); $data['csstidy']['shorthands']['padding'] = array('padding-top','padding-right','padding-bottom','padding-left'); -$data['csstidy']['shorthands']['-moz-border-radius'] = 0; + +$data['csstidy']['radius_shorthands']['border-radius'] = array('border-top-left-radius','border-top-right-radius','border-bottom-right-radius','border-bottom-left-radius'); +$data['csstidy']['radius_shorthands']['-webkit-border-radius'] = array('-webkit-border-top-left-radius','-webkit-border-top-right-radius','-webkit-border-bottom-right-radius','-webkit-border-bottom-left-radius'); +$data['csstidy']['radius_shorthands']['-moz-border-radius'] = array('-moz-border-radius-topleft','-moz-border-radius-topright','-moz-border-radius-bottomright','-moz-border-radius-bottomleft'); /** * All CSS Properties. Needed for csstidy::property_is_next() @@ -612,7 +615,7 @@ $data['csstidy']['predefined_templates']['high_compression'][] = "\n"; $data['csstidy']['predefined_templates']['high_compression'][] = "\n". '}'."\n".''; $data['csstidy']['predefined_templates']['high_compression'][] = ''; $data['csstidy']['predefined_templates']['high_compression'][] = ''; // before comment -$data['csstidy']['predefined_templates']['high_compression'][] = ''; // after comment +$data['csstidy']['predefined_templates']['high_compression'][] = ''."\n"; // after comment $data['csstidy']['predefined_templates']['high_compression'][] = "\n"; $data['csstidy']['predefined_templates']['highest_compression'][] = ''; diff --git a/www/plugins-dist/compresseur/paquet.xml b/www/plugins-dist/compresseur/paquet.xml index 99a5de7f..4bedc0fc 100644 --- a/www/plugins-dist/compresseur/paquet.xml +++ b/www/plugins-dist/compresseur/paquet.xml @@ -1,7 +1,7 @@ - \ No newline at end of file +
diff --git a/www/plugins-dist/dump/action/restaurer.php b/www/plugins-dist/dump/action/restaurer.php index 846bb37c..320aecc3 100644 --- a/www/plugins-dist/dump/action/restaurer.php +++ b/www/plugins-dist/dump/action/restaurer.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/dump/action/sauvegarder.php b/www/plugins-dist/dump/action/sauvegarder.php index fa7da2c9..04e8790a 100644 --- a/www/plugins-dist/dump/action/sauvegarder.php +++ b/www/plugins-dist/dump/action/sauvegarder.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/dump/action/supprimer_dump.php b/www/plugins-dist/dump/action/supprimer_dump.php index bc885ee8..87e2a5c8 100644 --- a/www/plugins-dist/dump/action/supprimer_dump.php +++ b/www/plugins-dist/dump/action/supprimer_dump.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/dump/action/telecharger_dump.php b/www/plugins-dist/dump/action/telecharger_dump.php index 749dc931..2b17a1c4 100644 --- a/www/plugins-dist/dump/action/telecharger_dump.php +++ b/www/plugins-dist/dump/action/telecharger_dump.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/dump/base/restaurer.php b/www/plugins-dist/dump/base/restaurer.php index c99a5ba2..f68d5ffc 100644 --- a/www/plugins-dist/dump/base/restaurer.php +++ b/www/plugins-dist/dump/base/restaurer.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/dump/connect/dump.php b/www/plugins-dist/dump/connect/dump.php index d3943afe..a4318a06 100644 --- a/www/plugins-dist/dump/connect/dump.php +++ b/www/plugins-dist/dump/connect/dump.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/dump/dump_autoriser.php b/www/plugins-dist/dump/dump_autoriser.php index d8211174..4dea71e6 100644 --- a/www/plugins-dist/dump/dump_autoriser.php +++ b/www/plugins-dist/dump/dump_autoriser.php @@ -1,9 +1,9 @@ - (#ENV{choisi}) - [<:bouton_changer:>] ] #SET{name,fichier}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}#SET{obli,obligatoire} diff --git a/www/plugins-dist/dump/formulaires/restaurer.php b/www/plugins-dist/dump/formulaires/restaurer.php index 0c192c3e..076aeae3 100644 --- a/www/plugins-dist/dump/formulaires/restaurer.php +++ b/www/plugins-dist/dump/formulaires/restaurer.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/dump/formulaires/sauvegarder.php b/www/plugins-dist/dump/formulaires/sauvegarder.php index f32226e7..5600c78d 100644 --- a/www/plugins-dist/dump/formulaires/sauvegarder.php +++ b/www/plugins-dist/dump/formulaires/sauvegarder.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/dump/inc/dump.php b/www/plugins-dist/dump/inc/dump.php index dbc0da42..6835a6fa 100644 --- a/www/plugins-dist/dump/inc/dump.php +++ b/www/plugins-dist/dump/inc/dump.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/dump/inc/sauvegarder.php b/www/plugins-dist/dump/inc/sauvegarder.php index 0aa09211..d5076c36 100644 --- a/www/plugins-dist/dump/inc/sauvegarder.php +++ b/www/plugins-dist/dump/inc/sauvegarder.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/dump/paquet.xml b/www/plugins-dist/dump/paquet.xml index af29be21..99e2502d 100644 --- a/www/plugins-dist/dump/paquet.xml +++ b/www/plugins-dist/dump/paquet.xml @@ -1,7 +1,7 @@ " . singulier_ou_pluriel($nb, "forum:info_1_message_forum", - "forum:info_nb_messages_forum") . ""; + $nb = '
' . singulier_ou_pluriel($nb, "forum:info_1_message_forum", + 'forum:info_nb_messages_forum') . '
'; if ($p = strpos($flux['data'], "")) { $flux['data'] = substr_replace($flux['data'], $nb, $p, 0); } diff --git a/www/plugins-dist/forum/inc/email_notification_forum.php b/www/plugins-dist/forum/inc/email_notification_forum.php index 16e27a62..41d2907f 100644 --- a/www/plugins-dist/forum/inc/email_notification_forum.php +++ b/www/plugins-dist/forum/inc/email_notification_forum.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/forum/inc/forum.php b/www/plugins-dist/forum/inc/forum.php index acd31ee1..27f675c5 100644 --- a/www/plugins-dist/forum/inc/forum.php +++ b/www/plugins-dist/forum/inc/forum.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/forum/inc/forum_insert.php b/www/plugins-dist/forum/inc/forum_insert.php index 2128c94d..f31ca311 100644 --- a/www/plugins-dist/forum/inc/forum_insert.php +++ b/www/plugins-dist/forum/inc/forum_insert.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/forum/paquet.xml b/www/plugins-dist/forum/paquet.xml index be195a24..0f8ee4da 100644 --- a/www/plugins-dist/forum/paquet.xml +++ b/www/plugins-dist/forum/paquet.xml @@ -1,7 +1,7 @@
- [(#SET{cpt,1})] <:medias:bouton_download_depuis:> - - [(#GET{cpt}|>{1}|oui) - [(#VAL{'|'})] - ] + [(#GET{methode_upload}|=={#CLE}|oui) #VALEUR{label_lien} ] [(#GET{methode_upload}|=={#CLE}|non) #VALEUR{label_lien} ] - [(#SET{cpt,#GET{cpt}|plus{1}})]

diff --git a/www/plugins-dist/medias/formulaires/joindre_document.php b/www/plugins-dist/medias/formulaires/joindre_document.php index 50243afa..de351ef6 100644 --- a/www/plugins-dist/medias/formulaires/joindre_document.php +++ b/www/plugins-dist/medias/formulaires/joindre_document.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/inc/choisir_mode_document.php b/www/plugins-dist/medias/inc/choisir_mode_document.php index e73457cf..528591d6 100644 --- a/www/plugins-dist/medias/inc/choisir_mode_document.php +++ b/www/plugins-dist/medias/inc/choisir_mode_document.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/inc/documenter_objet.php b/www/plugins-dist/medias/inc/documenter_objet.php index 7afe9f5e..eab6bdc5 100644 --- a/www/plugins-dist/medias/inc/documenter_objet.php +++ b/www/plugins-dist/medias/inc/documenter_objet.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/inc/documents.php b/www/plugins-dist/medias/inc/documents.php index 1cff6ade..9bfc5970 100644 --- a/www/plugins-dist/medias/inc/documents.php +++ b/www/plugins-dist/medias/inc/documents.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/inc/getdocument.php b/www/plugins-dist/medias/inc/getdocument.php index aa4d290c..cf54a711 100644 --- a/www/plugins-dist/medias/inc/getdocument.php +++ b/www/plugins-dist/medias/inc/getdocument.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/inc/joindre_document.php b/www/plugins-dist/medias/inc/joindre_document.php index 63324e78..51b2027a 100644 --- a/www/plugins-dist/medias/inc/joindre_document.php +++ b/www/plugins-dist/medias/inc/joindre_document.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * @@ -80,6 +80,10 @@ function joindre_trouver_fichier_envoye() { if (!strlen($path) or $path == 'http://') { return _T('medias:erreur_indiquez_un_fichier'); } + include_spip('inc/distant'); + if (!valider_url_distante($path)) { + return _T('medias:erreur_upload_type_interdit', array('nom' => $path)); + } include_spip('action/ajouter_documents'); $infos = renseigner_source_distante($path); if (!is_array($infos)) { @@ -306,7 +310,7 @@ function joindre_deballer_lister_zip($path, $tmp_dir) { $archive = new PclZip($path); $archive->extract( PCLZIP_OPT_PATH, - _TMP_DIR, + $tmp_dir, PCLZIP_CB_PRE_EXTRACT, 'callback_deballe_fichier' ); diff --git a/www/plugins-dist/medias/inc/marquer_doublons_doc.php b/www/plugins-dist/medias/inc/marquer_doublons_doc.php index 382166cb..fb690bcc 100644 --- a/www/plugins-dist/medias/inc/marquer_doublons_doc.php +++ b/www/plugins-dist/medias/inc/marquer_doublons_doc.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/inc/renseigner_document.php b/www/plugins-dist/medias/inc/renseigner_document.php index 8ab77f98..003fcf8e 100644 --- a/www/plugins-dist/medias/inc/renseigner_document.php +++ b/www/plugins-dist/medias/inc/renseigner_document.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/inc/verifier_document_mode_image.php b/www/plugins-dist/medias/inc/verifier_document_mode_image.php index 0023505a..1501157e 100644 --- a/www/plugins-dist/medias/inc/verifier_document_mode_image.php +++ b/www/plugins-dist/medias/inc/verifier_document_mode_image.php @@ -2,7 +2,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/inc/verifier_document_mode_vignette.php b/www/plugins-dist/medias/inc/verifier_document_mode_vignette.php index 44dc6f4e..cc8cd24d 100644 --- a/www/plugins-dist/medias/inc/verifier_document_mode_vignette.php +++ b/www/plugins-dist/medias/inc/verifier_document_mode_vignette.php @@ -2,7 +2,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/inc/vignette.php b/www/plugins-dist/medias/inc/vignette.php index 9e6a8222..2dd05749 100644 --- a/www/plugins-dist/medias/inc/vignette.php +++ b/www/plugins-dist/medias/inc/vignette.php @@ -2,7 +2,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/lib/getid3/extension.cache.dbm.php b/www/plugins-dist/medias/lib/getid3/extension.cache.dbm.php index a9332b92..2d72d955 100644 --- a/www/plugins-dist/medias/lib/getid3/extension.cache.dbm.php +++ b/www/plugins-dist/medias/lib/getid3/extension.cache.dbm.php @@ -1,10 +1,10 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // // // // extension.cache.dbm.php - part of getID3() // // Please see readme.txt for more information // @@ -72,8 +72,36 @@ class getID3_cached_dbm extends getID3 { - - // public: constructor - see top of this file for cache type and cache_options + /** + * @var resource + */ + private $dba; + + /** + * @var resource|bool + */ + private $lock; + + /** + * @var string + */ + private $cache_type; + + /** + * @var string + */ + private $dbm_filename; + + /** + * constructor - see top of this file for cache type and cache_options + * + * @param string $cache_type + * @param string $dbm_filename + * @param string $lock_filename + * + * @throws Exception + * @throws getid3_exception + */ public function __construct($cache_type, $dbm_filename, $lock_filename) { // Check for dba extension @@ -141,7 +169,9 @@ class getID3_cached_dbm extends getID3 - // public: destructor + /** + * destructor + */ public function __destruct() { // Close dbm file @@ -156,7 +186,11 @@ class getID3_cached_dbm extends getID3 - // public: clear cache + /** + * clear cache + * + * @throws Exception + */ public function clear_cache() { // Close dbm file @@ -178,8 +212,16 @@ class getID3_cached_dbm extends getID3 - // public: analyze file - public function analyze($filename) { + /** + * clear cache + * + * @param string $filename + * @param int $filesize + * @param string $original_filename + * + * @return mixed + */ + public function analyze($filename, $filesize=null, $original_filename='') { if (file_exists($filename)) { @@ -199,7 +241,7 @@ class getID3_cached_dbm extends getID3 $result = parent::analyze($filename); // Save result - if (file_exists($filename)) { + if (isset($key) && file_exists($filename)) { dba_insert($key, serialize($result), $this->dba); } diff --git a/www/plugins-dist/medias/lib/getid3/extension.cache.mysql.php b/www/plugins-dist/medias/lib/getid3/extension.cache.mysql.php index b572676a..2dd2b12a 100644 --- a/www/plugins-dist/medias/lib/getid3/extension.cache.mysql.php +++ b/www/plugins-dist/medias/lib/getid3/extension.cache.mysql.php @@ -1,10 +1,10 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // // // // extension.cache.mysql.php - part of getID3() // // Please see readme.txt for more information // @@ -73,13 +73,34 @@ class getID3_cached_mysql extends getID3 { - - // private vars + /** + * @var resource + */ private $cursor; - private $connection; + /** + * @var resource + */ + private $connection; - // public: constructor - see top of this file for cache type and cache_options + /** + * @var string + */ + private $table; + + + /** + * constructor - see top of this file for cache type and cache_options + * + * @param string $host + * @param string $database + * @param string $username + * @param string $password + * @param string $table + * + * @throws Exception + * @throws getid3_exception + */ public function __construct($host, $database, $username, $password, $table='getid3_cache') { // Check for mysql support @@ -124,7 +145,9 @@ class getID3_cached_mysql extends getID3 - // public: clear cache + /** + * clear cache + */ public function clear_cache() { $this->cursor = mysql_query('DELETE FROM `'.mysql_real_escape_string($this->table).'`', $this->connection); @@ -133,9 +156,18 @@ class getID3_cached_mysql extends getID3 - // public: analyze file + /** + * analyze file + * + * @param string $filename + * @param int $filesize + * @param string $original_filename + * + * @return mixed + */ public function analyze($filename, $filesize=null, $original_filename='') { + $filetime = 0; if (file_exists($filename)) { // Short-hands @@ -174,7 +206,11 @@ class getID3_cached_mysql extends getID3 - // private: (re)create sql table + /** + * (re)create sql table + * + * @param bool $drop + */ private function create_table($drop=false) { $SQLquery = 'CREATE TABLE IF NOT EXISTS `'.mysql_real_escape_string($this->table).'` ('; @@ -183,7 +219,7 @@ class getID3_cached_mysql extends getID3 $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`)) ENGINE=MyISAM CHARACTER SET=latin1 COLLATE=latin1_general_ci'; + $SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`))'; $this->cursor = mysql_query($SQLquery, $this->connection); echo mysql_error($this->connection); } diff --git a/www/plugins-dist/medias/lib/getid3/extension.cache.mysqli.php b/www/plugins-dist/medias/lib/getid3/extension.cache.mysqli.php index 3299caae..44ea694e 100644 --- a/www/plugins-dist/medias/lib/getid3/extension.cache.mysqli.php +++ b/www/plugins-dist/medias/lib/getid3/extension.cache.mysqli.php @@ -1,14 +1,14 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // // // -// extension.cache.mysqli.php - part of getID3() // +// extension.cache.mysqli.php - part of getID3() // // Please see readme.txt for more information // -// /// +// // ///////////////////////////////////////////////////////////////// // // // This extension written by Allan Hansen // @@ -72,12 +72,34 @@ class getID3_cached_mysqli extends getID3 { - // private vars + /** + * @var mysqli + */ private $mysqli; - private $cursor; + /** + * @var mysqli_result + */ + private $cursor; - // public: constructor - see top of this file for cache type and cache_options + /** + * @var string + */ + private $table; + + + /** + * constructor - see top of this file for cache type and cache_options + * + * @param string $host + * @param string $database + * @param string $username + * @param string $password + * @param string $table + * + * @throws Exception + * @throws getid3_exception + */ public function __construct($host, $database, $username, $password, $table='getid3_cache') { // Check for mysqli support @@ -121,16 +143,27 @@ class getID3_cached_mysqli extends getID3 } - // public: clear cache + /** + * 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.'\')'); } - // public: analyze file + /** + * analyze file + * + * @param string $filename + * @param int $filesize + * @param string $original_filename + * + * @return mixed + */ public function analyze($filename, $filesize=null, $original_filename='') { + $filetime = 0; if (file_exists($filename)) { // Short-hands @@ -168,7 +201,11 @@ class getID3_cached_mysqli extends getID3 } - // private: (re)create mysqli table + /** + * (re)create mysqli table + * + * @param bool $drop + */ private function create_table($drop=false) { $SQLquery = 'CREATE TABLE IF NOT EXISTS `'.$this->mysqli->real_escape_string($this->table).'` ('; $SQLquery .= '`filename` VARCHAR(990) NOT NULL DEFAULT \'\''; @@ -176,8 +213,8 @@ class getID3_cached_mysqli extends getID3 $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`)) ENGINE=MyISAM CHARACTER SET=latin1 COLLATE=latin1_general_ci'; + $SQLquery .= ', PRIMARY KEY (`filename`, `filesize`, `filetime`))'; $this->cursor = $this->mysqli->query($SQLquery); echo $this->mysqli->error; } -} \ No newline at end of file +} diff --git a/www/plugins-dist/medias/lib/getid3/extension.cache.sqlite3.php b/www/plugins-dist/medias/lib/getid3/extension.cache.sqlite3.php index 58d4dc88..9e4a8436 100644 --- a/www/plugins-dist/medias/lib/getid3/extension.cache.sqlite3.php +++ b/www/plugins-dist/medias/lib/getid3/extension.cache.sqlite3.php @@ -1,21 +1,27 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////////////////////// -/// // -// extension.cache.sqlite3.php - part of getID3() // -// Please see readme.txt for more information // -// /// -///////////////////////////////////////////////////////////////////////////////// -/// // -// MySQL extension written by Allan Hansen // -// Table name mod by Carlo Capocasa // -// MySQL extension was reworked for SQLite3 by Karl G. Holz // -// /// -///////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +/// getID3() by James Heinrich // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// // +// extension.cache.mysqli.php - part of getID3() // +// Please see readme.txt for more information // +// // +///////////////////////////////////////////////////////////////// +// // +// extension.cache.sqlite3.php - part of getID3() // +// Please see readme.txt for more information // +// // +///////////////////////////////////////////////////////////////// +/// // +// MySQL extension written by Allan Hansen // +// Table name mod by Carlo Capocasa // +// MySQL extension was reworked for SQLite3 by // +// Karl G. Holz // +// /// +///////////////////////////////////////////////////////////////// + /** * This is a caching extension for getID3(). It works the exact same * way as the getID3 class, but return cached information much faster @@ -89,14 +95,35 @@ * * */ -class getID3_cached_sqlite3 extends getID3 { +class getID3_cached_sqlite3 extends getID3 +{ + /** + * hold the sqlite db + * + * @var SQLite3 Resource + */ + private $db; /** - * __construct() - * @param string $table holds name of sqlite table - * @return type - */ + * table to use for caching + * + * @var string $table + */ + private $table; + + /** + * @param string $table holds name of sqlite table + * @param boolean $hide + * + * @throws getid3_exception + * @throws Exception + */ public function __construct($table='getid3_cache', $hide=false) { + // Check for SQLite3 support + if (!function_exists('sqlite_open')) { + throw new Exception('PHP not compiled with SQLite3 support.'); + } + $this->table = $table; // Set table $file = dirname(__FILE__).'/'.basename(__FILE__, 'php').'sqlite'; if ($hide) { @@ -106,7 +133,7 @@ class getID3_cached_sqlite3 extends getID3 { $db = $this->db; $this->create_table(); // Create cache table if not exists $version = ''; - $sql = $this->version_check; + $sql = $this->getQuery('version_check'); $stmt = $db->prepare($sql); $stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT); $result = $stmt->execute(); @@ -114,39 +141,27 @@ class getID3_cached_sqlite3 extends getID3 { if ($version != getID3::VERSION) { // Check version number and clear cache if changed $this->clear_cache(); } - return parent::__construct(); + parent::__construct(); } /** - * close the database connection - */ + * close the database connection + */ public function __destruct() { $db=$this->db; $db->close(); } /** - * hold the sqlite db - * @var SQLite Resource - */ - private $db; - - /** - * table to use for caching - * @var string $table - */ - private $table; - - /** - * clear the cache - * @access private - * @return type - */ + * clear the cache + * + * @return SQLite3Result + */ private function clear_cache() { $db = $this->db; - $sql = $this->delete_cache; + $sql = $this->getQuery('delete_cache'); $db->exec($sql); - $sql = $this->set_version; + $sql = $this->getQuery('set_version'); $stmt = $db->prepare($sql); $stmt->bindValue(':filename', getID3::VERSION, SQLITE3_TEXT); $stmt->bindValue(':dirname', getID3::VERSION, SQLITE3_TEXT); @@ -155,10 +170,14 @@ class getID3_cached_sqlite3 extends getID3 { } /** - * analyze file and cache them, if cached pull from the db - * @param type $filename - * @return boolean - */ + * analyze file and cache them, if cached pull from the db + * + * @param string $filename + * @param integer $filesize + * @param string $original_filename + * + * @return mixed|false + */ public function analyze($filename, $filesize=null, $original_filename='') { if (!file_exists($filename)) { return false; @@ -171,7 +190,7 @@ class getID3_cached_sqlite3 extends getID3 { $dirname = dirname($filename); // Lookup file $db = $this->db; - $sql = $this->get_id3_data; + $sql = $this->getQuery('get_id3_data'); $stmt = $db->prepare($sql); $stmt->bindValue(':filename', $filename, SQLITE3_TEXT); $stmt->bindValue(':filesize', $filesize_real, SQLITE3_INTEGER); @@ -184,7 +203,7 @@ class getID3_cached_sqlite3 extends getID3 { // if it hasn't been analyzed before, then do it now $analysis = parent::analyze($filename, $filesize, $original_filename); // Save result - $sql = $this->cache_file; + $sql = $this->getQuery('cache_file'); $stmt = $db->prepare($sql); $stmt->bindValue(':filename', $filename, SQLITE3_TEXT); $stmt->bindValue(':dirname', $dirname, SQLITE3_TEXT); @@ -197,30 +216,31 @@ class getID3_cached_sqlite3 extends getID3 { } /** - * create data base table - * this is almost the same as MySQL, with the exception of the dirname being added - * @return type - */ + * create data base table + * this is almost the same as MySQL, with the exception of the dirname being added + * + * @return bool + */ private function create_table() { $db = $this->db; - $sql = $this->make_table; + $sql = $this->getQuery('make_table'); return $db->exec($sql); } /** - * get cached directory - * - * This function is not in the MySQL extention, it's ment to speed up requesting multiple files - * which is ideal for podcasting, playlists, etc. - * - * @access public - * @param string $dir directory to search the cache database for - * @return array return an array of matching id3 data - */ + * get cached directory + * + * This function is not in the MySQL extention, it's ment to speed up requesting multiple files + * which is ideal for podcasting, playlists, etc. + * + * @param string $dir directory to search the cache database for + * + * @return array return an array of matching id3 data + */ public function get_cached_dir($dir) { $db = $this->db; $rows = array(); - $sql = $this->get_cached_dir; + $sql = $this->getQuery('get_cached_dir'); $stmt = $db->prepare($sql); $stmt->bindValue(':dirname', $dir, SQLITE3_TEXT); $res = $stmt->execute(); @@ -231,12 +251,15 @@ class getID3_cached_sqlite3 extends getID3 { } /** - * use the magical __get() for sql queries - * - * access as easy as $this->{case name}, returns NULL if query is not found - */ - public function __get($name) { - switch($name) { + * returns NULL if query is not found + * + * @param string $name + * + * @return null|string + */ + public function getQuery($name) + { + switch ($name) { case 'version_check': return "SELECT val FROM $this->table WHERE filename = :filename AND filesize = '-1' AND filetime = '-1' AND analyzetime = '-1'"; break; @@ -253,14 +276,28 @@ class getID3_cached_sqlite3 extends getID3 { 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) NOT NULL DEFAULT '', dirname VARCHAR(255) NOT NULL DEFAULT '', filesize INT(11) NOT NULL DEFAULT '0', filetime INT(11) NOT NULL DEFAULT '0', analyzetime INT(11) NOT NULL DEFAULT '0', val text not null, PRIMARY KEY (filename, filesize, filetime))"; 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; } - return null; + } + + /** + * use the magical __get() for sql queries + * + * access as easy as $this->{case name}, returns NULL if query is not found + * + * @param string $name + * + * @return string + * @deprecated use getQuery() instead + */ + public function __get($name) { + return $this->getQuery($name); } } diff --git a/www/plugins-dist/medias/lib/getid3/getid3.lib.php b/www/plugins-dist/medias/lib/getid3/getid3.lib.php index 808f5921..5c5a5dfa 100644 --- a/www/plugins-dist/medias/lib/getid3/getid3.lib.php +++ b/www/plugins-dist/medias/lib/getid3/getid3.lib.php @@ -1,20 +1,27 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // // // // getid3.lib.php - part of getID3() // -// See readme.txt for more details // +// see readme.txt for more details // // /// ///////////////////////////////////////////////////////////////// class getid3_lib { - + /** + * @param string $string + * @param bool $hex + * @param bool $spaces + * @param string $htmlencoding + * + * @return string + */ public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') { $returnstring = ''; for ($i = 0; $i < strlen($string); $i++) { @@ -36,9 +43,14 @@ class getid3_lib return $returnstring; } + /** + * Truncates a floating-point number at the decimal point. + * + * @param float $floatnumber + * + * @return float|int returns int (if possible, otherwise float) + */ public static function trunc($floatnumber) { - // truncates a floating-point number at the decimal point - // returns int (if possible, otherwise float) if ($floatnumber >= 1) { $truncatednumber = floor($floatnumber); } elseif ($floatnumber <= -1) { @@ -52,7 +64,12 @@ class getid3_lib return $truncatednumber; } - + /** + * @param int|null $variable + * @param int $increment + * + * @return bool + */ public static function safe_inc(&$variable, $increment=1) { if (isset($variable)) { $variable += $increment; @@ -62,6 +79,11 @@ class getid3_lib return true; } + /** + * @param int|float $floatnum + * + * @return int|float + */ public static function CastAsInt($floatnum) { // convert to float if not already $floatnum = (float) $floatnum; @@ -77,6 +99,11 @@ class getid3_lib return $floatnum; } + /** + * @param int $num + * + * @return bool + */ public static function intValueSupported($num) { // check if integers are 64-bit static $hasINT64 = null; @@ -93,21 +120,36 @@ class getid3_lib return false; } + /** + * @param string $fraction + * + * @return float + */ public static function DecimalizeFraction($fraction) { list($numerator, $denominator) = explode('/', $fraction); return $numerator / ($denominator ? $denominator : 1); } - + /** + * @param string $binarynumerator + * + * @return float + */ public static function DecimalBinary2Float($binarynumerator) { $numerator = self::Bin2Dec($binarynumerator); $denominator = self::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator))); return ($numerator / $denominator); } - + /** + * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html + * + * @param string $binarypointnumber + * @param int $maxbits + * + * @return array + */ public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) { - // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html if (strpos($binarypointnumber, '.') === false) { $binarypointnumber = '0.'.$binarypointnumber; } elseif ($binarypointnumber{0} == '.') { @@ -129,9 +171,14 @@ class getid3_lib return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent); } - + /** + * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html + * + * @param float $floatvalue + * + * @return string + */ public static function Float2BinaryDecimal($floatvalue) { - // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html $maxbits = 128; // to how many bits of precision should the calculations be taken? $intpart = self::trunc($floatvalue); $floatpart = abs($floatvalue - $intpart); @@ -145,9 +192,17 @@ class getid3_lib return $binarypointnumber; } - + /** + * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html + * + * @param float $floatvalue + * @param int $bits + * + * @return string|false + */ public static function Float2String($floatvalue, $bits) { - // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html + $exponentbits = 0; + $fractionbits = 0; switch ($bits) { case 32: $exponentbits = 8; @@ -176,22 +231,34 @@ class getid3_lib return self::BigEndian2String(self::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false); } - + /** + * @param string $byteword + * + * @return float|false + */ public static function LittleEndian2Float($byteword) { return self::BigEndian2Float(strrev($byteword)); } - + /** + * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic + * + * @link http://www.psc.edu/general/software/packages/ieee/ieee.html + * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html + * + * @param string $byteword + * + * @return float|false + */ public static function BigEndian2Float($byteword) { - // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic - // http://www.psc.edu/general/software/packages/ieee/ieee.html - // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html - $bitword = self::BigEndian2Bin($byteword); if (!$bitword) { return 0; } $signbit = $bitword{0}; + $floatvalue = 0; + $exponentbits = 0; + $fractionbits = 0; switch (strlen($byteword) * 8) { case 32: @@ -259,7 +326,14 @@ class getid3_lib return (float) $floatvalue; } - + /** + * @param string $byteword + * @param bool $synchsafe + * @param bool $signed + * + * @return int|float|false + * @throws Exception + */ public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) { $intvalue = 0; $bytewordlen = strlen($byteword); @@ -288,12 +362,30 @@ class getid3_lib return self::CastAsInt($intvalue); } - + /** + * @param string $byteword + * @param bool $signed + * + * @return int|float|false + */ public static function LittleEndian2Int($byteword, $signed=false) { return self::BigEndian2Int(strrev($byteword), false, $signed); } + /** + * @param string $byteword + * + * @return string + */ + public static function LittleEndian2Bin($byteword) { + return self::BigEndian2Bin(strrev($byteword)); + } + /** + * @param string $byteword + * + * @return string + */ public static function BigEndian2Bin($byteword) { $binvalue = ''; $bytewordlen = strlen($byteword); @@ -303,7 +395,15 @@ class getid3_lib return $binvalue; } - + /** + * @param int $number + * @param int $minbytes + * @param bool $synchsafe + * @param bool $signed + * + * @return string + * @throws Exception + */ public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) { if ($number < 0) { throw new Exception('ERROR: self::BigEndian2String() does not support negative numbers'); @@ -324,7 +424,11 @@ class getid3_lib return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT); } - + /** + * @param int $number + * + * @return string + */ public static function Dec2Bin($number) { while ($number >= 256) { $bytes[] = (($number / 256) - (floor($number / 256))) * 256; @@ -338,7 +442,12 @@ class getid3_lib return $binstring; } - + /** + * @param string $binstring + * @param bool $signed + * + * @return int|float + */ public static function Bin2Dec($binstring, $signed=false) { $signmult = 1; if ($signed) { @@ -354,7 +463,11 @@ class getid3_lib return self::CastAsInt($decvalue * $signmult); } - + /** + * @param string $binstring + * + * @return string + */ public static function Bin2String($binstring) { // return 'hi' for input of '0110100001101001' $string = ''; @@ -365,7 +478,13 @@ class getid3_lib return $string; } - + /** + * @param int $number + * @param int $minbytes + * @param bool $synchsafe + * + * @return string + */ public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) { $intstring = ''; while ($number > 0) { @@ -380,7 +499,12 @@ class getid3_lib return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT); } - + /** + * @param array $array1 + * @param array $array2 + * + * @return array|false + */ public static function array_merge_clobber($array1, $array2) { // written by kcØhireability*com // taken from http://www.php.net/manual/en/function.array-merge-recursive.php @@ -398,7 +522,12 @@ class getid3_lib return $newarray; } - + /** + * @param array $array1 + * @param array $array2 + * + * @return array|false + */ public static function array_merge_noclobber($array1, $array2) { if (!is_array($array1) || !is_array($array2)) { return false; @@ -414,6 +543,12 @@ class getid3_lib return $newarray; } + /** + * @param array $array1 + * @param array $array2 + * + * @return array|false|null + */ public static function flipped_array_merge_noclobber($array1, $array2) { if (!is_array($array1) || !is_array($array2)) { return false; @@ -428,7 +563,11 @@ class getid3_lib return array_flip($newarray); } - + /** + * @param array $theArray + * + * @return bool + */ public static function ksort_recursive(&$theArray) { ksort($theArray); foreach ($theArray as $key => $value) { @@ -439,6 +578,12 @@ class getid3_lib return true; } + /** + * @param string $filename + * @param int $numextensions + * + * @return string + */ public static function fileextension($filename, $numextensions=1) { if (strstr($filename, '.')) { $reversedfilename = strrev($filename); @@ -454,7 +599,11 @@ class getid3_lib return ''; } - + /** + * @param int $seconds + * + * @return string + */ public static function PlaytimeString($seconds) { $sign = (($seconds < 0) ? '-' : ''); $seconds = round(abs($seconds)); @@ -464,30 +613,53 @@ class getid3_lib return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT); } - + /** + * @param int $macdate + * + * @return int|float + */ public static function DateMac2Unix($macdate) { // Macintosh timestamp: seconds since 00:00h January 1, 1904 // UNIX timestamp: seconds since 00:00h January 1, 1970 return self::CastAsInt($macdate - 2082844800); } - + /** + * @param string $rawdata + * + * @return float + */ public static function FixedPoint8_8($rawdata) { return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8)); } - + /** + * @param string $rawdata + * + * @return float + */ public static function FixedPoint16_16($rawdata) { return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16)); } - + /** + * @param string $rawdata + * + * @return float + */ public static function FixedPoint2_30($rawdata) { $binarystring = self::BigEndian2Bin($rawdata); return self::Bin2Dec(substr($binarystring, 0, 2)) + (float) (self::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30)); } + /** + * @param string $ArrayPath + * @param string $Separator + * @param mixed $Value + * + * @return array + */ public static function CreateDeepArray($ArrayPath, $Separator, $Value) { // assigns $Value to a nested array path: // $foo = self::CreateDeepArray('/path/to/my', '/', 'file.txt') @@ -504,6 +676,12 @@ class getid3_lib return $ReturnedArray; } + /** + * @param array $arraydata + * @param bool $returnkey + * + * @return int|false + */ public static function array_max($arraydata, $returnkey=false) { $maxvalue = false; $maxkey = false; @@ -518,6 +696,12 @@ class getid3_lib return ($returnkey ? $maxkey : $maxvalue); } + /** + * @param array $arraydata + * @param bool $returnkey + * + * @return int|false + */ public static function array_min($arraydata, $returnkey=false) { $minvalue = false; $minkey = false; @@ -532,6 +716,11 @@ class getid3_lib return ($returnkey ? $minkey : $minvalue); } + /** + * @param string $XMLstring + * + * @return array|false + */ public static function XML2array($XMLstring) { if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) { // http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html @@ -545,22 +734,42 @@ class getid3_lib return false; } + /** + * @param SimpleXMLElement|array $XMLobject + * + * @return array + */ public static function SimpleXMLelement2array($XMLobject) { if (!is_object($XMLobject) && !is_array($XMLobject)) { return $XMLobject; } - $XMLarray = (is_object($XMLobject) ? get_object_vars($XMLobject) : $XMLobject); + $XMLarray = $XMLobject instanceof SimpleXMLElement ? get_object_vars($XMLobject) : $XMLobject; foreach ($XMLarray as $key => $value) { $XMLarray[$key] = self::SimpleXMLelement2array($value); } return $XMLarray; } - - // Allan Hansen - // self::md5_data() - returns md5sum for a file from startuing position to absolute end position + /** + * self::md5_data() - returns md5sum for a file from startuing position to absolute end position + * + * @author Allan Hansen + * + * @param string $file + * @param int $offset + * @param int $end + * @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; } @@ -645,6 +854,15 @@ class getid3_lib return $result; } + /** + * @param string $filename_source + * @param string $filename_dest + * @param int $offset + * @param int $length + * + * @return bool + * @throws Exception + */ public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) { if (!self::intValueSupported($offset + $length)) { throw new Exception('cannot copy file portion, it extends beyond the '.round(PHP_INT_MAX / 1073741824).'GB limit'); @@ -657,21 +875,25 @@ class getid3_lib $byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite); $byteslefttowrite -= $byteswritten; } + fclose($fp_dest); return true; } else { + fclose($fp_src); throw new Exception('failed to seek to offset '.$offset.' in '.$filename_source); } - fclose($fp_dest); } else { throw new Exception('failed to create file for writing '.$filename_dest); } - fclose($fp_src); } else { throw new Exception('failed to open file for reading '.$filename_source); } - return false; } + /** + * @param int $charval + * + * @return string + */ public static function iconv_fallback_int_utf8($charval) { if ($charval < 128) { // 0bbbbbbb @@ -695,7 +917,14 @@ class getid3_lib return $newcharstring; } - // ISO-8859-1 => UTF-8 + /** + * ISO-8859-1 => UTF-8 + * + * @param string $string + * @param bool $bom + * + * @return string + */ public static function iconv_fallback_iso88591_utf8($string, $bom=false) { if (function_exists('utf8_encode')) { return utf8_encode($string); @@ -712,7 +941,14 @@ class getid3_lib return $newcharstring; } - // ISO-8859-1 => UTF-16BE + /** + * ISO-8859-1 => UTF-16BE + * + * @param string $string + * @param bool $bom + * + * @return string + */ public static function iconv_fallback_iso88591_utf16be($string, $bom=false) { $newcharstring = ''; if ($bom) { @@ -724,7 +960,14 @@ class getid3_lib return $newcharstring; } - // ISO-8859-1 => UTF-16LE + /** + * ISO-8859-1 => UTF-16LE + * + * @param string $string + * @param bool $bom + * + * @return string + */ public static function iconv_fallback_iso88591_utf16le($string, $bom=false) { $newcharstring = ''; if ($bom) { @@ -736,12 +979,24 @@ class getid3_lib return $newcharstring; } - // ISO-8859-1 => UTF-16LE (BOM) + /** + * ISO-8859-1 => UTF-16LE (BOM) + * + * @param string $string + * + * @return string + */ public static function iconv_fallback_iso88591_utf16($string) { return self::iconv_fallback_iso88591_utf16le($string, true); } - // UTF-8 => ISO-8859-1 + /** + * UTF-8 => ISO-8859-1 + * + * @param string $string + * + * @return string + */ public static function iconv_fallback_utf8_iso88591($string) { if (function_exists('utf8_decode')) { return utf8_decode($string); @@ -785,7 +1040,14 @@ class getid3_lib return $newcharstring; } - // UTF-8 => UTF-16BE + /** + * UTF-8 => UTF-16BE + * + * @param string $string + * @param bool $bom + * + * @return string + */ public static function iconv_fallback_utf8_utf16be($string, $bom=false) { $newcharstring = ''; if ($bom) { @@ -828,7 +1090,14 @@ class getid3_lib return $newcharstring; } - // UTF-8 => UTF-16LE + /** + * UTF-8 => UTF-16LE + * + * @param string $string + * @param bool $bom + * + * @return string + */ public static function iconv_fallback_utf8_utf16le($string, $bom=false) { $newcharstring = ''; if ($bom) { @@ -871,12 +1140,24 @@ class getid3_lib return $newcharstring; } - // UTF-8 => UTF-16LE (BOM) + /** + * UTF-8 => UTF-16LE (BOM) + * + * @param string $string + * + * @return string + */ public static function iconv_fallback_utf8_utf16($string) { return self::iconv_fallback_utf8_utf16le($string, true); } - // UTF-16BE => UTF-8 + /** + * UTF-16BE => UTF-8 + * + * @param string $string + * + * @return string + */ public static function iconv_fallback_utf16be_utf8($string) { if (substr($string, 0, 2) == "\xFE\xFF") { // strip BOM @@ -890,7 +1171,13 @@ class getid3_lib return $newcharstring; } - // UTF-16LE => UTF-8 + /** + * UTF-16LE => UTF-8 + * + * @param string $string + * + * @return string + */ public static function iconv_fallback_utf16le_utf8($string) { if (substr($string, 0, 2) == "\xFF\xFE") { // strip BOM @@ -904,7 +1191,13 @@ class getid3_lib return $newcharstring; } - // UTF-16BE => ISO-8859-1 + /** + * UTF-16BE => ISO-8859-1 + * + * @param string $string + * + * @return string + */ public static function iconv_fallback_utf16be_iso88591($string) { if (substr($string, 0, 2) == "\xFE\xFF") { // strip BOM @@ -918,7 +1211,13 @@ class getid3_lib return $newcharstring; } - // UTF-16LE => ISO-8859-1 + /** + * UTF-16LE => ISO-8859-1 + * + * @param string $string + * + * @return string + */ public static function iconv_fallback_utf16le_iso88591($string) { if (substr($string, 0, 2) == "\xFF\xFE") { // strip BOM @@ -932,7 +1231,13 @@ class getid3_lib return $newcharstring; } - // UTF-16 (BOM) => ISO-8859-1 + /** + * UTF-16 (BOM) => ISO-8859-1 + * + * @param string $string + * + * @return string + */ public static function iconv_fallback_utf16_iso88591($string) { $bom = substr($string, 0, 2); if ($bom == "\xFE\xFF") { @@ -943,7 +1248,13 @@ class getid3_lib return $string; } - // UTF-16 (BOM) => UTF-8 + /** + * UTF-16 (BOM) => UTF-8 + * + * @param string $string + * + * @return string + */ public static function iconv_fallback_utf16_utf8($string) { $bom = substr($string, 0, 2); if ($bom == "\xFE\xFF") { @@ -954,13 +1265,21 @@ class getid3_lib return $string; } + /** + * @param string $in_charset + * @param string $out_charset + * @param string $string + * + * @return string + * @throws Exception + */ public static function iconv_fallback($in_charset, $out_charset, $string) { if ($in_charset == $out_charset) { return $string; } - // mb_convert_encoding() availble + // mb_convert_encoding() available if (function_exists('mb_convert_encoding')) { if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) { switch ($out_charset) { @@ -972,7 +1291,7 @@ class getid3_lib } return $string; } - // iconv() availble + // iconv() available else if (function_exists('iconv')) { if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) { switch ($out_charset) { @@ -1014,6 +1333,12 @@ class getid3_lib throw new Exception('PHP does not has mb_convert_encoding() or iconv() support - cannot convert from '.$in_charset.' to '.$out_charset); } + /** + * @param mixed $data + * @param string $charset + * + * @return mixed + */ public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') { if (is_string($data)) { return self::MultiByteCharString2HTML($data, $charset); @@ -1028,6 +1353,12 @@ class getid3_lib return $data; } + /** + * @param string|int|float $string + * @param string $charset + * + * @return string + */ public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') { $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string $HTMLstring = ''; @@ -1120,8 +1451,11 @@ class getid3_lib return $HTMLstring; } - - + /** + * @param int $namecode + * + * @return string + */ public static function RGADnameLookup($namecode) { static $RGADname = array(); if (empty($RGADname)) { @@ -1133,7 +1467,11 @@ class getid3_lib return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : ''); } - + /** + * @param int $originatorcode + * + * @return string + */ public static function RGADoriginatorLookup($originatorcode) { static $RGADoriginator = array(); if (empty($RGADoriginator)) { @@ -1146,16 +1484,27 @@ class getid3_lib return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : ''); } - + /** + * @param int $rawadjustment + * @param int $signbit + * + * @return float + */ public static function RGADadjustmentLookup($rawadjustment, $signbit) { - $adjustment = $rawadjustment / 10; + $adjustment = (float) $rawadjustment / 10; if ($signbit == 1) { $adjustment *= -1; } - return (float) $adjustment; + return $adjustment; } - + /** + * @param int $namecode + * @param int $originatorcode + * @param int $replaygain + * + * @return string + */ public static function RGADgainString($namecode, $originatorcode, $replaygain) { if ($replaygain < 0) { $signbit = '1'; @@ -1171,11 +1520,21 @@ class getid3_lib return $gainstring; } + /** + * @param float $amplitude + * + * @return float + */ public static function RGADamplitude2dB($amplitude) { return 20 * log10($amplitude); } - + /** + * @param string $imgData + * @param array $imageinfo + * + * @return array|false + */ public static function GetDataImageSize($imgData, &$imageinfo=array()) { static $tempdir = ''; if (empty($tempdir)) { @@ -1210,32 +1569,21 @@ class getid3_lib return $GetDataImageSize; } + /** + * @param string $mime_type + * + * @return string + */ public static function ImageExtFromMime($mime_type) { // temporary way, works OK for now, but should be reworked in the future return str_replace(array('image/', 'x-', 'jpeg'), array('', '', 'jpg'), $mime_type); } - public static function ImageTypesLookup($imagetypeid) { - static $ImageTypesLookup = array(); - if (empty($ImageTypesLookup)) { - $ImageTypesLookup[1] = 'gif'; - $ImageTypesLookup[2] = 'jpeg'; - $ImageTypesLookup[3] = 'png'; - $ImageTypesLookup[4] = 'swf'; - $ImageTypesLookup[5] = 'psd'; - $ImageTypesLookup[6] = 'bmp'; - $ImageTypesLookup[7] = 'tiff (little-endian)'; - $ImageTypesLookup[8] = 'tiff (big-endian)'; - $ImageTypesLookup[9] = 'jpc'; - $ImageTypesLookup[10] = 'jp2'; - $ImageTypesLookup[11] = 'jpx'; - $ImageTypesLookup[12] = 'jb2'; - $ImageTypesLookup[13] = 'swc'; - $ImageTypesLookup[14] = 'iff'; - } - return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : ''); - } - + /** + * @param array $ThisFileInfo + * + * @return bool + */ public static function CopyTagsToComments(&$ThisFileInfo) { // Copy all entries from ['tags'] into common ['comments'] @@ -1323,7 +1671,15 @@ class getid3_lib return true; } - + /** + * @param string $key + * @param int $begin + * @param int $end + * @param string $file + * @param string $name + * + * @return string + */ public static function EmbeddedLookup($key, $begin, $end, $file, $name) { // Cached @@ -1370,6 +1726,14 @@ class getid3_lib return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : ''); } + /** + * @param string $filename + * @param string $sourcefile + * @param bool $DieOnFailure + * + * @return bool + * @throws Exception + */ public static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) { global $GETID3_ERRORARRAY; @@ -1390,10 +1754,20 @@ class getid3_lib return false; } + /** + * @param string $string + * + * @return string + */ public static function trimNullByte($string) { return trim($string, "\x00"); } + /** + * @param string $path + * + * @return float|bool + */ public static function getFileSizeSyscall($path) { $filesize = false; @@ -1418,13 +1792,44 @@ class getid3_lib return $filesize; } + /** + * @param string $filename + * + * @return string|false + */ + public static function truepath($filename) { + // 2017-11-08: this could use some improvement, patches welcome + if (preg_match('#^(\\\\\\\\|//)[a-z0-9]#i', $filename, $matches)) { + // PHP's built-in realpath function does not work on UNC Windows shares + $goodpath = array(); + foreach (explode('/', str_replace('\\', '/', $filename)) as $part) { + if ($part == '.') { + continue; + } + if ($part == '..') { + if (count($goodpath)) { + array_pop($goodpath); + } else { + // cannot step above this level, already at top level + return false; + } + } else { + $goodpath[] = $part; + } + } + return implode(DIRECTORY_SEPARATOR, $goodpath); + } + return realpath($filename); + } /** - * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268) - * @param string $path A path. - * @param string $suffix If the name component ends in suffix this will also be cut off. - * @return string - */ + * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268) + * + * @param string $path A path. + * @param string $suffix If the name component ends in suffix this will also be cut off. + * + * @return string + */ public static function mb_basename($path, $suffix = null) { $splited = preg_split('#/#', rtrim($path, '/ ')); return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1); diff --git a/www/plugins-dist/medias/lib/getid3/getid3.php b/www/plugins-dist/medias/lib/getid3/getid3.php index 37bf9443..90d7c9c2 100644 --- a/www/plugins-dist/medias/lib/getid3/getid3.php +++ b/www/plugins-dist/medias/lib/getid3/getid3.php @@ -1,10 +1,10 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // // // // Please see readme.txt for more information // // /// @@ -26,6 +26,14 @@ if (!defined('ENT_SUBSTITUTE')) { // PHP5.3 adds ENT_IGNORE, PHP5.4 adds ENT_SUB define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8)); } +/* +https://www.getid3.org/phpBB3/viewtopic.php?t=2114 +If you are running into a the problem where filenames with special characters are being handled +incorrectly by external helper programs (e.g. metaflac), notably with the special characters removed, +and you are passing in the filename in UTF8 (typically via a HTML form), try uncommenting this line: +*/ +//setlocale(LC_CTYPE, 'en_US.UTF-8'); + // attempt to define temp dir as something flexible but reliable $temp_dir = ini_get('upload_tmp_dir'); if ($temp_dir && (!is_dir($temp_dir) || !is_readable($temp_dir))) { @@ -74,66 +82,196 @@ unset($open_basedir, $temp_dir); class getID3 { - // public: Settings - public $encoding = 'UTF-8'; // CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE - public $encoding_id3v1 = 'ISO-8859-1'; // Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252' - - // public: Optional tag checks - disable for speed. - public $option_tag_id3v1 = true; // Read and process ID3v1 tags - public $option_tag_id3v2 = true; // Read and process ID3v2 tags - public $option_tag_lyrics3 = true; // Read and process Lyrics3 tags - public $option_tag_apetag = true; // Read and process APE tags - public $option_tags_process = true; // Copy tags to root key 'tags' and encode to $this->encoding - public $option_tags_html = true; // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities - - // public: Optional tag/comment calucations - public $option_extra_info = true; // Calculate additional info such as bitrate, channelmode etc - - // public: Optional handling of embedded attachments (e.g. images) - public $option_save_attachments = true; // defaults to true (ATTACHMENTS_INLINE) for backward compatibility - - // public: Optional calculations - public $option_md5_data = false; // Get MD5 sum of data part - slow - public $option_md5_data_source = false; // Use MD5 of source file if availble - only FLAC and OptimFROG - public $option_sha1_data = false; // Get SHA1 sum of data part - slow - public $option_max_2gb_check = null; // Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on PHP_INT_MAX) - - // public: Read buffer size in bytes + /* + * Settings + */ + + /** + * CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE + * + * @var string + */ + public $encoding = 'UTF-8'; + + /** + * Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252' + * + * @var string + */ + public $encoding_id3v1 = 'ISO-8859-1'; + + /* + * Optional tag checks - disable for speed. + */ + + /** + * Read and process ID3v1 tags + * + * @var bool + */ + public $option_tag_id3v1 = true; + + /** + * Read and process ID3v2 tags + * + * @var bool + */ + public $option_tag_id3v2 = true; + + /** + * Read and process Lyrics3 tags + * + * @var bool + */ + public $option_tag_lyrics3 = true; + + /** + * Read and process APE tags + * + * @var bool + */ + public $option_tag_apetag = true; + + /** + * Copy tags to root key 'tags' and encode to $this->encoding + * + * @var bool + */ + public $option_tags_process = true; + + /** + * Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities + * + * @var bool + */ + public $option_tags_html = true; + + /* + * Optional tag/comment calculations + */ + + /** + * Calculate additional info such as bitrate, channelmode etc + * + * @var bool + */ + public $option_extra_info = true; + + /* + * Optional handling of embedded attachments (e.g. images) + */ + + /** + * Defaults to true (ATTACHMENTS_INLINE) for backward compatibility + * + * @var bool|string + */ + public $option_save_attachments = true; + + /* + * Optional calculations + */ + + /** + * Get MD5 sum of data part - slow + * + * @var bool + */ + public $option_md5_data = false; + + /** + * Use MD5 of source file if availble - only FLAC and OptimFROG + * + * @var bool + */ + public $option_md5_data_source = false; + + /** + * Get SHA1 sum of data part - slow + * + * @var bool + */ + public $option_sha1_data = false; + + /** + * Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on + * PHP_INT_MAX) + * + * @var bool|null + */ + public $option_max_2gb_check; + + /** + * Read buffer size in bytes + * + * @var int + */ public $option_fread_buffer_size = 32768; // Public variables - public $filename; // Filename of file being analysed. - public $fp; // Filepointer to file being analysed. - public $info; // Result array. + + /** + * Filename of file being analysed. + * + * @var string + */ + public $filename; + + /** + * Filepointer to file being analysed. + * + * @var resource + */ + public $fp; + + /** + * Result array. + * + * @var array + */ + public $info; + + /** + * @var string + */ public $tempdir = GETID3_TEMP_DIR; + + /** + * @var int + */ public $memory_limit = 0; - // Protected variables + /** + * @var string + */ protected $startup_error = ''; + + /** + * @var string + */ protected $startup_warning = ''; - const VERSION = '1.9.14-201703261440'; + const VERSION = '1.9.16-201810171314'; const FREAD_BUFFER_SIZE = 32768; const ATTACHMENTS_NONE = false; const ATTACHMENTS_INLINE = true; - // public: constructor public function __construct() { // Check for PHP version $required_php_version = '5.3.0'; if (version_compare(PHP_VERSION, $required_php_version, '<')) { $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION."\n"; - return false; + return; } // Check memory $this->memory_limit = ini_get('memory_limit'); - if (preg_match('#([0-9]+)M#i', $this->memory_limit, $matches)) { + if (preg_match('#([0-9]+) ?M#i', $this->memory_limit, $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 + } elseif (preg_match('#([0-9]+) ?G#i', $this->memory_limit, $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; } @@ -226,20 +364,27 @@ class getID3 echo $this->startup_error; throw new getid3_exception($this->startup_error); } - - return true; } + /** + * @return string + */ public function version() { return self::VERSION; } + /** + * @return int + */ public function fread_buffer_size() { return $this->option_fread_buffer_size; } - - // public: setOption + /** + * @param array $optArray + * + * @return bool + */ public function setOption($optArray) { if (!is_array($optArray) || empty($optArray)) { return false; @@ -253,7 +398,14 @@ class getID3 return true; } - + /** + * @param string $filename + * @param int $filesize + * + * @return bool + * + * @throws getid3_exception + */ public function openfile($filename, $filesize=null) { try { if (!empty($this->startup_error)) { @@ -277,10 +429,10 @@ class getID3 } $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename); - $filename = preg_replace('#(.+)'.preg_quote(DIRECTORY_SEPARATOR).'{2,}#U', '\1'.DIRECTORY_SEPARATOR, $filename); + //$filename = preg_replace('#(?fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720 + //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'))) { // great } else { @@ -338,10 +490,10 @@ class getID3 } elseif (getid3_lib::intValueSupported($real_filesize)) { unset($this->info['filesize']); fclose($this->fp); - throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize, 3).'GB, please report to info@getid3.org'); + throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB, please report to info@getid3.org'); } $this->info['filesize'] = $real_filesize; - $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize, 3).'GB) and is not properly supported by PHP.'); + $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB) and is not properly supported by PHP.'); } } @@ -353,7 +505,15 @@ class getID3 return false; } - // public: analyze file + /** + * analyze file + * + * @param string $filename + * @param int $filesize + * @param string $original_filename + * + * @return array + */ public function analyze($filename, $filesize=null, $original_filename='') { try { if (!$this->openfile($filename, $filesize)) { @@ -504,7 +664,13 @@ class getID3 } - // private: error handling + /** + * Error handling. + * + * @param string $message + * + * @return array + */ public function error($message) { $this->CleanUp(); if (!isset($this->info['error'])) { @@ -515,14 +681,22 @@ class getID3 } - // private: warning handling + /** + * Warning handling. + * + * @param string $message + * + * @return bool + */ public function warning($message) { $this->info['warning'][] = $message; return true; } - // private: CleanUp + /** + * @return bool + */ private function CleanUp() { // remove possible empty keys @@ -569,8 +743,11 @@ class getID3 return true; } - - // return array containing information about all supported formats + /** + * Return array containing information about all supported formats. + * + * @return array + */ public function GetFileFormatArray() { static $format_info = array(); if (empty($format_info)) { @@ -591,7 +768,7 @@ class getID3 'pattern' => '^ADIF', 'group' => 'audio', 'module' => 'aac', - 'mime_type' => 'application/octet-stream', + 'mime_type' => 'audio/aac', 'fail_ape' => 'WARNING', ), @@ -609,7 +786,7 @@ class getID3 'pattern' => '^\\xFF[\\xF0-\\xF1\\xF8-\\xF9]', 'group' => 'audio', 'module' => 'aac', - 'mime_type' => 'application/octet-stream', + 'mime_type' => 'audio/aac', 'fail_ape' => 'WARNING', ), @@ -675,7 +852,7 @@ class getID3 'pattern' => '^fLaC', 'group' => 'audio', 'module' => 'flac', - 'mime_type' => 'audio/x-flac', + 'mime_type' => 'audio/flac', ), // LA - audio - Lossless Audio (LA) @@ -707,7 +884,7 @@ class getID3 'pattern' => '^MAC ', 'group' => 'audio', 'module' => 'monkey', - 'mime_type' => 'application/octet-stream', + 'mime_type' => 'audio/x-monkeys-audio', ), // has been known to produce false matches in random files (e.g. JPEGs), leave out until more precise matching available @@ -896,7 +1073,7 @@ class getID3 'pattern' => '^(RIFF|SDSS|FORM)', 'group' => 'audio-video', 'module' => 'riff', - 'mime_type' => 'audio/x-wav', + 'mime_type' => 'audio/wav', 'fail_ape' => 'WARNING', ), @@ -1060,7 +1237,7 @@ class getID3 'pattern' => '^\\x1F\\x8B\\x08', 'group' => 'archive', 'module' => 'gzip', - 'mime_type' => 'application/x-gzip', + 'mime_type' => 'application/gzip', 'fail_id3' => 'ERROR', 'fail_ape' => 'ERROR', ), @@ -1122,8 +1299,12 @@ class getID3 return $format_info; } - - + /** + * @param string $filedata + * @param string $filename + * + * @return mixed|false + */ public function GetFileFormat(&$filedata, $filename='') { // this function will determine the format of a file based on usually // the first 2-4 bytes of the file (8 bytes for PNG, 16 bytes for JPG, @@ -1161,8 +1342,12 @@ class getID3 return false; } - - // converts array to $encoding charset from $this->encoding + /** + * Converts array to $encoding charset from $this->encoding. + * + * @param array $array + * @param string $encoding + */ public function CharConvert(&$array, $encoding) { // identical encoding - end here @@ -1185,7 +1370,9 @@ class getID3 } } - + /** + * @return bool + */ public function HandleAllTags() { // key name => array (tag name, character encoding) @@ -1308,6 +1495,11 @@ class getID3 return true; } + /** + * @param string $algorithm + * + * @return array|bool + */ public function getHashdata($algorithm) { switch ($algorithm) { case 'md5': @@ -1372,7 +1564,6 @@ class getID3 } else { - $commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1'; $commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1'; $VorbisCommentError = `$commandline`; @@ -1431,7 +1622,6 @@ class getID3 return true; } - public function ChannelsBitratePlaytimeCalculations() { // set channelmode on audio @@ -1496,7 +1686,9 @@ class getID3 } } - + /** + * @return bool + */ public function CalculateCompressionRatioVideo() { if (empty($this->info['video'])) { return false; @@ -1544,7 +1736,9 @@ class getID3 return true; } - + /** + * @return bool + */ public function CalculateCompressionRatioAudio() { if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) { return false; @@ -1561,11 +1755,13 @@ class getID3 return true; } - + /** + * @return bool + */ public function CalculateReplayGain() { if (isset($this->info['replay_gain'])) { if (!isset($this->info['replay_gain']['reference_volume'])) { - $this->info['replay_gain']['reference_volume'] = (double) 89.0; + $this->info['replay_gain']['reference_volume'] = 89.0; } if (isset($this->info['replay_gain']['track']['adjustment'])) { $this->info['replay_gain']['track']['volume'] = $this->info['replay_gain']['reference_volume'] - $this->info['replay_gain']['track']['adjustment']; @@ -1584,6 +1780,9 @@ class getID3 return true; } + /** + * @return bool + */ public function ProcessAudioStreams() { if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) { if (!isset($this->info['audio']['streams'])) { @@ -1597,10 +1796,20 @@ class getID3 return true; } + /** + * @return string|bool + */ public function getid3_tempnam() { return tempnam($this->tempdir, 'gI3'); } + /** + * @param string $name + * + * @return bool + * + * @throws getid3_exception + */ public function include_module($name) { //if (!file_exists($this->include_path.'module.'.$name.'.php')) { if (!file_exists(GETID3_INCLUDEPATH.'module.'.$name.'.php')) { @@ -1610,24 +1819,72 @@ class getID3 return true; } + /** + * @param string $filename + * + * @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; + } + } -abstract class getid3_handler { +abstract class getid3_handler +{ /** * @var getID3 */ protected $getid3; // pointer - protected $data_string_flag = false; // analyzing filepointer or string - protected $data_string = ''; // string to analyze - protected $data_string_position = 0; // seek position in string - protected $data_string_length = 0; // string length + /** + * Analyzing filepointer or string. + * + * @var bool + */ + protected $data_string_flag = false; - private $dependency_to = null; + /** + * String to analyze. + * + * @var string + */ + protected $data_string = ''; + /** + * Seek position in string. + * + * @var int + */ + protected $data_string_position = 0; + /** + * String length. + * + * @var int + */ + protected $data_string_length = 0; + + /** + * @var string + */ + private $dependency_to; + + /** + * getid3_handler constructor. + * + * @param getID3 $getid3 + * @param string $call_module + */ public function __construct(getID3 $getid3, $call_module=null) { $this->getid3 = $getid3; @@ -1636,12 +1893,18 @@ abstract class getid3_handler { } } - - // Analyze from file pointer + /** + * Analyze from file pointer. + * + * @return bool + */ abstract public function Analyze(); - - // Analyze from string instead + /** + * Analyze from string instead. + * + * @param string $string + */ public function AnalyzeString($string) { // Enter string mode $this->setStringMode($string); @@ -1667,12 +1930,18 @@ abstract class getid3_handler { $this->data_string_flag = false; } + /** + * @param string $string + */ public function setStringMode($string) { $this->data_string_flag = true; $this->data_string = $string; $this->data_string_length = strlen($string); } + /** + * @return int|bool + */ protected function ftell() { if ($this->data_string_flag) { return $this->data_string_position; @@ -1680,6 +1949,13 @@ abstract class getid3_handler { return ftell($this->getid3->fp); } + /** + * @param int $bytes + * + * @return string|false + * + * @throws getid3_exception + */ protected function fread($bytes) { if ($this->data_string_flag) { $this->data_string_position += $bytes; @@ -1692,7 +1968,7 @@ abstract class getid3_handler { //return fread($this->getid3->fp, $bytes); /* - * http://www.getid3.org/phpBB3/viewtopic.php?t=1930 + * https://www.getid3.org/phpBB3/viewtopic.php?t=1930 * "I found out that the root cause for the problem was how getID3 uses the PHP system function fread(). * It seems to assume that fread() would always return as many bytes as were requested. * However, according the PHP manual (http://php.net/manual/en/function.fread.php), this is the case only with regular local files, but not e.g. with Linux pipes. @@ -1700,6 +1976,9 @@ abstract class getid3_handler { */ $contents = ''; do { + if (($this->getid3->memory_limit > 0) && ($bytes > $this->getid3->memory_limit)) { + 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); $partLength = strlen($part); $bytes -= $partLength; @@ -1708,6 +1987,14 @@ abstract class getid3_handler { return $contents; } + /** + * @param int $bytes + * @param int $whence + * + * @return int + * + * @throws getid3_exception + */ protected function fseek($bytes, $whence=SEEK_SET) { if ($this->data_string_flag) { switch ($whence) { @@ -1738,6 +2025,9 @@ abstract class getid3_handler { return fseek($this->getid3->fp, $bytes, $whence); } + /** + * @return bool + */ protected function feof() { if ($this->data_string_flag) { return $this->data_string_position >= $this->data_string_length; @@ -1745,24 +2035,53 @@ abstract class getid3_handler { return feof($this->getid3->fp); } + /** + * @param string $module + * + * @return bool + */ final protected function isDependencyFor($module) { return $this->dependency_to == $module; } + /** + * @param string $text + * + * @return bool + */ protected function error($text) { $this->getid3->info['error'][] = $text; return false; } + /** + * @param string $text + * + * @return bool + */ protected function warning($text) { return $this->getid3->warning($text); } + /** + * @param string $text + */ protected function notice($text) { // does nothing for now } + /** + * @param string $name + * @param int $offset + * @param int $length + * @param string $image_mime + * + * @return string|null + * + * @throws Exception + * @throws getid3_exception + */ public function saveAttachment($name, $offset, $length, $image_mime=null) { try { @@ -1785,7 +2104,7 @@ abstract class getid3_handler { // set up destination path $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR); - if (!is_dir($dir) || !is_writable($dir)) { // check supplied directory + if (!is_dir($dir) || !getID3::is_writable($dir)) { // check supplied directory throw new Exception('supplied path ('.$dir.') does not exist, or is not writable'); } $dest = $dir.DIRECTORY_SEPARATOR.$name.($image_mime ? '.'.getid3_lib::ImageExtFromMime($image_mime) : ''); @@ -1816,6 +2135,9 @@ abstract class getid3_handler { // close and remove dest file if created if (isset($fp_dest) && is_resource($fp_dest)) { fclose($fp_dest); + } + + if (isset($dest) && file_exists($dest)) { unlink($dest); } diff --git a/www/plugins-dist/medias/lib/getid3/module.archive.gzip.php b/www/plugins-dist/medias/lib/getid3/module.archive.gzip.php index 112a1e6d..5d730be8 100644 --- a/www/plugins-dist/medias/lib/getid3/module.archive.gzip.php +++ b/www/plugins-dist/medias/lib/getid3/module.archive.gzip.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.archive.gzip.php // @@ -20,11 +20,20 @@ ///////////////////////////////////////////////////////////////// -class getid3_gzip extends getid3_handler { - - // public: Optional file list - disable for speed. - public $option_gzip_parse_contents = false; // decode gzipped files, if possible, and parse recursively (.tar.gz for example) +class getid3_gzip extends getid3_handler +{ + /** + * Optional file list - disable for speed. + * + * Decode gzipped files, if possible, and parse recursively (.tar.gz for example). + * + * @var bool + */ + public $option_gzip_parse_contents = false; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -44,6 +53,7 @@ class getid3_gzip extends getid3_handler { $buffer = $this->fread($info['filesize']); $arr_members = explode("\x1F\x8B\x08", $buffer); + $num_members = 0; while (true) { $is_wrong_members = false; $num_members = intval(count($arr_members)); @@ -199,7 +209,7 @@ class getid3_gzip extends getid3_handler { $inflated = gzinflate($cdata); // Calculate CRC32 for inflated content - $thisInfo['crc32_valid'] = (bool) (sprintf('%u', crc32($inflated)) == $thisInfo['crc32']); + $thisInfo['crc32_valid'] = sprintf('%u', crc32($inflated)) == $thisInfo['crc32']; // determine format $formattest = substr($inflated, 0, 32774); @@ -240,13 +250,21 @@ class getid3_gzip extends getid3_handler { // unknown or unhandled format break; } + } else { + $this->warning('PHP is not compiled with gzinflate() support. Please enable PHP Zlib extension or recompile with the --with-zlib switch'); } } } return true; } - // Converts the OS type + /** + * Converts the OS type. + * + * @param string $key + * + * @return string + */ public function get_os_type($key) { static $os_type = array( '0' => 'FAT filesystem (MS-DOS, OS/2, NT/Win32)', @@ -268,7 +286,13 @@ class getid3_gzip extends getid3_handler { return (isset($os_type[$key]) ? $os_type[$key] : ''); } - // Converts the eXtra FLags + /** + * Converts the eXtra FLags. + * + * @param string $key + * + * @return string + */ public function get_xflag_type($key) { static $xflag_type = array( '0' => 'unknown', diff --git a/www/plugins-dist/medias/lib/getid3/module.archive.rar.php b/www/plugins-dist/medias/lib/getid3/module.archive.rar.php index 30961fb5..c8f26788 100644 --- a/www/plugins-dist/medias/lib/getid3/module.archive.rar.php +++ b/www/plugins-dist/medias/lib/getid3/module.archive.rar.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.archive.rar.php // @@ -17,9 +17,14 @@ class getid3_rar extends getid3_handler { - + /** + * @var bool + */ public $option_use_rar_extension = false; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; diff --git a/www/plugins-dist/medias/lib/getid3/module.archive.szip.php b/www/plugins-dist/medias/lib/getid3/module.archive.szip.php index 67517294..5b0601b4 100644 --- a/www/plugins-dist/medias/lib/getid3/module.archive.szip.php +++ b/www/plugins-dist/medias/lib/getid3/module.archive.szip.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.archive.szip.php // @@ -17,7 +17,9 @@ class getid3_szip extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -30,8 +32,8 @@ class getid3_szip extends getid3_handler $info['fileformat'] = 'szip'; $info['szip']['major_version'] = getid3_lib::BigEndian2Int(substr($SZIPHeader, 4, 1)); $info['szip']['minor_version'] = getid3_lib::BigEndian2Int(substr($SZIPHeader, 5, 1)); -$this->error('SZIP parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); -return false; + $this->error('SZIP parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); + return false; while (!$this->feof()) { $NextBlockID = $this->fread(2); diff --git a/www/plugins-dist/medias/lib/getid3/module.archive.tar.php b/www/plugins-dist/medias/lib/getid3/module.archive.tar.php index 9e8d72a2..952a626e 100644 --- a/www/plugins-dist/medias/lib/getid3/module.archive.tar.php +++ b/www/plugins-dist/medias/lib/getid3/module.archive.tar.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.archive.tar.php // @@ -22,7 +22,9 @@ class getid3_tar extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -117,7 +119,13 @@ class getid3_tar extends getid3_handler return true; } - // Parses the file mode to file permissions + /** + * Parses the file mode to file permissions. + * + * @param int $mode + * + * @return string + */ public function display_perms($mode) { // Determine Type if ($mode & 0x1000) $type='p'; // FIFO pipe @@ -152,7 +160,13 @@ class getid3_tar extends getid3_handler return $s; } - // Converts the file type + /** + * Converts the file type. + * + * @param string $typflag + * + * @return mixed|string + */ public function get_flag_type($typflag) { static $flag_types = array( '0' => 'LF_NORMAL', diff --git a/www/plugins-dist/medias/lib/getid3/module.archive.zip.php b/www/plugins-dist/medias/lib/getid3/module.archive.zip.php index 4b7aa583..7cb8719d 100644 --- a/www/plugins-dist/medias/lib/getid3/module.archive.zip.php +++ b/www/plugins-dist/medias/lib/getid3/module.archive.zip.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.archive.zip.php // @@ -17,7 +17,9 @@ class getid3_zip extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -48,7 +50,7 @@ class getid3_zip extends getid3_handler $this->fseek($info['zip']['end_central_directory']['directory_offset']); $info['zip']['entries_count'] = 0; - while ($centraldirectoryentry = $this->ZIPparseCentralDirectory($this->getid3->fp)) { + while ($centraldirectoryentry = $this->ZIPparseCentralDirectory()) { $info['zip']['central_directory'][] = $centraldirectoryentry; $info['zip']['entries_count']++; $info['zip']['compressed_size'] += $centraldirectoryentry['compressed_size']; @@ -129,7 +131,9 @@ class getid3_zip extends getid3_handler return true; } - + /** + * @return bool + */ public function getZIPHeaderFilepointerTopDown() { $info = &$this->getid3->info; @@ -150,7 +154,7 @@ class getid3_zip extends getid3_handler } $info['zip']['entries_count'] = 0; - while ($centraldirectoryentry = $this->ZIPparseCentralDirectory($this->getid3->fp)) { + while ($centraldirectoryentry = $this->ZIPparseCentralDirectory()) { $info['zip']['central_directory'][] = $centraldirectoryentry; $info['zip']['entries_count']++; $info['zip']['compressed_size'] += $centraldirectoryentry['compressed_size']; @@ -175,7 +179,9 @@ class getid3_zip extends getid3_handler return true; } - + /** + * @return bool + */ public function getZIPentriesFilepointer() { $info = &$this->getid3->info; @@ -198,7 +204,9 @@ class getid3_zip extends getid3_handler return true; } - + /** + * @return array|false + */ public function ZIPparseLocalFileHeader() { $LocalFileHeader['offset'] = $this->ftell(); @@ -265,7 +273,7 @@ class getid3_zip extends getid3_handler $DataDescriptor = $this->fread(16); $LocalFileHeader['data_descriptor']['signature'] = getid3_lib::LittleEndian2Int(substr($DataDescriptor, 0, 4)); if ($LocalFileHeader['data_descriptor']['signature'] != 0x08074B50) { // "PK\x07\x08" - $this->getid3->warning[] = 'invalid Local File Header Data Descriptor Signature at offset '.($this->ftell() - 16).' - expecting 08 07 4B 50, found '.getid3_lib::PrintHexBytes($LocalFileHeader['data_descriptor']['signature']); + $this->getid3->warning('invalid Local File Header Data Descriptor Signature at offset '.($this->ftell() - 16).' - expecting 08 07 4B 50, found '.getid3_lib::PrintHexBytes($LocalFileHeader['data_descriptor']['signature'])); $this->fseek($LocalFileHeader['offset']); // seek back to where filepointer originally was so it can be handled properly return false; } @@ -294,7 +302,9 @@ class getid3_zip extends getid3_handler return $LocalFileHeader; } - + /** + * @return array|false + */ public function ZIPparseCentralDirectory() { $CentralDirectory['offset'] = $this->ftell(); @@ -351,6 +361,9 @@ class getid3_zip extends getid3_handler return $CentralDirectory; } + /** + * @return array|false + */ public function ZIPparseEndOfCentralDirectory() { $EndOfCentralDirectory['offset'] = $this->ftell(); @@ -377,9 +390,15 @@ class getid3_zip extends getid3_handler return $EndOfCentralDirectory; } - + /** + * @param int $flagbytes + * @param int $compressionmethod + * + * @return array + */ public static function ZIPparseGeneralPurposeFlags($flagbytes, $compressionmethod) { // https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip-printable.html + $ParsedFlags = array(); $ParsedFlags['encrypted'] = (bool) ($flagbytes & 0x0001); // 0x0002 -- see below // 0x0004 -- see below @@ -425,7 +444,11 @@ class getid3_zip extends getid3_handler return $ParsedFlags; } - + /** + * @param int $index + * + * @return string + */ public static function ZIPversionOSLookup($index) { static $ZIPversionOSLookup = array( 0 => 'MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems)', @@ -453,6 +476,11 @@ class getid3_zip extends getid3_handler return (isset($ZIPversionOSLookup[$index]) ? $ZIPversionOSLookup[$index] : '[unknown]'); } + /** + * @param int $index + * + * @return string + */ public static function ZIPcompressionMethodLookup($index) { // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/ZIP.html static $ZIPcompressionMethodLookup = array( @@ -484,6 +512,12 @@ class getid3_zip extends getid3_handler return (isset($ZIPcompressionMethodLookup[$index]) ? $ZIPcompressionMethodLookup[$index] : '[unknown]'); } + /** + * @param int $DOSdate + * @param int $DOStime + * + * @return int + */ public static function DOStime2UNIXtime($DOSdate, $DOStime) { // wFatDate // Specifies the MS-DOS date. The date is a packed 16-bit value with the following format: diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.asf.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.asf.php index 23d3a0e6..d42607e0 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.asf.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.asf.php @@ -1,11 +1,10 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio-video.asf.php // @@ -16,8 +15,11 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); -class getid3_asf extends getid3_handler { - +class getid3_asf extends getid3_handler +{ + /** + * @param getID3 $getid3 + */ public function __construct(getID3 $getid3) { parent::__construct($getid3); // extends getid3_handler::__construct() @@ -30,6 +32,9 @@ class getid3_asf extends getid3_handler { } } + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -83,6 +88,8 @@ class getid3_asf extends getid3_handler { $NextObjectOffset = $this->ftell(); $ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30); $offset = 0; + $thisfile_asf_streambitratepropertiesobject = array(); + $thisfile_asf_codeclistobject = array(); for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) { $NextObjectGUID = substr($ASFHeaderData, $offset, 16); @@ -970,18 +977,18 @@ class getid3_asf extends getid3_handler { break; } } - if (isset($thisfile_asf_streambitrateproperties['bitrate_records_count'])) { + if (isset($thisfile_asf_streambitratepropertiesobject['bitrate_records_count'])) { $ASFbitrateAudio = 0; $ASFbitrateVideo = 0; - for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitrateproperties['bitrate_records_count']; $BitrateRecordsCounter++) { + for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) { if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) { switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) { case 1: - $ASFbitrateVideo += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate']; + $ASFbitrateVideo += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate']; break; case 2: - $ASFbitrateAudio += $thisfile_asf_streambitrateproperties['bitrate_records'][$BitrateRecordsCounter]['bitrate']; + $ASFbitrateAudio += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate']; break; default: @@ -1440,6 +1447,11 @@ class getid3_asf extends getid3_handler { return true; } + /** + * @param int $CodecListType + * + * @return string + */ public static function codecListObjectTypeLookup($CodecListType) { static $lookup = array( 0x0001 => 'Video Codec', @@ -1450,6 +1462,9 @@ class getid3_asf extends getid3_handler { return (isset($lookup[$CodecListType]) ? $lookup[$CodecListType] : 'Invalid Codec Type'); } + /** + * @return array + */ public static function KnownGUIDs() { static $GUIDarray = array( 'GETID3_ASF_Extended_Stream_Properties_Object' => '14E6A5CB-C672-4332-8399-A96952065B5A', @@ -1564,6 +1579,11 @@ class getid3_asf extends getid3_handler { return $GUIDarray; } + /** + * @param string $GUIDstring + * + * @return string|false + */ public static function GUIDname($GUIDstring) { static $GUIDarray = array(); if (empty($GUIDarray)) { @@ -1572,6 +1592,11 @@ class getid3_asf extends getid3_handler { return array_search($GUIDstring, $GUIDarray); } + /** + * @param int $id + * + * @return string + */ public static function ASFIndexObjectIndexTypeLookup($id) { static $ASFIndexObjectIndexTypeLookup = array(); if (empty($ASFIndexObjectIndexTypeLookup)) { @@ -1582,6 +1607,11 @@ class getid3_asf extends getid3_handler { return (isset($ASFIndexObjectIndexTypeLookup[$id]) ? $ASFIndexObjectIndexTypeLookup[$id] : 'invalid'); } + /** + * @param string $GUIDstring + * + * @return string + */ public static function GUIDtoBytestring($GUIDstring) { // Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way: // first 4 bytes are in little-endian order @@ -1617,6 +1647,11 @@ class getid3_asf extends getid3_handler { return $hexbytecharstring; } + /** + * @param string $Bytestring + * + * @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); @@ -1642,6 +1677,12 @@ class getid3_asf extends getid3_handler { return strtoupper($GUIDstring); } + /** + * @param int $FILETIME + * @param bool $round + * + * @return float|int + */ public static function FILETIMEtoUNIXtime($FILETIME, $round=true) { // FILETIME is a 64-bit unsigned integer representing // the number of 100-nanosecond intervals since January 1, 1601 @@ -1653,6 +1694,11 @@ class getid3_asf extends getid3_handler { return ($FILETIME - 116444736000000000) / 10000000; } + /** + * @param int $WMpictureType + * + * @return string + */ public static function WMpictureTypeLookup($WMpictureType) { static $lookup = null; if ($lookup === null) { @@ -1684,6 +1730,12 @@ class getid3_asf extends getid3_handler { return (isset($lookup[$WMpictureType]) ? $lookup[$WMpictureType] : ''); } + /** + * @param string $asf_header_extension_object_data + * @param int $unhandled_sections + * + * @return array + */ public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) { // http://msdn.microsoft.com/en-us/library/bb643323.aspx @@ -1930,7 +1982,11 @@ class getid3_asf extends getid3_handler { return $HeaderExtensionObjectParsed; } - + /** + * @param int $id + * + * @return string + */ public static function metadataLibraryObjectDataTypeLookup($id) { static $lookup = array( 0x0000 => 'Unicode string', // The data consists of a sequence of Unicode characters @@ -1944,6 +2000,11 @@ class getid3_asf extends getid3_handler { return (isset($lookup[$id]) ? $lookup[$id] : 'invalid'); } + /** + * @param string $data + * + * @return array + */ public function ASF_WMpicture(&$data) { //typedef struct _WMPicture{ // LPWSTR pwszMIMEType; @@ -1994,14 +2055,24 @@ class getid3_asf extends getid3_handler { return $WMpicture; } - - // Remove terminator 00 00 and convert UTF-16LE to Latin-1 + /** + * Remove terminator 00 00 and convert UTF-16LE to Latin-1. + * + * @param string $string + * + * @return string + */ public static function TrimConvert($string) { return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' '); } - - // Remove terminator 00 00 + /** + * Remove terminator 00 00. + * + * @param string $string + * + * @return string + */ public static function TrimTerm($string) { // remove terminator, only if present (it should be, but...) if (substr($string, -2) === "\x00\x00") { diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.bink.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.bink.php index af4b4f8d..bd38e339 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.bink.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.bink.php @@ -1,11 +1,10 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.bink.php // @@ -17,11 +16,13 @@ class getid3_bink extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; -$this->error('Bink / Smacker files not properly processed by this version of getID3() ['.$this->getid3->version().']'); + $this->error('Bink / Smacker files not properly processed by this version of getID3() ['.$this->getid3->version().']'); $this->fseek($info['avdataoffset']); $fileTypeID = $this->fread(3); @@ -44,6 +45,9 @@ $this->error('Bink / Smacker files not properly processed by this version of get } + /** + * @return bool + */ public function ParseBink() { $info = &$this->getid3->info; $info['fileformat'] = 'bink'; @@ -61,6 +65,9 @@ $this->error('Bink / Smacker files not properly processed by this version of get return true; } + /** + * @return bool + */ public function ParseSmacker() { $info = &$this->getid3->info; $info['fileformat'] = 'smacker'; diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.flv.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.flv.php index 661c77ca..eb292c61 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.flv.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.flv.php @@ -1,15 +1,22 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.audio-video.flv.php // +// module for analyzing Shockwave Flash Video files // +// dependencies: NONE // +// // +///////////////////////////////////////////////////////////////// // // // FLV module by Seth Kaufman // // // // * version 0.1 (26 June 2005) // // // -// // // * version 0.1.1 (15 July 2005) // // minor modifications by James Heinrich // // // @@ -43,12 +50,6 @@ // handle GETID3_FLV_VIDEO_VP6FLV_ALPHA // // improved AVCSequenceParameterSetReader::readData() // // by Xander Schouwerwou // -// // -///////////////////////////////////////////////////////////////// -// // -// module.audio-video.flv.php // -// module for analyzing Shockwave Flash Video files // -// dependencies: NONE // // /// ///////////////////////////////////////////////////////////////// @@ -73,12 +74,21 @@ define('H264_PROFILE_HIGH422', 122); define('H264_PROFILE_HIGH444', 144); define('H264_PROFILE_HIGH444_PREDICTIVE', 244); -class getid3_flv extends getid3_handler { - +class getid3_flv extends getid3_handler +{ const magic = 'FLV'; - public $max_frames = 100000; // break out of the loop if too many frames have been scanned; only scan this many if meta frame does not contain useful duration - + /** + * Break out of the loop if too many frames have been scanned; only scan this + * many if meta frame does not contain useful duration. + * + * @var int + */ + public $max_frames = 100000; + + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -332,7 +342,11 @@ class getid3_flv extends getid3_handler { return true; } - + /** + * @param int $id + * + * @return string|false + */ public static function audioFormatLookup($id) { static $lookup = array( 0 => 'Linear PCM, platform endian', @@ -355,6 +369,11 @@ class getid3_flv extends getid3_handler { return (isset($lookup[$id]) ? $lookup[$id] : false); } + /** + * @param int $id + * + * @return int|false + */ public static function audioRateLookup($id) { static $lookup = array( 0 => 5500, @@ -365,6 +384,11 @@ class getid3_flv extends getid3_handler { return (isset($lookup[$id]) ? $lookup[$id] : false); } + /** + * @param int $id + * + * @return int|false + */ public static function audioBitDepthLookup($id) { static $lookup = array( 0 => 8, @@ -373,6 +397,11 @@ class getid3_flv extends getid3_handler { return (isset($lookup[$id]) ? $lookup[$id] : false); } + /** + * @param int $id + * + * @return string|false + */ public static function videoCodecLookup($id) { static $lookup = array( GETID3_FLV_VIDEO_H263 => 'Sorenson H.263', @@ -386,47 +415,84 @@ class getid3_flv extends getid3_handler { } } -class AMFStream { +class AMFStream +{ + /** + * @var string + */ public $bytes; + + /** + * @var int + */ public $pos; + /** + * @param string $bytes + */ public function __construct(&$bytes) { $this->bytes =& $bytes; $this->pos = 0; } - public function readByte() { - return getid3_lib::BigEndian2Int(substr($this->bytes, $this->pos++, 1)); + /** + * @return int + */ + public function readByte() { // 8-bit + return ord(substr($this->bytes, $this->pos++, 1)); } - public function readInt() { + /** + * @return int + */ + public function readInt() { // 16-bit return ($this->readByte() << 8) + $this->readByte(); } - public function readLong() { + /** + * @return int + */ + public function readLong() { // 32-bit return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte(); } + /** + * @return float|false + */ public function readDouble() { return getid3_lib::BigEndian2Float($this->read(8)); } + /** + * @return string + */ public function readUTF() { $length = $this->readInt(); return $this->read($length); } + /** + * @return string + */ public function readLongUTF() { $length = $this->readLong(); return $this->read($length); } + /** + * @param int $length + * + * @return string + */ public function read($length) { $val = substr($this->bytes, $this->pos, $length); $this->pos += $length; return $val; } + /** + * @return int + */ public function peekByte() { $pos = $this->pos; $val = $this->readByte(); @@ -434,6 +500,9 @@ class AMFStream { return $val; } + /** + * @return int + */ public function peekInt() { $pos = $this->pos; $val = $this->readInt(); @@ -441,6 +510,9 @@ class AMFStream { return $val; } + /** + * @return int + */ public function peekLong() { $pos = $this->pos; $val = $this->readLong(); @@ -448,6 +520,9 @@ class AMFStream { return $val; } + /** + * @return float|false + */ public function peekDouble() { $pos = $this->pos; $val = $this->readDouble(); @@ -455,6 +530,9 @@ class AMFStream { return $val; } + /** + * @return string + */ public function peekUTF() { $pos = $this->pos; $val = $this->readUTF(); @@ -462,6 +540,9 @@ class AMFStream { return $val; } + /** + * @return string + */ public function peekLongUTF() { $pos = $this->pos; $val = $this->readLongUTF(); @@ -470,13 +551,23 @@ class AMFStream { } } -class AMFReader { +class AMFReader +{ + /** + * @var AMFStream + */ public $stream; - public function __construct(&$stream) { - $this->stream =& $stream; + /** + * @param AMFStream $stream + */ + public function __construct(AMFStream $stream) { + $this->stream = $stream; } + /** + * @return mixed + */ public function readData() { $value = null; @@ -547,23 +638,36 @@ class AMFReader { return $value; } + /** + * @return float|false + */ public function readDouble() { return $this->stream->readDouble(); } + /** + * @return bool + */ public function readBoolean() { return $this->stream->readByte() == 1; } + /** + * @return string + */ public function readString() { return $this->stream->readUTF(); } + /** + * @return array + */ public function readObject() { // Get highest numerical index - ignored // $highestIndex = $this->stream->readLong(); $data = array(); + $key = null; while ($key = $this->stream->readUTF()) { $data[$key] = $this->readData(); @@ -576,15 +680,19 @@ class AMFReader { return $data; } + /** + * @return array + */ public function readMixedArray() { // Get highest numerical index - ignored $highestIndex = $this->stream->readLong(); $data = array(); + $key = null; while ($key = $this->stream->readUTF()) { if (is_numeric($key)) { - $key = (float) $key; + $key = (int) $key; } $data[$key] = $this->readData(); } @@ -597,6 +705,9 @@ class AMFReader { return $data; } + /** + * @return array + */ public function readArray() { $length = $this->stream->readLong(); $data = array(); @@ -607,34 +718,61 @@ class AMFReader { return $data; } + /** + * @return float|false + */ public function readDate() { $timestamp = $this->stream->readDouble(); $timezone = $this->stream->readInt(); return $timestamp; } + /** + * @return string + */ public function readLongString() { return $this->stream->readLongUTF(); } + /** + * @return string + */ public function readXML() { return $this->stream->readLongUTF(); } + /** + * @return array + */ public function readTypedObject() { $className = $this->stream->readUTF(); return $this->readObject(); } } -class AVCSequenceParameterSetReader { +class AVCSequenceParameterSetReader +{ + /** + * @var string + */ public $sps; public $start = 0; public $currentBytes = 0; public $currentBits = 0; + + /** + * @var int + */ public $width; + + /** + * @var int + */ public $height; + /** + * @param string $sps + */ public function __construct($sps) { $this->sps = $sps; } @@ -691,18 +829,29 @@ class AVCSequenceParameterSetReader { } } + /** + * @param int $bits + */ public function skipBits($bits) { $newBits = $this->currentBits + $bits; $this->currentBytes += (int)floor($newBits / 8); $this->currentBits = $newBits % 8; } + /** + * @return int + */ public function getBit() { $result = (getid3_lib::BigEndian2Int(substr($this->sps, $this->currentBytes, 1)) >> (7 - $this->currentBits)) & 0x01; $this->skipBits(1); return $result; } + /** + * @param int $bits + * + * @return int + */ public function getBits($bits) { $result = 0; for ($i = 0; $i < $bits; $i++) { @@ -711,6 +860,9 @@ class AVCSequenceParameterSetReader { return $result; } + /** + * @return int + */ public function expGolombUe() { $significantBits = 0; $bit = $this->getBit(); @@ -726,6 +878,9 @@ class AVCSequenceParameterSetReader { return (1 << $significantBits) + $this->getBits($significantBits) - 1; } + /** + * @return int + */ public function expGolombSe() { $result = $this->expGolombUe(); if (($result & 0x01) == 0) { @@ -735,10 +890,16 @@ class AVCSequenceParameterSetReader { } } + /** + * @return int + */ public function getWidth() { return $this->width; } + /** + * @return int + */ public function getHeight() { return $this->height; } diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.matroska.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.matroska.php index 825a22e1..b2b187b6 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.matroska.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.matroska.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio-video.matriska.php // @@ -72,7 +72,7 @@ define('EBML_ID_FILEREFERRAL', 0x0675); // [46][75] -- define('EBML_ID_FILEDESCRIPTION', 0x067E); // [46][7E] -- A human-friendly name for the attached file. define('EBML_ID_FILEUID', 0x06AE); // [46][AE] -- Unique ID representing the file, as random as possible. define('EBML_ID_CONTENTENCALGO', 0x07E1); // [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values: -define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the the data was encrypted with. +define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the data was encrypted with. define('EBML_ID_CONTENTSIGNATURE', 0x07E3); // [47][E3] -- A cryptographic signature of the contents. define('EBML_ID_CONTENTSIGKEYID', 0x07E4); // [47][E4] -- This is the ID of the private key the data was signed with. define('EBML_ID_CONTENTSIGALGO', 0x07E5); // [47][E5] -- The algorithm used for the signature. A value of '0' means that the contents have not been signed but only encrypted. Predefined values: @@ -215,17 +215,33 @@ define('EBML_ID_CLUSTERREFERENCEVIRTUAL', 0x7D); // [FD] -- */ class getid3_matroska extends getid3_handler { - // public options - public static $hide_clusters = true; // if true, do not return information about CLUSTER chunks, since there's a lot of them and they're not usually useful [default: TRUE] - public static $parse_whole_file = false; // true to parse the whole file, not only header [default: FALSE] - - // private parser settings/placeholders + /** + * If true, do not return information about CLUSTER chunks, since there's a lot of them + * and they're not usually useful [default: TRUE]. + * + * @var bool + */ + public static $hide_clusters = true; + + /** + * True to parse the whole file, not only header [default: FALSE]. + * + * @var bool + */ + public static $parse_whole_file = false; + + /* + * Private parser settings/placeholders. + */ private $EBMLbuffer = ''; private $EBMLbuffer_offset = 0; private $EBMLbuffer_length = 0; private $current_offset = 0; private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID); + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -366,8 +382,8 @@ class getid3_matroska extends getid3_handler if (!empty($getid3_temp->info[$header_data_key])) { $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key]; if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) { - foreach ($getid3_temp->info['audio'] as $key => $value) { - $track_info[$key] = $value; + foreach ($getid3_temp->info['audio'] as $sub_key => $value) { + $track_info[$sub_key] = $value; } } } @@ -421,8 +437,8 @@ class getid3_matroska extends getid3_handler if (!empty($getid3_temp->info['ogg'])) { $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg']; if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) { - foreach ($getid3_temp->info['audio'] as $key => $value) { - $track_info[$key] = $value; + foreach ($getid3_temp->info['audio'] as $sub_key => $value) { + $track_info[$sub_key] = $value; } } } @@ -449,9 +465,9 @@ class getid3_matroska extends getid3_handler getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); $parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']); - foreach ($parsed as $key => $value) { - if ($key != 'raw') { - $track_info[$key] = $value; + foreach ($parsed as $sub_key => $value) { + if ($sub_key != 'raw') { + $track_info[$sub_key] = $value; } } $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $parsed; @@ -496,6 +512,9 @@ class getid3_matroska extends getid3_handler return true; } + /** + * @param array $info + */ private function parseEBML(&$info) { // http://www.matroska.org/technical/specs/index.html#EBMLBasics $this->current_offset = $info['avdataoffset']; @@ -1228,6 +1247,11 @@ class getid3_matroska extends getid3_handler } } + /** + * @param int $min_data + * + * @return bool + */ private function EnsureBufferHasEnoughData($min_data=1024) { if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) { $read_bytes = max($min_data, $this->getid3->fread_buffer_size()); @@ -1249,6 +1273,9 @@ class getid3_matroska extends getid3_handler return true; } + /** + * @return int|float|false + */ private function readEBMLint() { $actual_offset = $this->current_offset - $this->EBMLbuffer_offset; @@ -1281,6 +1308,12 @@ class getid3_matroska extends getid3_handler return $int_value; } + /** + * @param int $length + * @param bool $check_buffer + * + * @return string|false + */ private function readEBMLelementData($length, $check_buffer=false) { if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) { return false; @@ -1290,6 +1323,13 @@ class getid3_matroska extends getid3_handler return $data; } + /** + * @param array $element + * @param int $parent_end + * @param array|bool $get_data + * + * @return bool + */ private function getEBMLelement(&$element, $parent_end, $get_data=false) { if ($this->current_offset >= $parent_end) { return false; @@ -1326,6 +1366,11 @@ class getid3_matroska extends getid3_handler return true; } + /** + * @param string $type + * @param int $line + * @param array $element + */ private function unhandledElement($type, $line, $element) { // warn only about unknown and missed elements, not about unuseful if (!in_array($element['id'], $this->unuseful_elements)) { @@ -1338,6 +1383,11 @@ class getid3_matroska extends getid3_handler } } + /** + * @param array $SimpleTagArray + * + * @return bool + */ private function ExtractCommentsSimpleTag($SimpleTagArray) { if (!empty($SimpleTagArray['SimpleTag'])) { foreach ($SimpleTagArray['SimpleTag'] as $SimpleTagKey => $SimpleTagData) { @@ -1353,6 +1403,11 @@ class getid3_matroska extends getid3_handler return true; } + /** + * @param int $parent_end + * + * @return array + */ private function HandleEMBLSimpleTag($parent_end) { $simpletag_entry = array(); @@ -1383,6 +1438,13 @@ class getid3_matroska extends getid3_handler return $simpletag_entry; } + /** + * @param array $element + * @param int $block_type + * @param array $info + * + * @return array + */ private function HandleEMBLClusterBlock($element, $block_type, &$info) { // http://www.matroska.org/technical/specs/index.html#block_structure // http://www.matroska.org/technical/specs/index.html#simpleblock_structure @@ -1446,6 +1508,11 @@ class getid3_matroska extends getid3_handler return $block_data; } + /** + * @param string $EBMLstring + * + * @return int|float|false + */ private static function EBML2Int($EBMLstring) { // http://matroska.org/specs/ @@ -1488,12 +1555,22 @@ class getid3_matroska extends getid3_handler return getid3_lib::BigEndian2Int($EBMLstring); } + /** + * @param int $EBMLdatestamp + * + * @return float + */ private static function EBMLdate2unix($EBMLdatestamp) { // Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC) // 978307200 == mktime(0, 0, 0, 1, 1, 2001) == January 1, 2001 12:00:00am UTC return round(($EBMLdatestamp / 1000000000) + 978307200); } + /** + * @param int $target_type + * + * @return string|int + */ public static function TargetTypeValue($target_type) { // http://www.matroska.org/technical/specs/tagging/index.html static $TargetTypeValue = array(); @@ -1509,6 +1586,11 @@ class getid3_matroska extends getid3_handler return (isset($TargetTypeValue[$target_type]) ? $TargetTypeValue[$target_type] : $target_type); } + /** + * @param int $lacingtype + * + * @return string|int + */ public static function BlockLacingType($lacingtype) { // http://matroska.org/technical/specs/index.html#block_structure static $BlockLacingType = array(); @@ -1521,6 +1603,11 @@ class getid3_matroska extends getid3_handler return (isset($BlockLacingType[$lacingtype]) ? $BlockLacingType[$lacingtype] : $lacingtype); } + /** + * @param string $codecid + * + * @return string + */ public static function CodecIDtoCommonName($codecid) { // http://www.matroska.org/technical/specs/codecid/index.html static $CodecIDlist = array(); @@ -1557,6 +1644,11 @@ class getid3_matroska extends getid3_handler return (isset($CodecIDlist[$codecid]) ? $CodecIDlist[$codecid] : $codecid); } + /** + * @param int $value + * + * @return string + */ private static function EBMLidName($value) { static $EBMLidList = array(); if (empty($EBMLidList)) { @@ -1755,6 +1847,11 @@ class getid3_matroska extends getid3_handler return (isset($EBMLidList[$value]) ? $EBMLidList[$value] : dechex($value)); } + /** + * @param int $value + * + * @return string + */ public static function displayUnit($value) { // http://www.matroska.org/technical/specs/index.html#DisplayUnit static $units = array( @@ -1766,8 +1863,14 @@ class getid3_matroska extends getid3_handler return (isset($units[$value]) ? $units[$value] : 'unknown'); } + /** + * @param array $streams + * + * @return array + */ private static function getDefaultStreamInfo($streams) { + $stream = array(); foreach (array_reverse($streams) as $stream) { if ($stream['default']) { break; diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.mpeg.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.mpeg.php index 044481fb..f27cd4b3 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.mpeg.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.mpeg.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio-video.mpeg.php // @@ -16,7 +16,8 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true); -class getid3_mpeg extends getid3_handler { +class getid3_mpeg extends getid3_handler +{ const START_CODE_BASE = "\x00\x00\x01"; const VIDEO_PICTURE_START = "\x00\x00\x01\x00"; @@ -28,7 +29,9 @@ class getid3_mpeg extends getid3_handler { const VIDEO_GROUP_START = "\x00\x00\x01\xB8"; const AUDIO_START = "\x00\x00\x01\xC0"; - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -122,8 +125,8 @@ class getid3_mpeg extends getid3_handler { } } - $info['mpeg']['video']['pixel_aspect_ratio'] = self::videoAspectRatioLookup($info['mpeg']['video']['raw']['aspect_ratio_information']); - $info['mpeg']['video']['pixel_aspect_ratio_text'] = self::videoAspectRatioTextLookup($info['mpeg']['video']['raw']['aspect_ratio_information']); + $info['mpeg']['video']['pixel_aspect_ratio'] = self::videoAspectRatioLookup($info['mpeg']['video']['raw']['aspect_ratio_information']); // may be overridden later if file turns out to be MPEG-2 + $info['mpeg']['video']['pixel_aspect_ratio_text'] = self::videoAspectRatioTextLookup($info['mpeg']['video']['raw']['aspect_ratio_information']); // may be overridden later if file turns out to be MPEG-2 $info['mpeg']['video']['frame_rate'] = self::videoFramerateLookup($info['mpeg']['video']['raw']['frame_rate_code']); if ($info['mpeg']['video']['raw']['bitrate'] == 0x3FFFF) { // 18 set bits = VBR //$this->warning('This version of getID3() ['.$this->getid3->version().'] cannot determine average bitrate of VBR MPEG video files'); @@ -169,6 +172,16 @@ class getid3_mpeg extends getid3_handler { $info['video']['interlaced'] = !$info['mpeg']['video']['raw']['progressive_sequence']; $info['mpeg']['video']['interlaced'] = !$info['mpeg']['video']['raw']['progressive_sequence']; $info['mpeg']['video']['chroma_format'] = self::chromaFormatTextLookup($info['mpeg']['video']['raw']['chroma_format']); + + if (isset($info['mpeg']['video']['raw']['aspect_ratio_information'])) { + // MPEG-2 defines the aspect ratio flag differently from MPEG-1, but the MPEG-2 extension start code may occur after we've already looked up the aspect ratio assuming it was MPEG-1, so re-lookup assuming MPEG-2 + // This must be done after the extended size is known, so the display aspect ratios can be converted to pixel aspect ratios. + $info['mpeg']['video']['pixel_aspect_ratio'] = self::videoAspectRatioLookup($info['mpeg']['video']['raw']['aspect_ratio_information'], 2, $info['video']['resolution_x'], $info['video']['resolution_y']); + $info['mpeg']['video']['pixel_aspect_ratio_text'] = self::videoAspectRatioTextLookup($info['mpeg']['video']['raw']['aspect_ratio_information'], 2); + $info['video']['pixel_aspect_ratio'] = $info['mpeg']['video']['pixel_aspect_ratio']; + $info['video']['pixel_aspect_ratio_text'] = $info['mpeg']['video']['pixel_aspect_ratio_text']; + } + break; case 2: // 0010 Sequence Display Extension ID @@ -258,7 +271,7 @@ class getid3_mpeg extends getid3_handler { case 0xB8: // group_of_pictures_header $GOPcounter++; - if ($info['mpeg']['video']['bitrate_mode'] == 'vbr') { + if (!empty($info['mpeg']['video']['bitrate_mode']) && ($info['mpeg']['video']['bitrate_mode'] == 'vbr')) { $bitstream = getid3_lib::BigEndian2Bin(substr($MPEGstreamData, $StartCodeOffset + 4, 4)); // 27 bits needed for group_of_pictures_header $bitstreamoffset = 0; @@ -274,7 +287,7 @@ class getid3_mpeg extends getid3_handler { $GOPheader['closed_gop'] = self::readBitsFromStream($bitstream, $bitstreamoffset, 1); // 1 bit flag: closed_gop $GOPheader['broken_link'] = self::readBitsFromStream($bitstream, $bitstreamoffset, 1); // 1 bit flag: broken_link - $time_code_separator = ($GOPheader['drop_frame_flag'] ? ';' : ':'); // While non-drop time code is displayed with colons separating the digit pairs—"HH:MM:SS:FF"—drop frame is usually represented with a semi-colon (;) or period (.) as the divider between all the digit pairs—"HH;MM;SS;FF", "HH.MM.SS.FF" + $time_code_separator = ($GOPheader['drop_frame_flag'] ? ';' : ':'); // While non-drop time code is displayed with colons separating the digit pairs "HH:MM:SS:FF" drop frame is usually represented with a semi-colon (;) or period (.) as the divider between all the digit pairs "HH;MM;SS;FF", "HH.MM.SS.FF" $GOPheader['time_code'] = sprintf('%02d'.$time_code_separator.'%02d'.$time_code_separator.'%02d'.$time_code_separator.'%02d', $GOPheader['time_code_hours'], $GOPheader['time_code_minutes'], $GOPheader['time_code_seconds'], $GOPheader['time_code_pictures']); $info['mpeg']['group_of_pictures'][] = $GOPheader; @@ -502,6 +515,14 @@ echo 'average_File_bitrate = '.number_format(array_sum($vbr_bitrates) / count($v return true; } + /** + * @param string $bitstream + * @param int $bitstreamoffset + * @param int $bits_to_read + * @param bool $return_singlebit_as_boolean + * + * @return bool|float|int + */ private function readBitsFromStream(&$bitstream, &$bitstreamoffset, $bits_to_read, $return_singlebit_as_boolean=true) { $return = bindec(substr($bitstream, $bitstreamoffset, $bits_to_read)); $bitstreamoffset += $bits_to_read; @@ -511,7 +532,12 @@ echo 'average_File_bitrate = '.number_format(array_sum($vbr_bitrates) / count($v return $return; } - + /** + * @param int $VideoBitrate + * @param int $AudioBitrate + * + * @return float|int + */ public static function systemNonOverheadPercentage($VideoBitrate, $AudioBitrate) { $OverheadPercentage = 0; @@ -563,44 +589,93 @@ echo 'average_File_bitrate = '.number_format(array_sum($vbr_bitrates) / count($v return $OverheadPercentage; } - + /** + * @param int $rawframerate + * + * @return float + */ public static function videoFramerateLookup($rawframerate) { $lookup = array(0, 23.976, 24, 25, 29.97, 30, 50, 59.94, 60); - return (isset($lookup[$rawframerate]) ? (float) $lookup[$rawframerate] : (float) 0); + return (float) (isset($lookup[$rawframerate]) ? $lookup[$rawframerate] : 0); } - public static function videoAspectRatioLookup($rawaspectratio) { - $lookup = array(0, 1, 0.6735, 0.7031, 0.7615, 0.8055, 0.8437, 0.8935, 0.9157, 0.9815, 1.0255, 1.0695, 1.0950, 1.1575, 1.2015, 0); - return (isset($lookup[$rawaspectratio]) ? (float) $lookup[$rawaspectratio] : (float) 0); + /** + * @param int $rawaspectratio + * @param int $mpeg_version + * @param int $width + * @param int $height + * + * @return float + */ + public static function videoAspectRatioLookup($rawaspectratio, $mpeg_version=1, $width=0, $height=0) { + $lookup = array( + 1 => array(0, 1, 0.6735, 0.7031, 0.7615, 0.8055, 0.8437, 0.8935, 0.9157, 0.9815, 1.0255, 1.0695, 1.0950, 1.1575, 1.2015, 0), + 2 => array(0, 1, 1.3333, 1.7778, 2.2100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + ); + $ratio = (float) (isset($lookup[$mpeg_version][$rawaspectratio]) ? $lookup[$mpeg_version][$rawaspectratio] : 0); + if ($mpeg_version == 2 && $ratio != 1) { + // Calculate pixel aspect ratio from MPEG-2 display aspect ratio + $ratio = $ratio * $height / $width; + } + return $ratio; } - public static function videoAspectRatioTextLookup($rawaspectratio) { - $lookup = array('forbidden', 'square pixels', '0.6735', '16:9, 625 line, PAL', '0.7615', '0.8055', '16:9, 525 line, NTSC', '0.8935', '4:3, 625 line, PAL, CCIR601', '0.9815', '1.0255', '1.0695', '4:3, 525 line, NTSC, CCIR601', '1.1575', '1.2015', 'reserved'); - return (isset($lookup[$rawaspectratio]) ? $lookup[$rawaspectratio] : ''); + /** + * @param int $rawaspectratio + * @param int $mpeg_version + * + * @return string + */ + public static function videoAspectRatioTextLookup($rawaspectratio, $mpeg_version=1) { + $lookup = array( + 1 => array('forbidden', 'square pixels', '0.6735', '16:9, 625 line, PAL', '0.7615', '0.8055', '16:9, 525 line, NTSC', '0.8935', '4:3, 625 line, PAL, CCIR601', '0.9815', '1.0255', '1.0695', '4:3, 525 line, NTSC, CCIR601', '1.1575', '1.2015', 'reserved'), + 2 => array('forbidden', 'square pixels', '4:3', '16:9', '2.21:1', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved', 'reserved'), // http://dvd.sourceforge.net/dvdinfo/mpeghdrs.html + ); + return (isset($lookup[$mpeg_version][$rawaspectratio]) ? $lookup[$mpeg_version][$rawaspectratio] : ''); } + /** + * @param int $video_format + * + * @return string + */ public static function videoFormatTextLookup($video_format) { // ISO/IEC 13818-2, section 6.3.6, Table 6-6. Meaning of video_format $lookup = array('component', 'PAL', 'NTSC', 'SECAM', 'MAC', 'Unspecified video format', 'reserved(6)', 'reserved(7)'); return (isset($lookup[$video_format]) ? $lookup[$video_format] : ''); } + /** + * @param int $scalable_mode + * + * @return string + */ public static function scalableModeTextLookup($scalable_mode) { // ISO/IEC 13818-2, section 6.3.8, Table 6-10. Definition of scalable_mode $lookup = array('data partitioning', 'spatial scalability', 'SNR scalability', 'temporal scalability'); return (isset($lookup[$scalable_mode]) ? $lookup[$scalable_mode] : ''); } + /** + * @param int $picture_structure + * + * @return string + */ public static function pictureStructureTextLookup($picture_structure) { // ISO/IEC 13818-2, section 6.3.11, Table 6-14 Meaning of picture_structure $lookup = array('reserved', 'Top Field', 'Bottom Field', 'Frame picture'); return (isset($lookup[$picture_structure]) ? $lookup[$picture_structure] : ''); } + /** + * @param int $chroma_format + * + * @return string + */ public static function chromaFormatTextLookup($chroma_format) { // ISO/IEC 13818-2, section 6.3.11, Table 6-14 Meaning of picture_structure $lookup = array('reserved', '4:2:0', '4:2:2', '4:4:4'); return (isset($lookup[$chroma_format]) ? $lookup[$chroma_format] : ''); } -} \ No newline at end of file +} diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.nsv.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.nsv.php index eab601b7..68a2ca1b 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.nsv.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.nsv.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.nsv.php // @@ -17,7 +17,9 @@ class getid3_nsv extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -59,6 +61,11 @@ class getid3_nsv extends getid3_handler return true; } + /** + * @param int $fileoffset + * + * @return bool + */ public function getNSVsHeaderFilepointer($fileoffset) { $info = &$this->getid3->info; $this->fseek($fileoffset); @@ -132,6 +139,12 @@ class getid3_nsv extends getid3_handler return true; } + /** + * @param int $fileoffset + * @param bool $getTOCoffsets + * + * @return bool + */ public function getNSVfHeaderFilepointer($fileoffset, $getTOCoffsets=false) { $info = &$this->getid3->info; $this->fseek($fileoffset); @@ -205,18 +218,22 @@ class getid3_nsv extends getid3_handler return true; } - + /** + * @param int $framerateindex + * + * @return float|false + */ public static function NSVframerateLookup($framerateindex) { if ($framerateindex <= 127) { return (float) $framerateindex; } static $NSVframerateLookup = array(); if (empty($NSVframerateLookup)) { - $NSVframerateLookup[129] = (float) 29.970; - $NSVframerateLookup[131] = (float) 23.976; - $NSVframerateLookup[133] = (float) 14.985; - $NSVframerateLookup[197] = (float) 59.940; - $NSVframerateLookup[199] = (float) 47.952; + $NSVframerateLookup[129] = 29.970; + $NSVframerateLookup[131] = 23.976; + $NSVframerateLookup[133] = 14.985; + $NSVframerateLookup[197] = 59.940; + $NSVframerateLookup[199] = 47.952; } return (isset($NSVframerateLookup[$framerateindex]) ? $NSVframerateLookup[$framerateindex] : false); } diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.quicktime.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.quicktime.php index 2ae7c749..5c791e32 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.quicktime.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.quicktime.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio-video.quicktime.php // @@ -24,6 +24,9 @@ class getid3_quicktime extends getid3_handler public $ReturnAtomData = true; public $ParseAllPossibleAtoms = false; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -162,6 +165,9 @@ class getid3_quicktime extends getid3_handler if (isset($info['bitrate']) && !isset($info['audio']['bitrate']) && !isset($info['quicktime']['video'])) { $info['audio']['bitrate'] = $info['bitrate']; } + if (!empty($info['bitrate']) && !empty($info['audio']['bitrate']) && empty($info['video']['bitrate']) && !empty($info['video']['frame_rate']) && !empty($info['video']['resolution_x']) && ($info['bitrate'] > $info['audio']['bitrate'])) { + $info['video']['bitrate'] = $info['bitrate'] - $info['audio']['bitrate']; + } if (!empty($info['playtime_seconds']) && !isset($info['video']['frame_rate']) && !empty($info['quicktime']['stts_framecount'])) { foreach ($info['quicktime']['stts_framecount'] as $key => $samples_count) { $samples_per_second = $samples_count / $info['playtime_seconds']; @@ -193,318 +199,353 @@ class getid3_quicktime extends getid3_handler if (empty($info['video']['dataformat']) && !empty($info['quicktime']['video'])) { $info['video']['dataformat'] = 'quicktime'; } + if (isset($info['video']) && ($info['mime_type'] == 'audio/mp4') && empty($info['video']['resolution_x']) && empty($info['video']['resolution_y'])) { + unset($info['video']); + } return true; } + /** + * @param string $atomname + * @param int $atomsize + * @param string $atom_data + * @param int $baseoffset + * @param array $atomHierarchy + * @param bool $ParseAllPossibleAtoms + * + * @return array|false + */ public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm // https://code.google.com/p/mp4v2/wiki/iTunesMetadata $info = &$this->getid3->info; - $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see http://www.getid3.org/phpBB3/viewtopic.php?t=1717 + $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see https://www.getid3.org/phpBB3/viewtopic.php?t=1717 array_push($atomHierarchy, $atomname); $atom_structure['hierarchy'] = implode(' ', $atomHierarchy); $atom_structure['name'] = $atomname; $atom_structure['size'] = $atomsize; $atom_structure['offset'] = $baseoffset; - switch ($atomname) { - case 'moov': // MOVie container atom - case 'trak': // TRAcK container atom - case 'clip': // CLIPping container atom - case 'matt': // track MATTe container atom - case 'edts': // EDiTS container atom - case 'tref': // Track REFerence container atom - case 'mdia': // MeDIA container atom - case 'minf': // Media INFormation container atom - case 'dinf': // Data INFormation container atom - case 'udta': // User DaTA container atom - case 'cmov': // Compressed MOVie container atom - case 'rmra': // Reference Movie Record Atom - case 'rmda': // Reference Movie Descriptor Atom - case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR) - $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); - break; + if (substr($atomname, 0, 3) == "\x00\x00\x00") { + // https://github.com/JamesHeinrich/getID3/issues/139 + $atomname = getid3_lib::BigEndian2Int($atomname); + $atom_structure['name'] = $atomname; + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + } else { + switch ($atomname) { + case 'moov': // MOVie container atom + case 'trak': // TRAcK container atom + case 'clip': // CLIPping container atom + case 'matt': // track MATTe container atom + case 'edts': // EDiTS container atom + case 'tref': // Track REFerence container atom + case 'mdia': // MeDIA container atom + case 'minf': // Media INFormation container atom + case 'dinf': // Data INFormation container atom + case 'udta': // User DaTA container atom + case 'cmov': // Compressed MOVie container atom + case 'rmra': // Reference Movie Record Atom + case 'rmda': // Reference Movie Descriptor Atom + case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR) + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + break; - case 'ilst': // Item LiST container atom - if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) { - // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted - $allnumericnames = true; - foreach ($atom_structure['subatoms'] as $subatomarray) { - if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) { - $allnumericnames = false; - break; - } - } - if ($allnumericnames) { - $newData = array(); + case 'ilst': // Item LiST container atom + if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) { + // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted + $allnumericnames = true; foreach ($atom_structure['subatoms'] as $subatomarray) { - foreach ($subatomarray['subatoms'] as $newData_subatomarray) { - unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']); - $newData[$subatomarray['name']] = $newData_subatomarray; + if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) { + $allnumericnames = false; break; } } - $atom_structure['data'] = $newData; - unset($atom_structure['subatoms']); + if ($allnumericnames) { + $newData = array(); + foreach ($atom_structure['subatoms'] as $subatomarray) { + foreach ($subatomarray['subatoms'] as $newData_subatomarray) { + unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']); + $newData[$subatomarray['name']] = $newData_subatomarray; + break; + } + } + $atom_structure['data'] = $newData; + unset($atom_structure['subatoms']); + } } - } - break; - - case "\x00\x00\x00\x01": - case "\x00\x00\x00\x02": - case "\x00\x00\x00\x03": - case "\x00\x00\x00\x04": - case "\x00\x00\x00\x05": - $atomname = getid3_lib::BigEndian2Int($atomname); - $atom_structure['name'] = $atomname; - $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); - break; + break; - case 'stbl': // Sample TaBLe container atom - $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); - $isVideo = false; - $framerate = 0; - $framecount = 0; - foreach ($atom_structure['subatoms'] as $key => $value_array) { - if (isset($value_array['sample_description_table'])) { - foreach ($value_array['sample_description_table'] as $key2 => $value_array2) { - if (isset($value_array2['data_format'])) { - switch ($value_array2['data_format']) { - case 'avc1': - case 'mp4v': - // video data - $isVideo = true; - break; - case 'mp4a': - // audio data - break; + case 'stbl': // Sample TaBLe container atom + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + $isVideo = false; + $framerate = 0; + $framecount = 0; + foreach ($atom_structure['subatoms'] as $key => $value_array) { + if (isset($value_array['sample_description_table'])) { + foreach ($value_array['sample_description_table'] as $key2 => $value_array2) { + if (isset($value_array2['data_format'])) { + switch ($value_array2['data_format']) { + case 'avc1': + case 'mp4v': + // video data + $isVideo = true; + break; + case 'mp4a': + // audio data + break; + } } } - } - } elseif (isset($value_array['time_to_sample_table'])) { - foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) { - if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) { - $framerate = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3); - $framecount = $value_array2['sample_count']; + } elseif (isset($value_array['time_to_sample_table'])) { + foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) { + if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) { + $framerate = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3); + $framecount = $value_array2['sample_count']; + } } } } - } - if ($isVideo && $framerate) { - $info['quicktime']['video']['frame_rate'] = $framerate; - $info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate']; - } - if ($isVideo && $framecount) { - $info['quicktime']['video']['frame_count'] = $framecount; - } - break; - + if ($isVideo && $framerate) { + $info['quicktime']['video']['frame_rate'] = $framerate; + $info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate']; + } + if ($isVideo && $framecount) { + $info['quicktime']['video']['frame_count'] = $framecount; + } + break; - case "\xA9".'alb': // ALBum - case "\xA9".'ART': // - case "\xA9".'art': // ARTist - case "\xA9".'aut': // - case "\xA9".'cmt': // CoMmenT - case "\xA9".'com': // COMposer - case "\xA9".'cpy': // - case "\xA9".'day': // content created year - case "\xA9".'dir': // - case "\xA9".'ed1': // - case "\xA9".'ed2': // - case "\xA9".'ed3': // - case "\xA9".'ed4': // - case "\xA9".'ed5': // - case "\xA9".'ed6': // - case "\xA9".'ed7': // - case "\xA9".'ed8': // - case "\xA9".'ed9': // - case "\xA9".'enc': // - case "\xA9".'fmt': // - case "\xA9".'gen': // GENre - case "\xA9".'grp': // GRouPing - case "\xA9".'hst': // - case "\xA9".'inf': // - case "\xA9".'lyr': // LYRics - case "\xA9".'mak': // - case "\xA9".'mod': // - case "\xA9".'nam': // full NAMe - case "\xA9".'ope': // - case "\xA9".'PRD': // - case "\xA9".'prf': // - case "\xA9".'req': // - case "\xA9".'src': // - case "\xA9".'swr': // - case "\xA9".'too': // encoder - case "\xA9".'trk': // TRacK - case "\xA9".'url': // - case "\xA9".'wrn': // - case "\xA9".'wrt': // WRiTer - case '----': // itunes specific - case 'aART': // Album ARTist - case 'akID': // iTunes store account type - case 'apID': // Purchase Account - case 'atID': // - case 'catg': // CaTeGory - case 'cmID': // - case 'cnID': // - case 'covr': // COVeR artwork - case 'cpil': // ComPILation - case 'cprt': // CoPyRighT - case 'desc': // DESCription - case 'disk': // DISK number - case 'egid': // Episode Global ID - case 'geID': // - case 'gnre': // GeNRE - case 'hdvd': // HD ViDeo - case 'keyw': // KEYWord - case 'ldes': // Long DEScription - case 'pcst': // PodCaST - case 'pgap': // GAPless Playback - case 'plID': // - case 'purd': // PURchase Date - case 'purl': // Podcast URL - case 'rati': // - case 'rndu': // - case 'rpdu': // - case 'rtng': // RaTiNG - case 'sfID': // iTunes store country - case 'soaa': // SOrt Album Artist - case 'soal': // SOrt ALbum - case 'soar': // SOrt ARtist - case 'soco': // SOrt COmposer - case 'sonm': // SOrt NaMe - case 'sosn': // SOrt Show Name - case 'stik': // - case 'tmpo': // TeMPO (BPM) - case 'trkn': // TRacK Number - case 'tven': // tvEpisodeID - case 'tves': // TV EpiSode - case 'tvnn': // TV Network Name - case 'tvsh': // TV SHow Name - case 'tvsn': // TV SeasoN - if ($atom_parent == 'udta') { - // User data atom handler - $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); - $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); - $atom_structure['data'] = substr($atom_data, 4); - $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); - if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { - $info['comments']['language'][] = $atom_structure['language']; - } - } else { - // Apple item list box atom handler - $atomoffset = 0; - if (substr($atom_data, 2, 2) == "\x10\xB5") { - // not sure what it means, but observed on iPhone4 data. - // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data - while ($atomoffset < strlen($atom_data)) { - $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 2)); - $boxsmalltype = substr($atom_data, $atomoffset + 2, 2); - $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize); - if ($boxsmallsize <= 1) { - $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset)); - $atom_structure['data'] = null; - $atomoffset = strlen($atom_data); - break; - } - switch ($boxsmalltype) { - case "\x10\xB5": - $atom_structure['data'] = $boxsmalldata; - break; - default: - $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset); - $atom_structure['data'] = $atom_data; - break; - } - $atomoffset += (4 + $boxsmallsize); + case "\xA9".'alb': // ALBum + case "\xA9".'ART': // + case "\xA9".'art': // ARTist + case "\xA9".'aut': // + case "\xA9".'cmt': // CoMmenT + case "\xA9".'com': // COMposer + case "\xA9".'cpy': // + case "\xA9".'day': // content created year + case "\xA9".'dir': // + case "\xA9".'ed1': // + case "\xA9".'ed2': // + case "\xA9".'ed3': // + case "\xA9".'ed4': // + case "\xA9".'ed5': // + case "\xA9".'ed6': // + case "\xA9".'ed7': // + case "\xA9".'ed8': // + case "\xA9".'ed9': // + case "\xA9".'enc': // + case "\xA9".'fmt': // + case "\xA9".'gen': // GENre + case "\xA9".'grp': // GRouPing + case "\xA9".'hst': // + case "\xA9".'inf': // + case "\xA9".'lyr': // LYRics + case "\xA9".'mak': // + case "\xA9".'mod': // + case "\xA9".'nam': // full NAMe + case "\xA9".'ope': // + case "\xA9".'PRD': // + case "\xA9".'prf': // + case "\xA9".'req': // + case "\xA9".'src': // + case "\xA9".'swr': // + case "\xA9".'too': // encoder + case "\xA9".'trk': // TRacK + case "\xA9".'url': // + case "\xA9".'wrn': // + case "\xA9".'wrt': // WRiTer + case '----': // itunes specific + case 'aART': // Album ARTist + case 'akID': // iTunes store account type + case 'apID': // Purchase Account + case 'atID': // + case 'catg': // CaTeGory + case 'cmID': // + case 'cnID': // + case 'covr': // COVeR artwork + case 'cpil': // ComPILation + case 'cprt': // CoPyRighT + case 'desc': // DESCription + case 'disk': // DISK number + case 'egid': // Episode Global ID + case 'geID': // + case 'gnre': // GeNRE + case 'hdvd': // HD ViDeo + case 'keyw': // KEYWord + case 'ldes': // Long DEScription + case 'pcst': // PodCaST + case 'pgap': // GAPless Playback + case 'plID': // + case 'purd': // PURchase Date + case 'purl': // Podcast URL + case 'rati': // + case 'rndu': // + case 'rpdu': // + case 'rtng': // RaTiNG + case 'sfID': // iTunes store country + case 'soaa': // SOrt Album Artist + case 'soal': // SOrt ALbum + case 'soar': // SOrt ARtist + case 'soco': // SOrt COmposer + case 'sonm': // SOrt NaMe + case 'sosn': // SOrt Show Name + case 'stik': // + case 'tmpo': // TeMPO (BPM) + case 'trkn': // TRacK Number + case 'tven': // tvEpisodeID + case 'tves': // TV EpiSode + case 'tvnn': // TV Network Name + case 'tvsh': // TV SHow Name + case 'tvsn': // TV SeasoN + if ($atom_parent == 'udta') { + // User data atom handler + $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); + $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); + $atom_structure['data'] = substr($atom_data, 4); + + $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); + if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { + $info['comments']['language'][] = $atom_structure['language']; } } else { - while ($atomoffset < strlen($atom_data)) { - $boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4)); - $boxtype = substr($atom_data, $atomoffset + 4, 4); - $boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8); - if ($boxsize <= 1) { - $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset)); - $atom_structure['data'] = null; - $atomoffset = strlen($atom_data); - break; + // Apple item list box atom handler + $atomoffset = 0; + if (substr($atom_data, 2, 2) == "\x10\xB5") { + // not sure what it means, but observed on iPhone4 data. + // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data + while ($atomoffset < strlen($atom_data)) { + $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 2)); + $boxsmalltype = substr($atom_data, $atomoffset + 2, 2); + $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize); + if ($boxsmallsize <= 1) { + $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset)); + $atom_structure['data'] = null; + $atomoffset = strlen($atom_data); + break; + } + switch ($boxsmalltype) { + case "\x10\xB5": + $atom_structure['data'] = $boxsmalldata; + break; + default: + $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset); + $atom_structure['data'] = $atom_data; + break; + } + $atomoffset += (4 + $boxsmallsize); } - $atomoffset += $boxsize; - - switch ($boxtype) { - case 'mean': - case 'name': - $atom_structure[$boxtype] = substr($boxdata, 4); + } else { + while ($atomoffset < strlen($atom_data)) { + $boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4)); + $boxtype = substr($atom_data, $atomoffset + 4, 4); + $boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8); + if ($boxsize <= 1) { + $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset)); + $atom_structure['data'] = null; + $atomoffset = strlen($atom_data); break; + } + $atomoffset += $boxsize; + + switch ($boxtype) { + case 'mean': + case 'name': + $atom_structure[$boxtype] = substr($boxdata, 4); + break; - case 'data': - $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($boxdata, 0, 1)); - $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata, 1, 3)); - switch ($atom_structure['flags_raw']) { - case 0: // data flag - case 21: // tmpo/cpil flag - switch ($atomname) { - case 'cpil': - case 'hdvd': - case 'pcst': - case 'pgap': - // 8-bit integer (boolean) - $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); - break; - - case 'tmpo': - // 16-bit integer - $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2)); - break; - - case 'disk': - case 'trkn': - // binary - $num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2)); - $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2)); - $atom_structure['data'] = empty($num) ? '' : $num; - $atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total; - break; - - case 'gnre': - // enum - $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); - $atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1); - break; - - case 'rtng': - // 8-bit integer - $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); - $atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]); - break; - - case 'stik': - // 8-bit integer (enum) - $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); - $atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]); - break; - - case 'sfID': - // 32-bit integer - $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); - $atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]); - break; - - case 'egid': - case 'purl': - $atom_structure['data'] = substr($boxdata, 8); - break; - - case 'plID': - // 64-bit integer - $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8)); - break; - - case 'covr': - $atom_structure['data'] = substr($boxdata, 8); + case 'data': + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($boxdata, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata, 1, 3)); + switch ($atom_structure['flags_raw']) { + case 0: // data flag + case 21: // tmpo/cpil flag + switch ($atomname) { + case 'cpil': + case 'hdvd': + case 'pcst': + case 'pgap': + // 8-bit integer (boolean) + $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); + break; + + case 'tmpo': + // 16-bit integer + $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2)); + break; + + case 'disk': + case 'trkn': + // binary + $num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2)); + $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2)); + $atom_structure['data'] = empty($num) ? '' : $num; + $atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total; + break; + + case 'gnre': + // enum + $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); + $atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1); + break; + + case 'rtng': + // 8-bit integer + $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); + $atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]); + break; + + case 'stik': + // 8-bit integer (enum) + $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); + $atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]); + break; + + case 'sfID': + // 32-bit integer + $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); + $atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]); + break; + + case 'egid': + case 'purl': + $atom_structure['data'] = substr($boxdata, 8); + break; + + case 'plID': + // 64-bit integer + $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8)); + break; + + case 'covr': + $atom_structure['data'] = substr($boxdata, 8); + // not a foolproof check, but better than nothing + if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) { + $atom_structure['image_mime'] = 'image/jpeg'; + } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) { + $atom_structure['image_mime'] = 'image/png'; + } elseif (preg_match('#^GIF#', $atom_structure['data'])) { + $atom_structure['image_mime'] = 'image/gif'; + } + break; + + case 'atID': + case 'cnID': + case 'geID': + case 'tves': + case 'tvsn': + default: + // 32-bit integer + $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); + } + break; + + case 1: // text flag + case 13: // image flag + default: + $atom_structure['data'] = substr($boxdata, 8); + if ($atomname == 'covr') { // not a foolproof check, but better than nothing if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) { $atom_structure['image_mime'] = 'image/jpeg'; @@ -513,1074 +554,1312 @@ class getid3_quicktime extends getid3_handler } elseif (preg_match('#^GIF#', $atom_structure['data'])) { $atom_structure['image_mime'] = 'image/gif'; } - break; - - case 'atID': - case 'cnID': - case 'geID': - case 'tves': - case 'tvsn': - default: - // 32-bit integer - $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); - } - break; - - case 1: // text flag - case 13: // image flag - default: - $atom_structure['data'] = substr($boxdata, 8); - if ($atomname == 'covr') { - // not a foolproof check, but better than nothing - if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) { - $atom_structure['image_mime'] = 'image/jpeg'; - } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) { - $atom_structure['image_mime'] = 'image/png'; - } elseif (preg_match('#^GIF#', $atom_structure['data'])) { - $atom_structure['image_mime'] = 'image/gif'; } - } - break; + break; - } - break; + } + break; - default: - $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset); - $atom_structure['data'] = $atom_data; + default: + $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset); + $atom_structure['data'] = $atom_data; + } } } } - } - $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 - $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + case 'play': // auto-PLAY atom + $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); - $info['quicktime']['autoplay'] = $atom_structure['autoplay']; - break; + $info['quicktime']['autoplay'] = $atom_structure['autoplay']; + break; - case 'WLOC': // Window LOCation atom - $atom_structure['location_x'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); - $atom_structure['location_y'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); - break; + case 'WLOC': // Window LOCation atom + $atom_structure['location_x'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); + $atom_structure['location_y'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); + break; - case 'LOOP': // LOOPing atom - case 'SelO': // play SELection Only atom - case 'AllF': // play ALL Frames atom - $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data); - break; + case 'LOOP': // LOOPing atom + case 'SelO': // play SELection Only atom + case 'AllF': // play ALL Frames atom + $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data); + break; - case 'name': // - case 'MCPS': // Media Cleaner PRo - case '@PRM': // adobe PReMiere version - case '@PRQ': // adobe PRemiere Quicktime version - $atom_structure['data'] = $atom_data; - break; + case 'name': // + case 'MCPS': // Media Cleaner PRo + case '@PRM': // adobe PReMiere version + case '@PRQ': // adobe PRemiere Quicktime version + $atom_structure['data'] = $atom_data; + break; - case 'cmvd': // Compressed MooV Data atom - // Code by ubergeekØubergeek*tv based on information from - // http://developer.apple.com/quicktime/icefloe/dispatch012.html - $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); + case 'cmvd': // Compressed MooV Data atom + // Code by ubergeekØubergeek*tv based on information from + // http://developer.apple.com/quicktime/icefloe/dispatch012.html + $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); - $CompressedFileData = substr($atom_data, 4); - if ($UncompressedHeader = @gzuncompress($CompressedFileData)) { - $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms); - } else { - $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']); - } - break; + $CompressedFileData = substr($atom_data, 4); + if ($UncompressedHeader = @gzuncompress($CompressedFileData)) { + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms); + } else { + $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']); + } + break; - case 'dcom': // Data COMpression atom - $atom_structure['compression_id'] = $atom_data; - $atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data); - break; + case 'dcom': // Data COMpression atom + $atom_structure['compression_id'] = $atom_data; + $atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data); + break; - case 'rdrf': // Reference movie Data ReFerence atom - $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); - $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); - $atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001); + case 'rdrf': // Reference movie Data ReFerence atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001); - $atom_structure['reference_type_name'] = substr($atom_data, 4, 4); - $atom_structure['reference_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); - switch ($atom_structure['reference_type_name']) { - case 'url ': - $atom_structure['url'] = $this->NoNullString(substr($atom_data, 12)); - break; + $atom_structure['reference_type_name'] = substr($atom_data, 4, 4); + $atom_structure['reference_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + switch ($atom_structure['reference_type_name']) { + case 'url ': + $atom_structure['url'] = $this->NoNullString(substr($atom_data, 12)); + break; - case 'alis': - $atom_structure['file_alias'] = substr($atom_data, 12); - break; + case 'alis': + $atom_structure['file_alias'] = substr($atom_data, 12); + break; - case 'rsrc': - $atom_structure['resource_alias'] = substr($atom_data, 12); - break; + case 'rsrc': + $atom_structure['resource_alias'] = substr($atom_data, 12); + break; - default: - $atom_structure['data'] = substr($atom_data, 12); - break; - } - break; + default: + $atom_structure['data'] = substr($atom_data, 12); + break; + } + break; - case 'rmqu': // Reference Movie QUality atom - $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data); - break; + case 'rmqu': // Reference Movie QUality atom + $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data); + break; - case 'rmcs': // Reference Movie Cpu Speed atom - $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 - $atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); - break; + case 'rmcs': // Reference Movie Cpu Speed atom + $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 + $atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + break; - case 'rmvc': // Reference Movie Version Check atom - $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 - $atom_structure['gestalt_selector'] = substr($atom_data, 4, 4); - $atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); - $atom_structure['gestalt_value'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); - $atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2)); - break; + case 'rmvc': // Reference Movie Version Check atom + $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 + $atom_structure['gestalt_selector'] = substr($atom_data, 4, 4); + $atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $atom_structure['gestalt_value'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); + $atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2)); + break; - case 'rmcd': // Reference Movie Component check atom - $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 - $atom_structure['component_type'] = substr($atom_data, 4, 4); - $atom_structure['component_subtype'] = substr($atom_data, 8, 4); - $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_min_version'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4)); - break; + case 'rmcd': // Reference Movie Component check atom + $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 + $atom_structure['component_type'] = substr($atom_data, 4, 4); + $atom_structure['component_subtype'] = substr($atom_data, 8, 4); + $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_min_version'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4)); + break; - case 'rmdr': // Reference Movie Data Rate atom - $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 - $atom_structure['data_rate'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + case 'rmdr': // Reference Movie Data Rate atom + $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 + $atom_structure['data_rate'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10; - break; + $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10; + break; - case 'rmla': // Reference Movie Language Atom - $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 - $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + case 'rmla': // Reference Movie Language Atom + $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 + $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); - $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); - if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { - $info['comments']['language'][] = $atom_structure['language']; - } - break; + $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); + if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { + $info['comments']['language'][] = $atom_structure['language']; + } + break; - case 'rmla': // Reference Movie Language Atom - $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 - $atom_structure['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); - break; + case 'ptv ': // Print To Video - defines a movie's full screen mode + // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm + $atom_structure['display_size_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); + $atom_structure['reserved_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000 + $atom_structure['reserved_2'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000 + $atom_structure['slide_show_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1)); + $atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1)); + + $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag']; + $atom_structure['flags']['slide_show'] = (bool) $atom_structure['slide_show_flag']; + + $ptv_lookup[0] = 'normal'; + $ptv_lookup[1] = 'double'; + $ptv_lookup[2] = 'half'; + $ptv_lookup[3] = 'full'; + $ptv_lookup[4] = 'current'; + if (isset($ptv_lookup[$atom_structure['display_size_raw']])) { + $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']]; + } else { + $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')'); + } + break; - case 'ptv ': // Print To Video - defines a movie's full screen mode - // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm - $atom_structure['display_size_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); - $atom_structure['reserved_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000 - $atom_structure['reserved_2'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000 - $atom_structure['slide_show_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1)); - $atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1)); - - $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag']; - $atom_structure['flags']['slide_show'] = (bool) $atom_structure['slide_show_flag']; - - $ptv_lookup[0] = 'normal'; - $ptv_lookup[1] = 'double'; - $ptv_lookup[2] = 'half'; - $ptv_lookup[3] = 'full'; - $ptv_lookup[4] = 'current'; - if (isset($ptv_lookup[$atom_structure['display_size_raw']])) { - $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']]; - } else { - $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')'); - } - break; + case 'stsd': // Sample Table Sample Description atom + $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 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + // see: https://github.com/JamesHeinrich/getID3/issues/111 + // Some corrupt files have been known to have high bits set in the number_entries field + // This field shouldn't really need to be 32-bits, values stores are likely in the range 1-100000 + // Workaround: mask off the upper byte and throw a warning if it's nonzero + if ($atom_structure['number_entries'] > 0x000FFFFF) { + if ($atom_structure['number_entries'] > 0x00FFFFFF) { + $this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Ignoring upper byte and interpreting this as 0x'.getid3_lib::PrintHexBytes(substr($atom_data, 5, 3), true, false).' = '.($atom_structure['number_entries'] & 0x00FFFFFF)); + $atom_structure['number_entries'] = ($atom_structure['number_entries'] & 0x00FFFFFF); + } else { + $this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Please report this to info@getid3.org referencing bug report #111'); + } + } - case 'stsd': // Sample Table Sample Description atom - $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 - $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $stsdEntriesDataOffset = 8; - for ($i = 0; $i < $atom_structure['number_entries']; $i++) { - $atom_structure['sample_description_table'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4)); - $stsdEntriesDataOffset += 4; - $atom_structure['sample_description_table'][$i]['data_format'] = substr($atom_data, $stsdEntriesDataOffset, 4); - $stsdEntriesDataOffset += 4; - $atom_structure['sample_description_table'][$i]['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6)); - $stsdEntriesDataOffset += 6; - $atom_structure['sample_description_table'][$i]['reference_index'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2)); - $stsdEntriesDataOffset += 2; - $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); - - $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); - - switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) { - - case "\x00\x00\x00\x00": - // audio tracks - $atom_structure['sample_description_table'][$i]['audio_channels'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 2)); - $atom_structure['sample_description_table'][$i]['audio_bit_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10, 2)); - $atom_structure['sample_description_table'][$i]['audio_compression_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 2)); - $atom_structure['sample_description_table'][$i]['audio_packet_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14, 2)); - $atom_structure['sample_description_table'][$i]['audio_sample_rate'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16, 4)); - - // video tracks - // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html - $atom_structure['sample_description_table'][$i]['temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4)); - $atom_structure['sample_description_table'][$i]['spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4)); - $atom_structure['sample_description_table'][$i]['width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2)); - $atom_structure['sample_description_table'][$i]['height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2)); - $atom_structure['sample_description_table'][$i]['resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4)); - $atom_structure['sample_description_table'][$i]['resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4)); - $atom_structure['sample_description_table'][$i]['data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 4)); - $atom_structure['sample_description_table'][$i]['frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36, 2)); - $atom_structure['sample_description_table'][$i]['compressor_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 38, 4); - $atom_structure['sample_description_table'][$i]['pixel_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42, 2)); - $atom_structure['sample_description_table'][$i]['color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44, 2)); - - switch ($atom_structure['sample_description_table'][$i]['data_format']) { - case '2vuY': - case 'avc1': - case 'cvid': - case 'dvc ': - case 'dvcp': - case 'gif ': - case 'h263': - case 'jpeg': - case 'kpcd': - case 'mjpa': - case 'mjpb': - case 'mp4v': - case 'png ': - case 'raw ': - case 'rle ': - case 'rpza': - case 'smc ': - case 'SVQ1': - case 'SVQ3': - case 'tiff': - case 'v210': - case 'v216': - case 'v308': - case 'v408': - case 'v410': - case 'yuv2': - $info['fileformat'] = 'mp4'; - $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; -// http://www.getid3.org/phpBB3/viewtopic.php?t=1550 -//if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers -if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) { - // assume that values stored here are more important than values stored in [tkhd] atom - $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width']; - $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height']; - $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x']; - $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y']; -} - break; + $stsdEntriesDataOffset = 8; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['sample_description_table'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4)); + $stsdEntriesDataOffset += 4; + $atom_structure['sample_description_table'][$i]['data_format'] = substr($atom_data, $stsdEntriesDataOffset, 4); + $stsdEntriesDataOffset += 4; + $atom_structure['sample_description_table'][$i]['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6)); + $stsdEntriesDataOffset += 6; + $atom_structure['sample_description_table'][$i]['reference_index'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2)); + $stsdEntriesDataOffset += 2; + $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); + + $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); + + switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) { + + case "\x00\x00\x00\x00": + // audio tracks + $atom_structure['sample_description_table'][$i]['audio_channels'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 2)); + $atom_structure['sample_description_table'][$i]['audio_bit_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10, 2)); + $atom_structure['sample_description_table'][$i]['audio_compression_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 2)); + $atom_structure['sample_description_table'][$i]['audio_packet_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14, 2)); + $atom_structure['sample_description_table'][$i]['audio_sample_rate'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16, 4)); + + // video tracks + // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html + $atom_structure['sample_description_table'][$i]['temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4)); + $atom_structure['sample_description_table'][$i]['spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4)); + $atom_structure['sample_description_table'][$i]['width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2)); + $atom_structure['sample_description_table'][$i]['height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2)); + $atom_structure['sample_description_table'][$i]['resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4)); + $atom_structure['sample_description_table'][$i]['resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4)); + $atom_structure['sample_description_table'][$i]['data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 4)); + $atom_structure['sample_description_table'][$i]['frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36, 2)); + $atom_structure['sample_description_table'][$i]['compressor_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 38, 4); + $atom_structure['sample_description_table'][$i]['pixel_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42, 2)); + $atom_structure['sample_description_table'][$i]['color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44, 2)); + + switch ($atom_structure['sample_description_table'][$i]['data_format']) { + case '2vuY': + case 'avc1': + case 'cvid': + case 'dvc ': + case 'dvcp': + case 'gif ': + case 'h263': + case 'jpeg': + case 'kpcd': + case 'mjpa': + case 'mjpb': + case 'mp4v': + case 'png ': + case 'raw ': + case 'rle ': + case 'rpza': + case 'smc ': + case 'SVQ1': + case 'SVQ3': + case 'tiff': + case 'v210': + case 'v216': + case 'v308': + case 'v408': + case 'v410': + case 'yuv2': + $info['fileformat'] = 'mp4'; + $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; + if ($this->QuicktimeVideoCodecLookup($info['video']['fourcc'])) { + $info['video']['fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($info['video']['fourcc']); + } + + // https://www.getid3.org/phpBB3/viewtopic.php?t=1550 + //if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers + if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) { + // assume that values stored here are more important than values stored in [tkhd] atom + $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width']; + $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height']; + $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x']; + $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y']; + } + break; - case 'qtvr': - $info['video']['dataformat'] = 'quicktimevr'; - break; + case 'qtvr': + $info['video']['dataformat'] = 'quicktimevr'; + break; - case 'mp4a': - default: - $info['quicktime']['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); - $info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate']; - $info['quicktime']['audio']['channels'] = $atom_structure['sample_description_table'][$i]['audio_channels']; - $info['quicktime']['audio']['bit_depth'] = $atom_structure['sample_description_table'][$i]['audio_bit_depth']; - $info['audio']['codec'] = $info['quicktime']['audio']['codec']; - $info['audio']['sample_rate'] = $info['quicktime']['audio']['sample_rate']; - $info['audio']['channels'] = $info['quicktime']['audio']['channels']; - $info['audio']['bits_per_sample'] = $info['quicktime']['audio']['bit_depth']; - switch ($atom_structure['sample_description_table'][$i]['data_format']) { - case 'raw ': // PCM - case 'alac': // Apple Lossless Audio Codec - $info['audio']['lossless'] = true; - break; - default: - $info['audio']['lossless'] = false; - break; - } - break; - } - break; + case 'mp4a': + default: + $info['quicktime']['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); + $info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate']; + $info['quicktime']['audio']['channels'] = $atom_structure['sample_description_table'][$i]['audio_channels']; + $info['quicktime']['audio']['bit_depth'] = $atom_structure['sample_description_table'][$i]['audio_bit_depth']; + $info['audio']['codec'] = $info['quicktime']['audio']['codec']; + $info['audio']['sample_rate'] = $info['quicktime']['audio']['sample_rate']; + $info['audio']['channels'] = $info['quicktime']['audio']['channels']; + $info['audio']['bits_per_sample'] = $info['quicktime']['audio']['bit_depth']; + switch ($atom_structure['sample_description_table'][$i]['data_format']) { + case 'raw ': // PCM + case 'alac': // Apple Lossless Audio Codec + case 'sowt': // signed/two's complement (Little Endian) + case 'twos': // signed/two's complement (Big Endian) + case 'in24': // 24-bit Integer + case 'in32': // 32-bit Integer + case 'fl32': // 32-bit Floating Point + case 'fl64': // 64-bit Floating Point + $info['audio']['lossless'] = $info['quicktime']['audio']['lossless'] = true; + $info['audio']['bitrate'] = $info['quicktime']['audio']['bitrate'] = $info['audio']['channels'] * $info['audio']['bits_per_sample'] * $info['audio']['sample_rate']; + break; + default: + $info['audio']['lossless'] = false; + break; + } + break; + } + break; - default: - switch ($atom_structure['sample_description_table'][$i]['data_format']) { - case 'mp4s': - $info['fileformat'] = 'mp4'; - break; + default: + switch ($atom_structure['sample_description_table'][$i]['data_format']) { + case 'mp4s': + $info['fileformat'] = 'mp4'; + break; - default: - // video atom - $atom_structure['sample_description_table'][$i]['video_temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4)); - $atom_structure['sample_description_table'][$i]['video_spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4)); - $atom_structure['sample_description_table'][$i]['video_frame_width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2)); - $atom_structure['sample_description_table'][$i]['video_frame_height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2)); - $atom_structure['sample_description_table'][$i]['video_resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20, 4)); - $atom_structure['sample_description_table'][$i]['video_resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4)); - $atom_structure['sample_description_table'][$i]['video_data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4)); - $atom_structure['sample_description_table'][$i]['video_frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 2)); - $atom_structure['sample_description_table'][$i]['video_encoder_name_len'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34, 1)); - $atom_structure['sample_description_table'][$i]['video_encoder_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 35, $atom_structure['sample_description_table'][$i]['video_encoder_name_len']); - $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66, 2)); - $atom_structure['sample_description_table'][$i]['video_color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68, 2)); - - $atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color'); - $atom_structure['sample_description_table'][$i]['video_pixel_color_name'] = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']); - - if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') { - $info['quicktime']['video']['codec_fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; - $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); - $info['quicktime']['video']['codec'] = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']); - $info['quicktime']['video']['color_depth'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth']; - $info['quicktime']['video']['color_depth_name'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_name']; - - $info['video']['codec'] = $info['quicktime']['video']['codec']; - $info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth']; - } - $info['video']['lossless'] = false; - $info['video']['pixel_aspect_ratio'] = (float) 1; - break; - } - break; - } - switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) { - case 'mp4a': - $info['audio']['dataformat'] = 'mp4'; - $info['quicktime']['audio']['codec'] = 'mp4'; - break; + default: + // video atom + $atom_structure['sample_description_table'][$i]['video_temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4)); + $atom_structure['sample_description_table'][$i]['video_spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4)); + $atom_structure['sample_description_table'][$i]['video_frame_width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2)); + $atom_structure['sample_description_table'][$i]['video_frame_height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2)); + $atom_structure['sample_description_table'][$i]['video_resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20, 4)); + $atom_structure['sample_description_table'][$i]['video_resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4)); + $atom_structure['sample_description_table'][$i]['video_data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4)); + $atom_structure['sample_description_table'][$i]['video_frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 2)); + $atom_structure['sample_description_table'][$i]['video_encoder_name_len'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34, 1)); + $atom_structure['sample_description_table'][$i]['video_encoder_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 35, $atom_structure['sample_description_table'][$i]['video_encoder_name_len']); + $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66, 2)); + $atom_structure['sample_description_table'][$i]['video_color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68, 2)); + + $atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color'); + $atom_structure['sample_description_table'][$i]['video_pixel_color_name'] = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']); + + if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') { + $info['quicktime']['video']['codec_fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; + $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); + $info['quicktime']['video']['codec'] = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']); + $info['quicktime']['video']['color_depth'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth']; + $info['quicktime']['video']['color_depth_name'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_name']; + + $info['video']['codec'] = $info['quicktime']['video']['codec']; + $info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth']; + } + $info['video']['lossless'] = false; + $info['video']['pixel_aspect_ratio'] = (float) 1; + break; + } + break; + } + switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) { + case 'mp4a': + $info['audio']['dataformat'] = 'mp4'; + $info['quicktime']['audio']['codec'] = 'mp4'; + break; - case '3ivx': - case '3iv1': - case '3iv2': - $info['video']['dataformat'] = '3ivx'; - break; + case '3ivx': + case '3iv1': + case '3iv2': + $info['video']['dataformat'] = '3ivx'; + break; - case 'xvid': - $info['video']['dataformat'] = 'xvid'; - break; + case 'xvid': + $info['video']['dataformat'] = 'xvid'; + break; - case 'mp4v': - $info['video']['dataformat'] = 'mpeg4'; - break; + case 'mp4v': + $info['video']['dataformat'] = 'mpeg4'; + break; - case 'divx': - case 'div1': - case 'div2': - case 'div3': - case 'div4': - case 'div5': - case 'div6': - $info['video']['dataformat'] = 'divx'; - break; + case 'divx': + case 'div1': + case 'div2': + case 'div3': + case 'div4': + case 'div5': + case 'div6': + $info['video']['dataformat'] = 'divx'; + break; - default: - // do nothing - break; + default: + // do nothing + break; + } + unset($atom_structure['sample_description_table'][$i]['data']); } - unset($atom_structure['sample_description_table'][$i]['data']); - } - break; + break; - case 'stts': // Sample Table Time-to-Sample atom - $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 - $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $sttsEntriesDataOffset = 8; - //$FrameRateCalculatorArray = array(); - $frames_count = 0; + case 'stts': // Sample Table Time-to-Sample atom + $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 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $sttsEntriesDataOffset = 8; + //$FrameRateCalculatorArray = array(); + $frames_count = 0; - $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']); - if ($max_stts_entries_to_scan < $atom_structure['number_entries']) { - $this->warning('QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($atom_structure['number_entries'] / 1048576).'MB).'); - } - for ($i = 0; $i < $max_stts_entries_to_scan; $i++) { - $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); - $sttsEntriesDataOffset += 4; - $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); - $sttsEntriesDataOffset += 4; - - $frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count']; - - // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM - //if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) { - // $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration']; - // if ($stts_new_framerate <= 60) { - // // some atoms have durations of "1" giving a very large framerate, which probably is not right - // $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate); + $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']); + if ($max_stts_entries_to_scan < $atom_structure['number_entries']) { + $this->warning('QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($this->getid3->memory_limit / 1048576).'MB).'); + } + for ($i = 0; $i < $max_stts_entries_to_scan; $i++) { + $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); + $sttsEntriesDataOffset += 4; + $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); + $sttsEntriesDataOffset += 4; + + $frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count']; + + // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM + //if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) { + // $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration']; + // if ($stts_new_framerate <= 60) { + // // some atoms have durations of "1" giving a very large framerate, which probably is not right + // $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate); + // } + //} + // + //$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count']; + } + $info['quicktime']['stts_framecount'][] = $frames_count; + //$sttsFramesTotal = 0; + //$sttsSecondsTotal = 0; + //foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) { + // if (($frames_per_second > 60) || ($frames_per_second < 1)) { + // // not video FPS information, probably audio information + // $sttsFramesTotal = 0; + // $sttsSecondsTotal = 0; + // break; // } + // $sttsFramesTotal += $frame_count; + // $sttsSecondsTotal += $frame_count / $frames_per_second; //} - // - //$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count']; - } - $info['quicktime']['stts_framecount'][] = $frames_count; - //$sttsFramesTotal = 0; - //$sttsSecondsTotal = 0; - //foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) { - // if (($frames_per_second > 60) || ($frames_per_second < 1)) { - // // not video FPS information, probably audio information - // $sttsFramesTotal = 0; - // $sttsSecondsTotal = 0; - // break; - // } - // $sttsFramesTotal += $frame_count; - // $sttsSecondsTotal += $frame_count / $frames_per_second; - //} - //if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) { - // if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) { - // $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal; - // } - //} - break; + //if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) { + // if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) { + // $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal; + // } + //} + break; - case 'stss': // Sample Table Sync Sample (key frames) atom - 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 - $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $stssEntriesDataOffset = 8; - for ($i = 0; $i < $atom_structure['number_entries']; $i++) { - $atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4)); - $stssEntriesDataOffset += 4; + case 'stss': // Sample Table Sync Sample (key frames) atom + 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 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $stssEntriesDataOffset = 8; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4)); + $stssEntriesDataOffset += 4; + } } - } - break; + break; - case 'stsc': // Sample Table Sample-to-Chunk atom - 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 - $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $stscEntriesDataOffset = 8; - for ($i = 0; $i < $atom_structure['number_entries']; $i++) { - $atom_structure['sample_to_chunk_table'][$i]['first_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4)); - $stscEntriesDataOffset += 4; - $atom_structure['sample_to_chunk_table'][$i]['samples_per_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4)); - $stscEntriesDataOffset += 4; - $atom_structure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4)); - $stscEntriesDataOffset += 4; + case 'stsc': // Sample Table Sample-to-Chunk atom + 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 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $stscEntriesDataOffset = 8; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['sample_to_chunk_table'][$i]['first_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4)); + $stscEntriesDataOffset += 4; + $atom_structure['sample_to_chunk_table'][$i]['samples_per_chunk'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4)); + $stscEntriesDataOffset += 4; + $atom_structure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4)); + $stscEntriesDataOffset += 4; + } } - } - break; + break; - case 'stsz': // Sample Table SiZe atom - 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 - $atom_structure['sample_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); - $stszEntriesDataOffset = 12; - if ($atom_structure['sample_size'] == 0) { + case 'stsz': // Sample Table SiZe atom + 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 + $atom_structure['sample_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $stszEntriesDataOffset = 12; + if ($atom_structure['sample_size'] == 0) { + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stszEntriesDataOffset, 4)); + $stszEntriesDataOffset += 4; + } + } + } + break; + + + case 'stco': // Sample Table Chunk Offset atom + 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 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $stcoEntriesDataOffset = 8; for ($i = 0; $i < $atom_structure['number_entries']; $i++) { - $atom_structure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stszEntriesDataOffset, 4)); - $stszEntriesDataOffset += 4; + $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 4)); + $stcoEntriesDataOffset += 4; } } - } - break; + break; - case 'stco': // Sample Table Chunk Offset atom - 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 - $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $stcoEntriesDataOffset = 8; - for ($i = 0; $i < $atom_structure['number_entries']; $i++) { - $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 4)); - $stcoEntriesDataOffset += 4; + case 'co64': // Chunk Offset 64-bit (version of "stco" that supports > 2GB files) + 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 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $stcoEntriesDataOffset = 8; + for ($i = 0; $i < $atom_structure['number_entries']; $i++) { + $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 8)); + $stcoEntriesDataOffset += 8; + } } - } - break; + break; - case 'co64': // Chunk Offset 64-bit (version of "stco" that supports > 2GB files) - if ($ParseAllPossibleAtoms) { + case 'dref': // Data REFerence atom $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 $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $stcoEntriesDataOffset = 8; + $drefDataOffset = 8; for ($i = 0; $i < $atom_structure['number_entries']; $i++) { - $atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 8)); - $stcoEntriesDataOffset += 8; + $atom_structure['data_references'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4)); + $drefDataOffset += 4; + $atom_structure['data_references'][$i]['type'] = substr($atom_data, $drefDataOffset, 4); + $drefDataOffset += 4; + $atom_structure['data_references'][$i]['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 1)); + $drefDataOffset += 1; + $atom_structure['data_references'][$i]['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 3)); // hardcoded: 0x0000 + $drefDataOffset += 3; + $atom_structure['data_references'][$i]['data'] = substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3)); + $drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3); + + $atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001); } - } - break; + break; - case 'dref': // Data REFerence atom - $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 - $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $drefDataOffset = 8; - for ($i = 0; $i < $atom_structure['number_entries']; $i++) { - $atom_structure['data_references'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4)); - $drefDataOffset += 4; - $atom_structure['data_references'][$i]['type'] = substr($atom_data, $drefDataOffset, 4); - $drefDataOffset += 4; - $atom_structure['data_references'][$i]['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 1)); - $drefDataOffset += 1; - $atom_structure['data_references'][$i]['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 3)); // hardcoded: 0x0000 - $drefDataOffset += 3; - $atom_structure['data_references'][$i]['data'] = substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3)); - $drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3); - - $atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001); - } - break; + case 'gmin': // base Media INformation atom + $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 + $atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + $atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)); + $atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2)); + $atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); + $atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 2)); + $atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2)); + break; - case 'gmin': // base Media INformation atom - $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 - $atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); - $atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)); - $atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2)); - $atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); - $atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 2)); - $atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2)); - break; + case 'smhd': // Sound Media information HeaDer atom + $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 + $atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + $atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)); + break; - case 'smhd': // Sound Media information HeaDer atom - $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 - $atom_structure['balance'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); - $atom_structure['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)); - break; + case 'vmhd': // Video Media information HeaDer atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); + $atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)); + $atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2)); + $atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); + $atom_structure['flags']['no_lean_ahead'] = (bool) ($atom_structure['flags_raw'] & 0x001); + break; - case 'vmhd': // Video Media information HeaDer atom - $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); - $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); - $atom_structure['graphics_mode'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); - $atom_structure['opcolor_red'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)); - $atom_structure['opcolor_green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 2)); - $atom_structure['opcolor_blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); - $atom_structure['flags']['no_lean_ahead'] = (bool) ($atom_structure['flags_raw'] & 0x001); - break; + case 'hdlr': // HanDLeR reference atom + $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 + $atom_structure['component_type'] = substr($atom_data, 4, 4); + $atom_structure['component_subtype'] = substr($atom_data, 8, 4); + $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)); + if (($atom_structure['component_subtype'] == 'STpn') && ($atom_structure['component_manufacturer'] == 'zzzz')) { + $info['video']['dataformat'] = 'quicktimevr'; + } + break; - case 'hdlr': // HanDLeR reference atom - $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 - $atom_structure['component_type'] = substr($atom_data, 4, 4); - $atom_structure['component_subtype'] = substr($atom_data, 8, 4); - $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)); - if (($atom_structure['component_subtype'] == 'STpn') && ($atom_structure['component_manufacturer'] == 'zzzz')) { - $info['video']['dataformat'] = 'quicktimevr'; - } - break; + case 'mdhd': // MeDia HeaDer atom + $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 + $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); + $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); + $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 2)); + $atom_structure['quality'] = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2)); + + if ($atom_structure['time_scale'] == 0) { + $this->error('Corrupt Quicktime file: mdhd.time_scale == zero'); + return false; + } + $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']); + $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']); + $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']); + $atom_structure['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale']; + $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); + if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { + $info['comments']['language'][] = $atom_structure['language']; + } + break; - case 'mdhd': // MeDia HeaDer atom - $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 - $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); - $atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); - $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); - $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 2)); - $atom_structure['quality'] = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2)); - if ($atom_structure['time_scale'] == 0) { - $this->error('Corrupt Quicktime file: mdhd.time_scale == zero'); - return false; - } - $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']); - - $atom_structure['creation_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['creation_time']); - $atom_structure['modify_time_unix'] = getid3_lib::DateMac2Unix($atom_structure['modify_time']); - $atom_structure['playtime_seconds'] = $atom_structure['duration'] / $atom_structure['time_scale']; - $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); - if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { - $info['comments']['language'][] = $atom_structure['language']; - } - break; + case 'pnot': // Preview atom + $atom_structure['modification_date'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // "standard Macintosh format" + $atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x00 + $atom_structure['atom_type'] = substr($atom_data, 6, 4); // usually: 'PICT' + $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']); + break; - case 'pnot': // Preview atom - $atom_structure['modification_date'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // "standard Macintosh format" - $atom_structure['version_number'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x00 - $atom_structure['atom_type'] = substr($atom_data, 6, 4); // usually: 'PICT' - $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']); - break; + case 'crgn': // Clipping ReGioN atom + $atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); // The Region size, Region boundary box, + $atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8)); // and Clipping region data fields + $atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region. + break; - case 'crgn': // Clipping ReGioN atom - $atom_structure['region_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); // The Region size, Region boundary box, - $atom_structure['boundary_box'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 8)); // and Clipping region data fields - $atom_structure['clipping_data'] = substr($atom_data, 10); // constitute a QuickDraw region. - break; + case 'load': // track LOAD settings atom + $atom_structure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); + $atom_structure['preload_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['preload_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $atom_structure['default_hints_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); + $atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x0020); + $atom_structure['default_hints']['high_quality'] = (bool) ($atom_structure['default_hints_raw'] & 0x0100); + break; - case 'load': // track LOAD settings atom - $atom_structure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); - $atom_structure['preload_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $atom_structure['preload_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); - $atom_structure['default_hints_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); - $atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x0020); - $atom_structure['default_hints']['high_quality'] = (bool) ($atom_structure['default_hints_raw'] & 0x0100); - break; + case 'tmcd': // TiMe CoDe atom + case 'chap': // CHAPter list atom + case 'sync': // SYNChronization atom + case 'scpt': // tranSCriPT atom + case 'ssrc': // non-primary SouRCe atom + for ($i = 0; $i < strlen($atom_data); $i += 4) { + @$atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4)); + } + break; - case 'tmcd': // TiMe CoDe atom - case 'chap': // CHAPter list atom - case 'sync': // SYNChronization atom - case 'scpt': // tranSCriPT atom - case 'ssrc': // non-primary SouRCe atom - for ($i = 0; $i < strlen($atom_data); $i += 4) { - @$atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4)); - } - break; + case 'elst': // Edit LiST atom + $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 + $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) { + $atom_structure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4)); + $atom_structure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4)); + $atom_structure['edit_list'][$i]['media_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + ($i * 12) + 8, 4)); + } + break; - case 'elst': // Edit LiST atom - $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 - $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) { - $atom_structure['edit_list'][$i]['track_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4)); - $atom_structure['edit_list'][$i]['media_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4)); - $atom_structure['edit_list'][$i]['media_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + ($i * 12) + 8, 4)); - } - break; + case 'kmat': // compressed MATte atom + $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 + $atom_structure['matte_data_raw'] = substr($atom_data, 4); + break; - case 'kmat': // compressed MATte atom - $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 - $atom_structure['matte_data_raw'] = substr($atom_data, 4); - break; + case 'ctab': // Color TABle atom + $atom_structure['color_table_seed'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // hardcoded: 0x00000000 + $atom_structure['color_table_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x8000 + $atom_structure['color_table_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)) + 1; + for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) { + $atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2)); + $atom_structure['color_table'][$colortableentry]['red'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2)); + $atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2)); + $atom_structure['color_table'][$colortableentry]['blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2)); + } + break; - case 'ctab': // Color TABle atom - $atom_structure['color_table_seed'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); // hardcoded: 0x00000000 - $atom_structure['color_table_flags'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x8000 - $atom_structure['color_table_size'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 2)) + 1; - for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) { - $atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2)); - $atom_structure['color_table'][$colortableentry]['red'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2)); - $atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2)); - $atom_structure['color_table'][$colortableentry]['blue'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2)); - } - break; + case 'mvhd': // MoVie HeaDer atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); + $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); + $atom_structure['preferred_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4)); + $atom_structure['preferred_volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2)); + $atom_structure['reserved'] = substr($atom_data, 26, 10); + $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4)); + $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4)); + $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4)); + $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4)); + $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4)); + $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4)); + $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4)); + $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4)); + $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4)); + $atom_structure['preview_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 72, 4)); + $atom_structure['preview_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 76, 4)); + $atom_structure['poster_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 80, 4)); + $atom_structure['selection_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 84, 4)); + $atom_structure['selection_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 88, 4)); + $atom_structure['current_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 92, 4)); + $atom_structure['next_track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 96, 4)); + + if ($atom_structure['time_scale'] == 0) { + $this->error('Corrupt Quicktime file: mvhd.time_scale == zero'); + return false; + } + $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']['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']; + break; - case 'mvhd': // MoVie HeaDer atom - $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); - $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); - $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); - $atom_structure['time_scale'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); - $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); - $atom_structure['preferred_rate'] = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4)); - $atom_structure['preferred_volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2)); - $atom_structure['reserved'] = substr($atom_data, 26, 10); - $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4)); - $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4)); - $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4)); - $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4)); - $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4)); - $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4)); - $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4)); - $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4)); - $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4)); - $atom_structure['preview_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 72, 4)); - $atom_structure['preview_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 76, 4)); - $atom_structure['poster_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 80, 4)); - $atom_structure['selection_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 84, 4)); - $atom_structure['selection_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 88, 4)); - $atom_structure['current_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 92, 4)); - $atom_structure['next_track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 96, 4)); - - if ($atom_structure['time_scale'] == 0) { - $this->error('Corrupt Quicktime file: mvhd.time_scale == zero'); - return false; - } - $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']['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']; - break; + case 'tkhd': // TracK HeaDer atom + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); + $atom_structure['trackid'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); + $atom_structure['reserved1'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); + $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4)); + $atom_structure['reserved2'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 8)); + $atom_structure['layer'] = getid3_lib::BigEndian2Int(substr($atom_data, 32, 2)); + $atom_structure['alternate_group'] = getid3_lib::BigEndian2Int(substr($atom_data, 34, 2)); + $atom_structure['volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2)); + $atom_structure['reserved3'] = getid3_lib::BigEndian2Int(substr($atom_data, 38, 2)); + // http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html + // http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737 + $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4)); + $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4)); + $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4)); + $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4)); + $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4)); + $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4)); + $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4)); + $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4)); + $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4)); + $atom_structure['width'] = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4)); + $atom_structure['height'] = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4)); + $atom_structure['flags']['enabled'] = (bool) ($atom_structure['flags_raw'] & 0x0001); + $atom_structure['flags']['in_movie'] = (bool) ($atom_structure['flags_raw'] & 0x0002); + $atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x0004); + $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']); + + // https://www.getid3.org/phpBB3/viewtopic.php?t=1908 + // attempt to compute rotation from matrix values + // 2017-Dec-28: uncertain if 90/270 are correctly oriented; values returned by FixedPoint16_16 should perhaps be -1 instead of 65535(?) + $matrixRotation = 0; + switch ($atom_structure['matrix_a'].':'.$atom_structure['matrix_b'].':'.$atom_structure['matrix_c'].':'.$atom_structure['matrix_d']) { + case '1:0:0:1': $matrixRotation = 0; break; + case '0:1:65535:0': $matrixRotation = 90; break; + case '65535:0:0:65535': $matrixRotation = 180; break; + case '0:65535:1:0': $matrixRotation = 270; break; + default: break; + } + // https://www.getid3.org/phpBB3/viewtopic.php?t=2468 + // The rotation matrix can appear in the Quicktime file multiple times, at least once for each track, + // and it's possible that only the video track (or, in theory, one of the video tracks) is flagged as + // rotated while the other tracks (e.g. audio) is tagged as rotation=0 (behavior noted on iPhone 8 Plus) + // The correct solution would be to check if the TrackID associated with the rotation matrix is indeed + // a video track (or the main video track) and only set the rotation then, but since information about + // what track is what is not trivially there to be examined, the lazy solution is to set the rotation + // if it is found to be nonzero, on the assumption that tracks that don't need it will have rotation set + // to zero (and be effectively ignored) and the video track will have rotation set correctly, which will + // either be zero and automatically correct, or nonzero and be set correctly. + if (!isset($info['video']['rotate']) || (($info['video']['rotate'] == 0) && ($matrixRotation > 0))) { + $info['quicktime']['video']['rotate'] = $info['video']['rotate'] = $matrixRotation; + } - case 'tkhd': // TracK HeaDer atom - $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); - $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); - $atom_structure['creation_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $atom_structure['modify_time'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); - $atom_structure['trackid'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); - $atom_structure['reserved1'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); - $atom_structure['duration'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4)); - $atom_structure['reserved2'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 8)); - $atom_structure['layer'] = getid3_lib::BigEndian2Int(substr($atom_data, 32, 2)); - $atom_structure['alternate_group'] = getid3_lib::BigEndian2Int(substr($atom_data, 34, 2)); - $atom_structure['volume'] = getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2)); - $atom_structure['reserved3'] = getid3_lib::BigEndian2Int(substr($atom_data, 38, 2)); -// http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html -// http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737 - $atom_structure['matrix_a'] = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4)); - $atom_structure['matrix_b'] = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4)); - $atom_structure['matrix_u'] = getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4)); - $atom_structure['matrix_c'] = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4)); - $atom_structure['matrix_d'] = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4)); - $atom_structure['matrix_v'] = getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4)); - $atom_structure['matrix_x'] = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4)); - $atom_structure['matrix_y'] = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4)); - $atom_structure['matrix_w'] = getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4)); - $atom_structure['width'] = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4)); - $atom_structure['height'] = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4)); - $atom_structure['flags']['enabled'] = (bool) ($atom_structure['flags_raw'] & 0x0001); - $atom_structure['flags']['in_movie'] = (bool) ($atom_structure['flags_raw'] & 0x0002); - $atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x0004); - $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']); - - if ($atom_structure['flags']['enabled'] == 1) { - if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) { - $info['video']['resolution_x'] = $atom_structure['width']; - $info['video']['resolution_y'] = $atom_structure['height']; + if ($atom_structure['flags']['enabled'] == 1) { + if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) { + $info['video']['resolution_x'] = $atom_structure['width']; + $info['video']['resolution_y'] = $atom_structure['height']; + } + $info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']); + $info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']); + $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x']; + $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y']; + } else { + // see: https://www.getid3.org/phpBB3/viewtopic.php?t=1295 + //if (isset($info['video']['resolution_x'])) { unset($info['video']['resolution_x']); } + //if (isset($info['video']['resolution_y'])) { unset($info['video']['resolution_y']); } + //if (isset($info['quicktime']['video'])) { unset($info['quicktime']['video']); } } - $info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']); - $info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']); - $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x']; - $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y']; - } else { - // see: http://www.getid3.org/phpBB3/viewtopic.php?t=1295 - //if (isset($info['video']['resolution_x'])) { unset($info['video']['resolution_x']); } - //if (isset($info['video']['resolution_y'])) { unset($info['video']['resolution_y']); } - //if (isset($info['quicktime']['video'])) { unset($info['quicktime']['video']); } - } - break; + break; - case 'iods': // Initial Object DeScriptor atom - // http://www.koders.com/c/fid1FAB3E762903DC482D8A246D4A4BF9F28E049594.aspx?s=windows.h - // http://libquicktime.sourcearchive.com/documentation/1.0.2plus-pdebian/iods_8c-source.html - $offset = 0; - $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); - $offset += 1; - $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 3)); - $offset += 3; - $atom_structure['mp4_iod_tag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); - $offset += 1; - $atom_structure['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset); - //$offset already adjusted by quicktime_read_mp4_descr_length() - $atom_structure['object_descriptor_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); - $offset += 2; - $atom_structure['od_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); - $offset += 1; - $atom_structure['scene_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); - $offset += 1; - $atom_structure['audio_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); - $offset += 1; - $atom_structure['video_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); - $offset += 1; - $atom_structure['graphics_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); - $offset += 1; - - $atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6; // 6 bytes would only be right if all tracks use 1-byte length fields - for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) { - $atom_structure['track'][$i]['ES_ID_IncTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + case 'iods': // Initial Object DeScriptor atom + // http://www.koders.com/c/fid1FAB3E762903DC482D8A246D4A4BF9F28E049594.aspx?s=windows.h + // http://libquicktime.sourcearchive.com/documentation/1.0.2plus-pdebian/iods_8c-source.html + $offset = 0; + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); $offset += 1; - $atom_structure['track'][$i]['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 3)); + $offset += 3; + $atom_structure['mp4_iod_tag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset); //$offset already adjusted by quicktime_read_mp4_descr_length() - $atom_structure['track'][$i]['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4)); - $offset += 4; - } + $atom_structure['object_descriptor_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); + $offset += 2; + $atom_structure['od_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['scene_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['audio_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['video_profile_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['graphics_profile_level'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; - $atom_structure['audio_profile_name'] = $this->QuicktimeIODSaudioProfileName($atom_structure['audio_profile_id']); - $atom_structure['video_profile_name'] = $this->QuicktimeIODSvideoProfileName($atom_structure['video_profile_id']); - break; + $atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6; // 6 bytes would only be right if all tracks use 1-byte length fields + for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) { + $atom_structure['track'][$i]['ES_ID_IncTag'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1)); + $offset += 1; + $atom_structure['track'][$i]['length'] = $this->quicktime_read_mp4_descr_length($atom_data, $offset); + //$offset already adjusted by quicktime_read_mp4_descr_length() + $atom_structure['track'][$i]['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4)); + $offset += 4; + } - case 'ftyp': // FileTYPe (?) atom (for MP4 it seems) - $atom_structure['signature'] = substr($atom_data, 0, 4); - $atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $atom_structure['fourcc'] = substr($atom_data, 8, 4); - break; + $atom_structure['audio_profile_name'] = $this->QuicktimeIODSaudioProfileName($atom_structure['audio_profile_id']); + $atom_structure['video_profile_name'] = $this->QuicktimeIODSvideoProfileName($atom_structure['video_profile_id']); + break; - case 'mdat': // Media DATa atom - // 'mdat' contains the actual data for the audio/video, possibly also subtitles + case 'ftyp': // FileTYPe (?) atom (for MP4 it seems) + $atom_structure['signature'] = substr($atom_data, 0, 4); + $atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $atom_structure['fourcc'] = substr($atom_data, 8, 4); + break; -/* due to lack of known documentation, this is a kludge implementation. If you know of documentation on how mdat is properly structed, please send it to info@getid3.org */ + case 'mdat': // Media DATa atom + // 'mdat' contains the actual data for the audio/video, possibly also subtitles - // first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?) - $mdat_offset = 0; - while (true) { - if (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x08".'wide') { - $mdat_offset += 8; - } elseif (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x00".'mdat') { - $mdat_offset += 8; - } else { - break; - } - } + /* due to lack of known documentation, this is a kludge implementation. If you know of documentation on how mdat is properly structed, please send it to info@getid3.org */ - // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field - while (($mdat_offset < (strlen($atom_data) - 8)) - && ($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2))) - && ($chapter_string_length < 1000) - && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2)) - && preg_match('#^([\x00-\xFF]{2})([\x20-\xFF]+)$#', substr($atom_data, $mdat_offset, $chapter_string_length + 2), $chapter_matches)) { - list($dummy, $chapter_string_length_hex, $chapter_string) = $chapter_matches; - $mdat_offset += (2 + $chapter_string_length); - @$info['quicktime']['comments']['chapters'][] = $chapter_string; - - // "encd" atom specifies encoding. In theory could be anything, almost always UTF-8, but may be UTF-16 with BOM (not currently handled) - if (substr($atom_data, $mdat_offset, 12) == "\x00\x00\x00\x0C\x65\x6E\x63\x64\x00\x00\x01\x00") { // UTF-8 - $mdat_offset += 12; + // first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?) + $mdat_offset = 0; + while (true) { + if (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x08".'wide') { + $mdat_offset += 8; + } elseif (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x00".'mdat') { + $mdat_offset += 8; + } else { + break; } - } - - - if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) { + } + if (substr($atom_data, $mdat_offset, 4) == 'GPRO') { + $GOPRO_chunk_length = getid3_lib::LittleEndian2Int(substr($atom_data, $mdat_offset + 4, 4)); + $GOPRO_offset = 8; + $atom_structure['GPRO']['raw'] = substr($atom_data, $mdat_offset + 8, $GOPRO_chunk_length - 8); + $atom_structure['GPRO']['firmware'] = substr($atom_structure['GPRO']['raw'], 0, 15); + $atom_structure['GPRO']['unknown1'] = substr($atom_structure['GPRO']['raw'], 15, 16); + $atom_structure['GPRO']['unknown2'] = substr($atom_structure['GPRO']['raw'], 31, 32); + $atom_structure['GPRO']['unknown3'] = substr($atom_structure['GPRO']['raw'], 63, 16); + $atom_structure['GPRO']['camera'] = substr($atom_structure['GPRO']['raw'], 79, 32); + $info['quicktime']['camera']['model'] = rtrim($atom_structure['GPRO']['camera'], "\x00"); + } - $info['avdataoffset'] = $atom_structure['offset'] + 8; // $info['quicktime'][$atomname]['offset'] + 8; - $OldAVDataEnd = $info['avdataend']; - $info['avdataend'] = $atom_structure['offset'] + $atom_structure['size']; // $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size']; + // check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field + while (($mdat_offset < (strlen($atom_data) - 8)) + && ($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2))) + && ($chapter_string_length < 1000) + && ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2)) + && preg_match('#^([\x00-\xFF]{2})([\x20-\xFF]+)$#', substr($atom_data, $mdat_offset, $chapter_string_length + 2), $chapter_matches)) { + list($dummy, $chapter_string_length_hex, $chapter_string) = $chapter_matches; + $mdat_offset += (2 + $chapter_string_length); + @$info['quicktime']['comments']['chapters'][] = $chapter_string; + + // "encd" atom specifies encoding. In theory could be anything, almost always UTF-8, but may be UTF-16 with BOM (not currently handled) + if (substr($atom_data, $mdat_offset, 12) == "\x00\x00\x00\x0C\x65\x6E\x63\x64\x00\x00\x01\x00") { // UTF-8 + $mdat_offset += 12; + } + } - $getid3_temp = new getID3(); - $getid3_temp->openfile($this->getid3->filename); - $getid3_temp->info['avdataoffset'] = $info['avdataoffset']; - $getid3_temp->info['avdataend'] = $info['avdataend']; - $getid3_mp3 = new getid3_mp3($getid3_temp); - if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) { - $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); - if (!empty($getid3_temp->info['warning'])) { - foreach ($getid3_temp->info['warning'] as $value) { - $this->warning($value); + if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) { + + $info['avdataoffset'] = $atom_structure['offset'] + 8; // $info['quicktime'][$atomname]['offset'] + 8; + $OldAVDataEnd = $info['avdataend']; + $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->info['avdataoffset'] = $info['avdataoffset']; + $getid3_temp->info['avdataend'] = $info['avdataend']; + $getid3_mp3 = new getid3_mp3($getid3_temp); + if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) { + $getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false); + if (!empty($getid3_temp->info['warning'])) { + foreach ($getid3_temp->info['warning'] as $value) { + $this->warning($value); + } } - } - if (!empty($getid3_temp->info['mpeg'])) { - $info['mpeg'] = $getid3_temp->info['mpeg']; - if (isset($info['mpeg']['audio'])) { - $info['audio']['dataformat'] = 'mp3'; - $info['audio']['codec'] = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3'))); - $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; - $info['audio']['channels'] = $info['mpeg']['audio']['channels']; - $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; - $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); - $info['bitrate'] = $info['audio']['bitrate']; + if (!empty($getid3_temp->info['mpeg'])) { + $info['mpeg'] = $getid3_temp->info['mpeg']; + if (isset($info['mpeg']['audio'])) { + $info['audio']['dataformat'] = 'mp3'; + $info['audio']['codec'] = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3'))); + $info['audio']['sample_rate'] = $info['mpeg']['audio']['sample_rate']; + $info['audio']['channels'] = $info['mpeg']['audio']['channels']; + $info['audio']['bitrate'] = $info['mpeg']['audio']['bitrate']; + $info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']); + $info['bitrate'] = $info['audio']['bitrate']; + } } } - } - unset($getid3_mp3, $getid3_temp); - $info['avdataend'] = $OldAVDataEnd; - unset($OldAVDataEnd); + unset($getid3_mp3, $getid3_temp); + $info['avdataend'] = $OldAVDataEnd; + unset($OldAVDataEnd); - } + } - unset($mdat_offset, $chapter_string_length, $chapter_matches); - break; + unset($mdat_offset, $chapter_string_length, $chapter_matches); + break; - case 'free': // FREE space atom - case 'skip': // SKIP atom - case 'wide': // 64-bit expansion placeholder atom - // 'free', 'skip' and 'wide' are just padding, contains no useful data at all - - // When writing QuickTime files, it is sometimes necessary to update an atom's size. - // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom - // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime - // puts an 8-byte placeholder atom before any atoms it may have to update the size of. - // In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the - // placeholder atom can be overwritten to obtain the necessary 8 extra bytes. - // The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ). - break; + case 'free': // FREE space atom + case 'skip': // SKIP atom + case 'wide': // 64-bit expansion placeholder atom + // 'free', 'skip' and 'wide' are just padding, contains no useful data at all + + // When writing QuickTime files, it is sometimes necessary to update an atom's size. + // It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom + // is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime + // puts an 8-byte placeholder atom before any atoms it may have to update the size of. + // In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the + // placeholder atom can be overwritten to obtain the necessary 8 extra bytes. + // The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ). + break; - case 'nsav': // NoSAVe atom - // http://developer.apple.com/technotes/tn/tn2038.html - $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); - break; + case 'nsav': // NoSAVe atom + // http://developer.apple.com/technotes/tn/tn2038.html + $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); + break; - case 'ctyp': // Controller TYPe atom (seen on QTVR) - // http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt - // some controller names are: - // 0x00 + 'std' for linear movie - // 'none' for no controls - $atom_structure['ctyp'] = substr($atom_data, 0, 4); - $info['quicktime']['controller'] = $atom_structure['ctyp']; - switch ($atom_structure['ctyp']) { - case 'qtvr': - $info['video']['dataformat'] = 'quicktimevr'; - break; - } - break; + case 'ctyp': // Controller TYPe atom (seen on QTVR) + // http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt + // some controller names are: + // 0x00 + 'std' for linear movie + // 'none' for no controls + $atom_structure['ctyp'] = substr($atom_data, 0, 4); + $info['quicktime']['controller'] = $atom_structure['ctyp']; + switch ($atom_structure['ctyp']) { + case 'qtvr': + $info['video']['dataformat'] = 'quicktimevr'; + break; + } + break; - case 'pano': // PANOrama track (seen on QTVR) - $atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); - break; + case 'pano': // PANOrama track (seen on QTVR) + $atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); + break; - case 'hint': // HINT track - case 'hinf': // - case 'hinv': // - case 'hnti': // - $info['quicktime']['hinting'] = true; - break; + case 'hint': // HINT track + case 'hinf': // + case 'hinv': // + case 'hnti': // + $info['quicktime']['hinting'] = true; + break; - case 'imgt': // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR) - for ($i = 0; $i < ($atom_structure['size'] - 8); $i += 4) { - $atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4)); - } - break; + case 'imgt': // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR) + for ($i = 0; $i < ($atom_structure['size'] - 8); $i += 4) { + $atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4)); + } + break; - // Observed-but-not-handled atom types are just listed here to prevent warnings being generated - case 'FXTC': // Something to do with Adobe After Effects (?) - case 'PrmA': - case 'code': - case 'FIEL': // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html - case 'tapt': // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html - // tapt seems to be used to compute the video size [http://www.getid3.org/phpBB3/viewtopic.php?t=838] - // * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html - // * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html - case 'ctts':// STCompositionOffsetAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html - case 'cslg':// STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html - case 'sdtp':// STSampleDependencyAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html - case 'stps':// STPartialSyncSampleAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html - //$atom_structure['data'] = $atom_data; - break; + // Observed-but-not-handled atom types are just listed here to prevent warnings being generated + case 'FXTC': // Something to do with Adobe After Effects (?) + case 'PrmA': + case 'code': + case 'FIEL': // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html + case 'tapt': // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html + // tapt seems to be used to compute the video size [https://www.getid3.org/phpBB3/viewtopic.php?t=838] + // * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html + // * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html + case 'ctts':// STCompositionOffsetAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html + case 'cslg':// STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html + case 'sdtp':// STSampleDependencyAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html + case 'stps':// STPartialSyncSampleAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html + //$atom_structure['data'] = $atom_data; + break; - case "\xA9".'xyz': // GPS latitude+longitude+altitude - $atom_structure['data'] = $atom_data; - if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) { - @list($all, $latitude, $longitude, $altitude) = $matches; - $info['quicktime']['comments']['gps_latitude'][] = floatval($latitude); - $info['quicktime']['comments']['gps_longitude'][] = floatval($longitude); - if (!empty($altitude)) { - $info['quicktime']['comments']['gps_altitude'][] = floatval($altitude); + case "\xA9".'xyz': // GPS latitude+longitude+altitude + $atom_structure['data'] = $atom_data; + if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) { + @list($all, $latitude, $longitude, $altitude) = $matches; + $info['quicktime']['comments']['gps_latitude'][] = floatval($latitude); + $info['quicktime']['comments']['gps_longitude'][] = floatval($longitude); + if (!empty($altitude)) { + $info['quicktime']['comments']['gps_altitude'][] = floatval($altitude); + } + } else { + $this->warning('QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.'); } - } else { - $this->warning('QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.'); - } - break; + break; - case 'NCDT': - // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html - // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100 - $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms); - break; - case 'NCTH': // Nikon Camera THumbnail image - case 'NCVW': // Nikon Camera preVieW image - // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html - if (preg_match('/^\xFF\xD8\xFF/', $atom_data)) { + case 'NCDT': + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100 + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms); + break; + case 'NCTH': // Nikon Camera THumbnail image + case 'NCVW': // Nikon Camera preVieW image + // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + if (preg_match('/^\xFF\xD8\xFF/', $atom_data)) { + $atom_structure['data'] = $atom_data; + $atom_structure['image_mime'] = 'image/jpeg'; + $atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image')); + $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']); + } + break; + case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG + $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data); + break; + case 'NCHD': // Nikon:MakerNoteVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + case 'NCDB': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html + case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html $atom_structure['data'] = $atom_data; - $atom_structure['image_mime'] = 'image/jpeg'; - $atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image')); - $info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']); - } - break; - case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG - $atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data); - break; - case 'NCHD': // Nikon:MakerNoteVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html - case 'NCDB': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html - case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html - $atom_structure['data'] = $atom_data; - break; + break; - case "\x00\x00\x00\x00": - // some kind of metacontainer, may contain a big data dump such as: - // mdta keys \005 mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst \01D \001 \015data \001DE\010Apple 0 \002 (data \001DE\0102011-05-11T17:54:04+0200 2 \003 *data \001DE\010+52.4936+013.3897+040.247/ \01D \004 \015data \001DE\0104.3.1 \005 \018data \001DE\010iPhone 4 - // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt + case "\x00\x00\x00\x00": + // some kind of metacontainer, may contain a big data dump such as: + // mdta keys \005 mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst \01D \001 \015data \001DE\010Apple 0 \002 (data \001DE\0102011-05-11T17:54:04+0200 2 \003 *data \001DE\010+52.4936+013.3897+040.247/ \01D \004 \015data \001DE\0104.3.1 \005 \018data \001DE\010iPhone 4 + // http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt - $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); - $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); - $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); - //$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); - break; + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + //$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + break; - case 'meta': // METAdata atom - // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html + case 'meta': // METAdata atom + // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html - $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); - $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); - $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); - break; + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); + break; - case 'data': // metaDATA atom - static $metaDATAkey = 1; // real ugly, but so is the QuickTime structure that stores keys and values in different multinested locations that are hard to relate to each other - // seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data - $atom_structure['language'] = substr($atom_data, 4 + 0, 2); - $atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2)); - $atom_structure['data'] = substr($atom_data, 4 + 4); - $atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++]; + case 'data': // metaDATA atom + static $metaDATAkey = 1; // real ugly, but so is the QuickTime structure that stores keys and values in different multinested locations that are hard to relate to each other + // seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data + $atom_structure['language'] = substr($atom_data, 4 + 0, 2); + $atom_structure['unknown'] = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2)); + $atom_structure['data'] = substr($atom_data, 4 + 4); + $atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++]; - if ($atom_structure['key_name'] && $atom_structure['data']) { - @$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data']; - } - break; + if ($atom_structure['key_name'] && $atom_structure['data']) { + @$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data']; + } + break; - case 'keys': // KEYS that may be present in the metadata atom. - // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW21 - // The metadata item keys atom holds a list of the metadata keys that may be present in the metadata atom. - // This list is indexed starting with 1; 0 is a reserved index value. The metadata item keys atom is a full atom with an atom type of "keys". - $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); - $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); - $atom_structure['entry_count'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); - $keys_atom_offset = 8; - for ($i = 1; $i <= $atom_structure['entry_count']; $i++) { - $atom_structure['keys'][$i]['key_size'] = getid3_lib::BigEndian2Int(substr($atom_data, $keys_atom_offset + 0, 4)); - $atom_structure['keys'][$i]['key_namespace'] = substr($atom_data, $keys_atom_offset + 4, 4); - $atom_structure['keys'][$i]['key_value'] = substr($atom_data, $keys_atom_offset + 8, $atom_structure['keys'][$i]['key_size'] - 8); - $keys_atom_offset += $atom_structure['keys'][$i]['key_size']; // key_size includes the 4+4 bytes for key_size and key_namespace - - $info['quicktime']['temp_meta_key_names'][$i] = $atom_structure['keys'][$i]['key_value']; - } - break; + case 'keys': // KEYS that may be present in the metadata atom. + // https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW21 + // The metadata item keys atom holds a list of the metadata keys that may be present in the metadata atom. + // This list is indexed starting with 1; 0 is a reserved index value. The metadata item keys atom is a full atom with an atom type of "keys". + $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); + $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); + $atom_structure['entry_count'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); + $keys_atom_offset = 8; + for ($i = 1; $i <= $atom_structure['entry_count']; $i++) { + $atom_structure['keys'][$i]['key_size'] = getid3_lib::BigEndian2Int(substr($atom_data, $keys_atom_offset + 0, 4)); + $atom_structure['keys'][$i]['key_namespace'] = substr($atom_data, $keys_atom_offset + 4, 4); + $atom_structure['keys'][$i]['key_value'] = substr($atom_data, $keys_atom_offset + 8, $atom_structure['keys'][$i]['key_size'] - 8); + $keys_atom_offset += $atom_structure['keys'][$i]['key_size']; // key_size includes the 4+4 bytes for key_size and key_namespace + + $info['quicktime']['temp_meta_key_names'][$i] = $atom_structure['keys'][$i]['key_value']; + } + break; - default: - $this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset); - $atom_structure['data'] = $atom_data; - 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. + // The first row is version/metadata/notsure, I skip that. + // The following rows consist of 4byte address (absolute) and 4byte size (0x1000), these point to the GPS data in the file. + + $GPS_rowsize = 8; // 4 bytes for offset, 4 bytes for size + if (strlen($atom_data) > 0) { + if ((strlen($atom_data) % $GPS_rowsize) == 0) { + $atom_structure['gps_toc'] = array(); + foreach (str_split($atom_data, $GPS_rowsize) as $counter => $datapair) { + $atom_structure['gps_toc'][] = unpack('Noffset/Nsize', substr($atom_data, $counter * $GPS_rowsize, $GPS_rowsize)); + } + + $atom_structure['gps_entries'] = array(); + $previous_offset = $this->ftell(); + foreach ($atom_structure['gps_toc'] as $key => $gps_pointer) { + if ($key == 0) { + // "The first row is version/metadata/notsure, I skip that." + continue; + } + $this->fseek($gps_pointer['offset']); + $GPS_free_data = $this->fread($gps_pointer['size']); + + /* + // 2017-05-10: I see some of the data, notably the Hour-Minute-Second, but cannot reconcile the rest of the data. However, the NMEA "GPRMC" line is there and relatively easy to parse, so I'm using that instead + + // https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730 + // The structure of the GPS data atom (the 'free' atoms mentioned above) is following: + // hour,minute,second,year,month,day,active,latitude_b,longitude_b,unknown2,latitude,longitude,speed = struct.unpack_from(' 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; + + $GPS_this_GPRMC['active'] = ($GPS_this_GPRMC['raw']['status'] == 'A'); // A=Active,V=Void + + foreach (array('latitude','longitude') as $latlon) { + preg_match('#^([0-9]{1,3})([0-9]{2}\\.[0-9]+)$#', $GPS_this_GPRMC['raw'][$latlon], $matches); + list($dummy, $deg, $min) = $matches; + $GPS_this_GPRMC[$latlon] = $deg + ($min / 60); + } + $GPS_this_GPRMC['latitude'] *= (($GPS_this_GPRMC['raw']['latitude_direction'] == 'S') ? -1 : 1); + $GPS_this_GPRMC['longitude'] *= (($GPS_this_GPRMC['raw']['longitude_direction'] == 'W') ? -1 : 1); + + $GPS_this_GPRMC['heading'] = $GPS_this_GPRMC['raw']['angle']; + $GPS_this_GPRMC['speed_knot'] = $GPS_this_GPRMC['raw']['knots']; + $GPS_this_GPRMC['speed_kmh'] = $GPS_this_GPRMC['raw']['knots'] * 1.852; + if ($GPS_this_GPRMC['raw']['variation']) { + $GPS_this_GPRMC['variation'] = $GPS_this_GPRMC['raw']['variation']; + $GPS_this_GPRMC['variation'] *= (($GPS_this_GPRMC['raw']['variation_direction'] == 'W') ? -1 : 1); + } + + $atom_structure['gps_entries'][$key] = $GPS_this_GPRMC; + + @$info['quicktime']['gps_track'][$GPS_this_GPRMC['timestamp']] = array( + 'latitude' => (float) $GPS_this_GPRMC['latitude'], + 'longitude' => (float) $GPS_this_GPRMC['longitude'], + 'speed_kmh' => (float) $GPS_this_GPRMC['speed_kmh'], + 'heading' => (float) $GPS_this_GPRMC['heading'], + ); + + } else { + $this->warning('Unhandled GPS format in "free" atom at offset '.$gps_pointer['offset']); + } + } + $this->fseek($previous_offset); + + } else { + $this->warning('QuickTime atom "'.$atomname.'" is not mod-8 bytes long ('.$atomsize.' bytes) at offset '.$baseoffset); + } + } else { + $this->warning('QuickTime atom "'.$atomname.'" is zero bytes long at offset '.$baseoffset); + } + break; + + case 'loci':// 3GP location (El Loco) + $loffset = 0; + $info['quicktime']['comments']['gps_flags'] = array( getid3_lib::BigEndian2Int(substr($atom_data, 0, 4))); + $info['quicktime']['comments']['gps_lang'] = array( getid3_lib::BigEndian2Int(substr($atom_data, 4, 2))); + $info['quicktime']['comments']['gps_location'] = array( $this->LociString(substr($atom_data, 6), $loffset)); + $loci_data = substr($atom_data, 6 + $loffset); + $info['quicktime']['comments']['gps_role'] = array( getid3_lib::BigEndian2Int(substr($loci_data, 0, 1))); + $info['quicktime']['comments']['gps_longitude'] = array(getid3_lib::FixedPoint16_16(substr($loci_data, 1, 4))); + $info['quicktime']['comments']['gps_latitude'] = array(getid3_lib::FixedPoint16_16(substr($loci_data, 5, 4))); + $info['quicktime']['comments']['gps_altitude'] = array(getid3_lib::FixedPoint16_16(substr($loci_data, 9, 4))); + $info['quicktime']['comments']['gps_body'] = array( $this->LociString(substr($loci_data, 13 ), $loffset)); + $info['quicktime']['comments']['gps_notes'] = array( $this->LociString(substr($loci_data, 13 + $loffset), $loffset)); + break; + + case 'chpl': // CHaPter List + // https://www.adobe.com/content/dam/Adobe/en/devnet/flv/pdfs/video_file_format_spec_v10.pdf + $chpl_version = getid3_lib::BigEndian2Int(substr($atom_data, 4, 1)); // Expected to be 0 + $chpl_flags = getid3_lib::BigEndian2Int(substr($atom_data, 5, 3)); // Reserved, set to 0 + $chpl_count = getid3_lib::BigEndian2Int(substr($atom_data, 8, 1)); + $chpl_offset = 9; + for ($i = 0; $i < $chpl_count; $i++) { + if (($chpl_offset + 9) >= strlen($atom_data)) { + $this->warning('QuickTime chapter '.$i.' extends beyond end of "chpl" atom'); + break; + } + $info['quicktime']['chapters'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($atom_data, $chpl_offset, 8)) / 10000000; // timestamps are stored as 100-nanosecond units + $chpl_offset += 8; + $chpl_title_size = getid3_lib::BigEndian2Int(substr($atom_data, $chpl_offset, 1)); + $chpl_offset += 1; + $info['quicktime']['chapters'][$i]['title'] = substr($atom_data, $chpl_offset, $chpl_title_size); + $chpl_offset += $chpl_title_size; + } + break; + + case 'FIRM': // FIRMware version(?), seen on GoPro Hero4 + $info['quicktime']['camera']['firmware'] = $atom_data; + break; + + case 'CAME': // FIRMware version(?), seen on GoPro Hero4 + $info['quicktime']['camera']['serial_hash'] = unpack('H*', $atom_data); + break; + + case 'dscp': + case 'rcif': + // https://www.getid3.org/phpBB3/viewtopic.php?t=1908 + if (substr($atom_data, 0, 7) == "\x00\x00\x00\x00\x55\xC4".'{') { + if ($json_decoded = @json_decode(rtrim(substr($atom_data, 6), "\x00"), true)) { + $info['quicktime']['camera'][$atomname] = $json_decoded; + if (($atomname == 'rcif') && isset($info['quicktime']['camera']['rcif']['wxcamera']['rotate'])) { + $info['video']['rotate'] = $info['quicktime']['video']['rotate'] = $info['quicktime']['camera']['rcif']['wxcamera']['rotate']; + } + } else { + $this->warning('Failed to JSON decode atom "'.$atomname.'"'); + $atom_structure['data'] = $atom_data; + } + unset($json_decoded); + } else { + $this->warning('Expecting 55 C4 7B at start of atom "'.$atomname.'", found '.getid3_lib::PrintHexBytes(substr($atom_data, 4, 3)).' instead'); + $atom_structure['data'] = $atom_data; + } + break; + + case 'frea': + // https://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Kodak.html#frea + // may contain "scra" (PreviewImage) and/or "thma" (ThumbnailImage) + $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms); + break; + case 'tima': // subatom to "frea" + // no idea what this does, the one sample file I've seen has a value of 0x00000027 + $atom_structure['data'] = $atom_data; + break; + case 'ver ': // subatom to "frea" + // some kind of version number, the one sample file I've seen has a value of "3.00.073" + $atom_structure['data'] = $atom_data; + break; + 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'); + } + 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'); + } + 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); + $atom_structure['data'] = $atom_data; + break; + } } array_pop($atomHierarchy); return $atom_structure; } + /** + * @param string $atom_data + * @param int $baseoffset + * @param array $atomHierarchy + * @param bool $ParseAllPossibleAtoms + * + * @return array|false + */ public function QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { -//echo 'QuicktimeParseContainerAtom('.substr($atom_data, 4, 4).') @ '.$baseoffset.'

'; $atom_structure = false; $subatomoffset = 0; $subatomcounter = 0; @@ -1601,16 +1880,18 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ } return $atom_structure; } - - $atom_structure[$subatomcounter] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms); - + $atom_structure[$subatomcounter++] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms); $subatomoffset += $subatomsize; - $subatomcounter++; } return $atom_structure; } - + /** + * @param string $data + * @param int $offset + * + * @return int + */ public function quicktime_read_mp4_descr_length($data, &$offset) { // http://libquicktime.sourcearchive.com/documentation/2:1.0.2plus-pdebian-2build1/esds_8c-source.html $num_bytes = 0; @@ -1622,7 +1903,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return $length; } - + /** + * @param int $languageid + * + * @return string + */ public function QuicktimeLanguageLookup($languageid) { // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-34353 static $QuicktimeLanguageLookup = array(); @@ -1760,6 +2045,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeLanguageLookup[$languageid]) ? $QuicktimeLanguageLookup[$languageid] : 'invalid'); } + /** + * @param string $codecid + * + * @return string + */ public function QuicktimeVideoCodecLookup($codecid) { static $QuicktimeVideoCodecLookup = array(); if (empty($QuicktimeVideoCodecLookup)) { @@ -1819,6 +2109,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeVideoCodecLookup[$codecid]) ? $QuicktimeVideoCodecLookup[$codecid] : ''); } + /** + * @param string $codecid + * + * @return mixed|string + */ public function QuicktimeAudioCodecLookup($codecid) { static $QuicktimeAudioCodecLookup = array(); if (empty($QuicktimeAudioCodecLookup)) { @@ -1864,6 +2159,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeAudioCodecLookup[$codecid]) ? $QuicktimeAudioCodecLookup[$codecid] : ''); } + /** + * @param string $compressionid + * + * @return string + */ public function QuicktimeDCOMLookup($compressionid) { static $QuicktimeDCOMLookup = array(); if (empty($QuicktimeDCOMLookup)) { @@ -1873,6 +2173,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeDCOMLookup[$compressionid]) ? $QuicktimeDCOMLookup[$compressionid] : ''); } + /** + * @param int $colordepthid + * + * @return string + */ public function QuicktimeColorNameLookup($colordepthid) { static $QuicktimeColorNameLookup = array(); if (empty($QuicktimeColorNameLookup)) { @@ -1891,6 +2196,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeColorNameLookup[$colordepthid]) ? $QuicktimeColorNameLookup[$colordepthid] : 'invalid'); } + /** + * @param int $stik + * + * @return string + */ public function QuicktimeSTIKLookup($stik) { static $QuicktimeSTIKLookup = array(); if (empty($QuicktimeSTIKLookup)) { @@ -1908,6 +2218,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeSTIKLookup[$stik]) ? $QuicktimeSTIKLookup[$stik] : 'invalid'); } + /** + * @param int $audio_profile_id + * + * @return string + */ public function QuicktimeIODSaudioProfileName($audio_profile_id) { static $QuicktimeIODSaudioProfileNameLookup = array(); if (empty($QuicktimeIODSaudioProfileNameLookup)) { @@ -1967,7 +2282,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private'); } - + /** + * @param int $video_profile_id + * + * @return string + */ public function QuicktimeIODSvideoProfileName($video_profile_id) { static $QuicktimeIODSvideoProfileNameLookup = array(); if (empty($QuicktimeIODSvideoProfileNameLookup)) { @@ -2039,7 +2358,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeIODSvideoProfileNameLookup[$video_profile_id]) ? $QuicktimeIODSvideoProfileNameLookup[$video_profile_id] : 'ISO Reserved Profile'); } - + /** + * @param int $rtng + * + * @return string + */ public function QuicktimeContentRatingLookup($rtng) { static $QuicktimeContentRatingLookup = array(); if (empty($QuicktimeContentRatingLookup)) { @@ -2050,6 +2373,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeContentRatingLookup[$rtng]) ? $QuicktimeContentRatingLookup[$rtng] : 'invalid'); } + /** + * @param int $akid + * + * @return string + */ public function QuicktimeStoreAccountTypeLookup($akid) { static $QuicktimeStoreAccountTypeLookup = array(); if (empty($QuicktimeStoreAccountTypeLookup)) { @@ -2059,6 +2387,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeStoreAccountTypeLookup[$akid]) ? $QuicktimeStoreAccountTypeLookup[$akid] : 'invalid'); } + /** + * @param int $sfid + * + * @return string + */ public function QuicktimeStoreFrontCodeLookup($sfid) { static $QuicktimeStoreFrontCodeLookup = array(); if (empty($QuicktimeStoreFrontCodeLookup)) { @@ -2088,6 +2421,11 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ return (isset($QuicktimeStoreFrontCodeLookup[$sfid]) ? $QuicktimeStoreFrontCodeLookup[$sfid] : 'invalid'); } + /** + * @param string $atom_data + * + * @return array + */ public function QuicktimeParseNikonNCTG($atom_data) { // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG // Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100 @@ -2130,10 +2468,10 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ ); $offset = 0; + $data = null; $datalength = strlen($atom_data); $parsed = array(); while ($offset < $datalength) { -//echo getid3_lib::PrintHexBytes(substr($atom_data, $offset, 4)).'
'; $record_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4)); $offset += 4; $data_size_type = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2; $data_size = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2)); $offset += 2; @@ -2188,7 +2526,7 @@ if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($ $offset += ($data_size * 2); break; default: -echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
'; + echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
'; break 2; } @@ -2266,7 +2604,13 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
getid3->info; @@ -2402,6 +2746,50 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
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 ''; + } + + } + } + + /** + * @param string $nullterminatedstring + * + * @return string + */ public function NoNullString($nullterminatedstring) { // remove the single null terminator on null terminated strings if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === "\x00") { @@ -2410,16 +2798,26 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
$value) { $key_history = $history.'/'.$key; @@ -2433,6 +2831,13 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
$value) { $key_history = $history.'/'.$key; @@ -2446,6 +2851,11 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res); @@ -2463,7 +2873,12 @@ echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'
0) { $ts_res = array(); $this->search_tag_by_key($info['quicktime']['moov'], 'time_scale', 'quicktime/moov', $ts_res); - foreach ($ts_res as $value) { - $prefix = substr($value[0], 0, -12); + foreach ($ts_res as $sub_value) { + $prefix = substr($sub_value[0], 0, -12); if ((substr($stbl_res[0][0], 0, strlen($prefix)) === $prefix) && ($ts_prefix_len < strlen($prefix))) { - $time_scale = $value[1]['time_scale']; + $time_scale = $sub_value[1]['time_scale']; $ts_prefix_len = strlen($prefix); } } diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.real.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.real.php index 280d43c8..f5d2ce7f 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.real.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.real.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio-video.real.php // @@ -18,7 +18,9 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', class getid3_real extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -370,7 +372,12 @@ class getid3_real extends getid3_handler return true; } - + /** + * @param string $OldRAheaderData + * @param array $ParsedArray + * + * @return bool + */ public function ParseOldRAheader($OldRAheaderData, &$ParsedArray) { // http://www.freelists.org/archives/matroska-devel/07-2003/msg00010.html @@ -485,6 +492,12 @@ class getid3_real extends getid3_handler return true; } + /** + * @param string $fourcc + * @param int $bitrate + * + * @return string + */ public function RealAudioCodecFourCClookup($fourcc, $bitrate) { static $RealAudioCodecFourCClookup = array(); if (empty($RealAudioCodecFourCClookup)) { diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.riff.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.riff.php index f61f28ab..8992ad7c 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.riff.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.riff.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio-video.riff.php // @@ -27,10 +27,15 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE_ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ac3.php', __FILE__, true); getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.dts.php', __FILE__, true); -class getid3_riff extends getid3_handler { - +class getid3_riff extends getid3_handler +{ protected $container = 'riff'; // default + /** + * @return bool + * + * @throws getid3_exception + */ public function Analyze() { $info = &$this->getid3->info; @@ -46,6 +51,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(); $Original['avdataoffset'] = $info['avdataoffset']; $Original['avdataend'] = $info['avdataend']; @@ -357,6 +363,7 @@ class getid3_riff extends getid3_handler { } $thisfile_riff_WAVE_cart_0['url'] = trim(substr($thisfile_riff_WAVE_cart_0['data'], 748, 1024)); $thisfile_riff_WAVE_cart_0['tag_text'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_cart_0['data'], 1772))); + $thisfile_riff['comments']['tag_text'][] = substr($thisfile_riff_WAVE_cart_0['data'], 1772); $thisfile_riff['comments']['artist'][] = $thisfile_riff_WAVE_cart_0['artist']; $thisfile_riff['comments']['title'][] = $thisfile_riff_WAVE_cart_0['title']; @@ -405,7 +412,6 @@ class getid3_riff extends getid3_handler { 'tracktitle'=>'title', 'category' =>'genre', 'cdtitle' =>'album', - 'tracktitle'=>'title', ); foreach ($tagmapping as $fromkey => $tokey) { if (isset($thisfile_riff_WAVE_SNDM_0['parsed'][$fromkey])) { @@ -613,6 +619,8 @@ class getid3_riff extends getid3_handler { $thisfile_video['bitrate_mode'] = 'vbr'; // maybe not, but probably $thisfile_video['dataformat'] = 'avi'; + $thisfile_riff_video_current = array(); + if (isset($thisfile_riff[$RIFFsubtype]['movi']['offset'])) { $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['movi']['offset'] + 8; if (isset($thisfile_riff['AVIX'])) { @@ -701,6 +709,7 @@ class getid3_riff extends getid3_handler { // shortcut $thisfile_riff_video[$streamindex] = array(); + /** @var array $thisfile_riff_video_current */ $thisfile_riff_video_current = &$thisfile_riff_video[$streamindex]; if ($thisfile_riff_raw_avih['dwWidth'] > 0) { @@ -867,7 +876,7 @@ class getid3_riff extends getid3_handler { } } - if (isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) { + if (isset($thisfile_riff_raw_strf_strhfccType_streamindex) && isset($thisfile_riff_raw_strf_strhfccType_streamindex['fourcc'])) { $thisfile_video['fourcc'] = $thisfile_riff_raw_strf_strhfccType_streamindex['fourcc']; if (self::fourccLookup($thisfile_video['fourcc'])) { @@ -1077,6 +1086,7 @@ class getid3_riff extends getid3_handler { $thisfile_audio_dataformat = '8svx'; $thisfile_audio['bits_per_sample'] = 8; $thisfile_audio['channels'] = 1; // overridden below, if need be + $ActualBitsPerSample = 0; if (isset($thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'])) { $info['avdataoffset'] = $thisfile_riff[$RIFFsubtype]['BODY'][0]['offset'] + 8; @@ -1114,7 +1124,7 @@ class getid3_riff extends getid3_handler { break; default: - $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.sCompression.'"'); + $this->warning('Unexpected sCompression value in 8SVX.VHDR chunk - expecting 0 or 1, found "'.$thisfile_riff_RIFFsubtype_VHDR_0['sCompression'].'"'); break; } } @@ -1174,10 +1184,53 @@ class getid3_riff extends getid3_handler { case 'WEBP': // https://developers.google.com/speed/webp/docs/riff_container + // https://tools.ietf.org/html/rfc6386 + // https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt $info['fileformat'] = 'webp'; $info['mime_type'] = 'image/webp'; -$this->error('WebP image parsing not supported in this version of getID3()'); + if (!empty($thisfile_riff['WEBP']['VP8 '][0]['size'])) { + $old_offset = $this->ftell(); + $this->fseek($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8); // 4 bytes "VP8 " + 4 bytes chunk size + $WEBP_VP8_header = $this->fread(10); + $this->fseek($old_offset); + if (substr($WEBP_VP8_header, 3, 3) == "\x9D\x01\x2A") { + $thisfile_riff['WEBP']['VP8 '][0]['keyframe'] = !(getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x800000); + $thisfile_riff['WEBP']['VP8 '][0]['version'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x700000) >> 20; + $thisfile_riff['WEBP']['VP8 '][0]['show_frame'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x080000); + $thisfile_riff['WEBP']['VP8 '][0]['data_bytes'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 0, 3)) & 0x07FFFF) >> 0; + + $thisfile_riff['WEBP']['VP8 '][0]['scale_x'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0xC000) >> 14; + $thisfile_riff['WEBP']['VP8 '][0]['width'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 6, 2)) & 0x3FFF); + $thisfile_riff['WEBP']['VP8 '][0]['scale_y'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0xC000) >> 14; + $thisfile_riff['WEBP']['VP8 '][0]['height'] = (getid3_lib::LittleEndian2Int(substr($WEBP_VP8_header, 8, 2)) & 0x3FFF); + + $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8 '][0]['width']; + $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8 '][0]['height']; + } else { + $this->error('Expecting 9D 01 2A at offset '.($thisfile_riff['WEBP']['VP8 '][0]['offset'] + 8 + 3).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8_header, 3, 3)).'"'); + } + + } + if (!empty($thisfile_riff['WEBP']['VP8L'][0]['size'])) { + $old_offset = $this->ftell(); + $this->fseek($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8); // 4 bytes "VP8L" + 4 bytes chunk size + $WEBP_VP8L_header = $this->fread(10); + $this->fseek($old_offset); + if (substr($WEBP_VP8L_header, 0, 1) == "\x2F") { + $width_height_flags = getid3_lib::LittleEndian2Bin(substr($WEBP_VP8L_header, 1, 4)); + $thisfile_riff['WEBP']['VP8L'][0]['width'] = bindec(substr($width_height_flags, 18, 14)) + 1; + $thisfile_riff['WEBP']['VP8L'][0]['height'] = bindec(substr($width_height_flags, 4, 14)) + 1; + $thisfile_riff['WEBP']['VP8L'][0]['alpha_is_used'] = (bool) bindec(substr($width_height_flags, 3, 1)); + $thisfile_riff['WEBP']['VP8L'][0]['version'] = bindec(substr($width_height_flags, 0, 3)); + + $info['video']['resolution_x'] = $thisfile_riff['WEBP']['VP8L'][0]['width']; + $info['video']['resolution_y'] = $thisfile_riff['WEBP']['VP8L'][0]['height']; + } else { + $this->error('Expecting 2F at offset '.($thisfile_riff['WEBP']['VP8L'][0]['offset'] + 8).', found "'.getid3_lib::PrintHexBytes(substr($WEBP_VP8L_header, 0, 1)).'"'); + } + + } break; default: @@ -1329,6 +1382,15 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return true; } + /** + * @param int $startoffset + * @param int $maxoffset + * + * @return array|false + * + * @throws Exception + * @throws getid3_exception + */ public function ParseRIFFAMV($startoffset, $maxoffset) { // AMV files are RIFF-AVI files with parts of the spec deliberately broken, such as chunk size fields hardcoded to zero (because players known in hardware that these fields are always a certain size @@ -1437,7 +1499,13 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return $RIFFchunk; } - + /** + * @param int $startoffset + * @param int $maxoffset + * + * @return array|false + * @throws getid3_exception + */ public function ParseRIFF($startoffset, $maxoffset) { $info = &$this->getid3->info; @@ -1689,7 +1757,7 @@ $this->error('WebP image parsing not supported in this version of getID3()'); // break; default: - if (!empty($LISTchunkParent) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) { + if (!empty($LISTchunkParent) && isset($LISTchunkMaxOffset) && (($RIFFchunk[$chunkname][$thisindex]['offset'] + $RIFFchunk[$chunkname][$thisindex]['size']) <= $LISTchunkMaxOffset)) { $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['offset'] = $RIFFchunk[$chunkname][$thisindex]['offset']; $RIFFchunk[$LISTchunkParent][$chunkname][$thisindex]['size'] = $RIFFchunk[$chunkname][$thisindex]['size']; unset($RIFFchunk[$chunkname][$thisindex]['offset']); @@ -1724,6 +1792,11 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return $RIFFchunk; } + /** + * @param string $RIFFdata + * + * @return bool + */ public function ParseRIFFdata(&$RIFFdata) { $info = &$this->getid3->info; if ($RIFFdata) { @@ -1761,6 +1834,12 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return false; } + /** + * @param array $RIFFinfoArray + * @param array $CommentsTargetArray + * + * @return bool + */ public static function parseComments(&$RIFFinfoArray, &$CommentsTargetArray) { $RIFFinfoKeyLookup = array( 'IARL'=>'archivallocation', @@ -1820,8 +1899,14 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return true; } + /** + * @param string $WaveFormatExData + * + * @return array + */ public static function parseWAVEFORMATex($WaveFormatExData) { // shortcut + $WaveFormatEx = array(); $WaveFormatEx['raw'] = array(); $WaveFormatEx_raw = &$WaveFormatEx['raw']; @@ -1845,6 +1930,11 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return $WaveFormatEx; } + /** + * @param string $WavPackChunkData + * + * @return bool + */ public function parseWavPackHeader($WavPackChunkData) { // typedef struct { // char ckID [4]; @@ -1906,6 +1996,12 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return true; } + /** + * @param string $BITMAPINFOHEADER + * @param bool $littleEndian + * + * @return array + */ public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) { $parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure @@ -1925,6 +2021,12 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return $parsed; } + /** + * @param string $DIVXTAG + * @param bool $raw + * + * @return array + */ public static function ParseDIVXTAG($DIVXTAG, $raw=false) { // structure from "IDivX" source, Form1.frm, by "Greg Frazier of Daemonic Software Group", email: gfrazier@icestorm.net, web: http://dsg.cjb.net/ // source available at http://files.divx-digest.com/download/c663efe7ef8ad2e90bf4af4d3ea6188a/on0SWN2r/edit/IDivX.zip @@ -1971,6 +2073,7 @@ $this->error('WebP image parsing not supported in this version of getID3()'); 5 => 'NC-17', ); + $parsed = array(); $parsed['title'] = trim(substr($DIVXTAG, 0, 32)); $parsed['artist'] = trim(substr($DIVXTAG, 32, 28)); $parsed['year'] = intval(trim(substr($DIVXTAG, 60, 4))); @@ -1986,8 +2089,8 @@ $this->error('WebP image parsing not supported in this version of getID3()'); if (!$raw) { unset($parsed['genre_id'], $parsed['rating_id']); foreach ($parsed as $key => $value) { - if (!$value === '') { - unset($parsed['key']); + if (empty($value)) { + unset($parsed[$key]); } } } @@ -1999,6 +2102,11 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return $parsed; } + /** + * @param string $tagshortname + * + * @return string + */ public static function waveSNDMtagLookup($tagshortname) { $begin = __LINE__; @@ -2022,6 +2130,11 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return getid3_lib::EmbeddedLookup($tagshortname, $begin, __LINE__, __FILE__, 'riff-sndm'); } + /** + * @param int $wFormatTag + * + * @return string + */ public static function wFormatTagLookup($wFormatTag) { $begin = __LINE__; @@ -2191,6 +2304,11 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return getid3_lib::EmbeddedLookup('0x'.str_pad(strtoupper(dechex($wFormatTag)), 4, '0', STR_PAD_LEFT), $begin, __LINE__, __FILE__, 'riff-wFormatTag'); } + /** + * @param string $fourcc + * + * @return string + */ public static function fourccLookup($fourcc) { $begin = __LINE__; @@ -2585,6 +2703,12 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return getid3_lib::EmbeddedLookup($fourcc, $begin, __LINE__, __FILE__, 'riff-fourcc'); } + /** + * @param string $byteword + * @param bool $signed + * + * @return int|float|false + */ private function EitherEndian2Int($byteword, $signed=false) { if ($this->container == 'riff') { return getid3_lib::LittleEndian2Int($byteword, $signed); @@ -2592,4 +2716,4 @@ $this->error('WebP image parsing not supported in this version of getID3()'); return getid3_lib::BigEndian2Int($byteword, false, $signed); } -} \ No newline at end of file +} diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.swf.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.swf.php index 178f439a..e1151f31 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.swf.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.swf.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio-video.swf.php // @@ -19,6 +19,9 @@ class getid3_swf extends getid3_handler { public $ReturnAllTagData = false; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; diff --git a/www/plugins-dist/medias/lib/getid3/module.audio-video.ts.php b/www/plugins-dist/medias/lib/getid3/module.audio-video.ts.php index 33620242..24679bc7 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio-video.ts.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio-video.ts.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio-video.ts.php // @@ -17,7 +17,9 @@ class getid3_ts extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -66,12 +68,16 @@ class getid3_ts extends getid3_handler } } -$this->error('MPEG Transport Stream (.ts) parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); -return false; + $this->error('MPEG Transport Stream (.ts) parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); + return false; } - + /** + * @param int $raw + * + * @return string + */ public function TSscramblingControlLookup($raw) { $TSscramblingControlLookup = array(0x00=>'not scrambled', 0x01=>'reserved', 0x02=>'scrambled, even key', 0x03=>'scrambled, odd key'); return (isset($TSscramblingControlLookup[$raw]) ? $TSscramblingControlLookup[$raw] : 'invalid'); diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.aa.php b/www/plugins-dist/medias/lib/getid3/module.audio.aa.php index 889fd581..1eec54e2 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.aa.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.aa.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.aa.php // @@ -17,7 +17,9 @@ class getid3_aa extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -36,12 +38,12 @@ class getid3_aa extends getid3_handler $info['fileformat'] = 'aa'; $info['audio']['dataformat'] = 'aa'; -$this->error('Audible Audiobook (.aa) parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); -return false; + $this->error('Audible Audiobook (.aa) parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); + return false; $info['audio']['bitrate_mode'] = 'cbr'; // is it? $thisfile_aa['encoding'] = 'ISO-8859-1'; - $thisfile_aa['filesize'] = getid3_lib::BigEndian2Int(substr($AUheader, 0, 4)); + $thisfile_aa['filesize'] = getid3_lib::BigEndian2Int(substr($AAheader, 0, 4)); if ($thisfile_aa['filesize'] > ($info['avdataend'] - $info['avdataoffset'])) { $this->warning('Possible truncated file - expecting "'.$thisfile_aa['filesize'].'" bytes of data, only found '.($info['avdataend'] - $info['avdataoffset']).' bytes"'); } diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.aac.php b/www/plugins-dist/medias/lib/getid3/module.audio.aac.php index 59d79def..846850cf 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.aac.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.aac.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.aac.php // @@ -17,6 +17,9 @@ class getid3_aac extends getid3_handler { + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; $this->fseek($info['avdataoffset']); @@ -28,8 +31,9 @@ class getid3_aac extends getid3_handler return true; } - - + /** + * @return bool + */ public function getAACADIFheaderFilepointer() { $info = &$this->getid3->info; $info['fileformat'] = 'aac'; @@ -69,17 +73,17 @@ class getid3_aac extends getid3_handler $bitoffset += 32; $info['aac']['header']['mpeg_version'] = 4; - $info['aac']['header']['copyright'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1'); + $info['aac']['header']['copyright'] = substr($AACheaderBitstream, $bitoffset, 1) == '1'; $bitoffset += 1; if ($info['aac']['header']['copyright']) { $info['aac']['header']['copyright_id'] = getid3_lib::Bin2String(substr($AACheaderBitstream, $bitoffset, 72)); $bitoffset += 72; } - $info['aac']['header']['original_copy'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1'); + $info['aac']['header']['original_copy'] = substr($AACheaderBitstream, $bitoffset, 1) == '1'; $bitoffset += 1; - $info['aac']['header']['home'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1'); + $info['aac']['header']['home'] = substr($AACheaderBitstream, $bitoffset, 1) == '1'; $bitoffset += 1; - $info['aac']['header']['is_vbr'] = (bool) (substr($AACheaderBitstream, $bitoffset, 1) == '1'); + $info['aac']['header']['is_vbr'] = substr($AACheaderBitstream, $bitoffset, 1) == '1'; $bitoffset += 1; if ($info['aac']['header']['is_vbr']) { $info['audio']['bitrate_mode'] = 'vbr'; @@ -257,7 +261,12 @@ class getid3_aac extends getid3_handler } - + /** + * @param int $MaxFramesToScan + * @param bool $ReturnExtendedInfo + * + * @return bool + */ public function getAACADTSheaderFilepointer($MaxFramesToScan=1000000, $ReturnExtendedInfo=false) { $info = &$this->getid3->info; @@ -443,6 +452,11 @@ class getid3_aac extends getid3_handler // should never get here. } + /** + * @param int $samplerateid + * + * @return int|string + */ public static function AACsampleRateLookup($samplerateid) { static $AACsampleRateLookup = array(); if (empty($AACsampleRateLookup)) { @@ -466,6 +480,12 @@ class getid3_aac extends getid3_handler return (isset($AACsampleRateLookup[$samplerateid]) ? $AACsampleRateLookup[$samplerateid] : 'invalid'); } + /** + * @param int $profileid + * @param int $mpegversion + * + * @return string + */ public static function AACprofileLookup($profileid, $mpegversion) { static $AACprofileLookup = array(); if (empty($AACprofileLookup)) { @@ -481,6 +501,11 @@ class getid3_aac extends getid3_handler return (isset($AACprofileLookup[$mpegversion][$profileid]) ? $AACprofileLookup[$mpegversion][$profileid] : 'invalid'); } + /** + * @param array $program_configs + * + * @return int + */ public static function AACchannelCountCalculate($program_configs) { $channels = 0; for ($i = 0; $i < $program_configs['num_front_channel_elements']; $i++) { diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.ac3.php b/www/plugins-dist/medias/lib/getid3/module.audio.ac3.php index c370c7f6..d4e4e4ba 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.ac3.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.ac3.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.ac3.php // @@ -17,11 +17,21 @@ class getid3_ac3 extends getid3_handler { + /** + * @var array + */ private $AC3header = array(); + + /** + * @var int + */ private $BSIoffset = 0; const syncword = 0x0B77; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -161,21 +171,21 @@ class getid3_ac3 extends getid3_handler if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x01) { $thisfile_ac3_raw_bsi['timecod1'] = $this->readHeaderBSI(14); // 5.4.2.27 timecod1: Time code first half, 14 bits $thisfile_ac3['timecode1'] = 0; - $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x3E00) >> 9) * 3600; // The first 5 bits of this 14-bit field represent the time in hours, with valid values of 0–23 - $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x01F8) >> 3) * 60; // The next 6 bits represent the time in minutes, with valid values of 0–59 - $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x0003) >> 0) * 8; // The final 3 bits represents the time in 8 second increments, with valid values of 0–7 (representing 0, 8, 16, ... 56 seconds) + $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x3E00) >> 9) * 3600; // The first 5 bits of this 14-bit field represent the time in hours, with valid values of 0�23 + $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x01F8) >> 3) * 60; // The next 6 bits represent the time in minutes, with valid values of 0�59 + $thisfile_ac3['timecode1'] += (($thisfile_ac3_raw_bsi['timecod1'] & 0x0003) >> 0) * 8; // The final 3 bits represents the time in 8 second increments, with valid values of 0�7 (representing 0, 8, 16, ... 56 seconds) } if ($thisfile_ac3_raw_bsi['flags']['timecod1'] & 0x02) { $thisfile_ac3_raw_bsi['timecod2'] = $this->readHeaderBSI(14); // 5.4.2.28 timecod2: Time code second half, 14 bits $thisfile_ac3['timecode2'] = 0; - $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x3800) >> 11) * 1; // The first 3 bits of this 14-bit field represent the time in seconds, with valid values from 0–7 (representing 0-7 seconds) - $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x07C0) >> 6) * (1 / 30); // The next 5 bits represents the time in frames, with valid values from 0–29 (one frame = 1/30th of a second) - $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x003F) >> 0) * ((1 / 30) / 60); // The final 6 bits represents fractions of 1/64 of a frame, with valid values from 0–63 + $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x3800) >> 11) * 1; // The first 3 bits of this 14-bit field represent the time in seconds, with valid values from 0�7 (representing 0-7 seconds) + $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x07C0) >> 6) * (1 / 30); // The next 5 bits represents the time in frames, with valid values from 0�29 (one frame = 1/30th of a second) + $thisfile_ac3['timecode2'] += (($thisfile_ac3_raw_bsi['timecod2'] & 0x003F) >> 0) * ((1 / 30) / 60); // The final 6 bits represents fractions of 1/64 of a frame, with valid values from 0�63 } $thisfile_ac3_raw_bsi['flags']['addbsi'] = (bool) $this->readHeaderBSI(1); if ($thisfile_ac3_raw_bsi['flags']['addbsi']) { - $thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6) + 1; // This 6-bit code, which exists only if addbside is a 1, indicates the length in bytes of additional bit stream information. The valid range of addbsil is 0–63, indicating 1–64 additional bytes, respectively. + $thisfile_ac3_raw_bsi['addbsi_length'] = $this->readHeaderBSI(6) + 1; // This 6-bit code, which exists only if addbside is a 1, indicates the length in bytes of additional bit stream information. The valid range of addbsil is 0�63, indicating 1�64 additional bytes, respectively. $this->AC3header['bsi'] .= getid3_lib::BigEndian2Bin($this->fread($thisfile_ac3_raw_bsi['addbsi_length'])); @@ -187,7 +197,7 @@ class getid3_ac3 extends getid3_handler } elseif ($thisfile_ac3_raw_bsi['bsid'] <= 16) { // E-AC3 -$this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.'); + $this->error('E-AC3 parsing is incomplete and experimental in this version of getID3 ('.$this->getid3->version().'). Notably the bitrate calculations are wrong -- value might (or not) be correct, but it is not calculated correctly. Email info@getid3.org if you know how to calculate EAC3 bitrate correctly.'); $info['audio']['dataformat'] = 'eac3'; $thisfile_ac3_raw_bsi['strmtyp'] = $this->readHeaderBSI(2); @@ -431,15 +441,17 @@ $this->error('E-AC3 parsing is incomplete and experimental in this version of ge $thisfile_ac3['frame_length'] = self::frameSizeLookup($thisfile_ac3_raw_bsi['frmsizecod'], $thisfile_ac3_raw_bsi['fscod']); $thisfile_ac3['bitrate'] = self::bitrateLookup($thisfile_ac3_raw_bsi['frmsizecod']); } elseif (!empty($thisfile_ac3_raw_bsi['frmsiz'])) { -// this isn't right, but it's (usually) close, roughly 5% less than it should be. -// but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know! + // this isn't right, but it's (usually) close, roughly 5% less than it should be. + // but WHERE is the actual bitrate value stored in EAC3?? email info@getid3.org if you know! $thisfile_ac3['bitrate'] = ($thisfile_ac3_raw_bsi['frmsiz'] + 1) * 16 * 30; // The frmsiz field shall contain a value one less than the overall size of the coded syncframe in 16-bit words. That is, this field may assume a value ranging from 0 to 2047, and these values correspond to syncframe sizes ranging from 1 to 2048. -// kludge-fix to make it approximately the expected value, still not "right": -$thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000; + // kludge-fix to make it approximately the expected value, still not "right": + $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16000; } $info['audio']['bitrate'] = $thisfile_ac3['bitrate']; - $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']); + if (isset($thisfile_ac3_raw_bsi['bsmod']) && isset($thisfile_ac3_raw_bsi['acmod'])) { + $thisfile_ac3['service_type'] = self::serviceTypeLookup($thisfile_ac3_raw_bsi['bsmod'], $thisfile_ac3_raw_bsi['acmod']); + } $ac3_coding_mode = self::audioCodingModeLookup($thisfile_ac3_raw_bsi['acmod']); foreach($ac3_coding_mode as $key => $value) { $thisfile_ac3[$key] = $value; @@ -470,6 +482,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return true; } + /** + * @param int $length + * + * @return float|int + */ private function readHeaderBSI($length) { $data = substr($this->AC3header['bsi'], $this->BSIoffset, $length); $this->BSIoffset += $length; @@ -477,6 +494,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return bindec($data); } + /** + * @param int $fscod + * + * @return int|string|false + */ public static function sampleRateCodeLookup($fscod) { static $sampleRateCodeLookup = array( 0 => 48000, @@ -487,6 +509,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return (isset($sampleRateCodeLookup[$fscod]) ? $sampleRateCodeLookup[$fscod] : false); } + /** + * @param int $fscod2 + * + * @return int|string|false + */ public static function sampleRateCodeLookup2($fscod2) { static $sampleRateCodeLookup2 = array( 0 => 24000, @@ -497,6 +524,12 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return (isset($sampleRateCodeLookup2[$fscod2]) ? $sampleRateCodeLookup2[$fscod2] : false); } + /** + * @param int $bsmod + * @param int $acmod + * + * @return string|false + */ public static function serviceTypeLookup($bsmod, $acmod) { static $serviceTypeLookup = array(); if (empty($serviceTypeLookup)) { @@ -518,6 +551,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return (isset($serviceTypeLookup[$bsmod][$acmod]) ? $serviceTypeLookup[$bsmod][$acmod] : false); } + /** + * @param int $acmod + * + * @return array|false + */ public static function audioCodingModeLookup($acmod) { // array(channel configuration, # channels (not incl LFE), channel order) static $audioCodingModeLookup = array ( @@ -533,6 +571,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return (isset($audioCodingModeLookup[$acmod]) ? $audioCodingModeLookup[$acmod] : false); } + /** + * @param int $cmixlev + * + * @return int|float|string|false + */ public static function centerMixLevelLookup($cmixlev) { static $centerMixLevelLookup; if (empty($centerMixLevelLookup)) { @@ -546,6 +589,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return (isset($centerMixLevelLookup[$cmixlev]) ? $centerMixLevelLookup[$cmixlev] : false); } + /** + * @param int $surmixlev + * + * @return int|float|string|false + */ public static function surroundMixLevelLookup($surmixlev) { static $surroundMixLevelLookup; if (empty($surroundMixLevelLookup)) { @@ -559,6 +607,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return (isset($surroundMixLevelLookup[$surmixlev]) ? $surroundMixLevelLookup[$surmixlev] : false); } + /** + * @param int $dsurmod + * + * @return string|false + */ public static function dolbySurroundModeLookup($dsurmod) { static $dolbySurroundModeLookup = array( 0 => 'not indicated', @@ -569,12 +622,18 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return (isset($dolbySurroundModeLookup[$dsurmod]) ? $dolbySurroundModeLookup[$dsurmod] : false); } + /** + * @param int $acmod + * @param bool $lfeon + * + * @return array + */ public static function channelsEnabledLookup($acmod, $lfeon) { $lookup = array( - 'ch1'=>(bool) ($acmod == 0), - 'ch2'=>(bool) ($acmod == 0), - 'left'=>(bool) ($acmod > 1), - 'right'=>(bool) ($acmod > 1), + 'ch1'=>($acmod == 0), + 'ch2'=>($acmod == 0), + 'left'=>($acmod > 1), + 'right'=>($acmod > 1), 'center'=>(bool) ($acmod & 0x01), 'surround_mono'=>false, 'surround_left'=>false, @@ -594,6 +653,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return $lookup; } + /** + * @param int $compre + * + * @return float|int + */ public static function heavyCompression($compre) { // The first four bits indicate gain changes in 6.02dB increments which can be // implemented with an arithmetic shift operation. The following four bits @@ -644,6 +708,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return $log_gain - $lin_gain; } + /** + * @param int $roomtyp + * + * @return string|false + */ public static function roomTypeLookup($roomtyp) { static $roomTypeLookup = array( 0 => 'not indicated', @@ -654,6 +723,12 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return (isset($roomTypeLookup[$roomtyp]) ? $roomTypeLookup[$roomtyp] : false); } + /** + * @param int $frmsizecod + * @param int $fscod + * + * @return int|false + */ public static function frameSizeLookup($frmsizecod, $fscod) { // LSB is whether padding is used or not $padding = (bool) ($frmsizecod & 0x01); @@ -690,6 +765,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return (isset($frameSizeLookup[$framesizeid][$fscod]) ? $frameSizeLookup[$framesizeid][$fscod] : false); } + /** + * @param int $frmsizecod + * + * @return int|false + */ public static function bitrateLookup($frmsizecod) { // LSB is whether padding is used or not $padding = (bool) ($frmsizecod & 0x01); @@ -719,6 +799,11 @@ $thisfile_ac3['bitrate'] = round(($thisfile_ac3['bitrate'] * 1.05) / 16000) * 16 return (isset($bitrateLookup[$framesizeid]) ? $bitrateLookup[$framesizeid] : false); } + /** + * @param int $numblkscod + * + * @return int|false + */ public static function blocksPerSyncFrame($numblkscod) { static $blocksPerSyncFrameLookup = array( 0 => 1, diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.amr.php b/www/plugins-dist/medias/lib/getid3/module.audio.amr.php index ff505796..42ebd149 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.amr.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.amr.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.aa.php // @@ -17,7 +17,9 @@ class getid3_amr extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -63,7 +65,11 @@ class getid3_amr extends getid3_handler return true; } - + /** + * @param int $key + * + * @return int|false + */ public function amr_mode_bitrate($key) { static $amr_mode_bitrate = array( 0 => 4750, @@ -78,6 +84,11 @@ class getid3_amr extends getid3_handler return (isset($amr_mode_bitrate[$key]) ? $amr_mode_bitrate[$key] : false); } + /** + * @param int $key + * + * @return int|false + */ public function amr_mode_bytes_per_frame($key) { static $amr_mode_bitrate = array( 0 => 13, // 1-byte frame header + 95 bits [padded to: 12 bytes] audio data diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.au.php b/www/plugins-dist/medias/lib/getid3/module.audio.au.php index 075ee8c7..a99d05d7 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.au.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.au.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.au.php // @@ -17,7 +17,9 @@ class getid3_au extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -70,6 +72,11 @@ class getid3_au extends getid3_handler return true; } + /** + * @param int $id + * + * @return string|false + */ public function AUdataFormatNameLookup($id) { static $AUdataFormatNameLookup = array( 0 => 'unspecified format', @@ -104,6 +111,11 @@ class getid3_au extends getid3_handler return (isset($AUdataFormatNameLookup[$id]) ? $AUdataFormatNameLookup[$id] : false); } + /** + * @param int $id + * + * @return int|false + */ public function AUdataFormatBitsPerSampleLookup($id) { static $AUdataFormatBitsPerSampleLookup = array( 1 => 8, @@ -132,6 +144,11 @@ class getid3_au extends getid3_handler return (isset($AUdataFormatBitsPerSampleLookup[$id]) ? $AUdataFormatBitsPerSampleLookup[$id] : false); } + /** + * @param int $id + * + * @return int|false + */ public function AUdataFormatUsedBitsPerSampleLookup($id) { static $AUdataFormatUsedBitsPerSampleLookup = array( 1 => 8, diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.avr.php b/www/plugins-dist/medias/lib/getid3/module.audio.avr.php index 98666cf0..50e29940 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.avr.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.avr.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.avr.php // @@ -17,7 +17,9 @@ class getid3_avr extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.bonk.php b/www/plugins-dist/medias/lib/getid3/module.audio.bonk.php index f314a9f5..53983914 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.bonk.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.bonk.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.la.php // @@ -17,6 +17,9 @@ class getid3_bonk extends getid3_handler { + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -114,6 +117,9 @@ class getid3_bonk extends getid3_handler } + /** + * @param string $BonkTagName + */ public function HandleBonkTags($BonkTagName) { $info = &$this->getid3->info; switch ($BonkTagName) { @@ -213,6 +219,12 @@ class getid3_bonk extends getid3_handler } } + /** + * @param string $PossibleBonkTag + * @param bool $ignorecase + * + * @return bool + */ public static function BonkIsValidTagName($PossibleBonkTag, $ignorecase=false) { static $BonkIsValidTagName = array('BONK', 'INFO', ' ID3', 'META'); foreach ($BonkIsValidTagName as $validtagname) { diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.dsf.php b/www/plugins-dist/medias/lib/getid3/module.audio.dsf.php index 50be37c3..bbcee761 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.dsf.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.dsf.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.dsf.php // @@ -18,7 +18,9 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE_ class getid3_dsf extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -115,7 +117,11 @@ class getid3_dsf extends getid3_handler return true; } - + /** + * @param int $channel_type_id + * + * @return string + */ public static function DSFchannelTypeLookup($channel_type_id) { static $DSFchannelTypeLookup = array( // interleaving order: diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.dss.php b/www/plugins-dist/medias/lib/getid3/module.audio.dss.php index 6bd96682..492393a8 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.dss.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.dss.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.dss.php // @@ -17,7 +17,9 @@ class getid3_dss extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -71,6 +73,11 @@ class getid3_dss extends getid3_handler return true; } + /** + * @param string $datestring + * + * @return int|false + */ public function DSSdateStringToUnixDate($datestring) { $y = substr($datestring, 0, 2); $m = substr($datestring, 2, 2); @@ -82,6 +89,11 @@ class getid3_dss extends getid3_handler return mktime($h, $i, $s, $m, $d, $y); } + /** + * @param int $sample_rate_index + * + * @return int|false + */ public function DSSsampleRateLookup($sample_rate_index) { static $dssSampleRateLookup = array( 0x0A => 16000, diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.dts.php b/www/plugins-dist/medias/lib/getid3/module.audio.dts.php index bdc78f0b..2dd44e9e 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.dts.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.dts.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.dts.php // @@ -21,21 +21,27 @@ class getid3_dts extends getid3_handler { /** - * Default DTS syncword used in native .cpt or .dts formats - */ - const syncword = "\x7F\xFE\x80\x01"; + * Default DTS syncword used in native .cpt or .dts formats. + */ + const syncword = "\x7F\xFE\x80\x01"; + /** + * @var int + */ private $readBinDataOffset = 0; - /** - * Possible syncwords indicating bitstream encoding - */ - public static $syncwords = array( - 0 => "\x7F\xFE\x80\x01", // raw big-endian - 1 => "\xFE\x7F\x01\x80", // raw little-endian - 2 => "\x1F\xFF\xE8\x00", // 14-bit big-endian - 3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian + /** + * Possible syncwords indicating bitstream encoding. + */ + public static $syncwords = array( + 0 => "\x7F\xFE\x80\x01", // raw big-endian + 1 => "\xFE\x7F\x01\x80", // raw little-endian + 2 => "\x1F\xFF\xE8\x00", // 14-bit big-endian + 3 => "\xFF\x1F\x00\xE8"); // 14-bit little-endian + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; $info['fileformat'] = 'dts'; @@ -139,6 +145,12 @@ class getid3_dts extends getid3_handler return true; } + /** + * @param string $bin + * @param int $length + * + * @return float|int + */ private function readBinData($bin, $length) { $data = substr($bin, $this->readBinDataOffset, $length); $this->readBinDataOffset += $length; @@ -146,6 +158,11 @@ class getid3_dts extends getid3_handler return bindec($data); } + /** + * @param int $index + * + * @return int|string|false + */ public static function bitrateLookup($index) { static $lookup = array( 0 => 32000, @@ -184,6 +201,11 @@ class getid3_dts extends getid3_handler return (isset($lookup[$index]) ? $lookup[$index] : false); } + /** + * @param int $index + * + * @return int|string|false + */ public static function sampleRateLookup($index) { static $lookup = array( 0 => 'invalid', @@ -206,6 +228,11 @@ class getid3_dts extends getid3_handler return (isset($lookup[$index]) ? $lookup[$index] : false); } + /** + * @param int $index + * + * @return int|false + */ public static function bitPerSampleLookup($index) { static $lookup = array( 0 => 16, @@ -216,6 +243,11 @@ class getid3_dts extends getid3_handler return (isset($lookup[$index]) ? $lookup[$index] : false); } + /** + * @param int $index + * + * @return int|false + */ public static function numChannelsLookup($index) { switch ($index) { case 0: @@ -254,6 +286,11 @@ class getid3_dts extends getid3_handler return false; } + /** + * @param int $index + * + * @return string + */ public static function channelArrangementLookup($index) { static $lookup = array( 0 => 'A', @@ -276,6 +313,12 @@ class getid3_dts extends getid3_handler return (isset($lookup[$index]) ? $lookup[$index] : 'user-defined'); } + /** + * @param int $index + * @param int $version + * + * @return int|false + */ public static function dialogNormalization($index, $version) { switch ($version) { case 7: diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.flac.php b/www/plugins-dist/medias/lib/getid3/module.audio.flac.php index 348cce32..4edf587d 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.flac.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.flac.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.flac.php // @@ -24,6 +24,9 @@ class getid3_flac extends getid3_handler { const syncword = 'fLaC'; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -41,22 +44,30 @@ class getid3_flac extends getid3_handler return $this->parseMETAdata(); } + /** + * @return bool + */ public function parseMETAdata() { $info = &$this->getid3->info; do { $BlockOffset = $this->ftell(); $BlockHeader = $this->fread(4); - $LBFBT = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1)); + $LBFBT = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1)); // LBFBT = LastBlockFlag + BlockType $LastBlockFlag = (bool) ($LBFBT & 0x80); $BlockType = ($LBFBT & 0x7F); $BlockLength = getid3_lib::BigEndian2Int(substr($BlockHeader, 1, 3)); $BlockTypeText = self::metaBlockTypeLookup($BlockType); if (($BlockOffset + 4 + $BlockLength) > $info['avdataend']) { - $this->error('METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.') at offset '.$BlockOffset.' extends beyond end of file'); + $this->warning('METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.') at offset '.$BlockOffset.' extends beyond end of file'); break; } if ($BlockLength < 1) { + if ($BlockTypeText != 'reserved') { + // probably supposed to be zero-length + $this->warning('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockTypeText.') at offset '.$BlockOffset.' is zero bytes'); + continue; + } $this->error('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockLength.') at offset '.$BlockOffset.' is invalid'); break; } @@ -194,12 +205,14 @@ class getid3_flac extends getid3_handler return true; } - private function parseSTREAMINFO($BlockData) { - $info = &$this->getid3->info; - - $info['flac']['STREAMINFO'] = array(); - $streaminfo = &$info['flac']['STREAMINFO']; + /** + * @param string $BlockData + * + * @return array + */ + public static function parseSTREAMINFOdata($BlockData) { + $streaminfo = array(); $streaminfo['min_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 0, 2)); $streaminfo['max_block_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 2, 2)); $streaminfo['min_frame_size'] = getid3_lib::BigEndian2Int(substr($BlockData, 4, 3)); @@ -211,15 +224,28 @@ class getid3_flac extends getid3_handler $streaminfo['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 23, 5)) + 1; $streaminfo['samples_stream'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 28, 36)); - $streaminfo['audio_signature'] = substr($BlockData, 18, 16); + $streaminfo['audio_signature'] = substr($BlockData, 18, 16); + + return $streaminfo; + } + + /** + * @param string $BlockData + * + * @return bool + */ + private function parseSTREAMINFO($BlockData) { + $info = &$this->getid3->info; - if (!empty($streaminfo['sample_rate'])) { + $info['flac']['STREAMINFO'] = self::parseSTREAMINFOdata($BlockData); + + if (!empty($info['flac']['STREAMINFO']['sample_rate'])) { $info['audio']['bitrate_mode'] = 'vbr'; - $info['audio']['sample_rate'] = $streaminfo['sample_rate']; - $info['audio']['channels'] = $streaminfo['channels']; - $info['audio']['bits_per_sample'] = $streaminfo['bits_per_sample']; - $info['playtime_seconds'] = $streaminfo['samples_stream'] / $streaminfo['sample_rate']; + $info['audio']['sample_rate'] = $info['flac']['STREAMINFO']['sample_rate']; + $info['audio']['channels'] = $info['flac']['STREAMINFO']['channels']; + $info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample']; + $info['playtime_seconds'] = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate']; if ($info['playtime_seconds'] > 0) { if (!$this->isDependencyFor('matroska')) { $info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds']; @@ -236,6 +262,11 @@ class getid3_flac extends getid3_handler return true; } + /** + * @param string $BlockData + * + * @return bool + */ private function parseAPPLICATION($BlockData) { $info = &$this->getid3->info; @@ -246,6 +277,11 @@ class getid3_flac extends getid3_handler return true; } + /** + * @param string $BlockData + * + * @return bool + */ private function parseSEEKTABLE($BlockData) { $info = &$this->getid3->info; @@ -275,6 +311,11 @@ class getid3_flac extends getid3_handler return true; } + /** + * @param string $BlockData + * + * @return bool + */ private function parseVORBIS_COMMENT($BlockData) { $info = &$this->getid3->info; @@ -294,6 +335,11 @@ class getid3_flac extends getid3_handler return true; } + /** + * @param string $BlockData + * + * @return bool + */ private function parseCUESHEET($BlockData) { $info = &$this->getid3->info; $offset = 0; @@ -346,9 +392,11 @@ class getid3_flac extends getid3_handler } /** - * Parse METADATA_BLOCK_PICTURE flac structure and extract attachment - * External usage: audio.ogg - */ + * Parse METADATA_BLOCK_PICTURE flac structure and extract attachment + * External usage: audio.ogg + * + * @return bool + */ public function parsePICTURE() { $info = &$this->getid3->info; @@ -380,6 +428,11 @@ class getid3_flac extends getid3_handler return true; } + /** + * @param int $blocktype + * + * @return string + */ public static function metaBlockTypeLookup($blocktype) { static $lookup = array( 0 => 'STREAMINFO', @@ -393,6 +446,11 @@ class getid3_flac extends getid3_handler return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 'reserved'); } + /** + * @param int $applicationid + * + * @return string + */ public static function applicationIDLookup($applicationid) { // http://flac.sourceforge.net/id.html static $lookup = array( @@ -423,6 +481,11 @@ class getid3_flac extends getid3_handler return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 'reserved'); } + /** + * @param int $type_id + * + * @return string + */ public static function pictureTypeLookup($type_id) { static $lookup = array ( 0 => 'Other', diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.la.php b/www/plugins-dist/medias/lib/getid3/module.audio.la.php index f46c9aa0..3fee9d39 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.la.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.la.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.la.php // @@ -18,7 +18,9 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', class getid3_la extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.lpac.php b/www/plugins-dist/medias/lib/getid3/module.audio.lpac.php index 447cc2d6..375ba206 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.lpac.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.lpac.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.lpac.php // @@ -18,13 +18,16 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', class getid3_lpac extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; $this->fseek($info['avdataoffset']); $LPACheader = $this->fread(14); - if (substr($LPACheader, 0, 4) != 'LPAC') { + $StreamMarker = substr($LPACheader, 0, 4); + if ($StreamMarker != 'LPAC') { $this->error('Expected "LPAC" at offset '.$info['avdataoffset'].', found "'.$StreamMarker.'"'); return false; } diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.midi.php b/www/plugins-dist/medias/lib/getid3/module.audio.midi.php index 359aca26..770481c6 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.midi.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.midi.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.midi.php // @@ -19,8 +19,14 @@ define('GETID3_MIDI_MAGIC_MTRK', 'MTrk'); // MIDI track header magic class getid3_midi extends getid3_handler { + /** + * @var bool + */ public $scanwholefile = true; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -88,6 +94,7 @@ class getid3_midi extends getid3_handler $CurrentMicroSecondsPerBeat = 500000; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat $CurrentBeatsPerMinute = 120; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat $MicroSecondsPerQuarterNoteAfter = array (); + $MIDIevents = array(); foreach ($trackdataarray as $tracknumber => $trackdata) { @@ -283,7 +290,8 @@ class getid3_midi extends getid3_handler $thisfile_midi['totalticks'] = max($thisfile_midi['totalticks'], $CumulativeDeltaTime); } } - $previoustickoffset = null; + $previoustickoffset = null; + $prevmicrosecondsperbeat = null; ksort($MicroSecondsPerQuarterNoteAfter); foreach ($MicroSecondsPerQuarterNoteAfter as $tickoffset => $microsecondsperbeat) { @@ -312,7 +320,7 @@ class getid3_midi extends getid3_handler return false; } - $info['playtime_seconds'] += (($thisfile_midi['totalticks'] - $previoustickoffset) / $thisfile_midi_raw['ticksperqnote']) * ($microsecondsperbeat / 1000000); + $info['playtime_seconds'] += (($thisfile_midi['totalticks'] - $previoustickoffset) / $thisfile_midi_raw['ticksperqnote']) * ($prevmicrosecondsperbeat / 1000000); } } @@ -329,6 +337,11 @@ class getid3_midi extends getid3_handler return true; } + /** + * @param int $instrumentid + * + * @return string + */ public function GeneralMIDIinstrumentLookup($instrumentid) { $begin = __LINE__; @@ -469,6 +482,11 @@ class getid3_midi extends getid3_handler return getid3_lib::EmbeddedLookup($instrumentid, $begin, __LINE__, __FILE__, 'GeneralMIDIinstrument'); } + /** + * @param int $instrumentid + * + * @return string + */ public function GeneralMIDIpercussionLookup($instrumentid) { $begin = __LINE__; diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.mod.php b/www/plugins-dist/medias/lib/getid3/module.audio.mod.php index 4b888ecd..708d213b 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.mod.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.mod.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.mod.php // @@ -17,7 +17,9 @@ class getid3_mod extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; $this->fseek($info['avdataoffset']); @@ -35,7 +37,9 @@ class getid3_mod extends getid3_handler return false; } - + /** + * @return bool + */ public function getMODheaderFilepointer() { $info = &$this->getid3->info; $this->fseek($info['avdataoffset'] + 1080); @@ -51,6 +55,9 @@ class getid3_mod extends getid3_handler return false; } + /** + * @return bool + */ public function getXMheaderFilepointer() { $info = &$this->getid3->info; $this->fseek($info['avdataoffset']); @@ -66,6 +73,9 @@ class getid3_mod extends getid3_handler return false; } + /** + * @return bool + */ public function getS3MheaderFilepointer() { $info = &$this->getid3->info; $this->fseek($info['avdataoffset'] + 44); @@ -81,6 +91,9 @@ class getid3_mod extends getid3_handler return false; } + /** + * @return bool + */ public function getITheaderFilepointer() { $info = &$this->getid3->info; $this->fseek($info['avdataoffset']); diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.monkey.php b/www/plugins-dist/medias/lib/getid3/module.audio.monkey.php index afa2eaf2..3317a93e 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.monkey.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.monkey.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.monkey.php // @@ -17,7 +17,9 @@ class getid3_monkey extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -177,6 +179,11 @@ class getid3_monkey extends getid3_handler return true; } + /** + * @param int $compressionlevel + * + * @return string + */ public function MonkeyCompressionLevelNameLookup($compressionlevel) { static $MonkeyCompressionLevelNameLookup = array( 0 => 'unknown', @@ -189,6 +196,12 @@ class getid3_monkey extends getid3_handler return (isset($MonkeyCompressionLevelNameLookup[$compressionlevel]) ? $MonkeyCompressionLevelNameLookup[$compressionlevel] : 'invalid'); } + /** + * @param int $versionid + * @param int $compressionlevel + * + * @return int + */ public function MonkeySamplesPerFrame($versionid, $compressionlevel) { if ($versionid >= 3950) { return 73728 * 4; diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.mp3.php b/www/plugins-dist/medias/lib/getid3/module.audio.mp3.php index ca3ec545..44343804 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.mp3.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.mp3.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.mp3.php // @@ -24,9 +24,17 @@ define('GETID3_MP3_VALID_CHECK_FRAMES', 35); class getid3_mp3 extends getid3_handler { - - public $allow_bruteforce = false; // forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, unrecommended, but may provide data from otherwise-unusuable files - + /** + * Forces getID3() to scan the file byte-by-byte and log all the valid audio frame headers - extremely slow, + * unrecommended, but may provide data from otherwise-unusable files. + * + * @var bool + */ + public $allow_bruteforce = false; + + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -35,7 +43,7 @@ class getid3_mp3 extends getid3_handler if (!$this->getOnlyMPEGaudioInfo($info['avdataoffset'])) { if ($this->allow_bruteforce) { $this->error('Rescanning file in BruteForce mode'); - $this->getOnlyMPEGaudioInfoBruteForce($this->getid3->fp, $info); + $this->getOnlyMPEGaudioInfoBruteForce(); } } @@ -152,7 +160,11 @@ class getid3_mp3 extends getid3_handler // Calculate playtime if (!isset($info['playtime_seconds']) && isset($info['audio']['bitrate']) && ($info['audio']['bitrate'] > 0)) { - $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset']) * 8 / $info['audio']['bitrate']; + // https://github.com/JamesHeinrich/getID3/issues/161 + // VBR header frame contains ~0.026s of silent audio data, but is not actually part of the original encoding and should be ignored + $xingVBRheaderFrameLength = ((isset($info['mpeg']['audio']['VBR_frames']) && isset($info['mpeg']['audio']['framelength'])) ? $info['mpeg']['audio']['framelength'] : 0); + + $info['playtime_seconds'] = ($info['avdataend'] - $info['avdataoffset'] - $xingVBRheaderFrameLength) * 8 / $info['audio']['bitrate']; } $info['audio']['encoder_options'] = $this->GuessEncoderOptions(); @@ -160,10 +172,14 @@ class getid3_mp3 extends getid3_handler return true; } - + /** + * @return string + */ public function GuessEncoderOptions() { // shortcuts $info = &$this->getid3->info; + $thisfile_mpeg_audio = array(); + $thisfile_mpeg_audio_lame = array(); if (!empty($info['mpeg']['audio'])) { $thisfile_mpeg_audio = &$info['mpeg']['audio']; if (!empty($thisfile_mpeg_audio['LAME'])) { @@ -178,7 +194,7 @@ class getid3_mp3 extends getid3_handler $encoder_options = 'VBR q'.$thisfile_mpeg_audio['VBR_quality']; - } elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) { + } elseif (!empty($thisfile_mpeg_audio_lame['preset_used']) && isset($thisfile_mpeg_audio_lame['preset_used_id']) && (!in_array($thisfile_mpeg_audio_lame['preset_used_id'], $NamedPresetBitrates))) { $encoder_options = $thisfile_mpeg_audio_lame['preset_used']; @@ -404,7 +420,15 @@ class getid3_mp3 extends getid3_handler return $encoder_options; } - + /** + * @param int $offset + * @param array $info + * @param bool $recursivesearch + * @param bool $ScanAsCBR + * @param bool $FastMPEGheaderScan + * + * @return bool + */ public function decodeMPEGaudioHeader($offset, &$info, $recursivesearch=true, $ScanAsCBR=false, $FastMPEGheaderScan=false) { static $MPEGaudioVersionLookup; static $MPEGaudioLayerLookup; @@ -437,18 +461,19 @@ class getid3_mp3 extends getid3_handler // and $cc... is the audio data $head4 = substr($headerstring, 0, 4); + $head4_key = getid3_lib::PrintHexBytes($head4, true, false, false); static $MPEGaudioHeaderDecodeCache = array(); - if (isset($MPEGaudioHeaderDecodeCache[$head4])) { - $MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4]; + if (isset($MPEGaudioHeaderDecodeCache[$head4_key])) { + $MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4_key]; } else { $MPEGheaderRawArray = self::MPEGaudioHeaderDecode($head4); - $MPEGaudioHeaderDecodeCache[$head4] = $MPEGheaderRawArray; + $MPEGaudioHeaderDecodeCache[$head4_key] = $MPEGheaderRawArray; } static $MPEGaudioHeaderValidCache = array(); - if (!isset($MPEGaudioHeaderValidCache[$head4])) { // Not in cache - //$MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true); // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1) - $MPEGaudioHeaderValidCache[$head4] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false); + if (!isset($MPEGaudioHeaderValidCache[$head4_key])) { // Not in cache + //$MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, true); // allow badly-formatted freeformat (from LAME 3.90 - 3.93.1) + $MPEGaudioHeaderValidCache[$head4_key] = self::MPEGaudioHeaderValid($MPEGheaderRawArray, false, false); } // shortcut @@ -457,8 +482,7 @@ class getid3_mp3 extends getid3_handler } $thisfile_mpeg_audio = &$info['mpeg']['audio']; - - if ($MPEGaudioHeaderValidCache[$head4]) { + if ($MPEGaudioHeaderValidCache[$head4_key]) { $thisfile_mpeg_audio['raw'] = $MPEGheaderRawArray; } else { $this->error('Invalid MPEG audio header ('.getid3_lib::PrintHexBytes($head4).') at offset '.$offset); @@ -561,7 +585,7 @@ class getid3_mp3 extends getid3_handler $thisfile_mpeg_audio['bitrate_mode'] = 'vbr'; $thisfile_mpeg_audio['VBR_method'] = 'Fraunhofer'; - $info['audio']['codec'] = 'Fraunhofer'; + $info['audio']['codec'] = 'Fraunhofer'; $SideInfoData = substr($headerstring, 4 + 2, 32); @@ -654,7 +678,7 @@ class getid3_mp3 extends getid3_handler $used_filesize = $thisfile_mpeg_audio['VBR_bytes']; } elseif (!empty($info['filesize'])) { $used_filesize = $info['filesize']; - $used_filesize -= intval(@$info['id3v2']['headerlength']); + $used_filesize -= (isset($info['id3v2']['headerlength']) ? intval($info['id3v2']['headerlength']) : 0); $used_filesize -= (isset($info['id3v1']) ? 128 : 0); $used_filesize -= (isset($info['tag_offset_end']) ? $info['tag_offset_end'] - $info['tag_offset_start'] : 0); $this->warning('MP3.Xing header missing VBR_bytes, assuming MPEG audio portion of file is '.number_format($used_filesize).' bytes'); @@ -1082,6 +1106,13 @@ class getid3_mp3 extends getid3_handler return true; } + /** + * @param int $offset + * @param int $nextframetestoffset + * @param bool $ScanAsCBR + * + * @return bool + */ public function RecursiveFrameScanning(&$offset, &$nextframetestoffset, $ScanAsCBR) { $info = &$this->getid3->info; $firstframetestarray = array('error' => array(), 'warning'=> array(), 'avdataend' => $info['avdataend'], 'avdataoffset' => $info['avdataoffset']); @@ -1128,6 +1159,12 @@ class getid3_mp3 extends getid3_handler return true; } + /** + * @param int $offset + * @param bool $deepscan + * + * @return int|false + */ public function FreeFormatFrameLength($offset, $deepscan=false) { $info = &$this->getid3->info; @@ -1205,6 +1242,9 @@ class getid3_mp3 extends getid3_handler return $framelength; } + /** + * @return bool + */ public function getOnlyMPEGaudioInfoBruteForce() { $MPEGaudioHeaderDecodeCache = array(); $MPEGaudioHeaderValidCache = array(); @@ -1352,7 +1392,12 @@ class getid3_mp3 extends getid3_handler return true; } - + /** + * @param int $avdataoffset + * @param bool $BitrateHistogram + * + * @return bool + */ public function getOnlyMPEGaudioInfo($avdataoffset, $BitrateHistogram=false) { // looks for synch, decodes MPEG audio header @@ -1416,6 +1461,7 @@ class getid3_mp3 extends getid3_handler } if (($header{$SynchSeekOffset} == "\xFF") && ($header{($SynchSeekOffset + 1)} > "\xE0")) { // synch detected + $FirstFrameAVDataOffset = null; if (!isset($FirstFrameThisfileInfo) && !isset($info['mpeg']['audio'])) { $FirstFrameThisfileInfo = $info; $FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset; @@ -1439,7 +1485,7 @@ class getid3_mp3 extends getid3_handler $info['audio']['dataformat'] = 'mp3'; break; } - if (isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) { + if (isset($FirstFrameThisfileInfo) && isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) { if (!(abs($info['audio']['bitrate'] - $FirstFrameThisfileInfo['audio']['bitrate']) <= 1)) { // If there is garbage data between a valid VBR header frame and a sequence // of valid MPEG-audio frames the VBR data is no longer discarded. @@ -1521,7 +1567,7 @@ class getid3_mp3 extends getid3_handler } } $synchstartoffset = $scan_start_offset[$current_segment]; - while ($this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) { + while (($synchstartoffset < $info['avdataend']) && $this->decodeMPEGaudioHeader($synchstartoffset, $dummy, false, false, $FastMode)) { $FastMode = true; $thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']]; @@ -1632,17 +1678,25 @@ class getid3_mp3 extends getid3_handler return true; } - + /** + * @return array + */ public static function MPEGaudioVersionArray() { static $MPEGaudioVersion = array('2.5', false, '2', '1'); return $MPEGaudioVersion; } + /** + * @return array + */ public static function MPEGaudioLayerArray() { static $MPEGaudioLayer = array(false, 3, 2, 1); return $MPEGaudioLayer; } + /** + * @return array + */ public static function MPEGaudioBitrateArray() { static $MPEGaudioBitrate; if (empty($MPEGaudioBitrate)) { @@ -1662,6 +1716,9 @@ class getid3_mp3 extends getid3_handler return $MPEGaudioBitrate; } + /** + * @return array + */ public static function MPEGaudioFrequencyArray() { static $MPEGaudioFrequency; if (empty($MPEGaudioFrequency)) { @@ -1674,11 +1731,17 @@ class getid3_mp3 extends getid3_handler return $MPEGaudioFrequency; } + /** + * @return array + */ public static function MPEGaudioChannelModeArray() { static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono'); return $MPEGaudioChannelMode; } + /** + * @return array + */ public static function MPEGaudioModeExtensionArray() { static $MPEGaudioModeExtension; if (empty($MPEGaudioModeExtension)) { @@ -1691,15 +1754,31 @@ class getid3_mp3 extends getid3_handler return $MPEGaudioModeExtension; } + /** + * @return array + */ public static function MPEGaudioEmphasisArray() { static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17'); return $MPEGaudioEmphasis; } + /** + * @param string $head4 + * @param bool $allowBitrate15 + * + * @return bool + */ public static function MPEGaudioHeaderBytesValid($head4, $allowBitrate15=false) { return self::MPEGaudioHeaderValid(self::MPEGaudioHeaderDecode($head4), false, $allowBitrate15); } + /** + * @param array $rawarray + * @param bool $echoerrors + * @param bool $allowBitrate15 + * + * @return bool + */ public static function MPEGaudioHeaderValid($rawarray, $echoerrors=false, $allowBitrate15=false) { if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) { return false; @@ -1772,6 +1851,11 @@ class getid3_mp3 extends getid3_handler return true; } + /** + * @param string $Header4Bytes + * + * @return array|false + */ public static function MPEGaudioHeaderDecode($Header4Bytes) { // AAAA AAAA AAAB BCCD EEEE FFGH IIJJ KLMM // A - Frame sync (all bits set) @@ -1809,6 +1893,15 @@ class getid3_mp3 extends getid3_handler return $MPEGrawHeader; } + /** + * @param int|string $bitrate + * @param string $version + * @param string $layer + * @param bool $padding + * @param int $samplerate + * + * @return int|false + */ public static function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) { static $AudioFrameLengthCache = array(); @@ -1870,6 +1963,11 @@ class getid3_mp3 extends getid3_handler return $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate]; } + /** + * @param float|int $bit_rate + * + * @return int|float|string + */ public static function ClosestStandardMP3Bitrate($bit_rate) { static $standard_bit_rates = array (320000, 256000, 224000, 192000, 160000, 128000, 112000, 96000, 80000, 64000, 56000, 48000, 40000, 32000, 24000, 16000, 8000); static $bit_rate_table = array (0=>'-'); @@ -1890,10 +1988,16 @@ class getid3_mp3 extends getid3_handler return $bit_rate_table[$round_bit_rate]; } + /** + * @param string $version + * @param string $channelmode + * + * @return int + */ public static function XingVBRidOffset($version, $channelmode) { static $XingVBRidOffsetCache = array(); - if (empty($XingVBRidOffset)) { - $XingVBRidOffset = array ( + if (empty($XingVBRidOffsetCache)) { + $XingVBRidOffsetCache = array ( '1' => array ('mono' => 0x15, // 4 + 17 = 21 'stereo' => 0x24, // 4 + 32 = 36 'joint stereo' => 0x24, @@ -1913,9 +2017,14 @@ class getid3_mp3 extends getid3_handler ) ); } - return $XingVBRidOffset[$version][$channelmode]; + return $XingVBRidOffsetCache[$version][$channelmode]; } + /** + * @param int $VBRmethodID + * + * @return string + */ public static function LAMEvbrMethodLookup($VBRmethodID) { static $LAMEvbrMethodLookup = array( 0x00 => 'unknown', @@ -1932,6 +2041,11 @@ class getid3_mp3 extends getid3_handler return (isset($LAMEvbrMethodLookup[$VBRmethodID]) ? $LAMEvbrMethodLookup[$VBRmethodID] : ''); } + /** + * @param int $StereoModeID + * + * @return string + */ public static function LAMEmiscStereoModeLookup($StereoModeID) { static $LAMEmiscStereoModeLookup = array( 0 => 'mono', @@ -1946,6 +2060,11 @@ class getid3_mp3 extends getid3_handler return (isset($LAMEmiscStereoModeLookup[$StereoModeID]) ? $LAMEmiscStereoModeLookup[$StereoModeID] : ''); } + /** + * @param int $SourceSampleFrequencyID + * + * @return string + */ public static function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) { static $LAMEmiscSourceSampleFrequencyLookup = array( 0 => '<= 32 kHz', @@ -1956,6 +2075,11 @@ class getid3_mp3 extends getid3_handler return (isset($LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID]) ? $LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID] : ''); } + /** + * @param int $SurroundInfoID + * + * @return string + */ public static function LAMEsurroundInfoLookup($SurroundInfoID) { static $LAMEsurroundInfoLookup = array( 0 => 'no surround info', @@ -1966,6 +2090,11 @@ class getid3_mp3 extends getid3_handler return (isset($LAMEsurroundInfoLookup[$SurroundInfoID]) ? $LAMEsurroundInfoLookup[$SurroundInfoID] : 'reserved'); } + /** + * @param array $LAMEtag + * + * @return string + */ public static function LAMEpresetUsedLookup($LAMEtag) { if ($LAMEtag['preset_used_id'] == 0) { diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.mpc.php b/www/plugins-dist/medias/lib/getid3/module.audio.mpc.php index 14e829d9..6d7c8512 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.mpc.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.mpc.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.mpc.php // @@ -17,7 +17,9 @@ class getid3_mpc extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -56,10 +58,11 @@ class getid3_mpc extends getid3_handler return false; } - return false; } - + /** + * @return bool + */ public function ParseMPCsv8() { // this is SV8 // http://trac.musepack.net/trac/wiki/SV8Specification @@ -208,6 +211,9 @@ class getid3_mpc extends getid3_handler return true; } + /** + * @return bool + */ public function ParseMPCsv7() { // this is SV7 // http://www.uni-jena.de/~pfk/mpp/sv8/header.html @@ -322,6 +328,9 @@ class getid3_mpc extends getid3_handler return true; } + /** + * @return bool + */ public function ParseMPCsv6() { // this is SV4 - SV6 @@ -397,7 +406,11 @@ class getid3_mpc extends getid3_handler return true; } - + /** + * @param int $profileid + * + * @return string + */ public function MPCprofileNameLookup($profileid) { static $MPCprofileNameLookup = array( 0 => 'no profile', @@ -420,6 +433,11 @@ class getid3_mpc extends getid3_handler return (isset($MPCprofileNameLookup[$profileid]) ? $MPCprofileNameLookup[$profileid] : 'invalid'); } + /** + * @param int $frequencyid + * + * @return int|string + */ public function MPCfrequencyLookup($frequencyid) { static $MPCfrequencyLookup = array( 0 => 44100, @@ -430,6 +448,11 @@ class getid3_mpc extends getid3_handler return (isset($MPCfrequencyLookup[$frequencyid]) ? $MPCfrequencyLookup[$frequencyid] : 'invalid'); } + /** + * @param int $intvalue + * + * @return float|false + */ public function MPCpeakDBLookup($intvalue) { if ($intvalue > 0) { return ((log10($intvalue) / log10(2)) - 15) * 6; @@ -437,6 +460,11 @@ class getid3_mpc extends getid3_handler return false; } + /** + * @param int $encoderversion + * + * @return string + */ public function MPCencoderVersionLookup($encoderversion) { //Encoder version * 100 (106 = 1.06) //EncoderVersion % 10 == 0 Release (1.0) @@ -464,6 +492,13 @@ class getid3_mpc extends getid3_handler return number_format($encoderversion / 100, 2).' alpha'; } + /** + * @param string $data + * @param int $packetLength + * @param int $maxHandledPacketLength + * + * @return int|false + */ public function SV8variableLengthInteger($data, &$packetLength, $maxHandledPacketLength=9) { $packet_size = 0; for ($packetLength = 1; $packetLength <= $maxHandledPacketLength; $packetLength++) { @@ -488,6 +523,11 @@ class getid3_mpc extends getid3_handler return $packet_size; } + /** + * @param string $packetKey + * + * @return string + */ public function MPCsv8PacketName($packetKey) { static $MPCsv8PacketName = array(); if (empty($MPCsv8PacketName)) { diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.ogg.php b/www/plugins-dist/medias/lib/getid3/module.audio.ogg.php index e41c96c4..51fee3e1 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.ogg.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.ogg.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.ogg.php // @@ -18,7 +18,11 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.flac.php', __FILE class getid3_ogg extends getid3_handler { - // http://xiph.org/vorbis/doc/Vorbis_I_spec.html + /** + * @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html + * + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -65,7 +69,7 @@ class getid3_ogg extends getid3_handler } elseif (substr($filedata, 0, 8) == 'OpusHead') { - if( $this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) == false ) { + if ($this->ParseOpusPageHeader($filedata, $filedataoffset, $oggpageinfo) === false) { return false; } @@ -179,7 +183,7 @@ class getid3_ogg extends getid3_handler if ($info['ogg']['pageheader']['theora']['pixel_aspect_denominator'] > 0) { $info['video']['pixel_aspect_ratio'] = (float) $info['ogg']['pageheader']['theora']['pixel_aspect_numerator'] / $info['ogg']['pageheader']['theora']['pixel_aspect_denominator']; } -$this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable'); + $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 ['.$this->getid3->version().'] -- bitrate, playtime and all audio data are currently unavailable'); } elseif (substr($filedata, 0, 8) == "fishead\x00") { @@ -259,9 +263,34 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' $this->error('Ogg Skeleton not correctly handled in this version of getID3 ['.$this->getid3->version().']'); //return false; + } elseif (substr($filedata, 0, 5) == "\x7F".'FLAC') { + // https://xiph.org/flac/ogg_mapping.html + + $info['audio']['dataformat'] = 'flac'; + $info['audio']['bitrate_mode'] = 'vbr'; + $info['audio']['lossless'] = true; + + $info['ogg']['flac']['header']['version_major'] = ord(substr($filedata, 5, 1)); + $info['ogg']['flac']['header']['version_minor'] = ord(substr($filedata, 6, 1)); + $info['ogg']['flac']['header']['header_packets'] = getid3_lib::BigEndian2Int(substr($filedata, 7, 2)) + 1; // "A two-byte, big-endian binary number signifying the number of header (non-audio) packets, not including this one. This number may be zero (0x0000) to signify 'unknown' but be aware that some decoders may not be able to handle such streams." + $info['ogg']['flac']['header']['magic'] = substr($filedata, 9, 4); + if ($info['ogg']['flac']['header']['magic'] != 'fLaC') { + $this->error('Ogg-FLAC expecting "fLaC", found "'.$info['ogg']['flac']['header']['magic'].'" ('.trim(getid3_lib::PrintHexBytes($info['ogg']['flac']['header']['magic'])).')'); + return false; + } + $info['ogg']['flac']['header']['STREAMINFO_bytes'] = getid3_lib::BigEndian2Int(substr($filedata, 13, 4)); + $info['flac']['STREAMINFO'] = getid3_flac::parseSTREAMINFOdata(substr($filedata, 17, 34)); + if (!empty($info['flac']['STREAMINFO']['sample_rate'])) { + $info['audio']['bitrate_mode'] = 'vbr'; + $info['audio']['sample_rate'] = $info['flac']['STREAMINFO']['sample_rate']; + $info['audio']['channels'] = $info['flac']['STREAMINFO']['channels']; + $info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample']; + $info['playtime_seconds'] = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate']; + } + } else { - $this->error('Expecting either "Speex ", "OpusHead" or "vorbis" identifier strings, found "'.substr($filedata, 0, 8).'"'); + $this->error('Expecting one of "vorbis", "Speex", "OpusHead", "vorbis", "fishhead", "theora", "fLaC" identifier strings, found "'.substr($filedata, 0, 8).'"'); unset($info['ogg']); unset($info['mime_type']); return false; @@ -378,6 +407,13 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' return true; } + /** + * @param string $filedata + * @param int $filedataoffset + * @param array $oggpageinfo + * + * @return bool + */ public function ParseVorbisPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) { $info = &$this->getid3->info; $info['audio']['dataformat'] = 'vorbis'; @@ -426,7 +462,15 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' return true; } - // http://tools.ietf.org/html/draft-ietf-codec-oggopus-03 + /** + * @link http://tools.ietf.org/html/draft-ietf-codec-oggopus-03 + * + * @param string $filedata + * @param int $filedataoffset + * @param array $oggpageinfo + * + * @return bool + */ public function ParseOpusPageHeader(&$filedata, &$filedataoffset, &$oggpageinfo) { $info = &$this->getid3->info; $info['audio']['dataformat'] = 'opus'; @@ -458,7 +502,7 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' $info['ogg']['pageheader']['opus']['pre_skip'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2)); $filedataoffset += 2; - $info['ogg']['pageheader']['opus']['sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); + $info['ogg']['pageheader']['opus']['input_sample_rate'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 4)); $filedataoffset += 4; //$info['ogg']['pageheader']['opus']['output_gain'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 2)); @@ -467,16 +511,19 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' //$info['ogg']['pageheader']['opus']['channel_mapping_family'] = getid3_lib::LittleEndian2Int(substr($filedata, $filedataoffset, 1)); //$filedataoffset += 1; - $info['opus']['opus_version'] = $info['ogg']['pageheader']['opus']['version']; - $info['opus']['sample_rate'] = $info['ogg']['pageheader']['opus']['sample_rate']; - $info['opus']['out_channel_count'] = $info['ogg']['pageheader']['opus']['out_channel_count']; + $info['opus']['opus_version'] = $info['ogg']['pageheader']['opus']['version']; + $info['opus']['sample_rate_input'] = $info['ogg']['pageheader']['opus']['input_sample_rate']; + $info['opus']['out_channel_count'] = $info['ogg']['pageheader']['opus']['out_channel_count']; - $info['audio']['channels'] = $info['opus']['out_channel_count']; - $info['audio']['sample_rate'] = $info['opus']['sample_rate']; + $info['audio']['channels'] = $info['opus']['out_channel_count']; + $info['audio']['sample_rate_input'] = $info['opus']['sample_rate_input']; + $info['audio']['sample_rate'] = 48000; // "All Opus audio is coded at 48 kHz, and should also be decoded at 48 kHz for playback (unless the target hardware does not support this sampling rate). However, this field may be used to resample the audio back to the original sampling rate, for example, when saving the output to a file." -- https://mf4.xiph.org/jenkins/view/opus/job/opusfile-unix/ws/doc/html/structOpusHead.html return true; } - + /** + * @return array|false + */ public function ParseOggPageHeader() { // http://xiph.org/ogg/vorbis/doc/framing.html $oggheader['page_start_offset'] = $this->ftell(); // where we started from in the file @@ -489,7 +536,7 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' return false; } if ((($filedataoffset + 28) > strlen($filedata)) || (strlen($filedata) < 28)) { - if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === false)) { + if ($this->feof() || (($filedata .= $this->fread($this->getid3->fread_buffer_size())) === '')) { // get some more data, unless eof, in which case fail return false; } @@ -528,13 +575,19 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' return $oggheader; } - // http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005 + /** + * @link http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810005 + * + * @return bool + */ public function ParseVorbisComments() { $info = &$this->getid3->info; $OriginalOffset = $this->ftell(); + $commentdata = null; $commentdataoffset = 0; $VorbisCommentPage = 1; + $CommentStartOffset = 0; switch ($info['audio']['dataformat']) { case 'vorbis': @@ -765,6 +818,11 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' return true; } + /** + * @param int $mode + * + * @return string|null + */ public static function SpeexBandModeLookup($mode) { static $SpeexBandModeLookup = array(); if (empty($SpeexBandModeLookup)) { @@ -775,8 +833,14 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' return (isset($SpeexBandModeLookup[$mode]) ? $SpeexBandModeLookup[$mode] : null); } - + /** + * @param array $OggInfoArray + * @param int $SegmentNumber + * + * @return int + */ public static function OggPageSegmentLength($OggInfoArray, $SegmentNumber=1) { + $segmentlength = 0; for ($i = 0; $i < $SegmentNumber; $i++) { $segmentlength = 0; foreach ($OggInfoArray['segment_table'] as $key => $value) { @@ -789,7 +853,11 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' return $segmentlength; } - + /** + * @param int $nominal_bitrate + * + * @return float + */ public static function get_quality_from_nominal_bitrate($nominal_bitrate) { // decrease precision @@ -813,6 +881,11 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' return round($qval, 1); // 5 or 4.9 } + /** + * @param int $colorspace_id + * + * @return string|null + */ public static function TheoraColorSpace($colorspace_id) { // http://www.theora.org/doc/Theora.pdf (table 6.3) static $TheoraColorSpaceLookup = array(); @@ -825,6 +898,11 @@ $this->warning('Ogg Theora (v3) not fully supported in this version of getID3 [' return (isset($TheoraColorSpaceLookup[$colorspace_id]) ? $TheoraColorSpaceLookup[$colorspace_id] : null); } + /** + * @param int $pixelformat_id + * + * @return string|null + */ public static function TheoraPixelFormat($pixelformat_id) { // http://www.theora.org/doc/Theora.pdf (table 6.4) static $TheoraPixelFormatLookup = array(); diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.optimfrog.php b/www/plugins-dist/medias/lib/getid3/module.audio.optimfrog.php index 50e0ffd6..1c122305 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.optimfrog.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.optimfrog.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.optimfrog.php // @@ -18,7 +18,9 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', class getid3_optimfrog extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -44,7 +46,9 @@ class getid3_optimfrog extends getid3_handler return false; } - + /** + * @return bool + */ public function ParseOptimFROGheader42() { // for fileformat of v4.21 and older @@ -91,7 +95,9 @@ class getid3_optimfrog extends getid3_handler return true; } - + /** + * @return bool + */ public function ParseOptimFROGheader45() { // for fileformat of v4.50a and higher @@ -313,7 +319,11 @@ class getid3_optimfrog extends getid3_handler return true; } - + /** + * @param int $SampleType + * + * @return string|false + */ public static function OptimFROGsampleTypeLookup($SampleType) { static $OptimFROGsampleTypeLookup = array( 0 => 'unsigned int (8-bit)', @@ -331,6 +341,11 @@ class getid3_optimfrog extends getid3_handler return (isset($OptimFROGsampleTypeLookup[$SampleType]) ? $OptimFROGsampleTypeLookup[$SampleType] : false); } + /** + * @param int $SampleType + * + * @return int|false + */ public static function OptimFROGbitsPerSampleTypeLookup($SampleType) { static $OptimFROGbitsPerSampleTypeLookup = array( 0 => 8, @@ -348,6 +363,11 @@ class getid3_optimfrog extends getid3_handler return (isset($OptimFROGbitsPerSampleTypeLookup[$SampleType]) ? $OptimFROGbitsPerSampleTypeLookup[$SampleType] : false); } + /** + * @param int $ChannelConfiguration + * + * @return string|false + */ public static function OptimFROGchannelConfigurationLookup($ChannelConfiguration) { static $OptimFROGchannelConfigurationLookup = array( 0 => 'mono', @@ -356,6 +376,11 @@ class getid3_optimfrog extends getid3_handler return (isset($OptimFROGchannelConfigurationLookup[$ChannelConfiguration]) ? $OptimFROGchannelConfigurationLookup[$ChannelConfiguration] : false); } + /** + * @param int $ChannelConfiguration + * + * @return int|false + */ public static function OptimFROGchannelConfigNumChannelsLookup($ChannelConfiguration) { static $OptimFROGchannelConfigNumChannelsLookup = array( 0 => 1, @@ -365,13 +390,17 @@ class getid3_optimfrog extends getid3_handler } - // static function OptimFROGalgorithmNameLookup($AlgorithID) { // static $OptimFROGalgorithmNameLookup = array(); // return (isset($OptimFROGalgorithmNameLookup[$AlgorithID]) ? $OptimFROGalgorithmNameLookup[$AlgorithID] : false); // } + /** + * @param int $EncoderID + * + * @return string + */ public static function OptimFROGencoderNameLookup($EncoderID) { // version = (encoderID >> 4) + 4500 // system = encoderID & 0xF @@ -387,6 +416,11 @@ class getid3_optimfrog extends getid3_handler return $EncoderVersion.' ('.(isset($OptimFROGencoderSystemLookup[$EncoderSystemID]) ? $OptimFROGencoderSystemLookup[$EncoderSystemID] : 'undefined encoder type (0x'.dechex($EncoderSystemID).')').')'; } + /** + * @param int $CompressionID + * + * @return string + */ public static function OptimFROGcompressionLookup($CompressionID) { // mode = compression >> 3 // speedup = compression & 0x07 @@ -409,6 +443,11 @@ class getid3_optimfrog extends getid3_handler return (isset($OptimFROGencoderModeLookup[$CompressionModeID]) ? $OptimFROGencoderModeLookup[$CompressionModeID] : 'undefined mode (0x'.str_pad(dechex($CompressionModeID), 2, '0', STR_PAD_LEFT).')'); } + /** + * @param int $CompressionID + * + * @return string + */ public static function OptimFROGspeedupLookup($CompressionID) { // mode = compression >> 3 // speedup = compression & 0x07 diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.rkau.php b/www/plugins-dist/medias/lib/getid3/module.audio.rkau.php index d7c2f09a..7e1c8107 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.rkau.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.rkau.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.shorten.php // @@ -17,7 +17,9 @@ class getid3_rkau extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -50,7 +52,7 @@ class getid3_rkau extends getid3_handler $this->RKAUqualityLookup($info['rkau']); $info['rkau']['raw']['flags'] = getid3_lib::LittleEndian2Int(substr($RKAUHeader, 15, 1)); - $info['rkau']['flags']['joint_stereo'] = (bool) (!($info['rkau']['raw']['flags'] & 0x01)); + $info['rkau']['flags']['joint_stereo'] = !($info['rkau']['raw']['flags'] & 0x01); $info['rkau']['flags']['streaming'] = (bool) ($info['rkau']['raw']['flags'] & 0x02); $info['rkau']['flags']['vrq_lossy_mode'] = (bool) ($info['rkau']['raw']['flags'] & 0x04); @@ -76,7 +78,11 @@ class getid3_rkau extends getid3_handler } - + /** + * @param array $RKAUdata + * + * @return bool + */ public function RKAUqualityLookup(&$RKAUdata) { $level = ($RKAUdata['raw']['quality'] & 0xF0) >> 4; $quality = $RKAUdata['raw']['quality'] & 0x0F; diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.shorten.php b/www/plugins-dist/medias/lib/getid3/module.audio.shorten.php index 8d5c5d4b..f5e2a57d 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.shorten.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.shorten.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.shorten.php // @@ -17,7 +17,9 @@ class getid3_shorten extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -38,7 +40,7 @@ class getid3_shorten extends getid3_handler $this->fseek($info['avdataend'] - 12); $SeekTableSignatureTest = $this->fread(12); - $info['shn']['seektable']['present'] = (bool) (substr($SeekTableSignatureTest, 4, 8) == 'SHNAMPSK'); + $info['shn']['seektable']['present'] = substr($SeekTableSignatureTest, 4, 8) == 'SHNAMPSK'; if ($info['shn']['seektable']['present']) { $info['shn']['seektable']['length'] = getid3_lib::LittleEndian2Int(substr($SeekTableSignatureTest, 0, 4)); $info['shn']['seektable']['offset'] = $info['avdataend'] - $info['shn']['seektable']['length']; diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.tta.php b/www/plugins-dist/medias/lib/getid3/module.audio.tta.php index 78d27b0f..13d8fe2c 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.tta.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.tta.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.tta.php // @@ -17,7 +17,9 @@ class getid3_tta extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.voc.php b/www/plugins-dist/medias/lib/getid3/module.audio.voc.php index 3803d8a1..44831581 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.voc.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.voc.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.voc.php // @@ -17,7 +17,9 @@ class getid3_voc extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -164,6 +166,11 @@ class getid3_voc extends getid3_handler return true; } + /** + * @param int $index + * + * @return string + */ public function VOCcompressionTypeLookup($index) { static $VOCcompressionTypeLookup = array( 0 => '8-bit', @@ -174,6 +181,11 @@ class getid3_voc extends getid3_handler return (isset($VOCcompressionTypeLookup[$index]) ? $VOCcompressionTypeLookup[$index] : 'Multi DAC ('.($index - 3).') channels'); } + /** + * @param int $index + * + * @return string|false + */ public function VOCwFormatLookup($index) { static $VOCwFormatLookup = array( 0x0000 => '8-bit unsigned PCM', @@ -188,6 +200,11 @@ class getid3_voc extends getid3_handler return (isset($VOCwFormatLookup[$index]) ? $VOCwFormatLookup[$index] : false); } + /** + * @param int $index + * + * @return int|false + */ public function VOCwFormatActualBitsPerSampleLookup($index) { static $VOCwFormatLookup = array( 0x0000 => 8, diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.vqf.php b/www/plugins-dist/medias/lib/getid3/module.audio.vqf.php index a6a391c4..9ab821e2 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.vqf.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.vqf.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.vqf.php // @@ -17,6 +17,9 @@ class getid3_vqf extends getid3_handler { + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -136,6 +139,11 @@ class getid3_vqf extends getid3_handler return true; } + /** + * @param int $frequencyid + * + * @return int + */ public function VQFchannelFrequencyLookup($frequencyid) { static $VQFchannelFrequencyLookup = array( 11 => 11025, @@ -145,6 +153,11 @@ class getid3_vqf extends getid3_handler return (isset($VQFchannelFrequencyLookup[$frequencyid]) ? $VQFchannelFrequencyLookup[$frequencyid] : $frequencyid * 1000); } + /** + * @param string $shortname + * + * @return string + */ public function VQFcommentNiceNameLookup($shortname) { static $VQFcommentNiceNameLookup = array( 'NAME' => 'title', diff --git a/www/plugins-dist/medias/lib/getid3/module.audio.wavpack.php b/www/plugins-dist/medias/lib/getid3/module.audio.wavpack.php index b54c179f..a6e57fd9 100644 --- a/www/plugins-dist/medias/lib/getid3/module.audio.wavpack.php +++ b/www/plugins-dist/medias/lib/getid3/module.audio.wavpack.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.audio.wavpack.php // @@ -17,7 +17,9 @@ class getid3_wavpack extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -236,7 +238,7 @@ class getid3_wavpack extends getid3_handler case 0x22: // ID_RIFF_TRAILER - $metablockRIFFfooter = $metablockRIFFheader.$metablock['data']; + $metablockRIFFfooter = isset($metablockRIFFheader) ? $metablockRIFFheader : ''.$metablock['data']; getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); $startoffset = $metablock['offset'] + ($metablock['large_block'] ? 4 : 2); @@ -368,7 +370,11 @@ class getid3_wavpack extends getid3_handler return true; } - + /** + * @param int $id + * + * @return string + */ public function WavPackMetablockNameLookup(&$id) { static $WavPackMetablockNameLookup = array( 0x00 => 'Dummy', diff --git a/www/plugins-dist/medias/lib/getid3/module.graphic.bmp.php b/www/plugins-dist/medias/lib/getid3/module.graphic.bmp.php index 90cbb38f..dc7b30d7 100644 --- a/www/plugins-dist/medias/lib/getid3/module.graphic.bmp.php +++ b/www/plugins-dist/medias/lib/getid3/module.graphic.bmp.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.graphic.bmp.php // @@ -20,6 +20,9 @@ class getid3_bmp extends getid3_handler public $ExtractPalette = false; public $ExtractData = false; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -528,6 +531,7 @@ class getid3_bmp extends getid3_handler // high- and low-order 4 bits, one color index for each pixel. In absolute mode, // each run must be aligned on a word boundary. unset($paletteindexes); + $paletteindexes = array(); for ($i = 0; $i < ceil($secondbyte / 2); $i++) { $paletteindexbyte = getid3_lib::LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); $paletteindexes[] = ($paletteindexbyte & 0xF0) >> 4; @@ -625,7 +629,11 @@ class getid3_bmp extends getid3_handler return true; } - + /** + * @param array $BMPinfo + * + * @return bool + */ public function PlotBMP(&$BMPinfo) { $starttime = time(); if (!isset($BMPinfo['bmp']['data']) || !is_array($BMPinfo['bmp']['data'])) { @@ -633,15 +641,15 @@ class getid3_bmp extends getid3_handler return false; } set_time_limit(intval(round($BMPinfo['resolution_x'] * $BMPinfo['resolution_y'] / 10000))); - if ($im = ImageCreateTrueColor($BMPinfo['resolution_x'], $BMPinfo['resolution_y'])) { + if ($im = imagecreatetruecolor($BMPinfo['resolution_x'], $BMPinfo['resolution_y'])) { for ($row = 0; $row < $BMPinfo['resolution_y']; $row++) { for ($col = 0; $col < $BMPinfo['resolution_x']; $col++) { if (isset($BMPinfo['bmp']['data'][$row][$col])) { $red = ($BMPinfo['bmp']['data'][$row][$col] & 0x00FF0000) >> 16; $green = ($BMPinfo['bmp']['data'][$row][$col] & 0x0000FF00) >> 8; $blue = ($BMPinfo['bmp']['data'][$row][$col] & 0x000000FF); - $pixelcolor = ImageColorAllocate($im, $red, $green, $blue); - ImageSetPixel($im, $col, $row, $pixelcolor); + $pixelcolor = imagecolorallocate($im, $red, $green, $blue); + imagesetpixel($im, $col, $row, $pixelcolor); } else { //echo 'ERROR: no data for pixel '.$row.' x '.$col.'
'; //return false; @@ -650,18 +658,23 @@ class getid3_bmp extends getid3_handler } if (headers_sent()) { echo 'plotted '.($BMPinfo['resolution_x'] * $BMPinfo['resolution_y']).' pixels in '.(time() - $starttime).' seconds
'; - ImageDestroy($im); + imagedestroy($im); exit; } else { header('Content-type: image/png'); - ImagePNG($im); - ImageDestroy($im); + imagepng($im); + imagedestroy($im); return true; } } return false; } + /** + * @param int $compressionid + * + * @return string + */ public function BMPcompressionWindowsLookup($compressionid) { static $BMPcompressionWindowsLookup = array( 0 => 'BI_RGB', @@ -674,6 +687,11 @@ class getid3_bmp extends getid3_handler return (isset($BMPcompressionWindowsLookup[$compressionid]) ? $BMPcompressionWindowsLookup[$compressionid] : 'invalid'); } + /** + * @param int $compressionid + * + * @return string + */ public function BMPcompressionOS2Lookup($compressionid) { static $BMPcompressionOS2Lookup = array( 0 => 'BI_RGB', diff --git a/www/plugins-dist/medias/lib/getid3/module.graphic.efax.php b/www/plugins-dist/medias/lib/getid3/module.graphic.efax.php index 8c628543..426ef3e6 100644 --- a/www/plugins-dist/medias/lib/getid3/module.graphic.efax.php +++ b/www/plugins-dist/medias/lib/getid3/module.graphic.efax.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.archive.efax.php // @@ -17,7 +17,9 @@ class getid3_efax extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -42,8 +44,8 @@ class getid3_efax extends getid3_handler $info['efax']['header']['pages'] = getid3_lib::LittleEndian2Int(substr($efaxheader, 198, 2)); $info['efax']['header']['data_bytes'] = getid3_lib::LittleEndian2Int(substr($efaxheader, 202, 4)); -$this->error('eFax parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); -return false; + $this->error('eFax parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); + return false; return true; } diff --git a/www/plugins-dist/medias/lib/getid3/module.graphic.gif.php b/www/plugins-dist/medias/lib/getid3/module.graphic.gif.php index ab7d62ae..4fb1247a 100644 --- a/www/plugins-dist/medias/lib/getid3/module.graphic.gif.php +++ b/www/plugins-dist/medias/lib/getid3/module.graphic.gif.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.graphic.gif.php // @@ -14,10 +14,15 @@ // /// ///////////////////////////////////////////////////////////////// - +/** + * @link https://www.w3.org/Graphics/GIF/spec-gif89a.txt + * @link http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp + */ class getid3_gif extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -78,96 +83,112 @@ class getid3_gif extends getid3_handler $info['gif']['header']['aspect_ratio'] = ($info['gif']['header']['raw']['aspect_ratio'] + 15) / 64; } -// 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)); -// } -// } -// -// // Image Descriptor -// while (!feof($this->getid3->fp)) { -// $NextBlockTest = $this->fread(1); -// switch ($NextBlockTest) { -// -// case ',': // ',' - Image separator character -// -// $ImageDescriptorData = $NextBlockTest.$this->fread(9); -// $ImageDescriptor = array(); -// $ImageDescriptor['image_left'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 1, 2)); -// $ImageDescriptor['image_top'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 3, 2)); -// $ImageDescriptor['image_width'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 5, 2)); -// $ImageDescriptor['image_height'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 7, 2)); -// $ImageDescriptor['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 9, 1)); -// $ImageDescriptor['flags']['use_local_color_map'] = (bool) ($ImageDescriptor['flags_raw'] & 0x80); -// $ImageDescriptor['flags']['image_interlaced'] = (bool) ($ImageDescriptor['flags_raw'] & 0x40); -// $info['gif']['image_descriptor'][] = $ImageDescriptor; -// -// if ($ImageDescriptor['flags']['use_local_color_map']) { -// -// $this->warning('This version of getID3() cannot parse local color maps for GIFs'); -// return true; -// -// } -//echo 'Start of raster data: '.$this->ftell().'
'; -// $RasterData = array(); -// $RasterData['code_size'] = getid3_lib::LittleEndian2Int($this->fread(1)); -// $RasterData['block_byte_count'] = getid3_lib::LittleEndian2Int($this->fread(1)); -// $info['gif']['raster_data'][count($info['gif']['image_descriptor']) - 1] = $RasterData; -// -// $CurrentCodeSize = $RasterData['code_size'] + 1; -// for ($i = 0; $i < pow(2, $RasterData['code_size']); $i++) { -// $DefaultDataLookupTable[$i] = chr($i); -// } -// $DefaultDataLookupTable[pow(2, $RasterData['code_size']) + 0] = ''; // Clear Code -// $DefaultDataLookupTable[pow(2, $RasterData['code_size']) + 1] = ''; // End Of Image Code -// -// -// $NextValue = $this->GetLSBits($CurrentCodeSize); -// echo 'Clear Code: '.$NextValue.'
'; -// -// $NextValue = $this->GetLSBits($CurrentCodeSize); -// echo 'First Color: '.$NextValue.'
'; -// -// $Prefix = $NextValue; -//$i = 0; -// while ($i++ < 20) { -// $NextValue = $this->GetLSBits($CurrentCodeSize); -// echo $NextValue.'
'; -// } -//return true; -// break; -// -// case '!': -// // GIF Extension Block -// $ExtensionBlockData = $NextBlockTest.$this->fread(2); -// $ExtensionBlock = array(); -// $ExtensionBlock['function_code'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlockData, 1, 1)); -// $ExtensionBlock['byte_length'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlockData, 2, 1)); -// $ExtensionBlock['data'] = $this->fread($ExtensionBlock['byte_length']); -// $info['gif']['extension_blocks'][] = $ExtensionBlock; -// break; -// -// case ';': -// $info['gif']['terminator_offset'] = $this->ftell() - 1; -// // GIF Terminator -// break; -// -// default: -// break; -// -// -// } -// } + 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)); + } + } + + // Image Descriptor + $info['gif']['animation']['animated'] = false; + while (!feof($this->getid3->fp)) { + $NextBlockTest = $this->fread(1); + switch ($NextBlockTest) { + +/* + case ',': // ',' - Image separator character + $ImageDescriptorData = $NextBlockTest.$this->fread(9); + $ImageDescriptor = array(); + $ImageDescriptor['image_left'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 1, 2)); + $ImageDescriptor['image_top'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 3, 2)); + $ImageDescriptor['image_width'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 5, 2)); + $ImageDescriptor['image_height'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 7, 2)); + $ImageDescriptor['flags_raw'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 9, 1)); + $ImageDescriptor['flags']['use_local_color_map'] = (bool) ($ImageDescriptor['flags_raw'] & 0x80); + $ImageDescriptor['flags']['image_interlaced'] = (bool) ($ImageDescriptor['flags_raw'] & 0x40); + $info['gif']['image_descriptor'][] = $ImageDescriptor; + + if ($ImageDescriptor['flags']['use_local_color_map']) { + + $this->warning('This version of getID3() cannot parse local color maps for GIFs'); + return true; + + } + $RasterData = array(); + $RasterData['code_size'] = getid3_lib::LittleEndian2Int($this->fread(1)); + $RasterData['block_byte_count'] = getid3_lib::LittleEndian2Int($this->fread(1)); + $info['gif']['raster_data'][count($info['gif']['image_descriptor']) - 1] = $RasterData; + + $CurrentCodeSize = $RasterData['code_size'] + 1; + for ($i = 0; $i < pow(2, $RasterData['code_size']); $i++) { + $DefaultDataLookupTable[$i] = chr($i); + } + $DefaultDataLookupTable[pow(2, $RasterData['code_size']) + 0] = ''; // Clear Code + $DefaultDataLookupTable[pow(2, $RasterData['code_size']) + 1] = ''; // End Of Image Code + + $NextValue = $this->GetLSBits($CurrentCodeSize); + echo 'Clear Code: '.$NextValue.'
'; + + $NextValue = $this->GetLSBits($CurrentCodeSize); + echo 'First Color: '.$NextValue.'
'; + + $Prefix = $NextValue; + $i = 0; + while ($i++ < 20) { + $NextValue = $this->GetLSBits($CurrentCodeSize); + echo $NextValue.'
'; + } + echo 'escaping
'; + return true; + break; +*/ + + case '!': + // GIF Extension Block + $ExtensionBlockData = $NextBlockTest.$this->fread(2); + $ExtensionBlock = array(); + $ExtensionBlock['function_code'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlockData, 1, 1)); + $ExtensionBlock['byte_length'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlockData, 2, 1)); + $ExtensionBlock['data'] = (($ExtensionBlock['byte_length'] > 0) ? $this->fread($ExtensionBlock['byte_length']) : null); + + if (substr($ExtensionBlock['data'], 0, 11) == 'NETSCAPE2.0') { // Netscape Application Block (NAB) + $ExtensionBlock['data'] .= $this->fread(4); + if (substr($ExtensionBlock['data'], 11, 2) == "\x03\x01") { + $info['gif']['animation']['animated'] = true; + $info['gif']['animation']['loop_count'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlock['data'], 13, 2)); + } else { + $this->warning('Expecting 03 01 at offset '.($this->ftell() - 4).', found "'.getid3_lib::PrintHexBytes(substr($ExtensionBlock['data'], 11, 2)).'"'); + } + } + + $info['gif']['extension_blocks'][] = $ExtensionBlock; + break; + + case ';': + $info['gif']['terminator_offset'] = $this->ftell() - 1; + // GIF Terminator + break; + + default: + break; + + + } + } return true; } - + /** + * @param int $bits + * + * @return float|int + */ public function GetLSBits($bits) { static $bitbuffer = ''; while (strlen($bitbuffer) < $bits) { diff --git a/www/plugins-dist/medias/lib/getid3/module.graphic.jpg.php b/www/plugins-dist/medias/lib/getid3/module.graphic.jpg.php index 76edf145..3c874f32 100644 --- a/www/plugins-dist/medias/lib/getid3/module.graphic.jpg.php +++ b/www/plugins-dist/medias/lib/getid3/module.graphic.jpg.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.graphic.jpg.php // @@ -18,8 +18,9 @@ class getid3_jpg extends getid3_handler { - - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -33,7 +34,7 @@ class getid3_jpg extends getid3_handler $imageinfo = array(); //list($width, $height, $type) = getid3_lib::GetDataImageSize($this->fread($info['filesize']), $imageinfo); - list($width, $height, $type) = getimagesize($info['filenamepath'], $imageinfo); // http://www.getid3.org/phpBB3/viewtopic.php?t=1474 + list($width, $height, $type) = getimagesize($info['filenamepath'], $imageinfo); // https://www.getid3.org/phpBB3/viewtopic.php?t=1474 if (isset($imageinfo['APP13'])) { @@ -66,8 +67,8 @@ class getid3_jpg extends getid3_handler if (isset($imageinfo['APP1'])) { if (function_exists('exif_read_data')) { if (substr($imageinfo['APP1'], 0, 4) == 'Exif') { -//$this->warning('known issue: https://bugs.php.net/bug.php?id=62523'); -//return false; + //$this->warning('known issue: https://bugs.php.net/bug.php?id=62523'); + //return false; set_error_handler(function($errno, $errstr, $errfile, $errline, array $errcontext) { if (!(error_reporting() & $errno)) { // error is not specified in the error_reporting setting, so we ignore it @@ -108,6 +109,7 @@ class getid3_jpg extends getid3_handler if (isset($info['jpg']['exif']['GPS'])) { if (isset($info['jpg']['exif']['GPS']['GPSVersion'])) { + $version_subparts = array(); for ($i = 0; $i < 4; $i++) { $version_subparts[$i] = ord(substr($info['jpg']['exif']['GPS']['GPSVersion'], $i, 1)); } @@ -131,6 +133,7 @@ class getid3_jpg extends getid3_handler if (isset($info['jpg']['exif']['GPS']['GPSLatitude']) && is_array($info['jpg']['exif']['GPS']['GPSLatitude'])) { $direction_multiplier = ((isset($info['jpg']['exif']['GPS']['GPSLatitudeRef']) && ($info['jpg']['exif']['GPS']['GPSLatitudeRef'] == 'S')) ? -1 : 1); + $computed_latitude = array(); foreach ($info['jpg']['exif']['GPS']['GPSLatitude'] as $key => $value) { $computed_latitude[$key] = getid3_lib::DecimalizeFraction($value); } @@ -139,6 +142,7 @@ class getid3_jpg extends getid3_handler if (isset($info['jpg']['exif']['GPS']['GPSLongitude']) && is_array($info['jpg']['exif']['GPS']['GPSLongitude'])) { $direction_multiplier = ((isset($info['jpg']['exif']['GPS']['GPSLongitudeRef']) && ($info['jpg']['exif']['GPS']['GPSLongitudeRef'] == 'W')) ? -1 : 1); + $computed_longitude = array(); foreach ($info['jpg']['exif']['GPS']['GPSLongitude'] as $key => $value) { $computed_longitude[$key] = getid3_lib::DecimalizeFraction($value); } @@ -176,7 +180,11 @@ class getid3_jpg extends getid3_handler return true; } - + /** + * @param mixed $value + * + * @return mixed + */ public function CastAsAppropriate($value) { if (is_array($value)) { return $value; @@ -190,7 +198,11 @@ class getid3_jpg extends getid3_handler return $value; } - + /** + * @param int $iptc_record + * + * @return string + */ public function IPTCrecordName($iptc_record) { // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/IPTC.html static $IPTCrecordName = array(); @@ -207,7 +219,12 @@ class getid3_jpg extends getid3_handler return (isset($IPTCrecordName[$iptc_record]) ? $IPTCrecordName[$iptc_record] : ''); } - + /** + * @param int $iptc_record + * @param int $iptc_tagkey + * + * @return string + */ public function IPTCrecordTagName($iptc_record, $iptc_tagkey) { // http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/IPTC.html static $IPTCrecordTagName = array(); diff --git a/www/plugins-dist/medias/lib/getid3/module.graphic.pcd.php b/www/plugins-dist/medias/lib/getid3/module.graphic.pcd.php index c1efaa21..88244796 100644 --- a/www/plugins-dist/medias/lib/getid3/module.graphic.pcd.php +++ b/www/plugins-dist/medias/lib/getid3/module.graphic.pcd.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.graphic.pcd.php // @@ -19,6 +19,9 @@ class getid3_pcd extends getid3_handler { public $ExtractData = 0; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -73,11 +76,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{floor($x / 2)}), ord($PCD_data_Cr{floor($x / 2)})); - $info['pcd']['data'][$PCD_width - $x][$y + 1] = $this->YCbCr2RGB(ord($PCD_data_Y2{$x}), ord($PCD_data_Cb{floor($x / 2)}), ord($PCD_data_Cr{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{floor($x / 2)}), ord($PCD_data_Cr{floor($x / 2)})); - $info['pcd']['data'][$y + 1][$x] = $this->YCbCr2RGB(ord($PCD_data_Y2{$x}), ord($PCD_data_Cb{floor($x / 2)}), ord($PCD_data_Cr{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)})); } } } @@ -99,6 +102,13 @@ class getid3_pcd extends getid3_handler } + /** + * @param int $Y + * @param int $Cb + * @param int $Cr + * + * @return int + */ public function YCbCr2RGB($Y, $Cb, $Cr) { static $YCbCr_constants = array(); if (empty($YCbCr_constants)) { diff --git a/www/plugins-dist/medias/lib/getid3/module.graphic.png.php b/www/plugins-dist/medias/lib/getid3/module.graphic.png.php index c30caa43..a9827f2d 100644 --- a/www/plugins-dist/medias/lib/getid3/module.graphic.png.php +++ b/www/plugins-dist/medias/lib/getid3/module.graphic.png.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.graphic.png.php // @@ -17,8 +17,17 @@ class getid3_png extends getid3_handler { - public $max_data_bytes = 10000000; // if data chunk is larger than this do not read it completely (getID3 only needs the first few dozen bytes for parsing) - + /** + * If data chunk is larger than this do not read it completely (getID3 only needs the first + * few dozen bytes for parsing). + * + * @var int + */ + public $max_data_bytes = 10000000; + + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -138,6 +147,7 @@ class getid3_png extends getid3_handler case 4: case 6: $this->error('Invalid color_type in tRNS chunk: '.$thisfile_png['IHDR']['raw']['color_type']); + break; default: $this->warning('Unhandled color_type in tRNS chunk: '.$thisfile_png['IHDR']['raw']['color_type']); @@ -434,11 +444,46 @@ class getid3_png extends getid3_handler $thisfile_png_chunk_type_text[$idatinformationfieldindex]['header'] = $chunk; break; - case 'IEND': // Image Trailer $thisfile_png_chunk_type_text['header'] = $chunk; break; + case 'acTL': // Animation Control chunk + // https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk + $thisfile_png['animation']['num_frames'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)); // Number of frames + $thisfile_png['animation']['num_plays'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)); // Number of times to loop this APNG. 0 indicates infinite looping. + + unset($chunk['data']); + $thisfile_png_chunk_type_text['header'] = $chunk; + break; + + case 'fcTL': // Frame Control chunk + // https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk + $fcTL = array(); + $fcTL['sequence_number'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 0, 4)); // Sequence number of the animation chunk, starting from 0 + $fcTL['width'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 4, 4)); // Width of the following frame + $fcTL['height'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 8, 4)); // Height of the following frame + $fcTL['x_offset'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 12, 4)); // X position at which to render the following frame + $fcTL['y_offset'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 16, 4)); // Y position at which to render the following frame + $fcTL['delay_num'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 20, 2)); // Frame delay fraction numerator + $fcTL['delay_den'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 22, 2)); // Frame delay fraction numerator + $fcTL['dispose_op'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 23, 1)); // Type of frame area disposal to be done after rendering this frame + $fcTL['blend_op'] = getid3_lib::BigEndian2Int(substr($chunk['data'], 23, 1)); // Type of frame area rendering for this frame + if ($fcTL['delay_den']) { + $fcTL['delay'] = $fcTL['delay_num'] / $fcTL['delay_den']; + } + $thisfile_png['animation']['fcTL'][$fcTL['sequence_number']] = $fcTL; + + unset($chunk['data']); + $thisfile_png_chunk_type_text['header'] = $chunk; + break; + + case 'fdAT': // Frame Data chunk + // https://wiki.mozilla.org/APNG_Specification#.60fcTL.60:_The_Frame_Control_Chunk + // "The `fdAT` chunk has the same purpose as an `IDAT` chunk. It has the same structure as an `IDAT` chunk, except preceded by a sequence number." + unset($chunk['data']); + $thisfile_png_chunk_type_text['header'] = $chunk; + break; default: //unset($chunk['data']); @@ -447,10 +492,21 @@ class getid3_png extends getid3_handler break; } } - + if (!empty($thisfile_png['animation']['num_frames']) && !empty($thisfile_png['animation']['fcTL'])) { + $info['video']['dataformat'] = 'apng'; + $info['playtime_seconds'] = 0; + foreach ($thisfile_png['animation']['fcTL'] as $seqno => $fcTL) { + $info['playtime_seconds'] += $fcTL['delay']; + } + } return true; } + /** + * @param int $sRGB + * + * @return string + */ public function PNGsRGBintentLookup($sRGB) { static $PNGsRGBintentLookup = array( 0 => 'Perceptual', @@ -461,6 +517,11 @@ class getid3_png extends getid3_handler return (isset($PNGsRGBintentLookup[$sRGB]) ? $PNGsRGBintentLookup[$sRGB] : 'invalid'); } + /** + * @param int $compressionmethod + * + * @return string + */ public function PNGcompressionMethodLookup($compressionmethod) { static $PNGcompressionMethodLookup = array( 0 => 'deflate/inflate' @@ -468,6 +529,11 @@ class getid3_png extends getid3_handler return (isset($PNGcompressionMethodLookup[$compressionmethod]) ? $PNGcompressionMethodLookup[$compressionmethod] : 'invalid'); } + /** + * @param int $unitid + * + * @return string + */ public function PNGpHYsUnitLookup($unitid) { static $PNGpHYsUnitLookup = array( 0 => 'unknown', @@ -476,6 +542,11 @@ class getid3_png extends getid3_handler return (isset($PNGpHYsUnitLookup[$unitid]) ? $PNGpHYsUnitLookup[$unitid] : 'invalid'); } + /** + * @param int $unitid + * + * @return string + */ public function PNGoFFsUnitLookup($unitid) { static $PNGoFFsUnitLookup = array( 0 => 'pixel', @@ -484,6 +555,11 @@ class getid3_png extends getid3_handler return (isset($PNGoFFsUnitLookup[$unitid]) ? $PNGoFFsUnitLookup[$unitid] : 'invalid'); } + /** + * @param int $equationtype + * + * @return string + */ public function PNGpCALequationTypeLookup($equationtype) { static $PNGpCALequationTypeLookup = array( 0 => 'Linear mapping', @@ -494,6 +570,11 @@ class getid3_png extends getid3_handler return (isset($PNGpCALequationTypeLookup[$equationtype]) ? $PNGpCALequationTypeLookup[$equationtype] : 'invalid'); } + /** + * @param int $unitid + * + * @return string + */ public function PNGsCALUnitLookup($unitid) { static $PNGsCALUnitLookup = array( 0 => 'meter', @@ -502,6 +583,12 @@ class getid3_png extends getid3_handler return (isset($PNGsCALUnitLookup[$unitid]) ? $PNGsCALUnitLookup[$unitid] : 'invalid'); } + /** + * @param int $color_type + * @param int $bit_depth + * + * @return int|false + */ public function IHDRcalculateBitsPerSample($color_type, $bit_depth) { switch ($color_type) { case 0: // Each pixel is a grayscale sample. diff --git a/www/plugins-dist/medias/lib/getid3/module.graphic.svg.php b/www/plugins-dist/medias/lib/getid3/module.graphic.svg.php index e4502aae..73b9d843 100644 --- a/www/plugins-dist/medias/lib/getid3/module.graphic.svg.php +++ b/www/plugins-dist/medias/lib/getid3/module.graphic.svg.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.graphic.svg.php // @@ -17,8 +17,9 @@ class getid3_svg extends getid3_handler { - - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; diff --git a/www/plugins-dist/medias/lib/getid3/module.graphic.tiff.php b/www/plugins-dist/medias/lib/getid3/module.graphic.tiff.php index 90dcb5c8..57d500f5 100644 --- a/www/plugins-dist/medias/lib/getid3/module.graphic.tiff.php +++ b/www/plugins-dist/medias/lib/getid3/module.graphic.tiff.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.archive.tiff.php // @@ -17,7 +17,9 @@ class getid3_tiff extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -60,6 +62,8 @@ class getid3_tiff extends getid3_handler $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_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) { @@ -165,7 +169,7 @@ class getid3_tiff extends getid3_handler case 306: // DateTime case 315: // Artist case 316: // HostComputer - $TIFFcommentName = $this->TIFFcommentName($fieldarray['raw']['tag']); + $TIFFcommentName = strtolower($fieldarray['raw']['tag_name']); if (isset($info['tiff']['comments'][$TIFFcommentName])) { $info['tiff']['comments'][$TIFFcommentName][] = $info['tiff']['ifd'][$IFDid]['fields'][$key]['raw']['data']; } else { @@ -182,7 +186,12 @@ class getid3_tiff extends getid3_handler return true; } - + /** + * @param string $bytestring + * @param string $byteorder + * + * @return int|float|false + */ public function TIFFendian2Int($bytestring, $byteorder) { if ($byteorder == 'Intel') { return getid3_lib::LittleEndian2Int($bytestring); @@ -192,6 +201,11 @@ class getid3_tiff extends getid3_handler return false; } + /** + * @param int $id + * + * @return string + */ public function TIFFcompressionMethod($id) { static $TIFFcompressionMethod = array(); if (empty($TIFFcompressionMethod)) { @@ -206,20 +220,252 @@ class getid3_tiff extends getid3_handler return (isset($TIFFcompressionMethod[$id]) ? $TIFFcompressionMethod[$id] : 'unknown/invalid ('.$id.')'); } + /** + * @param int $id + * + * @return string + */ public function TIFFcommentName($id) { + // https://www.awaresystems.be/imaging/tiff/tifftags.html static $TIFFcommentName = array(); if (empty($TIFFcommentName)) { $TIFFcommentName = array( - 270 => 'imagedescription', - 271 => 'make', - 272 => 'model', - 305 => 'software', - 306 => 'datetime', - 315 => 'artist', - 316 => 'hostcomputer', + 254 => 'NewSubfileType', + 255 => 'SubfileType', + 256 => 'ImageWidth', + 257 => 'ImageLength', + 258 => 'BitsPerSample', + 259 => 'Compression', + 262 => 'PhotometricInterpretation', + 263 => 'Threshholding', + 264 => 'CellWidth', + 265 => 'CellLength', + 266 => 'FillOrder', + 269 => 'DocumentName', + 270 => 'ImageDescription', + 271 => 'Make', + 272 => 'Model', + 273 => 'StripOffsets', + 274 => 'Orientation', + 277 => 'SamplesPerPixel', + 278 => 'RowsPerStrip', + 279 => 'StripByteCounts', + 280 => 'MinSampleValue', + 281 => 'MaxSampleValue', + 282 => 'XResolution', + 283 => 'YResolution', + 284 => 'PlanarConfiguration', + 285 => 'PageName', + 286 => 'XPosition', + 287 => 'YPosition', + 288 => 'FreeOffsets', + 289 => 'FreeByteCounts', + 290 => 'GrayResponseUnit', + 291 => 'GrayResponseCurve', + 292 => 'T4Options', + 293 => 'T6Options', + 296 => 'ResolutionUnit', + 297 => 'PageNumber', + 301 => 'TransferFunction', + 305 => 'Software', + 306 => 'DateTime', + 315 => 'Artist', + 316 => 'HostComputer', + 317 => 'Predictor', + 318 => 'WhitePoint', + 319 => 'PrimaryChromaticities', + 320 => 'ColorMap', + 321 => 'HalftoneHints', + 322 => 'TileWidth', + 323 => 'TileLength', + 324 => 'TileOffsets', + 325 => 'TileByteCounts', + 326 => 'BadFaxLines', + 327 => 'CleanFaxData', + 328 => 'ConsecutiveBadFaxLines', + 330 => 'SubIFDs', + 332 => 'InkSet', + 333 => 'InkNames', + 334 => 'NumberOfInks', + 336 => 'DotRange', + 337 => 'TargetPrinter', + 338 => 'ExtraSamples', + 339 => 'SampleFormat', + 340 => 'SMinSampleValue', + 341 => 'SMaxSampleValue', + 342 => 'TransferRange', + 343 => 'ClipPath', + 344 => 'XClipPathUnits', + 345 => 'YClipPathUnits', + 346 => 'Indexed', + 347 => 'JPEGTables', + 351 => 'OPIProxy', + 400 => 'GlobalParametersIFD', + 401 => 'ProfileType', + 402 => 'FaxProfile', + 403 => 'CodingMethods', + 404 => 'VersionYear', + 405 => 'ModeNumber', + 433 => 'Decode', + 434 => 'DefaultImageColor', + 512 => 'JPEGProc', + 513 => 'JPEGInterchangeFormat', + 514 => 'JPEGInterchangeFormatLngth', + 515 => 'JPEGRestartInterval', + 517 => 'JPEGLosslessPredictors', + 518 => 'JPEGPointTransforms', + 519 => 'JPEGQTables', + 520 => 'JPEGDCTables', + 521 => 'JPEGACTables', + 529 => 'YCbCrCoefficients', + 530 => 'YCbCrSubSampling', + 531 => 'YCbCrPositioning', + 532 => 'ReferenceBlackWhite', + 559 => 'StripRowCounts', + 700 => 'XMP', + + 32781 => 'ImageID', + 33432 => 'Copyright', + 34732 => 'ImageLayer', + + // Private Tags - https://www.awaresystems.be/imaging/tiff/tifftags/private.html + 32932 => 'Wang Annotation', // Annotation data, as used in 'Imaging for Windows'. + 33445 => 'MD FileTag', // Specifies the pixel data format encoding in the Molecular Dynamics GEL file format. + 33446 => 'MD ScalePixel', // Specifies a scale factor in the Molecular Dynamics GEL file format. + 33447 => 'MD ColorTable', // Used to specify the conversion from 16bit to 8bit in the Molecular Dynamics GEL file format. + 33448 => 'MD LabName', // Name of the lab that scanned this file, as used in the Molecular Dynamics GEL file format. + 33449 => 'MD SampleInfo', // Information about the sample, as used in the Molecular Dynamics GEL file format. + 33450 => 'MD PrepDate', // Date the sample was prepared, as used in the Molecular Dynamics GEL file format. + 33451 => 'MD PrepTime', // Time the sample was prepared, as used in the Molecular Dynamics GEL file format. + 33452 => 'MD FileUnits', // Units for data in this file, as used in the Molecular Dynamics GEL file format. + 33550 => 'ModelPixelScaleTag', // Used in interchangeable GeoTIFF files. + 33723 => 'IPTC', // IPTC (International Press Telecommunications Council) metadata. + 33918 => 'INGR Packet Data Tag', // Intergraph Application specific storage. + 33919 => 'INGR Flag Registers', // Intergraph Application specific flags. + 33920 => 'IrasB Transformation Matrix', // Originally part of Intergraph's GeoTIFF tags, but likely understood by IrasB only. + 33922 => 'ModelTiepointTag', // Originally part of Intergraph's GeoTIFF tags, but now used in interchangeable GeoTIFF files. + 34264 => 'ModelTransformationTag', // Used in interchangeable GeoTIFF files. + 34377 => 'Photoshop', // Collection of Photoshop 'Image Resource Blocks'. + 34665 => 'Exif IFD', // A pointer to the Exif IFD. + 34675 => 'ICC Profile', // ICC profile data. + 34735 => 'GeoKeyDirectoryTag', // Used in interchangeable GeoTIFF files. + 34736 => 'GeoDoubleParamsTag', // Used in interchangeable GeoTIFF files. + 34737 => 'GeoAsciiParamsTag', // Used in interchangeable GeoTIFF files. + 34853 => 'GPS IFD', // A pointer to the Exif-related GPS Info IFD. + 34908 => 'HylaFAX FaxRecvParams', // Used by HylaFAX. + 34909 => 'HylaFAX FaxSubAddress', // Used by HylaFAX. + 34910 => 'HylaFAX FaxRecvTime', // Used by HylaFAX. + 37724 => 'ImageSourceData', // Used by Adobe Photoshop. + 40965 => 'Interoperability IFD', // A pointer to the Exif-related Interoperability IFD. + 42112 => 'GDAL_METADATA', // Used by the GDAL library, holds an XML list of name=value 'metadata' values about the image as a whole, and about specific samples. + 42113 => 'GDAL_NODATA', // Used by the GDAL library, contains an ASCII encoded nodata or background pixel value. + 50215 => 'Oce Scanjob Description', // Used in the Oce scanning process. + 50216 => 'Oce Application Selector', // Used in the Oce scanning process. + 50217 => 'Oce Identification Number', // Used in the Oce scanning process. + 50218 => 'Oce ImageLogic Characteristics', // Used in the Oce scanning process. + 50706 => 'DNGVersion', // Used in IFD 0 of DNG files. + 50707 => 'DNGBackwardVersion', // Used in IFD 0 of DNG files. + 50708 => 'UniqueCameraModel', // Used in IFD 0 of DNG files. + 50709 => 'LocalizedCameraModel', // Used in IFD 0 of DNG files. + 50710 => 'CFAPlaneColor', // Used in Raw IFD of DNG files. + 50711 => 'CFALayout', // Used in Raw IFD of DNG files. + 50712 => 'LinearizationTable', // Used in Raw IFD of DNG files. + 50713 => 'BlackLevelRepeatDim', // Used in Raw IFD of DNG files. + 50714 => 'BlackLevel', // Used in Raw IFD of DNG files. + 50715 => 'BlackLevelDeltaH', // Used in Raw IFD of DNG files. + 50716 => 'BlackLevelDeltaV', // Used in Raw IFD of DNG files. + 50717 => 'WhiteLevel', // Used in Raw IFD of DNG files. + 50718 => 'DefaultScale', // Used in Raw IFD of DNG files. + 50719 => 'DefaultCropOrigin', // Used in Raw IFD of DNG files. + 50720 => 'DefaultCropSize', // Used in Raw IFD of DNG files. + 50721 => 'ColorMatrix1', // Used in IFD 0 of DNG files. + 50722 => 'ColorMatrix2', // Used in IFD 0 of DNG files. + 50723 => 'CameraCalibration1', // Used in IFD 0 of DNG files. + 50724 => 'CameraCalibration2', // Used in IFD 0 of DNG files. + 50725 => 'ReductionMatrix1', // Used in IFD 0 of DNG files. + 50726 => 'ReductionMatrix2', // Used in IFD 0 of DNG files. + 50727 => 'AnalogBalance', // Used in IFD 0 of DNG files. + 50728 => 'AsShotNeutral', // Used in IFD 0 of DNG files. + 50729 => 'AsShotWhiteXY', // Used in IFD 0 of DNG files. + 50730 => 'BaselineExposure', // Used in IFD 0 of DNG files. + 50731 => 'BaselineNoise', // Used in IFD 0 of DNG files. + 50732 => 'BaselineSharpness', // Used in IFD 0 of DNG files. + 50733 => 'BayerGreenSplit', // Used in Raw IFD of DNG files. + 50734 => 'LinearResponseLimit', // Used in IFD 0 of DNG files. + 50735 => 'CameraSerialNumber', // Used in IFD 0 of DNG files. + 50736 => 'LensInfo', // Used in IFD 0 of DNG files. + 50737 => 'ChromaBlurRadius', // Used in Raw IFD of DNG files. + 50738 => 'AntiAliasStrength', // Used in Raw IFD of DNG files. + 50740 => 'DNGPrivateData', // Used in IFD 0 of DNG files. + 50741 => 'MakerNoteSafety', // Used in IFD 0 of DNG files. + 50778 => 'CalibrationIlluminant1', // Used in IFD 0 of DNG files. + 50779 => 'CalibrationIlluminant2', // Used in IFD 0 of DNG files. + 50780 => 'BestQualityScale', // Used in Raw IFD of DNG files. + 50784 => 'Alias Layer Metadata', // Alias Sketchbook Pro layer usage description. + 50908 => 'TIFF_RSID', // This private tag is used in a GEOTIFF standard by DGIWG. + 50909 => 'GEO_METADATA', // This private tag is used in a GEOTIFF standard by DGIWG. + + // EXIF tags - https://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif.html + 33434 => 'ExposureTime', // Exposure time, given in seconds. + 33437 => 'FNumber', // The F number. + 34850 => 'ExposureProgram', // The class of the program used by the camera to set exposure when the picture is taken. + 34852 => 'SpectralSensitivity', // Indicates the spectral sensitivity of each channel of the camera used. + 34855 => 'ISOSpeedRatings', // Indicates the ISO Speed and ISO Latitude of the camera or input device as specified in ISO 12232. + 34856 => 'OECF', // Indicates the Opto-Electric Conversion Function (OECF) specified in ISO 14524. + 36864 => 'ExifVersion', // The version of the supported Exif standard. + 36867 => 'DateTimeOriginal', // The date and time when the original image data was generated. + 36868 => 'DateTimeDigitized', // The date and time when the image was stored as digital data. + 37121 => 'ComponentsConfiguration', // Specific to compressed data; specifies the channels and complements PhotometricInterpretation + 37122 => 'CompressedBitsPerPixel', // Specific to compressed data; states the compressed bits per pixel. + 37377 => 'ShutterSpeedValue', // Shutter speed. + 37378 => 'ApertureValue', // The lens aperture. + 37379 => 'BrightnessValue', // The value of brightness. + 37380 => 'ExposureBiasValue', // The exposure bias. + 37381 => 'MaxApertureValue', // The smallest F number of the lens. + 37382 => 'SubjectDistance', // The distance to the subject, given in meters. + 37383 => 'MeteringMode', // The metering mode. + 37384 => 'LightSource', // The kind of light source. + 37385 => 'Flash', // Indicates the status of flash when the image was shot. + 37386 => 'FocalLength', // The actual focal length of the lens, in mm. + 37396 => 'SubjectArea', // Indicates the location and area of the main subject in the overall scene. + 37500 => 'MakerNote', // Manufacturer specific information. + 37510 => 'UserComment', // Keywords or comments on the image; complements ImageDescription. + 37520 => 'SubsecTime', // A tag used to record fractions of seconds for the DateTime tag. + 37521 => 'SubsecTimeOriginal', // A tag used to record fractions of seconds for the DateTimeOriginal tag. + 37522 => 'SubsecTimeDigitized', // A tag used to record fractions of seconds for the DateTimeDigitized tag. + 40960 => 'FlashpixVersion', // The Flashpix format version supported by a FPXR file. + 40961 => 'ColorSpace', // The color space information tag is always recorded as the color space specifier. + 40962 => 'PixelXDimension', // Specific to compressed data; the valid width of the meaningful image. + 40963 => 'PixelYDimension', // Specific to compressed data; the valid height of the meaningful image. + 40964 => 'RelatedSoundFile', // Used to record the name of an audio file related to the image data. + 41483 => 'FlashEnergy', // Indicates the strobe energy at the time the image is captured, as measured in Beam Candle Power Seconds + 41484 => 'SpatialFrequencyResponse', // Records the camera or input device spatial frequency table and SFR values in the direction of image width, image height, and diagonal direction, as specified in ISO 12233. + 41486 => 'FocalPlaneXResolution', // Indicates the number of pixels in the image width (X) direction per FocalPlaneResolutionUnit on the camera focal plane. + 41487 => 'FocalPlaneYResolution', // Indicates the number of pixels in the image height (Y) direction per FocalPlaneResolutionUnit on the camera focal plane. + 41488 => 'FocalPlaneResolutionUnit', // Indicates the unit for measuring FocalPlaneXResolution and FocalPlaneYResolution. + 41492 => 'SubjectLocation', // Indicates the location of the main subject in the scene. + 41493 => 'ExposureIndex', // Indicates the exposure index selected on the camera or input device at the time the image is captured. + 41495 => 'SensingMethod', // Indicates the image sensor type on the camera or input device. + 41728 => 'FileSource', // Indicates the image source. + 41729 => 'SceneType', // Indicates the type of scene. + 41730 => 'CFAPattern', // Indicates the color filter array (CFA) geometric pattern of the image sensor when a one-chip color area sensor is used. + 41985 => 'CustomRendered', // Indicates the use of special processing on image data, such as rendering geared to output. + 41986 => 'ExposureMode', // Indicates the exposure mode set when the image was shot. + 41987 => 'WhiteBalance', // Indicates the white balance mode set when the image was shot. + 41988 => 'DigitalZoomRatio', // Indicates the digital zoom ratio when the image was shot. + 41989 => 'FocalLengthIn35mmFilm', // Indicates the equivalent focal length assuming a 35mm film camera, in mm. + 41990 => 'SceneCaptureType', // Indicates the type of scene that was shot. + 41991 => 'GainControl', // Indicates the degree of overall image gain adjustment. + 41992 => 'Contrast', // Indicates the direction of contrast processing applied by the camera when the image was shot. + 41993 => 'Saturation', // Indicates the direction of saturation processing applied by the camera when the image was shot. + 41994 => 'Sharpness', // Indicates the direction of sharpness processing applied by the camera when the image was shot. + 41995 => 'DeviceSettingDescription', // This tag indicates information on the picture-taking conditions of a particular camera model. + 41996 => 'SubjectDistanceRange', // Indicates the distance to the subject. + 42016 => 'ImageUniqueID', // Indicates an identifier assigned uniquely to each image. ); } return (isset($TIFFcommentName[$id]) ? $TIFFcommentName[$id] : 'unknown/invalid ('.$id.')'); } + } diff --git a/www/plugins-dist/medias/lib/getid3/module.misc.cue.php b/www/plugins-dist/medias/lib/getid3/module.misc.cue.php index 9c42799e..4602cdec 100644 --- a/www/plugins-dist/medias/lib/getid3/module.misc.cue.php +++ b/www/plugins-dist/medias/lib/getid3/module.misc.cue.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.misc.cue.php // @@ -35,6 +35,9 @@ class getid3_cue extends getid3_handler { public $cuesheet = array(); + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -44,18 +47,24 @@ class getid3_cue extends getid3_handler return true; } - - + /** + * @param string $filename + * + * @return array + */ public function readCueSheetFilename($filename) { $filedata = file_get_contents($filename); return $this->readCueSheet($filedata); } + /** - * Parses a cue sheet file. - * - * @param string $filename - The filename for the cue sheet to open. - */ + * Parses a cue sheet file. + * + * @param string $filedata + * + * @return array + */ public function readCueSheet(&$filedata) { $cue_lines = array(); @@ -72,10 +81,10 @@ class getid3_cue extends getid3_handler } /** - * Parses the cue sheet array. - * - * @param array $file - The cuesheet as an array of each line. - */ + * Parses the cue sheet array. + * + * @param array $file - The cuesheet as an array of each line. + */ public function parseCueSheet($file) { //-1 means still global, all others are track specific @@ -125,11 +134,11 @@ class getid3_cue extends getid3_handler } /** - * Parses the REM command. - * - * @param string $line - The line in the cue file that contains the TRACK command. - * @param integer $track_on - The track currently processing. - */ + * Parses the REM command. + * + * @param string $line - The line in the cue file that contains the TRACK command. + * @param integer $track_on - The track currently processing. + */ public function parseComment($line, $track_on) { $explodedline = explode(' ', $line, 3); @@ -148,11 +157,12 @@ class getid3_cue extends getid3_handler } /** - * Parses the FILE command. - * - * @param string $line - The line in the cue file that contains the FILE command. - * @return array - Array of FILENAME and TYPE of file.. - */ + * Parses the FILE command. + * + * @param string $line - The line in the cue file that contains the FILE command. + * + * @return array - Array of FILENAME and TYPE of file.. + */ public function parseFile($line) { $line = substr($line, strpos($line, ' ') + 1); @@ -168,11 +178,11 @@ class getid3_cue extends getid3_handler } /** - * Parses the FLAG command. - * - * @param string $line - The line in the cue file that contains the TRACK command. - * @param integer $track_on - The track currently processing. - */ + * Parses the FLAG command. + * + * @param string $line - The line in the cue file that contains the TRACK command. + * @param integer $track_on - The track currently processing. + */ public function parseFlags($line, $track_on) { if ($track_on != -1) @@ -206,11 +216,11 @@ class getid3_cue extends getid3_handler } /** - * Collect any unidentified data. - * - * @param string $line - The line in the cue file that contains the TRACK command. - * @param integer $track_on - The track currently processing. - */ + * Collect any unidentified data. + * + * @param string $line - The line in the cue file that contains the TRACK command. + * @param integer $track_on - The track currently processing. + */ public function parseGarbage($line, $track_on) { if ( strlen($line) > 0 ) @@ -227,15 +237,16 @@ class getid3_cue extends getid3_handler } /** - * Parses the INDEX command of a TRACK. - * - * @param string $line - The line in the cue file that contains the TRACK command. - * @param integer $track_on - The track currently processing. - */ + * Parses the INDEX command of a TRACK. + * + * @param string $line - The line in the cue file that contains the TRACK command. + * @param integer $track_on - The track currently processing. + */ public function parseIndex($line, $track_on) { $type = strtolower(substr($line, 0, strpos($line, ' '))); $line = substr($line, strpos($line, ' ') + 1); + $number = 0; if ($type == 'index') { @@ -261,6 +272,10 @@ class getid3_cue extends getid3_handler } } + /** + * @param string $line + * @param int $track_on + */ public function parseString($line, $track_on) { $category = strtolower(substr($line, 0, strpos($line, ' '))); @@ -292,11 +307,11 @@ class getid3_cue extends getid3_handler } /** - * Parses the TRACK command. - * - * @param string $line - The line in the cue file that contains the TRACK command. - * @param integer $track_on - The track currently processing. - */ + * Parses the TRACK command. + * + * @param string $line - The line in the cue file that contains the TRACK command. + * @param integer $track_on - The track currently processing. + */ public function parseTrack($line, $track_on) { $line = substr($line, strpos($line, ' ') + 1); diff --git a/www/plugins-dist/medias/lib/getid3/module.misc.exe.php b/www/plugins-dist/medias/lib/getid3/module.misc.exe.php index 4f04ad72..57bea051 100644 --- a/www/plugins-dist/medias/lib/getid3/module.misc.exe.php +++ b/www/plugins-dist/medias/lib/getid3/module.misc.exe.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.misc.exe.php // @@ -17,7 +17,9 @@ class getid3_exe extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -51,8 +53,8 @@ class getid3_exe extends getid3_handler $info['exe']['mz']['memory_minimum'] = $info['exe']['mz']['raw']['min_memory_paragraphs'] * 16; $info['exe']['mz']['memory_recommended'] = $info['exe']['mz']['raw']['max_memory_paragraphs'] * 16; -$this->error('EXE parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); -return false; + $this->error('EXE parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); + return false; } diff --git a/www/plugins-dist/medias/lib/getid3/module.misc.iso.php b/www/plugins-dist/medias/lib/getid3/module.misc.iso.php index 04772856..231a32a2 100644 --- a/www/plugins-dist/medias/lib/getid3/module.misc.iso.php +++ b/www/plugins-dist/medias/lib/getid3/module.misc.iso.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.misc.iso.php // @@ -17,7 +17,9 @@ class getid3_iso extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -55,7 +57,11 @@ class getid3_iso extends getid3_handler return true; } - + /** + * @param string $ISOheader + * + * @return bool + */ public function ParsePrimaryVolumeDescriptor(&$ISOheader) { // ISO integer values are stored *BOTH* Little-Endian AND Big-Endian format!! // ie 12345 == 0x3039 is stored as $39 $30 $30 $39 in a 4-byte field @@ -129,7 +135,11 @@ class getid3_iso extends getid3_handler return true; } - + /** + * @param string $ISOheader + * + * @return bool + */ public function ParseSupplementaryVolumeDescriptor(&$ISOheader) { // ISO integer values are stored Both-Endian format!! // ie 12345 == 0x3039 is stored as $39 $30 $30 $39 in a 4-byte field @@ -208,7 +218,9 @@ class getid3_iso extends getid3_handler return true; } - + /** + * @return bool + */ public function ParsePathTable() { $info = &$this->getid3->info; if (!isset($info['iso']['supplementary_volume_descriptor']['raw']['path_table_l_location']) && !isset($info['iso']['primary_volume_descriptor']['raw']['path_table_l_location'])) { @@ -267,7 +279,11 @@ class getid3_iso extends getid3_handler return true; } - + /** + * @param array $directorydata + * + * @return array + */ public function ParseDirectoryRecord($directorydata) { $info = &$this->getid3->info; if (isset($info['iso']['supplementary_volume_descriptor'])) { @@ -278,11 +294,14 @@ class getid3_iso extends getid3_handler $this->fseek($directorydata['location_bytes']); $DirectoryRecordData = $this->fread(1); + $DirectoryRecord = array(); while (ord($DirectoryRecordData{0}) > 33) { $DirectoryRecordData .= $this->fread(ord($DirectoryRecordData{0}) - 1); + $ThisDirectoryRecord = array(); + $ThisDirectoryRecord['raw']['length'] = getid3_lib::LittleEndian2Int(substr($DirectoryRecordData, 0, 1)); $ThisDirectoryRecord['raw']['extended_attribute_length'] = getid3_lib::LittleEndian2Int(substr($DirectoryRecordData, 1, 1)); $ThisDirectoryRecord['raw']['offset_logical'] = getid3_lib::LittleEndian2Int(substr($DirectoryRecordData, 2, 4)); @@ -321,6 +340,11 @@ class getid3_iso extends getid3_handler return $DirectoryRecord; } + /** + * @param string $ISOfilename + * + * @return string + */ public function ISOstripFilenameVersion($ISOfilename) { // convert 'filename.ext;1' to 'filename.ext' if (!strstr($ISOfilename, ';')) { @@ -330,6 +354,11 @@ class getid3_iso extends getid3_handler } } + /** + * @param string $ISOtime + * + * @return int|false + */ public function ISOtimeText2UNIXtime($ISOtime) { $UNIXyear = (int) substr($ISOtime, 0, 4); @@ -345,6 +374,11 @@ class getid3_iso extends getid3_handler return gmmktime($UNIXhour, $UNIXminute, $UNIXsecond, $UNIXmonth, $UNIXday, $UNIXyear); } + /** + * @param string $ISOtime + * + * @return int + */ public function ISOtime2UNIXtime($ISOtime) { // Represented by seven bytes: // 1: Number of years since 1900 @@ -366,6 +400,11 @@ class getid3_iso extends getid3_handler return gmmktime($UNIXhour, $UNIXminute, $UNIXsecond, $UNIXmonth, $UNIXday, $UNIXyear); } + /** + * @param int $BinaryValue + * + * @return int + */ public function TwosCompliment2Decimal($BinaryValue) { // http://sandbox.mc.edu/~bennet/cs110/tc/tctod.html // First check if the number is negative or positive by looking at the sign bit. diff --git a/www/plugins-dist/medias/lib/getid3/module.misc.msoffice.php b/www/plugins-dist/medias/lib/getid3/module.misc.msoffice.php index 099e6fc9..9a60aa08 100644 --- a/www/plugins-dist/medias/lib/getid3/module.misc.msoffice.php +++ b/www/plugins-dist/medias/lib/getid3/module.misc.msoffice.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.misc.msoffice.php // @@ -17,7 +17,9 @@ class getid3_msoffice extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -30,8 +32,8 @@ class getid3_msoffice extends getid3_handler } $info['fileformat'] = 'msoffice'; -$this->error('MS Office (.doc, .xls, etc) parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); -return false; + $this->error('MS Office (.doc, .xls, etc) parsing not enabled in this version of getID3() ['.$this->getid3->version().']'); + return false; } diff --git a/www/plugins-dist/medias/lib/getid3/module.misc.par2.php b/www/plugins-dist/medias/lib/getid3/module.misc.par2.php index 2312bb84..f5da1937 100644 --- a/www/plugins-dist/medias/lib/getid3/module.misc.par2.php +++ b/www/plugins-dist/medias/lib/getid3/module.misc.par2.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.misc.par2.php // @@ -17,7 +17,9 @@ class getid3_par2 extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; diff --git a/www/plugins-dist/medias/lib/getid3/module.misc.pdf.php b/www/plugins-dist/medias/lib/getid3/module.misc.pdf.php index e8d25cba..c6896a69 100644 --- a/www/plugins-dist/medias/lib/getid3/module.misc.pdf.php +++ b/www/plugins-dist/medias/lib/getid3/module.misc.pdf.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.misc.pdf.php // @@ -17,7 +17,9 @@ class getid3_pdf extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; diff --git a/www/plugins-dist/medias/lib/getid3/module.tag.apetag.php b/www/plugins-dist/medias/lib/getid3/module.tag.apetag.php index 938625a8..37971a6b 100644 --- a/www/plugins-dist/medias/lib/getid3/module.tag.apetag.php +++ b/www/plugins-dist/medias/lib/getid3/module.tag.apetag.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.tag.apetag.php // @@ -16,9 +16,21 @@ class getid3_apetag extends getid3_handler { - public $inline_attachments = true; // true: return full data for all attachments; false: return no data for all attachments; integer: return data for attachments <= than this; string: save as file to this directory + /** + * true: return full data for all attachments; + * false: return no data for all attachments; + * integer: return data for attachments <= than this; + * string: save as file to this directory. + * + * @var int|bool|string + */ + public $inline_attachments = true; + public $overrideendoffset = 0; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -286,7 +298,7 @@ class getid3_apetag extends getid3_handler } } elseif (is_string($this->inline_attachments)) { $this->inline_attachments = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->inline_attachments), DIRECTORY_SEPARATOR); - if (!is_dir($this->inline_attachments) || !is_writable($this->inline_attachments)) { + if (!is_dir($this->inline_attachments) || !getID3::is_writable($this->inline_attachments)) { // cannot write, skip $this->warning('attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$this->inline_attachments.'" (not writable)'); unset($thisfile_ape_items_current['data']); @@ -296,7 +308,7 @@ class getid3_apetag extends getid3_handler // if we get this far, must be OK if (is_string($this->inline_attachments)) { $destination_filename = $this->inline_attachments.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$thisfile_ape_items_current['data_offset']; - if (!file_exists($destination_filename) || is_writable($destination_filename)) { + if (!file_exists($destination_filename) || getID3::is_writable($destination_filename)) { file_put_contents($destination_filename, $thisfile_ape_items_current['data']); } else { $this->warning('attachment at '.$thisfile_ape_items_current['offset'].' cannot be saved to "'.$destination_filename.'" (not writable)'); @@ -335,6 +347,11 @@ class getid3_apetag extends getid3_handler return true; } + /** + * @param string $APEheaderFooterData + * + * @return array|false + */ public function parseAPEheaderFooter($APEheaderFooterData) { // http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html @@ -359,6 +376,11 @@ class getid3_apetag extends getid3_handler return $headerfooterinfo; } + /** + * @param int $rawflagint + * + * @return array + */ public function parseAPEtagFlags($rawflagint) { // "Note: APE Tags 1.0 do not use any of the APE Tag flags. // All are set to zero on creation and ignored on reading." @@ -374,6 +396,11 @@ class getid3_apetag extends getid3_handler return $flags; } + /** + * @param int $contenttypeid + * + * @return string + */ public function APEcontentTypeFlagLookup($contenttypeid) { static $APEcontentTypeFlagLookup = array( 0 => 'utf-8', @@ -384,6 +411,11 @@ class getid3_apetag extends getid3_handler return (isset($APEcontentTypeFlagLookup[$contenttypeid]) ? $APEcontentTypeFlagLookup[$contenttypeid] : 'invalid'); } + /** + * @param string $itemkey + * + * @return bool + */ public function APEtagItemIsUTF8Lookup($itemkey) { static $APEtagItemIsUTF8Lookup = array( 'title', diff --git a/www/plugins-dist/medias/lib/getid3/module.tag.id3v1.php b/www/plugins-dist/medias/lib/getid3/module.tag.id3v1.php index d160e9b4..cafc3fba 100644 --- a/www/plugins-dist/medias/lib/getid3/module.tag.id3v1.php +++ b/www/plugins-dist/medias/lib/getid3/module.tag.id3v1.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.tag.id3v1.php // @@ -17,7 +17,9 @@ class getid3_id3v1 extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -124,10 +126,20 @@ class getid3_id3v1 extends getid3_handler return true; } + /** + * @param string $str + * + * @return string + */ public static function cutfield($str) { return trim(substr($str, 0, strcspn($str, "\x00"))); } + /** + * @param bool $allowSCMPXextended + * + * @return string[] + */ public static function ArrayOfGenres($allowSCMPXextended=false) { static $GenreLookup = array( 0 => 'Blues', @@ -312,6 +324,12 @@ class getid3_id3v1 extends getid3_handler return ($allowSCMPXextended ? $GenreLookupSCMPX : $GenreLookup); } + /** + * @param string $genreid + * @param bool $allowSCMPXextended + * + * @return string|false + */ public static function LookupGenreName($genreid, $allowSCMPXextended=true) { switch ($genreid) { case 'RX': @@ -328,6 +346,12 @@ class getid3_id3v1 extends getid3_handler return (isset($GenreLookup[$genreid]) ? $GenreLookup[$genreid] : false); } + /** + * @param string $genre + * @param bool $allowSCMPXextended + * + * @return string|false + */ public static function LookupGenreID($genre, $allowSCMPXextended=false) { $GenreLookup = self::ArrayOfGenres($allowSCMPXextended); $LowerCaseNoSpaceSearchTerm = strtolower(str_replace(' ', '', $genre)); @@ -339,6 +363,11 @@ class getid3_id3v1 extends getid3_handler return false; } + /** + * @param string $OriginalGenre + * + * @return string|false + */ public static function StandardiseID3v1GenreName($OriginalGenre) { if (($GenreID = self::LookupGenreID($OriginalGenre)) !== false) { return self::LookupGenreName($GenreID); @@ -346,6 +375,17 @@ class getid3_id3v1 extends getid3_handler return $OriginalGenre; } + /** + * @param string $title + * @param string $artist + * @param string $album + * @param string $year + * @param int $genreid + * @param string $comment + * @param int|string $track + * + * @return string + */ public static function GenerateID3v1Tag($title, $artist, $album, $year, $genreid, $comment, $track='') { $ID3v1Tag = 'TAG'; $ID3v1Tag .= str_pad(trim(substr($title, 0, 30)), 30, "\x00", STR_PAD_RIGHT); diff --git a/www/plugins-dist/medias/lib/getid3/module.tag.id3v2.php b/www/plugins-dist/medias/lib/getid3/module.tag.id3v2.php index 829f5ee2..c51dedb8 100644 --- a/www/plugins-dist/medias/lib/getid3/module.tag.id3v2.php +++ b/www/plugins-dist/medias/lib/getid3/module.tag.id3v2.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// /// // // module.tag.id3v2.php // @@ -20,6 +20,9 @@ class getid3_id3v2 extends getid3_handler { public $StartingOffset = 0; + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -266,6 +269,10 @@ class getid3_id3v2 extends getid3_handler } break; // skip rest of ID3v2 header } + $frame_header = null; + $frame_name = null; + $frame_size = null; + $frame_flags = null; if ($id3v2_majorversion == 2) { // Frame ID $xx xx xx (three characters) // Size $xx xx xx (24-bit integer) @@ -431,7 +438,7 @@ class getid3_id3v2 extends getid3_handler $thisfile_id3v2['minorversion_footer'] = ord($footer{4}); } if ($thisfile_id3v2['majorversion_footer'] <= 4) { - $id3_flags = ord(substr($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); @@ -498,7 +505,11 @@ class getid3_id3v2 extends getid3_handler return true; } - + /** + * @param string $genrestring + * + * @return array + */ public function ParseID3v2GenreString($genrestring) { // Parse genres into arrays of genreName and genreID // ID3v2.2.x, ID3v2.3.x: '(21)' or '(4)Eurodisco' or '(51)(39)' or '(55)((I think...)' @@ -530,7 +541,7 @@ class getid3_id3v2 extends getid3_handler foreach ($genre_elements as $element) { $element = trim($element); if ($element) { - if (preg_match('#^[0-9]{1,3}#', $element)) { + if (preg_match('#^[0-9]{1,3}$#', $element)) { $clean_genres[] = getid3_id3v1::LookupGenreName($element); } else { $clean_genres[] = str_replace('((', '(', $element); @@ -540,7 +551,11 @@ class getid3_id3v2 extends getid3_handler return $clean_genres; } - + /** + * @param array $parsedFrame + * + * @return bool + */ public function ParseID3v2Frame(&$parsedFrame) { // shortcuts @@ -774,10 +789,10 @@ class getid3_id3v2 extends getid3_handler $parsedFrame['encodingid'] = $frame_textencoding; $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); - $parsedFrame['url'] = $frame_urldata; - $parsedFrame['description'] = $frame_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($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['url']); + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']); } unset($parsedFrame['data']); @@ -789,9 +804,9 @@ class getid3_id3v2 extends getid3_handler // described in 4.3.2.> // URL - $parsedFrame['url'] = trim($parsedFrame['data']); + $parsedFrame['url'] = trim($parsedFrame['data']); // always ISO-8859-1 if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) { - $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['url']; + $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']); } unset($parsedFrame['data']); @@ -813,7 +828,7 @@ class getid3_id3v2 extends getid3_handler $parsedFrame['encoding'] = $this->TextEncodingNameLookup($parsedFrame['encodingid']); $parsedFrame['data_raw'] = (string) substr($parsedFrame['data'], $frame_offset); - // http://www.getid3.org/phpBB3/viewtopic.php?t=1369 + // https://www.getid3.org/phpBB3/viewtopic.php?t=1369 // "this tag typically contains null terminated strings, which are associated in pairs" // "there are users that use the tag incorrectly" $IPLS_parts = array(); @@ -933,6 +948,7 @@ class getid3_id3v2 extends getid3_handler $parsedFrame['bitsforbytesdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 8, 1)); $parsedFrame['bitsformsdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 9, 1)); $parsedFrame['data'] = substr($parsedFrame['data'], 10); + $deviationbitstream = ''; while ($frame_offset < strlen($parsedFrame['data'])) { $deviationbitstream .= getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1)); } @@ -1416,9 +1432,9 @@ class getid3_id3v2 extends getid3_handler $parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding); if ($id3v2_majorversion == 2) { - $parsedFrame['imagetype'] = $frame_imagetype; + $parsedFrame['imagetype'] = isset($frame_imagetype) ? $frame_imagetype : null; } else { - $parsedFrame['mime'] = $frame_mimetype; + $parsedFrame['mime'] = isset($frame_mimetype) ? $frame_mimetype : null; } $parsedFrame['picturetypeid'] = $frame_picturetype; $parsedFrame['picturetype'] = $this->APICPictureTypeLookup($frame_picturetype); @@ -1430,7 +1446,7 @@ class getid3_id3v2 extends getid3_handler $imageinfo = array(); if ($imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo)) { if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) { - $parsedFrame['image_mime'] = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]); + $parsedFrame['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]); if ($imagechunkcheck[0]) { $parsedFrame['image_width'] = $imagechunkcheck[0]; } @@ -1446,6 +1462,7 @@ class getid3_id3v2 extends getid3_handler unset($parsedFrame['data']); break; } + $dir = ''; if ($this->getid3->option_save_attachments === true) { // great /* @@ -1459,7 +1476,7 @@ class getid3_id3v2 extends getid3_handler */ } elseif (is_string($this->getid3->option_save_attachments)) { $dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR); - if (!is_dir($dir) || !is_writable($dir)) { + if (!is_dir($dir) || !getID3::is_writable($dir)) { // cannot write, skip $this->warning('attachment at '.$frame_offset.' cannot be saved to "'.$dir.'" (not writable)'); unset($parsedFrame['data']); @@ -1469,7 +1486,7 @@ class getid3_id3v2 extends getid3_handler // if we get this far, must be OK if (is_string($this->getid3->option_save_attachments)) { $destination_filename = $dir.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$frame_offset; - if (!file_exists($destination_filename) || is_writable($destination_filename)) { + if (!file_exists($destination_filename) || getID3::is_writable($destination_filename)) { file_put_contents($destination_filename, $parsedFrame['data']); } else { $this->warning('attachment at '.$frame_offset.' cannot be saved to "'.$destination_filename.'" (not writable)'); @@ -2181,11 +2198,20 @@ class getid3_id3v2 extends getid3_handler return true; } - + /** + * @param string $data + * + * @return string + */ public function DeUnsynchronise($data) { return str_replace("\xFF\x00", "\xFF", $data); } + /** + * @param int $index + * + * @return string + */ public function LookupExtendedHeaderRestrictionsTagSizeLimits($index) { static $LookupExtendedHeaderRestrictionsTagSizeLimits = array( 0x00 => 'No more than 128 frames and 1 MB total tag size', @@ -2196,6 +2222,11 @@ class getid3_id3v2 extends getid3_handler return (isset($LookupExtendedHeaderRestrictionsTagSizeLimits[$index]) ? $LookupExtendedHeaderRestrictionsTagSizeLimits[$index] : ''); } + /** + * @param int $index + * + * @return string + */ public function LookupExtendedHeaderRestrictionsTextEncodings($index) { static $LookupExtendedHeaderRestrictionsTextEncodings = array( 0x00 => 'No restrictions', @@ -2204,6 +2235,11 @@ class getid3_id3v2 extends getid3_handler return (isset($LookupExtendedHeaderRestrictionsTextEncodings[$index]) ? $LookupExtendedHeaderRestrictionsTextEncodings[$index] : ''); } + /** + * @param int $index + * + * @return string + */ public function LookupExtendedHeaderRestrictionsTextFieldSize($index) { static $LookupExtendedHeaderRestrictionsTextFieldSize = array( 0x00 => 'No restrictions', @@ -2214,6 +2250,11 @@ class getid3_id3v2 extends getid3_handler return (isset($LookupExtendedHeaderRestrictionsTextFieldSize[$index]) ? $LookupExtendedHeaderRestrictionsTextFieldSize[$index] : ''); } + /** + * @param int $index + * + * @return string + */ public function LookupExtendedHeaderRestrictionsImageEncoding($index) { static $LookupExtendedHeaderRestrictionsImageEncoding = array( 0x00 => 'No restrictions', @@ -2222,6 +2263,11 @@ class getid3_id3v2 extends getid3_handler return (isset($LookupExtendedHeaderRestrictionsImageEncoding[$index]) ? $LookupExtendedHeaderRestrictionsImageEncoding[$index] : ''); } + /** + * @param int $index + * + * @return string + */ public function LookupExtendedHeaderRestrictionsImageSizeSize($index) { static $LookupExtendedHeaderRestrictionsImageSizeSize = array( 0x00 => 'No restrictions', @@ -2232,6 +2278,11 @@ class getid3_id3v2 extends getid3_handler return (isset($LookupExtendedHeaderRestrictionsImageSizeSize[$index]) ? $LookupExtendedHeaderRestrictionsImageSizeSize[$index] : ''); } + /** + * @param string $currencyid + * + * @return string + */ public function LookupCurrencyUnits($currencyid) { $begin = __LINE__; @@ -2428,7 +2479,11 @@ class getid3_id3v2 extends getid3_handler return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-units'); } - + /** + * @param string $currencyid + * + * @return string + */ public function LookupCurrencyCountry($currencyid) { $begin = __LINE__; @@ -2624,8 +2679,12 @@ class getid3_id3v2 extends getid3_handler return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-country'); } - - + /** + * @param string $languagecode + * @param bool $casesensitive + * + * @return string + */ public static function LanguageLookup($languagecode, $casesensitive=false) { if (!$casesensitive) { @@ -3081,7 +3140,11 @@ class getid3_id3v2 extends getid3_handler return getid3_lib::EmbeddedLookup($languagecode, $begin, __LINE__, __FILE__, 'id3v2-languagecode'); } - + /** + * @param int $index + * + * @return string + */ public static function ETCOEventLookup($index) { if (($index >= 0x17) && ($index <= 0xDF)) { return 'reserved for future use'; @@ -3125,6 +3188,11 @@ class getid3_id3v2 extends getid3_handler return (isset($EventLookup[$index]) ? $EventLookup[$index] : ''); } + /** + * @param int $index + * + * @return string + */ public static function SYTLContentTypeLookup($index) { static $SYTLContentTypeLookup = array( 0x00 => 'other', @@ -3141,6 +3209,12 @@ class getid3_id3v2 extends getid3_handler return (isset($SYTLContentTypeLookup[$index]) ? $SYTLContentTypeLookup[$index] : ''); } + /** + * @param int $index + * @param bool $returnarray + * + * @return array|string + */ public static function APICPictureTypeLookup($index, $returnarray=false) { static $APICPictureTypeLookup = array( 0x00 => 'Other', @@ -3171,6 +3245,11 @@ class getid3_id3v2 extends getid3_handler return (isset($APICPictureTypeLookup[$index]) ? $APICPictureTypeLookup[$index] : ''); } + /** + * @param int $index + * + * @return string + */ public static function COMRReceivedAsLookup($index) { static $COMRReceivedAsLookup = array( 0x00 => 'Other', @@ -3187,6 +3266,11 @@ class getid3_id3v2 extends getid3_handler return (isset($COMRReceivedAsLookup[$index]) ? $COMRReceivedAsLookup[$index] : ''); } + /** + * @param int $index + * + * @return string + */ public static function RVA2ChannelTypeLookup($index) { static $RVA2ChannelTypeLookup = array( 0x00 => 'Other', @@ -3203,6 +3287,11 @@ class getid3_id3v2 extends getid3_handler return (isset($RVA2ChannelTypeLookup[$index]) ? $RVA2ChannelTypeLookup[$index] : ''); } + /** + * @param string $framename + * + * @return string + */ public static function FrameNameLongLookup($framename) { $begin = __LINE__; @@ -3354,7 +3443,7 @@ class getid3_id3v2 extends getid3_handler TYER Year UFI Unique file identifier UFID Unique file identifier - ULT Unsychronised lyric/text transcription + ULT Unsynchronised lyric/text transcription USER Terms of use USLT Unsynchronised lyric/text transcription WAF Official audio file webpage @@ -3386,7 +3475,11 @@ class getid3_id3v2 extends getid3_handler // from http://privatewww.essex.ac.uk/~djmrob/replaygain/file_format_id3v2.html } - + /** + * @param string $framename + * + * @return string + */ public static function FrameNameShortLookup($framename) { $begin = __LINE__; @@ -3538,7 +3631,7 @@ class getid3_id3v2 extends getid3_handler TYER year UFI unique_file_identifier UFID unique_file_identifier - ULT unsychronised_lyric + ULT unsynchronised_lyric USER terms_of_use USLT unsynchronised_lyric WAF url_file @@ -3566,6 +3659,11 @@ class getid3_id3v2 extends getid3_handler return getid3_lib::EmbeddedLookup($framename, $begin, __LINE__, __FILE__, 'id3v2-framename_short'); } + /** + * @param string $encoding + * + * @return string + */ public static function TextEncodingTerminatorLookup($encoding) { // http://www.id3.org/id3v2.4.0-structure.txt // Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings: @@ -3579,6 +3677,11 @@ class getid3_id3v2 extends getid3_handler return (isset($TextEncodingTerminatorLookup[$encoding]) ? $TextEncodingTerminatorLookup[$encoding] : "\x00"); } + /** + * @param int $encoding + * + * @return string + */ public static function TextEncodingNameLookup($encoding) { // http://www.id3.org/id3v2.4.0-structure.txt // Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings: @@ -3592,6 +3695,12 @@ class getid3_id3v2 extends getid3_handler return (isset($TextEncodingNameLookup[$encoding]) ? $TextEncodingNameLookup[$encoding] : 'ISO-8859-1'); } + /** + * @param string $framename + * @param int $id3v2majorversion + * + * @return bool|int + */ public static function IsValidID3v2FrameName($framename, $id3v2majorversion) { switch ($id3v2majorversion) { case 2: @@ -3606,6 +3715,13 @@ class getid3_id3v2 extends getid3_handler return false; } + /** + * @param string $numberstring + * @param bool $allowdecimal + * @param bool $allownegative + * + * @return bool + */ 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'))) { @@ -3621,6 +3737,11 @@ class getid3_id3v2 extends getid3_handler return true; } + /** + * @param string $datestamp + * + * @return bool + */ public static function IsValidDateStampString($datestamp) { if (strlen($datestamp) != 8) { return false; @@ -3649,10 +3770,20 @@ class getid3_id3v2 extends getid3_handler return true; } + /** + * @param int $majorversion + * + * @return int + */ public static function ID3v2HeaderLength($majorversion) { return (($majorversion == 2) ? 6 : 10); } + /** + * @param string $frame_name + * + * @return string|false + */ public static function ID3v22iTunesBrokenFrameName($frame_name) { // iTunes (multiple versions) has been known to write ID3v2.3 style frames // but use ID3v2.2 frame names, right-padded using either [space] or [null] diff --git a/www/plugins-dist/medias/lib/getid3/module.tag.lyrics3.php b/www/plugins-dist/medias/lib/getid3/module.tag.lyrics3.php index 1645396b..80e81658 100644 --- a/www/plugins-dist/medias/lib/getid3/module.tag.lyrics3.php +++ b/www/plugins-dist/medias/lib/getid3/module.tag.lyrics3.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// /// // // module.tag.lyrics3.php // @@ -17,7 +17,9 @@ class getid3_lyrics3 extends getid3_handler { - + /** + * @return bool + */ public function Analyze() { $info = &$this->getid3->info; @@ -61,7 +63,7 @@ class getid3_lyrics3 extends getid3_handler // Lyrics3v2, no ID3v1, no APE - $lyrics3size = strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' + $lyrics3size = (int) strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200' $lyrics3offset = $info['filesize'] - $lyrics3size; $lyrics3version = 2; @@ -96,7 +98,7 @@ class getid3_lyrics3 extends getid3_handler } - if (isset($lyrics3offset)) { + if (isset($lyrics3offset) && isset($lyrics3version) && isset($lyrics3size)) { $info['avdataend'] = $lyrics3offset; $this->getLyrics3Data($lyrics3offset, $lyrics3version, $lyrics3size); @@ -126,6 +128,13 @@ class getid3_lyrics3 extends getid3_handler return true; } + /** + * @param int $endoffset + * @param int $version + * @param int $length + * + * @return bool + */ public function getLyrics3Data($endoffset, $version, $length) { // http://www.volweb.cz/str/tags.htm @@ -142,6 +151,8 @@ class getid3_lyrics3 extends getid3_handler } $rawdata = $this->fread($length); + $ParsedLyrics3 = array(); + $ParsedLyrics3['raw']['lyrics3version'] = $version; $ParsedLyrics3['raw']['lyrics3tagsize'] = $length; $ParsedLyrics3['tag_offset_start'] = $endoffset; @@ -250,6 +261,11 @@ class getid3_lyrics3 extends getid3_handler return true; } + /** + * @param string $rawtimestamp + * + * @return int|false + */ public function Lyrics3Timestamp2Seconds($rawtimestamp) { if (preg_match('#^\\[([0-9]{2}):([0-9]{2})\\]$#', $rawtimestamp, $regs)) { return (int) (($regs[1] * 60) + $regs[2]); @@ -257,8 +273,14 @@ class getid3_lyrics3 extends getid3_handler return false; } + /** + * @param array $Lyrics3data + * + * @return bool + */ public function Lyrics3LyricsTimestampParse(&$Lyrics3data) { $lyricsarray = explode("\r\n", $Lyrics3data['raw']['LYR']); + $notimestamplyricsarray = array(); foreach ($lyricsarray as $key => $lyricline) { $regs = array(); unset($thislinetimestamps); @@ -287,6 +309,11 @@ class getid3_lyrics3 extends getid3_handler return true; } + /** + * @param string $char + * + * @return bool|null + */ public function IntString2Bool($char) { if ($char == '1') { return true; diff --git a/www/plugins-dist/medias/lib/getid3/module.tag.xmp.php b/www/plugins-dist/medias/lib/getid3/module.tag.xmp.php index 40dd8bd8..a976ef8e 100644 --- a/www/plugins-dist/medias/lib/getid3/module.tag.xmp.php +++ b/www/plugins-dist/medias/lib/getid3/module.tag.xmp.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // module.tag.xmp.php // @@ -81,8 +81,8 @@ class Image_XMP * Reads all the JPEG header segments from an JPEG image file into an array * * @param string $filename - the filename of the JPEG file to read - * @return array $headerdata - Array of JPEG header segments - * @return boolean FALSE - if headers could not be read + * @return array|boolean $headerdata - Array of JPEG header segments, + * FALSE - if headers could not be read */ public function _get_jpeg_header_data($filename) { @@ -124,6 +124,7 @@ class Image_XMP // Flag that we havent yet hit the compressed image data $hit_compressed_image_data = false; + $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 @@ -191,8 +192,8 @@ class Image_XMP * Retrieves XMP information from an APP1 JPEG segment and returns the raw XML text as a string. * * @param string $filename - the filename of the JPEG file to read - * @return string $xmp_data - the string of raw XML text - * @return boolean FALSE - if an APP 1 XMP segment could not be found, or if an error occured + * @return string|boolean $xmp_data - the string of raw XML text, + * FALSE - if an APP 1 XMP segment could not be found, or if an error occured */ public function _get_XMP_text($filename) { @@ -212,7 +213,7 @@ class Image_XMP // Return the XMP text $xmp_data = substr($jpeg_header_data[$i]['SegData'], 29); - return trim($xmp_data); // trim() should not be neccesary, but some files found in the wild with null-terminated block (known samples from Apple Aperture) causes problems elsewhere (see http://www.getid3.org/phpBB3/viewtopic.php?f=4&t=1153) + return trim($xmp_data); // trim() should not be neccesary, but some files found in the wild with null-terminated block (known samples from Apple Aperture) causes problems elsewhere (see https://www.getid3.org/phpBB3/viewtopic.php?f=4&t=1153) } } } @@ -223,9 +224,9 @@ class Image_XMP * Parses a string containing XMP data (XML), and returns an array * which contains all the XMP (XML) information. * - * @param string $xml_text - a string containing the XMP data (XML) to be parsed - * @return array $xmp_array - an array containing all xmp details retrieved. - * @return boolean FALSE - couldn't parse the XMP data + * @param string $xmltext - a string containing the XMP data (XML) to be parsed + * @return array|boolean $xmp_array - an array containing all xmp details retrieved, + * FALSE - couldn't parse the XMP data. */ public function read_XMP_array_from_text($xmltext) { @@ -311,10 +312,12 @@ class Image_XMP } } } + break; case 'cdata': case 'close': break; } + break; case 'rdf:ID': case 'rdf:nodeID': @@ -397,7 +400,7 @@ class Image_XMP /** * Constructor * - * @param string - Name of the image file to access and extract XMP information from. + * @param string $sFilename - Name of the image file to access and extract XMP information from. */ public function __construct($sFilename) { @@ -409,8 +412,11 @@ class Image_XMP $xmp_data = $this->_get_XMP_text($sFilename); if ($xmp_data) { - $this->_aXMP = $this->read_XMP_array_from_text($xmp_data); - $this->_bXMPParse = true; + $aXMP = $this->read_XMP_array_from_text($xmp_data); + if ($aXMP !== false) { + $this->_aXMP = (array) $aXMP; + $this->_bXMPParse = true; + } } } } diff --git a/www/plugins-dist/medias/lib/getid3/write.apetag.php b/www/plugins-dist/medias/lib/getid3/write.apetag.php index d6044b29..7fc507c2 100644 --- a/www/plugins-dist/medias/lib/getid3/write.apetag.php +++ b/www/plugins-dist/medias/lib/getid3/write.apetag.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // write.apetag.php // @@ -19,17 +19,43 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE class getid3_write_apetag { - + /** + * @var string + */ public $filename; + + /** + * @var array + */ public $tag_data; - public $always_preserve_replaygain = true; // ReplayGain / MP3gain tags will be copied from old tag even if not passed in data - public $warnings = array(); // any non-critical errors will be stored here - public $errors = array(); // any critical errors will be stored here + + /** + * ReplayGain / MP3gain tags will be copied from old tag even if not passed in data. + * + * @var bool + */ + public $always_preserve_replaygain = true; + + /** + * Any non-critical errors will be stored here. + * + * @var array + */ + public $warnings = array(); + + /** + * Any critical errors will be stored here. + * + * @var array + */ + public $errors = array(); public function __construct() { - return true; } + /** + * @return bool + */ public function WriteAPEtag() { // NOTE: All data passed to this function must be UTF-8 format @@ -57,7 +83,7 @@ class getid3_write_apetag } if ($APEtag = $this->GenerateAPEtag()) { - if (is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { $oldignoreuserabort = ignore_user_abort(true); flock($fp, LOCK_EX); @@ -92,11 +118,14 @@ class getid3_write_apetag return false; } + /** + * @return bool + */ public function DeleteAPEtag() { $getID3 = new getID3; $ThisFileInfo = $getID3->analyze($this->filename); if (isset($ThisFileInfo['ape']['tag_offset_start']) && isset($ThisFileInfo['ape']['tag_offset_end'])) { - if (is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { flock($fp, LOCK_EX); $oldignoreuserabort = ignore_user_abort(true); @@ -125,7 +154,9 @@ class getid3_write_apetag return true; } - + /** + * @return string|false + */ public function GenerateAPEtag() { // NOTE: All data passed to this function must be UTF-8 format @@ -160,6 +191,12 @@ class getid3_write_apetag return $this->GenerateAPEtagHeaderFooter($items, true).implode('', $items).$this->GenerateAPEtagHeaderFooter($items, false); } + /** + * @param array $items + * @param bool $isheader + * + * @return string + */ public function GenerateAPEtagHeaderFooter(&$items, $isheader=false) { $tagdatalength = 0; foreach ($items as $itemdata) { @@ -176,6 +213,15 @@ class getid3_write_apetag return $APEheader; } + /** + * @param bool $header + * @param bool $footer + * @param bool $isheader + * @param int $encodingid + * @param bool $readonly + * + * @return string + */ public function GenerateAPEtagFlags($header=true, $footer=true, $isheader=false, $encodingid=0, $readonly=false) { $APEtagFlags = array_fill(0, 4, 0); if ($header) { @@ -201,6 +247,11 @@ class getid3_write_apetag return chr($APEtagFlags[3]).chr($APEtagFlags[2]).chr($APEtagFlags[1]).chr($APEtagFlags[0]); } + /** + * @param string $itemkey + * + * @return string + */ public function CleanAPEtagItemKey($itemkey) { $itemkey = preg_replace("#[^\x20-\x7E]#i", '', $itemkey); diff --git a/www/plugins-dist/medias/lib/getid3/write.id3v1.php b/www/plugins-dist/medias/lib/getid3/write.id3v1.php index 4fa6a6c3..6f84867d 100644 --- a/www/plugins-dist/medias/lib/getid3/write.id3v1.php +++ b/www/plugins-dist/medias/lib/getid3/write.id3v1.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // write.id3v1.php // @@ -18,19 +18,44 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v1.php', __FILE_ class getid3_write_id3v1 { + /** + * @var string + */ public $filename; + + /** + * @var int + */ public $filesize; + + /** + * @var array + */ public $tag_data; - public $warnings = array(); // any non-critical errors will be stored here - public $errors = array(); // any critical errors will be stored here + + /** + * Any non-critical errors will be stored here. + * + * @var array + */ + public $warnings = array(); + + /** + * Any critical errors will be stored here. + * + * @var array + */ + public $errors = array(); public function __construct() { - return true; } + /** + * @return bool + */ public function WriteID3v1() { // File MUST be writeable - CHMOD(646) at least - if (!empty($this->filename) && is_readable($this->filename) && is_writable($this->filename) && is_file($this->filename)) { + if (!empty($this->filename) && is_readable($this->filename) && getID3::is_writable($this->filename) && is_file($this->filename)) { $this->setRealFileSize(); if (($this->filesize <= 0) || !getid3_lib::intValueSupported($this->filesize)) { $this->errors[] = 'Unable to WriteID3v1('.$this->filename.') because filesize ('.$this->filesize.') is larger than '.round(PHP_INT_MAX / 1073741824).'GB'; @@ -66,6 +91,9 @@ class getid3_write_id3v1 return false; } + /** + * @return bool + */ public function FixID3v1Padding() { // ID3v1 data is supposed to be padded with NULL characters, but some taggers incorrectly use spaces // This function rewrites the ID3v1 tag with correct padding @@ -79,6 +107,7 @@ class getid3_write_id3v1 $getID3->option_tag_id3v1 = true; $ThisFileInfo = $getID3->analyze($this->filename); if (isset($ThisFileInfo['tags']['id3v1'])) { + $id3v1data = array(); foreach ($ThisFileInfo['tags']['id3v1'] as $key => $value) { $id3v1data[$key] = implode(',', $value); } @@ -88,9 +117,12 @@ class getid3_write_id3v1 return false; } + /** + * @return bool + */ public function RemoveID3v1() { // File MUST be writeable - CHMOD(646) at least - if (!empty($this->filename) && is_readable($this->filename) && is_writable($this->filename) && is_file($this->filename)) { + if (!empty($this->filename) && is_readable($this->filename) && getID3::is_writable($this->filename) && is_file($this->filename)) { $this->setRealFileSize(); if (($this->filesize <= 0) || !getid3_lib::intValueSupported($this->filesize)) { $this->errors[] = 'Unable to RemoveID3v1('.$this->filename.') because filesize ('.$this->filesize.') is larger than '.round(PHP_INT_MAX / 1073741824).'GB'; @@ -116,6 +148,9 @@ class getid3_write_id3v1 return false; } + /** + * @return bool + */ public function setRealFileSize() { if (PHP_INT_MAX > 2147483647) { $this->filesize = filesize($this->filename); diff --git a/www/plugins-dist/medias/lib/getid3/write.id3v2.php b/www/plugins-dist/medias/lib/getid3/write.id3v2.php index 17138db8..fae45d29 100644 --- a/www/plugins-dist/medias/lib/getid3/write.id3v2.php +++ b/www/plugins-dist/medias/lib/getid3/write.id3v2.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// /// // // write.id3v2.php // @@ -18,33 +18,96 @@ getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE_ class getid3_write_id3v2 { + /** + * @var string + */ public $filename; + + /** + * @var array + */ public $tag_data; - public $fread_buffer_size = 32768; // read buffer size in bytes - public $paddedlength = 4096; // minimum length of ID3v2 tag in bytes - public $majorversion = 3; // ID3v2 major version (2, 3 (recommended), 4) - public $minorversion = 0; // ID3v2 minor version - always 0 - public $merge_existing_data = false; // if true, merge new data with existing tags; if false, delete old tag data and only write new tags - public $id3v2_default_encodingid = 0; // default text encoding (ISO-8859-1) if not explicitly passed - public $id3v2_use_unsynchronisation = false; // the specs say it should be TRUE, but most other ID3v2-aware programs are broken if unsynchronization is used, so by default don't use it. - public $warnings = array(); // any non-critical errors will be stored here - public $errors = array(); // any critical errors will be stored here + + /** + * Read buffer size in bytes. + * + * @var int + */ + public $fread_buffer_size = 32768; + + /** + * Minimum length of ID3v2 tag in bytes. + * + * @var int + */ + public $paddedlength = 4096; + + /** + * ID3v2 major version (2, 3 (recommended), 4). + * + * @var int + */ + public $majorversion = 3; + + /** + * ID3v2 minor version - always 0. + * + * @var int + */ + public $minorversion = 0; + + /** + * If true, merge new data with existing tags; if false, delete old tag data and only write new tags. + * + * @var bool + */ + public $merge_existing_data = false; + + /** + * Default text encoding (ISO-8859-1) if not explicitly passed. + * + * @var int + */ + public $id3v2_default_encodingid = 0; + + /** + * The specs say it should be TRUE, but most other ID3v2-aware programs are broken if unsynchronization is used, + * so by default don't use it. + * + * @var bool + */ + public $id3v2_use_unsynchronisation = false; + + /** + * Any non-critical errors will be stored here. + * + * @var array + */ + public $warnings = array(); + + /** + * Any critical errors will be stored here. + * + * @var array + */ + public $errors = array(); public function __construct() { - return true; } + /** + * @return bool + */ public function WriteID3v2() { // File MUST be writeable - CHMOD(646) at least. It's best if the // directory is also writeable, because that method is both faster and less susceptible to errors. - if (!empty($this->filename) && (is_writeable($this->filename) || (!file_exists($this->filename) && is_writeable(dirname($this->filename))))) { + if (!empty($this->filename) && (getID3::is_writable($this->filename) || (!file_exists($this->filename) && getID3::is_writable(dirname($this->filename))))) { // Initialize getID3 engine $getID3 = new getID3; $OldThisFileInfo = $getID3->analyze($this->filename); if (!getid3_lib::intValueSupported($OldThisFileInfo['filesize'])) { $this->errors[] = 'Unable to write ID3v2 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB'; - fclose($fp_source); return false; } if ($this->merge_existing_data) { @@ -57,12 +120,12 @@ class getid3_write_id3v2 if ($NewID3v2Tag = $this->GenerateID3v2Tag()) { - if (file_exists($this->filename) && is_writeable($this->filename) && isset($OldThisFileInfo['id3v2']['headerlength']) && ($OldThisFileInfo['id3v2']['headerlength'] == strlen($NewID3v2Tag))) { + if (file_exists($this->filename) && getID3::is_writable($this->filename) && isset($OldThisFileInfo['id3v2']['headerlength']) && ($OldThisFileInfo['id3v2']['headerlength'] == strlen($NewID3v2Tag))) { // best and fastest method - insert-overwrite existing tag (padded to length of old tag if neccesary) if (file_exists($this->filename)) { - if (is_readable($this->filename) && is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'r+b'))) { + if (is_readable($this->filename) && getID3::is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'r+b'))) { rewind($fp); fwrite($fp, $NewID3v2Tag, strlen($NewID3v2Tag)); fclose($fp); @@ -72,7 +135,7 @@ class getid3_write_id3v2 } else { - if (is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'wb'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'wb'))) { rewind($fp); fwrite($fp, $NewID3v2Tag, strlen($NewID3v2Tag)); fclose($fp); @@ -86,7 +149,7 @@ class getid3_write_id3v2 if ($tempfilename = tempnam(GETID3_TEMP_DIR, 'getID3')) { if (is_readable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'rb'))) { - if (is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { + if (getID3::is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { fwrite($fp_temp, $NewID3v2Tag, strlen($NewID3v2Tag)); @@ -134,10 +197,13 @@ class getid3_write_id3v2 return false; } + /** + * @return bool + */ public function RemoveID3v2() { // File MUST be writeable - CHMOD(646) at least. It's best if the // directory is also writeable, because that method is both faster and less susceptible to errors. - if (is_writeable(dirname($this->filename))) { + if (getID3::is_writable(dirname($this->filename))) { // preferred method - only one copying operation, minimal chance of corrupting // original file if script is interrupted, but required directory to be writeable @@ -155,7 +221,7 @@ class getid3_write_id3v2 if ($OldThisFileInfo['avdataoffset'] !== false) { fseek($fp_source, $OldThisFileInfo['avdataoffset']); } - if (is_writable($this->filename) && is_file($this->filename) && ($fp_temp = fopen($this->filename.'getid3tmp', 'w+b'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp_temp = fopen($this->filename.'getid3tmp', 'w+b'))) { while ($buffer = fread($fp_source, $this->fread_buffer_size)) { fwrite($fp_temp, $buffer, strlen($buffer)); } @@ -172,7 +238,7 @@ class getid3_write_id3v2 } rename($this->filename.'getid3tmp', $this->filename); - } elseif (is_writable($this->filename)) { + } elseif (getID3::is_writable($this->filename)) { // less desirable alternate method - double-copies the file, overwrites original file // and could corrupt source file if the script is interrupted or an error occurs. @@ -195,7 +261,7 @@ class getid3_write_id3v2 fwrite($fp_temp, $buffer, strlen($buffer)); } fclose($fp_source); - if (is_writable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'wb'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'wb'))) { rewind($fp_temp); while ($buffer = fread($fp_temp, $this->fread_buffer_size)) { fwrite($fp_source, $buffer, strlen($buffer)); @@ -225,8 +291,13 @@ class getid3_write_id3v2 return true; } - + /** + * @param array $flags + * + * @return string|false + */ public function GenerateID3v2TagFlags($flags) { + $flag = null; switch ($this->majorversion) { case 4: // %abcd0000 @@ -259,9 +330,22 @@ class getid3_write_id3v2 return chr(bindec($flag)); } - + /** + * @param bool $TagAlter + * @param bool $FileAlter + * @param bool $ReadOnly + * @param bool $Compression + * @param bool $Encryption + * @param bool $GroupingIdentity + * @param bool $Unsynchronisation + * @param bool $DataLengthIndicator + * + * @return string|false + */ public function GenerateID3v2FrameFlags($TagAlter=false, $FileAlter=false, $ReadOnly=false, $Compression=false, $Encryption=false, $GroupingIdentity=false, $Unsynchronisation=false, $DataLengthIndicator=false) { - switch ($this->majorversion) { + $flag1 = null; + $flag2 = null; + switch ($this->majorversion) { case 4: // %0abc0000 %0h00kmnp $flag1 = '0'; @@ -300,6 +384,12 @@ class getid3_write_id3v2 return chr(bindec($flag1)).chr(bindec($flag2)); } + /** + * @param string $frame_name + * @param array $source_data_array + * + * @return string|false + */ public function GenerateID3v2FrameData($frame_name, $source_data_array) { if (!getid3_id3v2::IsValidID3v2FrameName($frame_name, $this->majorversion)) { return false; @@ -331,7 +421,7 @@ class getid3_write_id3v2 // Description $00 (00) // Value $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid); - if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'], $this->majorversion)) { + if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) { $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion; } else { $framedata .= chr($source_data_array['encodingid']); @@ -346,9 +436,9 @@ class getid3_write_id3v2 // Description $00 (00) // URL $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid); - if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'], $this->majorversion)) { + if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) { $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion; - } elseif (!isset($source_data_array['data']) || !$this->IsValidURL($source_data_array['data'], false, false)) { + } elseif (!isset($source_data_array['data']) || !$this->IsValidURL($source_data_array['data'], false)) { //$this->errors[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')'; // probably should be an error, need to rewrite IsValidURL() to handle other encodings $this->warnings[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')'; @@ -364,7 +454,7 @@ class getid3_write_id3v2 // Text encoding $xx // People list strings $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid); - if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'], $this->majorversion)) { + if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) { $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].') for ID3v2.'.$this->majorversion; } else { $framedata .= chr($source_data_array['encodingid']); @@ -397,13 +487,14 @@ class getid3_write_id3v2 if (!$this->ID3v2IsValidETCOevent($val['typeid'])) { $this->errors[] = 'Invalid Event Type byte in '.$frame_name.' ('.$val['typeid'].')'; } elseif (($key != 'timestampformat') && ($key != 'flags')) { - if (($val['timestamp'] > 0) && ($previousETCOtimestamp >= $val['timestamp'])) { + if (($val['timestamp'] > 0) && isset($previousETCOtimestamp) && ($previousETCOtimestamp >= $val['timestamp'])) { // The 'Time stamp' is set to zero if directly at the beginning of the sound // or after the previous event. All events MUST be sorted in chronological order. $this->errors[] = 'Out-of-order timestamp in '.$frame_name.' ('.$val['timestamp'].') for Event Type ('.$val['typeid'].')'; } else { $framedata .= chr($val['typeid']); $framedata .= getid3_lib::BigEndian2String($val['timestamp'], 4, false); + $previousETCOtimestamp = $val['timestamp']; } } } @@ -453,6 +544,7 @@ class getid3_write_id3v2 } else { $this->errors[] = 'Invalid Bits For Milliseconds Deviation in '.$frame_name.' ('.$source_data_array['bitsformsdeviation'].')'; } + $unwrittenbitstream = ''; foreach ($source_data_array as $key => $val) { if (($key != 'framesbetweenreferences') && ($key != 'bytesbetweenreferences') && ($key != 'msbetweenreferences') && ($key != 'bitsforbytesdeviation') && ($key != 'bitsformsdeviation') && ($key != 'flags')) { $unwrittenbitstream .= str_pad(getid3_lib::Dec2Bin($val['bytedeviation']), $source_data_array['bitsforbytesdeviation'], '0', STR_PAD_LEFT); @@ -617,7 +709,7 @@ class getid3_write_id3v2 if (!$this->IsWithinBitRange($source_data_array['bitsvolume'], 8, false)) { $this->errors[] = 'Invalid Bits For Volume Description byte in '.$frame_name.' ('.$source_data_array['bitsvolume'].') (range = 1 to 255)'; } else { - $incdecflag .= '00'; + $incdecflag = '00'; $incdecflag .= $source_data_array['incdec']['right'] ? '1' : '0'; // a - Relative volume change, right $incdecflag .= $source_data_array['incdec']['left'] ? '1' : '0'; // b - Relative volume change, left $incdecflag .= $source_data_array['incdec']['rightrear'] ? '1' : '0'; // c - Relative volume change, right back @@ -762,7 +854,7 @@ class getid3_write_id3v2 $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']))) { $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, false))) { + } elseif (($source_data_array['mime'] == '-->') && (!$this->IsValidURL($source_data_array['data'], false))) { //$this->errors[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')'; // probably should be an error, need to rewrite IsValidURL() to handle other encodings $this->warnings[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')'; @@ -835,7 +927,7 @@ class getid3_write_id3v2 $this->errors[] = 'Invalid Offset To Next Tag in '.$frame_name; } else { $framedata .= getid3_lib::BigEndian2String($source_data_array['buffersize'], 3, false); - $flag .= '0000000'; + $flag = '0000000'; $flag .= $source_data_array['flags']['embededinfo'] ? '1' : '0'; $framedata .= chr(bindec($flag)); $framedata .= getid3_lib::BigEndian2String($source_data_array['nexttagoffset'], 4, false); @@ -867,7 +959,7 @@ class getid3_write_id3v2 // ID and additional data if (!getid3_id3v2::IsValidID3v2FrameName($source_data_array['frameid'], $this->majorversion)) { $this->errors[] = 'Invalid Frame Identifier in '.$frame_name.' ('.$source_data_array['frameid'].')'; - } elseif (!$this->IsValidURL($source_data_array['data'], true, false)) { + } elseif (!$this->IsValidURL($source_data_array['data'], true)) { //$this->errors[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')'; // probably should be an error, need to rewrite IsValidURL() to handle other encodings $this->warnings[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')'; @@ -914,6 +1006,7 @@ class getid3_write_id3v2 } else { $this->errors[] = $source_data_array['frameid'].' is not a valid Frame Identifier in '.$frame_name.' (in ID3v2.'.$this->majorversion.')'; } + break; default: if ((substr($source_data_array['frameid'], 0, 1) == 'T') || (substr($source_data_array['frameid'], 0, 1) == 'W')) { @@ -966,9 +1059,9 @@ class getid3_write_id3v2 $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid); if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) { $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].')'; - } elseif (!$this->IsANumber($source_data_array['pricepaid']['value'], false)) { + } elseif (!getid3_id3v2::IsANumber($source_data_array['pricepaid']['value'], false)) { $this->errors[] = 'Invalid Price Paid in '.$frame_name.' ('.$source_data_array['pricepaid']['value'].')'; - } elseif (!$this->IsValidDateStampString($source_data_array['purchasedate'])) { + } elseif (!getid3_id3v2::IsValidDateStampString($source_data_array['purchasedate'])) { $this->errors[] = 'Invalid Date Of Purchase in '.$frame_name.' ('.$source_data_array['purchasedate'].') (format = YYYYMMDD)'; } else { $framedata .= chr($source_data_array['encodingid']); @@ -992,9 +1085,9 @@ class getid3_write_id3v2 $source_data_array['encodingid'] = (isset($source_data_array['encodingid']) ? $source_data_array['encodingid'] : $this->id3v2_default_encodingid); if (!$this->ID3v2IsValidTextEncoding($source_data_array['encodingid'])) { $this->errors[] = 'Invalid Text Encoding in '.$frame_name.' ('.$source_data_array['encodingid'].')'; - } elseif (!$this->IsValidDateStampString($source_data_array['pricevaliduntil'])) { + } elseif (!getid3_id3v2::IsValidDateStampString($source_data_array['pricevaliduntil'])) { $this->errors[] = 'Invalid Valid Until date in '.$frame_name.' ('.$source_data_array['pricevaliduntil'].') (format = YYYYMMDD)'; - } elseif (!$this->IsValidURL($source_data_array['contacturl'], false, true)) { + } elseif (!$this->IsValidURL($source_data_array['contacturl'], false)) { $this->errors[] = 'Invalid Contact URL in '.$frame_name.' ('.$source_data_array['contacturl'].') (allowed schemes: http, https, ftp, mailto)'; } elseif (!$this->ID3v2IsValidCOMRreceivedAs($source_data_array['receivedasid'])) { $this->errors[] = 'Invalid Received As byte in '.$frame_name.' ('.$source_data_array['contacturl'].') (range = 0 to 8)'; @@ -1003,6 +1096,7 @@ class getid3_write_id3v2 } 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'])) { $pricestrings[] = $key.$val['value']; @@ -1155,7 +1249,7 @@ class getid3_write_id3v2 } elseif ($frame_name{0} == 'W') { // 4.3. W??? URL link frames // URL - if (!$this->IsValidURL($source_data_array['data'], false, false)) { + if (!$this->IsValidURL($source_data_array['data'], false)) { //$this->errors[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')'; // probably should be an error, need to rewrite IsValidURL() to handle other encodings $this->warnings[] = 'Invalid URL in '.$frame_name.' ('.$source_data_array['data'].')'; @@ -1174,6 +1268,12 @@ class getid3_write_id3v2 return $framedata; } + /** + * @param string|null $frame_name + * @param array $source_data_array + * + * @return bool + */ public function ID3v2FrameIsAllowed($frame_name, $source_data_array) { static $PreviousFrames = array(); @@ -1530,6 +1630,11 @@ class getid3_write_id3v2 return true; } + /** + * @param bool $noerrorsonly + * + * @return string|false + */ public function GenerateID3v2Tag($noerrorsonly=true) { $this->ID3v2FrameIsAllowed(null, ''); // clear static array in case this isn't the first call to $this->GenerateID3v2Tag() @@ -1644,20 +1749,31 @@ class getid3_write_id3v2 return false; } + /** + * @param string $pricestring + * + * @return bool + */ public function ID3v2IsValidPriceString($pricestring) { if (getid3_id3v2::LanguageLookup(substr($pricestring, 0, 3), true) == '') { return false; - } elseif (!$this->IsANumber(substr($pricestring, 3), true)) { + } elseif (!getid3_id3v2::IsANumber(substr($pricestring, 3), true)) { return false; } return true; } + /** + * @param string $framename + * + * @return bool + */ public function ID3v2FrameFlagsLookupTagAlter($framename) { // unfinished switch ($framename) { case 'RGAD': $allow = true; + break; default: $allow = false; break; @@ -1665,6 +1781,11 @@ class getid3_write_id3v2 return $allow; } + /** + * @param string $framename + * + * @return bool + */ public function ID3v2FrameFlagsLookupFileAlter($framename) { // unfinished switch ($framename) { @@ -1678,6 +1799,11 @@ class getid3_write_id3v2 } } + /** + * @param int $eventid + * + * @return bool + */ public function ID3v2IsValidETCOevent($eventid) { if (($eventid < 0) || ($eventid > 0xFF)) { // outside range of 1 byte @@ -1698,6 +1824,11 @@ class getid3_write_id3v2 return true; } + /** + * @param int $contenttype + * + * @return bool + */ public function ID3v2IsValidSYLTtype($contenttype) { if (($contenttype >= 0) && ($contenttype <= 8) && ($this->majorversion == 4)) { return true; @@ -1707,6 +1838,11 @@ class getid3_write_id3v2 return false; } + /** + * @param int $channeltype + * + * @return bool + */ public function ID3v2IsValidRVA2channeltype($channeltype) { if (($channeltype >= 0) && ($channeltype <= 8) && ($this->majorversion == 4)) { return true; @@ -1714,6 +1850,11 @@ class getid3_write_id3v2 return false; } + /** + * @param int $picturetype + * + * @return bool + */ public function ID3v2IsValidAPICpicturetype($picturetype) { if (($picturetype >= 0) && ($picturetype <= 0x14) && ($this->majorversion >= 2) && ($this->majorversion <= 4)) { return true; @@ -1721,6 +1862,11 @@ class getid3_write_id3v2 return false; } + /** + * @param int|string $imageformat + * + * @return bool + */ public function ID3v2IsValidAPICimageformat($imageformat) { if ($imageformat == '-->') { return true; @@ -1736,6 +1882,11 @@ class getid3_write_id3v2 return false; } + /** + * @param int $receivedas + * + * @return bool + */ public function ID3v2IsValidCOMRreceivedAs($receivedas) { if (($this->majorversion >= 3) && ($receivedas >= 0) && ($receivedas <= 8)) { return true; @@ -1743,6 +1894,11 @@ class getid3_write_id3v2 return false; } + /** + * @param int $RGADname + * + * @return bool + */ public static function ID3v2IsValidRGADname($RGADname) { if (($RGADname >= 0) && ($RGADname <= 2)) { return true; @@ -1750,6 +1906,11 @@ class getid3_write_id3v2 return false; } + /** + * @param int $RGADoriginator + * + * @return bool + */ public static function ID3v2IsValidRGADoriginator($RGADoriginator) { if (($RGADoriginator >= 0) && ($RGADoriginator <= 3)) { return true; @@ -1757,6 +1918,11 @@ class getid3_write_id3v2 return false; } + /** + * @param int $textencodingbyte + * + * @return bool + */ public function ID3v2IsValidTextEncoding($textencodingbyte) { // 0 = ISO-8859-1 // 1 = UTF-16 with BOM @@ -1770,6 +1936,11 @@ class getid3_write_id3v2 return isset($ID3v2IsValidTextEncoding_cache[$this->majorversion][$textencodingbyte]); } + /** + * @param string $data + * + * @return string + */ public static function Unsynchronise($data) { // Whenever a false synchronisation is found within the tag, one zeroed // byte is inserted after the first false synchronisation byte. The @@ -1800,6 +1971,11 @@ class getid3_write_id3v2 return $unsyncheddata; } + /** + * @param mixed $var + * + * @return bool + */ public function is_hash($var) { // written by dev-nullØchristophe*vg // taken from http://www.php.net/manual/en/function.array-merge-recursive.php @@ -1815,6 +1991,12 @@ class getid3_write_id3v2 return false; } + /** + * @param mixed $arr1 + * @param mixed $arr2 + * + * @return array + */ public function array_join_merge($arr1, $arr2) { // written by dev-nullØchristophe*vg // taken from http://www.php.net/manual/en/function.array-merge-recursive.php @@ -1839,10 +2021,22 @@ class getid3_write_id3v2 } } + /** + * @param string $mimestring + * + * @return false|int + */ public static function IsValidMIMEstring($mimestring) { return preg_match('#^.+/.+$#', $mimestring); } + /** + * @param int $number + * @param int $maxbits + * @param bool $signed + * + * @return bool + */ public static function IsWithinBitRange($number, $maxbits, $signed=false) { if ($signed) { if (($number > (0 - pow(2, $maxbits - 1))) && ($number <= pow(2, $maxbits - 1))) { @@ -1856,6 +2050,11 @@ class getid3_write_id3v2 return false; } + /** + * @param string $email + * + * @return false|int|mixed + */ public static function IsValidEmail($email) { if (function_exists('filter_var')) { return filter_var($email, FILTER_VALIDATE_EMAIL); @@ -1864,6 +2063,12 @@ class getid3_write_id3v2 return preg_match('#^[^ ]+@[a-z\\-\\.]+\\.[a-z]{2,}$#', $email); } + /** + * @param string $url + * @param bool $allowUserPass + * + * @return bool + */ public static function IsValidURL($url, $allowUserPass=false) { if ($url == '') { return false; @@ -1876,7 +2081,7 @@ class getid3_write_id3v2 } } // 2016-06-08: relax URL checking to avoid falsely rejecting valid URLs, leave URL validation to the user - // http://www.getid3.org/phpBB3/viewtopic.php?t=1926 + // https://www.getid3.org/phpBB3/viewtopic.php?t=1926 return true; /* if ($parts = $this->safe_parse_url($url)) { @@ -1900,6 +2105,11 @@ class getid3_write_id3v2 */ } + /** + * @param string $url + * + * @return array + */ public static function safe_parse_url($url) { $parts = @parse_url($url); $parts['scheme'] = (isset($parts['scheme']) ? $parts['scheme'] : ''); @@ -1911,6 +2121,12 @@ class getid3_write_id3v2 return $parts; } + /** + * @param int $majorversion + * @param string $long_description + * + * @return string + */ public static function ID3v2ShortFrameNameLookup($majorversion, $long_description) { $long_description = str_replace(' ', '_', strtolower(trim($long_description))); static $ID3v2ShortFrameNameLookup = array(); @@ -1979,7 +2195,7 @@ class getid3_write_id3v2 $ID3v2ShortFrameNameLookup[2]['text'] = 'TXX'; $ID3v2ShortFrameNameLookup[2]['year'] = 'TYE'; $ID3v2ShortFrameNameLookup[2]['unique_file_identifier'] = 'UFI'; - $ID3v2ShortFrameNameLookup[2]['unsychronised_lyric'] = 'ULT'; + $ID3v2ShortFrameNameLookup[2]['unsynchronised_lyric'] = 'ULT'; $ID3v2ShortFrameNameLookup[2]['url_file'] = 'WAF'; $ID3v2ShortFrameNameLookup[2]['url_artist'] = 'WAR'; $ID3v2ShortFrameNameLookup[2]['url_source'] = 'WAS'; @@ -2054,7 +2270,7 @@ class getid3_write_id3v2 $ID3v2ShortFrameNameLookup[3]['text'] = 'TXXX'; $ID3v2ShortFrameNameLookup[3]['unique_file_identifier'] = 'UFID'; $ID3v2ShortFrameNameLookup[3]['terms_of_use'] = 'USER'; - $ID3v2ShortFrameNameLookup[3]['unsychronised_lyric'] = 'USLT'; + $ID3v2ShortFrameNameLookup[3]['unsynchronised_lyric'] = 'USLT'; $ID3v2ShortFrameNameLookup[3]['commercial_information'] = 'WCOM'; $ID3v2ShortFrameNameLookup[3]['copyright'] = 'WCOP'; $ID3v2ShortFrameNameLookup[3]['url_file'] = 'WOAF'; diff --git a/www/plugins-dist/medias/lib/getid3/write.lyrics3.php b/www/plugins-dist/medias/lib/getid3/write.lyrics3.php index 12275f49..4c5c8686 100644 --- a/www/plugins-dist/medias/lib/getid3/write.lyrics3.php +++ b/www/plugins-dist/medias/lib/getid3/write.lyrics3.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // write.lyrics3.php // @@ -17,26 +17,51 @@ class getid3_write_lyrics3 { + /** + * @var string + */ public $filename; + + /** + * @var array + */ public $tag_data; //public $lyrics3_version = 2; // 1 or 2 - public $warnings = array(); // any non-critical errors will be stored here - public $errors = array(); // any critical errors will be stored here + + /** + * Any non-critical errors will be stored here. + * + * @var array + */ + public $warnings = array(); + + /** + * Any critical errors will be stored here. + * + * @var array + */ + public $errors = array(); public function __construct() { - return true; } + /** + * @return bool + */ public function WriteLyrics3() { $this->errors[] = 'WriteLyrics3() not yet functional - cannot write Lyrics3'; return false; } + + /** + * @return bool + */ public function DeleteLyrics3() { // Initialize getID3 engine $getID3 = new getID3; $ThisFileInfo = $getID3->analyze($this->filename); if (isset($ThisFileInfo['lyrics3']['tag_offset_start']) && isset($ThisFileInfo['lyrics3']['tag_offset_end'])) { - if (is_readable($this->filename) && is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { + if (is_readable($this->filename) && getID3::is_writable($this->filename) && is_file($this->filename) && ($fp = fopen($this->filename, 'a+b'))) { flock($fp, LOCK_EX); $oldignoreuserabort = ignore_user_abort(true); diff --git a/www/plugins-dist/medias/lib/getid3/write.metaflac.php b/www/plugins-dist/medias/lib/getid3/write.metaflac.php index 186e2c17..29863344 100644 --- a/www/plugins-dist/medias/lib/getid3/write.metaflac.php +++ b/www/plugins-dist/medias/lib/getid3/write.metaflac.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // write.metaflac.php // @@ -17,16 +17,38 @@ class getid3_write_metaflac { - + /** + * @var string + */ public $filename; + + /** + * @var array + */ public $tag_data; - public $warnings = array(); // any non-critical errors will be stored here - public $errors = array(); // any critical errors will be stored here + + /** + * Any non-critical errors will be stored here. + * + * @var array + */ + public $warnings = array(); + + /** + * Any critical errors will be stored here. + * + * @var array + */ + public $errors = array(); + + private $pictures = array(); public function __construct() { - return true; } + /** + * @return bool + */ public function WriteMetaFLAC() { if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) { @@ -34,9 +56,35 @@ class getid3_write_metaflac return false; } + $tempfilenames = array(); + + + if (!empty($this->tag_data['ATTACHED_PICTURE'])) { + foreach ($this->tag_data['ATTACHED_PICTURE'] as $key => $picturedetails) { + $temppicturefilename = tempnam(GETID3_TEMP_DIR, 'getID3'); + $tempfilenames[] = $temppicturefilename; + if (getID3::is_writable($temppicturefilename) && is_file($temppicturefilename) && ($fpcomments = fopen($temppicturefilename, 'wb'))) { + // https://xiph.org/flac/documentation_tools_flac.html#flac_options_picture + // [TYPE]|[MIME-TYPE]|[DESCRIPTION]|[WIDTHxHEIGHTxDEPTH[/COLORS]]|FILE + fwrite($fpcomments, $picturedetails['data']); + fclose($fpcomments); + $picture_typeid = (!empty($picturedetails['picturetypeid']) ? $this->ID3v2toFLACpictureTypes($picturedetails['picturetypeid']) : 3); // default to "3:Cover (front)" + $picture_mimetype = (!empty($picturedetails['mime']) ? $picturedetails['mime'] : ''); // should be auto-detected + $picture_width_height_depth = ''; + $this->pictures[] = $picture_typeid.'|'.$picture_mimetype.'|'.preg_replace('#[^\x20-\x7B\x7D-\x7F]#', '', $picturedetails['description']).'|'.$picture_width_height_depth.'|'.$temppicturefilename; + } else { + $this->errors[] = 'failed to open temporary tags file, tags not written - fopen("'.$temppicturefilename.'", "wb")'; + return false; + } + } + unset($this->tag_data['ATTACHED_PICTURE']); + } + + // Create file with new comments $tempcommentsfilename = tempnam(GETID3_TEMP_DIR, 'getID3'); - if (is_writable($tempcommentsfilename) && is_file($tempcommentsfilename) && ($fpcomments = fopen($tempcommentsfilename, 'wb'))) { + $tempfilenames[] = $tempcommentsfilename; + if (getID3::is_writable($tempcommentsfilename) && is_file($tempcommentsfilename) && ($fpcomments = fopen($tempcommentsfilename, 'wb'))) { foreach ($this->tag_data as $key => $value) { foreach ($value as $commentdata) { fwrite($fpcomments, $this->CleanmetaflacName($key).'='.$commentdata."\n"); @@ -65,7 +113,11 @@ class getid3_write_metaflac clearstatcache(); $timestampbeforewriting = filemtime($this->filename); - $commandline = GETID3_HELPERAPPSDIR.'metaflac.exe --no-utf8-convert --remove-all-tags --import-tags-from='.escapeshellarg($tempcommentsfilename).' '.escapeshellarg($this->filename).' 2>&1'; + $commandline = GETID3_HELPERAPPSDIR.'metaflac.exe --no-utf8-convert --remove-all-tags --import-tags-from='.escapeshellarg($tempcommentsfilename); + foreach ($this->pictures as $picturecommand) { + $commandline .= ' --import-picture-from='.escapeshellarg($picturecommand); + } + $commandline .= ' '.escapeshellarg($this->filename).' 2>&1'; $metaflacError = `$commandline`; if (empty($metaflacError)) { @@ -81,13 +133,19 @@ class getid3_write_metaflac } else { // It's simpler on *nix - $commandline = 'metaflac --no-utf8-convert --remove-all-tags --import-tags-from='.escapeshellarg($tempcommentsfilename).' '.escapeshellarg($this->filename).' 2>&1'; + $commandline = 'metaflac --no-utf8-convert --remove-all-tags --import-tags-from='.escapeshellarg($tempcommentsfilename); + foreach ($this->pictures as $picturecommand) { + $commandline .= ' --import-picture-from='.escapeshellarg($picturecommand); + } + $commandline .= ' '.escapeshellarg($this->filename).' 2>&1'; $metaflacError = `$commandline`; } // Remove temporary comments file - unlink($tempcommentsfilename); + foreach ($tempfilenames as $tempfilename) { + unlink($tempfilename); + } ignore_user_abort($oldignoreuserabort); if (!empty($metaflacError)) { @@ -100,7 +158,9 @@ class getid3_write_metaflac return true; } - + /** + * @return bool + */ public function DeleteMetaFLAC() { if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) { @@ -146,7 +206,24 @@ class getid3_write_metaflac return true; } + /** + * @param int $id3v2_picture_typeid + * + * @return int + */ + public function ID3v2toFLACpictureTypes($id3v2_picture_typeid) { + // METAFLAC picture type list is identical to ID3v2 picture type list (as least up to 0x14 "Publisher/Studio logotype") + // http://id3.org/id3v2.4.0-frames (section 4.14) + // https://xiph.org/flac/documentation_tools_flac.html#flac_options_picture + //return (isset($ID3v2toFLACpictureTypes[$id3v2_picture_typeid]) ? $ID3v2toFLACpictureTypes[$id3v2_picture_typeid] : 3); // default: "3: Cover (front)" + return (($id3v2_picture_typeid <= 0x14) ? $id3v2_picture_typeid : 3); // default: "3: Cover (front)" + } + /** + * @param string $originalcommentname + * + * @return string + */ public function CleanmetaflacName($originalcommentname) { // A case-insensitive field name that may consist of ASCII 0x20 through 0x7D, 0x3D ('=') excluded. // ASCII 0x41 through 0x5A inclusive (A-Z) is to be considered equivalent to ASCII 0x61 through @@ -156,7 +233,6 @@ class getid3_write_metaflac // Thanks Chris Bolt for improving this function // note: *reg_replace() replaces nulls with empty string (not space) return strtoupper(preg_replace('#[^ -<>-}]#', ' ', str_replace("\x00", ' ', $originalcommentname))); - } } diff --git a/www/plugins-dist/medias/lib/getid3/write.php b/www/plugins-dist/medias/lib/getid3/write.php index d4416549..cc98e5d3 100644 --- a/www/plugins-dist/medias/lib/getid3/write.php +++ b/www/plugins-dist/medias/lib/getid3/write.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// /// // // write.php // @@ -27,48 +27,113 @@ if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) { throw new Exception('write.php depends on getid3.lib.php, which is missing.'); } - -// NOTES: -// -// You should pass data here with standard field names as follows: -// * TITLE -// * ARTIST -// * ALBUM -// * TRACKNUMBER -// * COMMENT -// * GENRE -// * YEAR -// * ATTACHED_PICTURE (ID3v2 only) -// -// http://www.personal.uni-jena.de/~pfk/mpp/sv8/apekey.html -// The APEv2 Tag Items Keys definition says "TRACK" is correct but foobar2000 uses "TRACKNUMBER" instead -// Pass data here as "TRACKNUMBER" for compatability with all formats - - +/** + * NOTES: + * + * You should pass data here with standard field names as follows: + * * TITLE + * * ARTIST + * * ALBUM + * * TRACKNUMBER + * * COMMENT + * * GENRE + * * YEAR + * * ATTACHED_PICTURE (ID3v2 only) + * The APEv2 Tag Items Keys definition says "TRACK" is correct but foobar2000 uses "TRACKNUMBER" instead + * Pass data here as "TRACKNUMBER" for compatability with all formats + * + * @link http://www.personal.uni-jena.de/~pfk/mpp/sv8/apekey.html + */ class getid3_writetags { - // public - public $filename; // absolute filename of file to write tags to - public $tagformats = array(); // array of tag formats to write ('id3v1', 'id3v2.2', 'id2v2.3', 'id3v2.4', 'ape', 'vorbiscomment', 'metaflac', 'real') - public $tag_data = array(array()); // 2-dimensional array of tag data (ex: $data['ARTIST'][0] = 'Elvis') - public $tag_encoding = 'ISO-8859-1'; // text encoding used for tag data ('ISO-8859-1', 'UTF-8', 'UTF-16', 'UTF-16LE', 'UTF-16BE', ) - public $overwrite_tags = true; // if true will erase existing tag data and write only passed data; if false will merge passed data with existing tag data - public $remove_other_tags = false; // if true will erase remove all existing tags and only write those passed in $tagformats; if false will ignore any tags not mentioned in $tagformats - - public $id3v2_tag_language = 'eng'; // ISO-639-2 3-character language code needed for some ID3v2 frames (http://www.id3.org/iso639-2.html) - public $id3v2_paddedlength = 4096; // minimum length of ID3v2 tags (will be padded to this length if tag data is shorter) - - public $warnings = array(); // any non-critical errors will be stored here - public $errors = array(); // any critical errors will be stored here - - // private - private $ThisFileInfo; // analysis of file before writing + /** + * Absolute filename of file to write tags to. + * + * @var string + */ + public $filename; + + /** + * Array of tag formats to write ('id3v1', 'id3v2.2', 'id2v2.3', 'id3v2.4', 'ape', 'vorbiscomment', + * 'metaflac', 'real'). + * + * @var array + */ + public $tagformats = array(); + + /** + * 2-dimensional array of tag data (ex: $data['ARTIST'][0] = 'Elvis'). + * + * @var array + */ + public $tag_data = array(array()); + + /** + * Text encoding used for tag data ('ISO-8859-1', 'UTF-8', 'UTF-16', 'UTF-16LE', 'UTF-16BE', ). + * + * @var string + */ + public $tag_encoding = 'ISO-8859-1'; + + /** + * If true will erase existing tag data and write only passed data; if false will merge passed data + * with existing tag data. + * + * @var bool + */ + public $overwrite_tags = true; + + /** + * If true will erase remove all existing tags and only write those passed in $tagformats; + * If false will ignore any tags not mentioned in $tagformats. + * + * @var bool + */ + public $remove_other_tags = false; + + /** + * ISO-639-2 3-character language code needed for some ID3v2 frames. + * + * @link http://www.id3.org/iso639-2.html + * + * @var string + */ + public $id3v2_tag_language = 'eng'; + + /** + * Minimum length of ID3v2 tags (will be padded to this length if tag data is shorter). + * + * @var int + */ + public $id3v2_paddedlength = 4096; + + /** + * Any non-critical errors will be stored here. + * + * @var array + */ + public $warnings = array(); + + /** + * Any critical errors will be stored here. + * + * @var array + */ + public $errors = array(); + + /** + * Analysis of file before writing. + * + * @var array + */ + private $ThisFileInfo; public function __construct() { - return true; } - + /** + * @return bool + */ public function WriteTags() { if (empty($this->filename)) { @@ -83,8 +148,23 @@ class getid3_writetags $this->errors[] = 'tagformats must be an array in getid3_writetags'; return false; } + // prevent duplicate tag formats + $this->tagformats = array_unique($this->tagformats); + + // prevent trying to specify more than one version of ID3v2 tag to write simultaneously + $id3typecounter = 0; + foreach ($this->tagformats as $tagformat) { + if (substr(strtolower($tagformat), 0, 6) == 'id3v2.') { + $id3typecounter++; + } + } + if ($id3typecounter > 1) { + $this->errors[] = 'tagformats must not contain more than one version of ID3v2'; + return false; + } $TagFormatsToRemove = array(); + $AllowedTagFormats = array(); if (filesize($this->filename) == 0) { // empty file special case - allow any tag format, don't check existing format @@ -248,7 +328,7 @@ class getid3_writetags switch ($tagformat) { case 'ape': $ape_writer = new getid3_write_apetag; - if (($ape_writer->tag_data = $this->FormatDataForAPE()) !== false) { + if ($ape_writer->tag_data = $this->FormatDataForAPE()) { $ape_writer->filename = $this->filename; if (($success = $ape_writer->WriteAPEtag()) === false) { $this->errors[] = 'WriteAPEtag() failed with message(s):
  • '.str_replace("\n", '
  • ', htmlentities(trim(implode("\n", $ape_writer->errors)))).'
'; @@ -260,7 +340,7 @@ class getid3_writetags case 'id3v1': $id3v1_writer = new getid3_write_id3v1; - if (($id3v1_writer->tag_data = $this->FormatDataForID3v1()) !== false) { + if ($id3v1_writer->tag_data = $this->FormatDataForID3v1()) { $id3v1_writer->filename = $this->filename; if (($success = $id3v1_writer->WriteID3v1()) === false) { $this->errors[] = 'WriteID3v1() failed with message(s):
  • '.str_replace("\n", '
  • ', htmlentities(trim(implode("\n", $id3v1_writer->errors)))).'
'; @@ -276,7 +356,10 @@ class getid3_writetags $id3v2_writer = new getid3_write_id3v2; $id3v2_writer->majorversion = intval(substr($tagformat, -1)); $id3v2_writer->paddedlength = $this->id3v2_paddedlength; - if (($id3v2_writer->tag_data = $this->FormatDataForID3v2($id3v2_writer->majorversion)) !== false) { + $id3v2_writer_tag_data = $this->FormatDataForID3v2($id3v2_writer->majorversion); + if ($id3v2_writer_tag_data !== false) { + $id3v2_writer->tag_data = $id3v2_writer_tag_data; + unset($id3v2_writer_tag_data); $id3v2_writer->filename = $this->filename; if (($success = $id3v2_writer->WriteID3v2()) === false) { $this->errors[] = 'WriteID3v2() failed with message(s):
  • '.str_replace("\n", '
  • ', htmlentities(trim(implode("\n", $id3v2_writer->errors)))).'
'; @@ -288,7 +371,7 @@ class getid3_writetags case 'vorbiscomment': $vorbiscomment_writer = new getid3_write_vorbiscomment; - if (($vorbiscomment_writer->tag_data = $this->FormatDataForVorbisComment()) !== false) { + if ($vorbiscomment_writer->tag_data = $this->FormatDataForVorbisComment()) { $vorbiscomment_writer->filename = $this->filename; if (($success = $vorbiscomment_writer->WriteVorbisComment()) === false) { $this->errors[] = 'WriteVorbisComment() failed with message(s):
  • '.str_replace("\n", '
  • ', htmlentities(trim(implode("\n", $vorbiscomment_writer->errors)))).'
'; @@ -300,7 +383,7 @@ class getid3_writetags case 'metaflac': $metaflac_writer = new getid3_write_metaflac; - if (($metaflac_writer->tag_data = $this->FormatDataForMetaFLAC()) !== false) { + if ($metaflac_writer->tag_data = $this->FormatDataForMetaFLAC()) { $metaflac_writer->filename = $this->filename; if (($success = $metaflac_writer->WriteMetaFLAC()) === false) { $this->errors[] = 'WriteMetaFLAC() failed with message(s):
  • '.str_replace("\n", '
  • ', htmlentities(trim(implode("\n", $metaflac_writer->errors)))).'
'; @@ -312,7 +395,7 @@ class getid3_writetags case 'real': $real_writer = new getid3_write_real; - if (($real_writer->tag_data = $this->FormatDataForReal()) !== false) { + if ($real_writer->tag_data = $this->FormatDataForReal()) { $real_writer->filename = $this->filename; if (($success = $real_writer->WriteReal()) === false) { $this->errors[] = 'WriteReal() failed with message(s):
  • '.str_replace("\n", '
  • ', htmlentities(trim(implode("\n", $real_writer->errors)))).'
'; @@ -335,7 +418,11 @@ class getid3_writetags } - + /** + * @param string[] $TagFormatsToDelete + * + * @return bool + */ public function DeleteTags($TagFormatsToDelete) { foreach ($TagFormatsToDelete as $DeleteTagFormat) { $success = false; // overridden if tag deletion is successful @@ -397,7 +484,7 @@ class getid3_writetags break; default: - $this->errors[] = 'Invalid tag format to delete: "'.$tagformat.'"'; + $this->errors[] = 'Invalid tag format to delete: "'.$DeleteTagFormat.'"'; return false; break; } @@ -408,13 +495,19 @@ class getid3_writetags return true; } - + /** + * @param string $TagFormat + * @param array $tag_data + * + * @return bool + * @throws Exception + */ public function MergeExistingTagData($TagFormat, &$tag_data) { // Merge supplied data with existing data, if requested if ($this->overwrite_tags) { // do nothing - ignore previous data } else { -throw new Exception('$this->overwrite_tags=false is known to be buggy in this version of getID3. Will be fixed in the near future, check www.getid3.org for a newer version.'); + 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; } @@ -423,6 +516,9 @@ throw new Exception('$this->overwrite_tags=false is known to be buggy in this ve return true; } + /** + * @return array + */ public function FormatDataForAPE() { $ape_tag_data = array(); foreach ($this->tag_data as $tag_key => $valuearray) { @@ -449,8 +545,11 @@ throw new Exception('$this->overwrite_tags=false is known to be buggy in this ve return $ape_tag_data; } - + /** + * @return array + */ public function FormatDataForID3v1() { + $tag_data_id3v1 = array(); $tag_data_id3v1['genreid'] = 255; if (!empty($this->tag_data['GENRE'])) { foreach ($this->tag_data['GENRE'] as $key => $value) { @@ -474,6 +573,11 @@ throw new Exception('$this->overwrite_tags=false is known to be buggy in this ve return $tag_data_id3v1; } + /** + * @param int $id3v2_majorversion + * + * @return array|false + */ public function FormatDataForID3v2($id3v2_majorversion) { $tag_data_id3v2 = array(); @@ -605,6 +709,9 @@ throw new Exception('$this->overwrite_tags=false is known to be buggy in this ve return $tag_data_id3v2; } + /** + * @return array + */ public function FormatDataForVorbisComment() { $tag_data_vorbiscomment = $this->tag_data; @@ -612,21 +719,25 @@ throw new Exception('$this->overwrite_tags=false is known to be buggy in this ve // and convert data to UTF-8 strings foreach ($tag_data_vorbiscomment as $tag_key => $valuearray) { foreach ($valuearray as $key => $value) { - str_replace("\r", "\n", $value); - if (strstr($value, "\n")) { - unset($tag_data_vorbiscomment[$tag_key][$key]); - $multilineexploded = explode("\n", $value); - foreach ($multilineexploded as $newcomment) { - if (strlen(trim($newcomment)) > 0) { - $tag_data_vorbiscomment[$tag_key][] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $newcomment); + if (($tag_key == 'ATTACHED_PICTURE') && is_array($value)) { + continue; // handled separately in write.metaflac.php + } else { + str_replace("\r", "\n", $value); + if (strstr($value, "\n")) { + unset($tag_data_vorbiscomment[$tag_key][$key]); + $multilineexploded = explode("\n", $value); + foreach ($multilineexploded as $newcomment) { + if (strlen(trim($newcomment)) > 0) { + $tag_data_vorbiscomment[$tag_key][] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $newcomment); + } } + } elseif (is_string($value) || is_numeric($value)) { + $tag_data_vorbiscomment[$tag_key][$key] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $value); + } else { + $this->warnings[] = '$data['.$tag_key.']['.$key.'] is not a string value - all of $data['.$tag_key.'] NOT written to VorbisComment tag'; + unset($tag_data_vorbiscomment[$tag_key]); + break; } - } elseif (is_string($value) || is_numeric($value)) { - $tag_data_vorbiscomment[$tag_key][$key] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $value); - } else { - $this->warnings[] = '$data['.$tag_key.']['.$key.'] is not a string value - all of $data['.$tag_key.'] NOT written to VorbisComment tag'; - unset($tag_data_vorbiscomment[$tag_key]); - break; } } } @@ -634,12 +745,18 @@ throw new Exception('$this->overwrite_tags=false is known to be buggy in this ve return $tag_data_vorbiscomment; } + /** + * @return array + */ public function FormatDataForMetaFLAC() { // FLAC & OggFLAC use VorbisComments same as OggVorbis // but require metaflac to do the writing rather than vorbiscomment return $this->FormatDataForVorbisComment(); } + /** + * @return array + */ public function FormatDataForReal() { $tag_data_real['title'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['TITLE'] ) ? $this->tag_data['TITLE'] : array()))); $tag_data_real['artist'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', implode(' ', (isset($this->tag_data['ARTIST'] ) ? $this->tag_data['ARTIST'] : array()))); diff --git a/www/plugins-dist/medias/lib/getid3/write.real.php b/www/plugins-dist/medias/lib/getid3/write.real.php index fd67c859..38c0648c 100644 --- a/www/plugins-dist/medias/lib/getid3/write.real.php +++ b/www/plugins-dist/medias/lib/getid3/write.real.php @@ -1,11 +1,11 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // -///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // write.real.php // @@ -16,20 +16,53 @@ class getid3_write_real { + /** + * @var string + */ public $filename; + + /** + * @var array + */ public $tag_data = array(); - public $fread_buffer_size = 32768; // read buffer size in bytes - public $warnings = array(); // any non-critical errors will be stored here - public $errors = array(); // any critical errors will be stored here - public $paddedlength = 512; // minimum length of CONT tag in bytes + + /** + * Read buffer size in bytes. + * + * @var int + */ + public $fread_buffer_size = 32768; + + /** + * Any non-critical errors will be stored here. + * + * @var array + */ + public $warnings = array(); + + /** + * Any critical errors will be stored here. + * + * @var array + */ + public $errors = array(); + + /** + * Minimum length of CONT tag in bytes. + * + * @var int + */ + public $paddedlength = 512; public function __construct() { - return true; } + /** + * @return bool + */ public function WriteReal() { // File MUST be writeable - CHMOD(646) at least - if (is_writeable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'r+b'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'r+b'))) { // Initialize getID3 engine $getID3 = new getID3; @@ -45,6 +78,7 @@ class getid3_write_real fclose($fp_source); return false; } + $oldChunkInfo = array(); foreach ($OldThisFileInfo['real']['chunks'] as $chunknumber => $chunkarray) { $oldChunkInfo[$chunkarray['name']] = $chunkarray; } @@ -94,7 +128,7 @@ class getid3_write_real $AfterOffset = $oldChunkInfo['CONT']['offset'] + $oldChunkInfo['CONT']['length']; } if ($tempfilename = tempnam(GETID3_TEMP_DIR, 'getID3')) { - if (is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { + if (getID3::is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { rewind($fp_source); fwrite($fp_temp, fread($fp_source, $BeforeOffset)); @@ -127,8 +161,14 @@ class getid3_write_real return false; } + /** + * @param array $chunks + * + * @return string + */ public function GenerateRMFchunk(&$chunks) { $oldCONTexists = false; + $chunkNameKeys = array(); foreach ($chunks as $key => $chunk) { $chunkNameKeys[$chunk['name']] = $key; if ($chunk['name'] == 'CONT') { @@ -145,10 +185,17 @@ class getid3_write_real return $RMFchunk; } + /** + * @param array $chunks + * @param string $new_CONT_tag_data + * + * @return string + */ public function GeneratePROPchunk(&$chunks, &$new_CONT_tag_data) { $old_CONT_length = 0; $old_DATA_offset = 0; $old_INDX_offset = 0; + $chunkNameKeys = array(); foreach ($chunks as $key => $chunk) { $chunkNameKeys[$chunk['name']] = $key; if ($chunk['name'] == 'CONT') { @@ -182,6 +229,9 @@ class getid3_write_real return $PROPchunk; } + /** + * @return string + */ public function GenerateCONTchunk() { foreach ($this->tag_data as $key => $value) { // limit each value to 0xFFFF bytes @@ -211,9 +261,12 @@ class getid3_write_real return $CONTchunk; } + /** + * @return bool + */ public function RemoveReal() { // File MUST be writeable - CHMOD(646) at least - if (is_writeable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'r+b'))) { + if (getID3::is_writable($this->filename) && is_file($this->filename) && ($fp_source = fopen($this->filename, 'r+b'))) { // Initialize getID3 engine $getID3 = new getID3; @@ -242,7 +295,7 @@ class getid3_write_real $BeforeOffset = $oldChunkInfo['CONT']['offset']; $AfterOffset = $oldChunkInfo['CONT']['offset'] + $oldChunkInfo['CONT']['length']; if ($tempfilename = tempnam(GETID3_TEMP_DIR, 'getID3')) { - if (is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { + if (getID3::is_writable($tempfilename) && is_file($tempfilename) && ($fp_temp = fopen($tempfilename, 'wb'))) { rewind($fp_source); fwrite($fp_temp, fread($fp_source, $BeforeOffset)); diff --git a/www/plugins-dist/medias/lib/getid3/write.vorbiscomment.php b/www/plugins-dist/medias/lib/getid3/write.vorbiscomment.php index 971f91fe..5f89868c 100644 --- a/www/plugins-dist/medias/lib/getid3/write.vorbiscomment.php +++ b/www/plugins-dist/medias/lib/getid3/write.vorbiscomment.php @@ -1,11 +1,12 @@ // -// available at http://getid3.sourceforge.net // -// or http://www.getid3.org // -// also https://github.com/JamesHeinrich/getID3 // +// available at https://github.com/JamesHeinrich/getID3 // +// or https://www.getid3.org // +// or http://getid3.sourceforge.net // ///////////////////////////////////////////////////////////////// -// See readme.txt for more details // +// see readme.txt for more details // ///////////////////////////////////////////////////////////////// // // // write.vorbiscomment.php // @@ -17,16 +18,36 @@ class getid3_write_vorbiscomment { - + /** + * @var string + */ public $filename; + + /** + * @var array + */ public $tag_data; - public $warnings = array(); // any non-critical errors will be stored here - public $errors = array(); // any critical errors will be stored here + + /** + * Any non-critical errors will be stored here. + * + * @var array + */ + public $warnings = array(); + + /** + * Any critical errors will be stored here. + * + * @var array + */ + public $errors = array(); public function __construct() { - return true; } + /** + * @return bool + */ public function WriteVorbisComment() { if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) { @@ -36,7 +57,7 @@ class getid3_write_vorbiscomment // Create file with new comments $tempcommentsfilename = tempnam(GETID3_TEMP_DIR, 'getID3'); - if (is_writable($tempcommentsfilename) && is_file($tempcommentsfilename) && ($fpcomments = fopen($tempcommentsfilename, 'wb'))) { + if (getID3::is_writable($tempcommentsfilename) && is_file($tempcommentsfilename) && ($fpcomments = fopen($tempcommentsfilename, 'wb'))) { foreach ($this->tag_data as $key => $value) { foreach ($value as $commentdata) { @@ -100,11 +121,19 @@ class getid3_write_vorbiscomment return true; } + /** + * @return bool + */ public function DeleteVorbisComment() { $this->tag_data = array(array()); return $this->WriteVorbisComment(); } + /** + * @param string $originalcommentname + * + * @return string + */ public function CleanVorbisCommentName($originalcommentname) { // A case-insensitive field name that may consist of ASCII 0x20 through 0x7D, 0x3D ('=') excluded. // ASCII 0x41 through 0x5A inclusive (A-Z) is to be considered equivalent to ASCII 0x61 through diff --git a/www/plugins-dist/medias/medias_administrations.php b/www/plugins-dist/medias/medias_administrations.php index d7dba546..11a4260c 100644 --- a/www/plugins-dist/medias/medias_administrations.php +++ b/www/plugins-dist/medias/medias_administrations.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/medias_autoriser.php b/www/plugins-dist/medias/medias_autoriser.php index 300e89f9..96ea39f7 100644 --- a/www/plugins-dist/medias/medias_autoriser.php +++ b/www/plugins-dist/medias/medias_autoriser.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/medias_fonctions.php b/www/plugins-dist/medias/medias_fonctions.php index 44c97d21..17d7f85a 100644 --- a/www/plugins-dist/medias/medias_fonctions.php +++ b/www/plugins-dist/medias/medias_fonctions.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/medias_pipelines.php b/www/plugins-dist/medias/medias_pipelines.php index 38d39f8b..2399a4a3 100644 --- a/www/plugins-dist/medias/medias_pipelines.php +++ b/www/plugins-dist/medias/medias_pipelines.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * @@ -356,20 +356,20 @@ function medias_boite_infos($flux) { function medias_revisions_chercher_label($flux) { foreach (array('id_vignette', 'hauteur', 'largeur', 'mode', 'taille') as $champ) { if ($flux['args']['champ'] == $champ) { - $flux['data'] = _T('medias:info_' . $champ); + $flux['data'] = 'medias:info_' . $champ; return $flux; } } foreach (array('fichier', 'taille', 'mode', 'credits') as $champ) { if ($flux['args']['champ'] == $champ) { - $flux['data'] = _T('medias:label_' . $champ); + $flux['data'] = 'medias:label_' . $champ; return $flux; } } if ($flux['args']['champ'] == 'distant') { - $flux['data'] = $flux['data'] = _T('medias:fichier_distant'); + $flux['data'] = $flux['data'] = 'medias:fichier_distant'; } return $flux; diff --git a/www/plugins-dist/medias/metadata/audio.php b/www/plugins-dist/medias/metadata/audio.php index 3553f3f6..f0a94f10 100644 --- a/www/plugins-dist/medias/metadata/audio.php +++ b/www/plugins-dist/medias/metadata/audio.php @@ -33,7 +33,6 @@ function metadata_audio($file) { // Scan file - should parse correctly if file is not corrupted $file_info = $getID3->analyze($file); - header('Content-Type: text/plain'); if (isset($file_info['id3v2']['comments']['title'])) { $meta['titre'] = ucfirst(trim(implode(' ',$file_info['id3v2']['comments']['title']))); } diff --git a/www/plugins-dist/medias/metadata/html.php b/www/plugins-dist/medias/metadata/html.php index b91c89a4..e1c9b0b3 100644 --- a/www/plugins-dist/medias/metadata/html.php +++ b/www/plugins-dist/medias/metadata/html.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/metadata/image.php b/www/plugins-dist/medias/metadata/image.php index 992e02e2..35af1af1 100644 --- a/www/plugins-dist/medias/metadata/image.php +++ b/www/plugins-dist/medias/metadata/image.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/metadata/svg.php b/www/plugins-dist/medias/metadata/svg.php index f37adf96..b2914415 100644 --- a/www/plugins-dist/medias/metadata/svg.php +++ b/www/plugins-dist/medias/metadata/svg.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/metadata/swf.php b/www/plugins-dist/medias/metadata/swf.php index 60b0348d..75c46996 100644 --- a/www/plugins-dist/medias/metadata/swf.php +++ b/www/plugins-dist/medias/metadata/swf.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2016 * + * Copyright (c) 2001-2019 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * diff --git a/www/plugins-dist/medias/modeles/document_case_fonctions.php b/www/plugins-dist/medias/modeles/document_case_fonctions.php index e79b12a7..1e8494af 100644 --- a/www/plugins-dist/medias/modeles/document_case_fonctions.php +++ b/www/plugins-dist/medias/modeles/document_case_fonctions.php @@ -12,7 +12,9 @@ if (!defined('_ECRIRE_INC_VERSION')) { return; } -define('_BOUTON_MODE_IMAGE', true); +if (!defined('_BOUTON_MODE_IMAGE')) { + define('_BOUTON_MODE_IMAGE', true); +} include_spip('inc/documents'); // pour la fonction affiche_raccourci_doc function medias_raccourcis_doc( diff --git a/www/plugins-dist/medias/modeles/document_desc.html b/www/plugins-dist/medias/modeles/document_desc.html index 9d49e4aa..6ffa763c 100644 --- a/www/plugins-dist/medias/modeles/document_desc.html +++ b/www/plugins-dist/medias/modeles/document_desc.html @@ -86,8 +86,8 @@ Distribue sous licence GPL ][(#MODE|=={image}|non)[(#BOUTON_ACTION{<:medias:upload_info_mode_image:>,#URL_ACTION_AUTEUR{changer_mode_document,#ID_DOCUMENT-image,#SELF},ajax})]] ] - [(#TOTAL_BOUCLE|=={1}|et{#AUTORISER{dissocierdocuments,#OBJET,#ID_OBJET}}|et{#VU|=={non}})[(#BOUTON_ACTION{<:medias:bouton_enlever_supprimer_document:>,#URL_ACTION_AUTEUR{dissocier_document,#ID_OBJET-#OBJET-#ID_DOCUMENT-suppr-safe,#SELF},ajax,<:medias:bouton_enlever_supprimer_document_confirmation:>,'',[(function(){jQuery("#doc(#ID_DOCUMENT)").animateRemove();return true;})()]})]] - [(#AUTORISER{dissocierdocuments,#OBJET,#ID_OBJET})[(#BOUTON_ACTION{<:medias:bouton_enlever_document:>,#URL_ACTION_AUTEUR{dissocier_document,#ID_OBJET-#OBJET-#ID_DOCUMENT--safe,#SELF},ajax,'','',[(function(){jQuery("#doc(#ID_DOCUMENT)").animateRemove();return true;})()]})]] + [(#TOTAL_BOUCLE|=={1}|et{#AUTORISER{dissocierdocuments,#OBJET,#ID_OBJET}}|et{#VU|=={non}})[(#BOUTON_ACTION{<:medias:bouton_enlever_supprimer_document:>,#URL_ACTION_AUTEUR{dissocier_document,#ID_OBJET-#OBJET-#ID_DOCUMENT-suppr-safe,#SELF},ajax noscroll,<:medias:bouton_enlever_supprimer_document_confirmation:>,'',[(function(){jQuery("#doc(#ID_DOCUMENT)").animateRemove();return true;})()]})]] + [(#AUTORISER{dissocierdocuments,#OBJET,#ID_OBJET})[(#BOUTON_ACTION{<:medias:bouton_enlever_document:>,#URL_ACTION_AUTEUR{dissocier_document,#ID_OBJET-#OBJET-#ID_DOCUMENT--safe,#SELF},ajax noscroll,'','',[(function(){jQuery("#doc(#ID_DOCUMENT)").animateRemove();return true;})()]})]] [(#AUTORISER{modifier,document,#ID_DOCUMENT}|oui)
<:medias:ordonner_ce_document|attribut_html:> diff --git a/www/plugins-dist/medias/modeles/video.html b/www/plugins-dist/medias/modeles/video.html index 053a572e..3ca25e9e 100644 --- a/www/plugins-dist/medias/modeles/video.html +++ b/www/plugins-dist/medias/modeles/video.html @@ -14,7 +14,7 @@