�PNG  IHDR22?�� pHYs  �� OiCCPPhotoshop ICC profilexڝSgTS�=���BK���KoR RB���&*! J�!��Q�EEȠ�����Q, � ��!���������{�kּ������>���� �H3Q5� �B�������.@� $p�d!s�#�~<<+"��x� �M��0���B�\���t�8K�@z�B�@F���&S�`�cb�P-`'������{[�!�� e�Dh;��V�EX0fK�9�-0IWfH���� � 0Q��){`�##x��F�W<�+��*x��<�$9E�[-qWW.(�I+6aa�@.�y�2�4���������x����6��_-��"bb���ϫp@�t~��,/��;�m��%�h^ �u��f�@����W�p�~<�5�j>{�-�]c�K'Xt����o��(�h���w��?�G�%�fI�q^D$.Tʳ?�D��*�A��,���� �`6�B$��BB d�r`)��B(�Ͱ*`/�@4�Qh��p.�U�=p�a��(�� A�a!ڈb�X#����!�H�$ ɈQ"K�5H1R�T UH�=r9�\F��;�2����G1���Q=� �C��7�F� �dt1�����r�=�6��Ыhڏ>C�0��3�l0.��B�8, �c˱"� ���V����cϱw�E� 6wB aAHXLXN�H� $4� 7 �Q�'"��K�&���b21�XH,#��/{�C�7$�C2'��I��T��F�nR#�,��4H#���dk�9�, +ȅ����3��!�[ �b@q��S�(R�jJ��4�e�2AU��Rݨ�T5�ZB���R�Q��4u�9̓IK�����hh�i��t�ݕN��W���G���w ��Ljg(�gw��L�Ӌ�T071���oUX*�*|�� �J�&�*/T����ު U�U�T��^S}�FU3S� Ԗ�U��P�SSg�;���g�oT?�~Y��Y�L�OC�Q��_�� c�x,!k ��u�5�&���|v*�����=���9C3J3W�R�f?�q��tN �(���~���)�)�4L�1e\k����X�H�Q�G�6������E�Y��A�J'\'Gg����S�Sݧ �M=:��.�k���Dw�n��^��Lo��y���}/�T�m���G X� $� �<�5qo</���QC]�@C�a�a�ᄑ��<��F�F�i�\�$�m�mƣ&&!&KM�M�RM��)�;L;L���͢�֙5�=1�2��כ߷`ZxZ,����eI��Z�Yn�Z9Y�XUZ]�F���%ֻ�����N�N���gð�ɶ�����ۮ�m�}agbg�Ů��}�}��= ���Z~s�r:V:ޚΜ�?}����/gX���3��)�i�S��Ggg�s�󈋉K��.�>.���Ƚ�Jt�q]�z���������ۯ�6�i�ܟ�4�)�Y3s���C�Q��? ��0k߬~OCO�g��#/c/�W�װ��w��a�>�>r��>�<7�2�Y_�7��ȷ�O�o�_��C#�d�z����%g��A�[��z|!��?:�e����A���AA�������!h�쐭!��Α�i�P~���a�a��~ '���W�?�p�X�1�5w��Cs�D�D�Dޛg1O9�-J5*>�.j<�7�4�?�.fY��X�XIlK9.*�6nl������� �{�/�]py�����.,:�@L�N8��A*��%�w%� y��g"/�6ш�C\*N�H*Mz�쑼5y$�3�,幄'���L Lݛ:��v m2=:�1����qB�!M��g�g�fvˬe����n��/��k���Y- �B��TZ(�*�geWf�͉�9���+��̳�ې7�����ᒶ��KW-X潬j9�������(�x��oʿ�ܔ���Ĺd�f�f���-�[����n �ڴ �V����E�/��(ۻ��C���<��e����;?T�T�T�T6��ݵa��n��{��4���[���>ɾ�UUM�f�e�I���?�������m]�Nmq����#�׹���=TR��+�G�����w- 6 U����#pDy��� �� :�v�{���vg/jB��F�S��[b[�O�>����z�G��499�?r����C�d�&����ˮ/~�����јѡ�򗓿m|������������x31^�V���w�w��O�| (�h���SЧ��������c3-� cHRMz%������u0�`:�o�_�F5IDATx��ytUս�?�;���fN$$��@B�!�k��� -*�gE���j�O�kQ�ʠ`U�B_ �AÐ0%�Ȕ�@r3ޛ;߳��$�@��v����^�s����������$��ߢ !�W��5�̱'-٘������4�>�Rƫ$�G��0U�H}�_ _� #��k�MJ/=�9Du *ڲ�k�PQ;0��j|�*�$�^컂脛y���>�z×� B��� ��(�:$�ʔ_�6��C!B����MVx��a��ζyY����j��ƋY2�9�F�{r��r�딟F��Q��hY6��� x��[l��RC��������nt@��;P��3��� F�w��7��:�P���ɋ'���mj���Bƪ�$�Q�L��y��߷g��\���z����v5�p�v$�v櫻�`6~K �Y�X����,�:��"�o�e0II"(��,������l_�C���/4�+f�E�!q��:����u����c��樼.UE�@� �]K�W���$-�h]�JG���Dz)�`��.�A/ ���mᏣc�3jK� �!�>���$�Q�!�_�? \�C2(E �M$Z I{�U���s�ǣ���=��@Բe ޻��W�����@ �w����}�9v,)��.}*|"�s��di���,���G�]W�AC�������|<����[��ߕ������K�*�G nߴ!��‹��J�!��6(L�a)��Am��������;adf��:�xm��nh�;֦I��(���o�C~ډa?�=��s����h��E������xp����)���_���t��W�����´;8���`dz=(��@@�+,�;�`�fhl��XȌ�3,uI�~z(J����� �ZX�A����H'�À�㜦�82|��a�n�z2��I���� ���EY�h�ε<�0�q�{��C��v�˅��?"@��χ�x�WS+��N�~�KQ�J�8ل�� _.W��� !TU{�����,��"�� �;�������HI S� ��))�o�1�H�D� ���� (� ;����"Ҕ��,���� �F=���O��&�Ph>�`���y��߲ &S��P�<��'��1s�1cĂ�N����2)����@�u��tv��<�+�-&�����h��[!FSG���' � z z0��<����8d&�����E0�,��<��"!P�b4��� �{S�����X����.�囤���T��hEF��X�q0"-<����h���]�Py*����F⩍��@v�˂�Y08�� .q��a��s����(!<̫1�3�L�H��7sYW�`��qtu�\7��?�@�Y�� %Ka�x�GZ�*W�P��y�����N0r9��Z�c�%���q,��k�����!!,��>���IB��� �x1�Xu�Y���v-���ֺ��N������JP��a�2`�e5��w��u;�6�i���̃��(K���ťa��(l51��JL��O'%���]���ٖ뿉!��{*�p+f ���i8��D�ȑ���ܩ�M��V��ӟz��x�7Z�1i}�^͜���6e����x��)u�d�ˏ�V�eG�\�X1�����=n�U'�~Y����L�\,�(d!x ,�:�TW8� M`r���@��r+v�Q0��>^;˴�VbF��('����� �*O��i��j�Ӆ����^�S3&� ���{������.ی�� N;��NU%d0�Ce\r"�C�b��&t7N�7��� �ȪD�[%l�۪�$��'m?�A9tI�9>��NVL ��� 6v~M�����ъ�B���0����9$&=ώm��W�0���L���&��E���f�f��'+�9��hv��7,���M��6�D�&�^� �����8 D֮�����o��k^z��O��hP�8q�5d*��YVq3�{��������#LX4�?��jP=3�~�؅c�ݰ�̱�ұ��8̲��2�G�����j��έ�9��w7���U�X�w�85C��?!I&���o&����L���I#�^�eV�,�^t5�k� �xs˛\��U�8��."���{���ǵ�l4��ݼ�;��r"���G�/~���gJV�N糦��ZZ^k+NN�D��I$�=OE�z����|*�*{��%k���G��>�`9��b;�s���8,�qs��c��.b��q�%�>r��n�R�Ƨ�%�,�A��le#�8���}; 21�0�b�&�QX�f���q�00����$>�h�N�'�a3��A���/�r ��L5�8�GԲ'�����w;��c#�q1���h$*��V^�k��QĽ�b:i������� ����H F#�_���,��]g����Ը����`RUU���� ��"�qD���>-��ϤI�~��3�̴�����NZ[[555�eeek7�m����YF#[��Đ��R��i��L�H�r ��@��J-�Pŝ��_|�-��6y��ks�V�U~��6���w.����(��0A� 4��f��� /���C�xŊ�ٳ����z=6�����rg���mKo��o�/����a�g���?'9%9��P��斓��~���L{�� �H��{AW��B��$����v�1b�&Mb�ر��ر#�0`�`xMBp! )Z�Nmo�mZ�g�}�eذaWTVV ���'99��C5��&�&+5�bT>|8��PUUETT����&���t��~TE%��'������b�tEGG;RSS�S�N�v��ѯ��t����u1@�ޚ"f��͈���r'L�Ph��m��ƌ�74o��`�x�q�P���NRSS�X,�����l&&&��MFFA!-��`��ҷ�n��Yuu�����x<I�LB%����KԒ50�!�3�bz�����ʸKL���;---�l6[��`��������Ȏ;�����egg4��!D�T��jWujyZ��������K����%����p�^���X,6��sV=�ܖ����6�3�X ���4ҿ��A2�&����_k�;d�� �VfOIEND�B`� 0x0x
PHP 8.1.34
Preview: module.tag.apetag.php Size: 18.63 KB
//home2/astrociv/www/wp-includes/ID3/module.tag.apetag.php
<?php

/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org>               //
//  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                                       //
// module for analyzing APE tags                               //
// dependencies: NONE                                          //
//                                                            ///
/////////////////////////////////////////////////////////////////

if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
	exit;
}

class getid3_apetag extends getid3_handler
{
	/**
	 * 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;

		if (!getid3_lib::intValueSupported($info['filesize'])) {
			$this->warning('Unable to check for APEtags because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
			return false;
		}
		if (PHP_INT_MAX == 2147483647) {
			// https://github.com/JamesHeinrich/getID3/issues/439
			$this->warning('APEtag flags may not be parsed correctly on 32-bit PHP');
		}

		$id3v1tagsize     = 128;
		$apetagheadersize = 32;
		$lyrics3tagsize   = 10;

		if ($this->overrideendoffset == 0) {

			$this->fseek(0 - $id3v1tagsize - $apetagheadersize - $lyrics3tagsize, SEEK_END);
			$APEfooterID3v1 = $this->fread($id3v1tagsize + $apetagheadersize + $lyrics3tagsize);

			//if (preg_match('/APETAGEX.{24}TAG.{125}$/i', $APEfooterID3v1)) {
			if (substr($APEfooterID3v1, strlen($APEfooterID3v1) - $id3v1tagsize - $apetagheadersize, 8) == 'APETAGEX') {

				// APE tag found before ID3v1
				$info['ape']['tag_offset_end'] = $info['filesize'] - $id3v1tagsize;

			//} elseif (preg_match('/APETAGEX.{24}$/i', $APEfooterID3v1)) {
			} elseif (substr($APEfooterID3v1, strlen($APEfooterID3v1) - $apetagheadersize, 8) == 'APETAGEX') {

				// APE tag found, no ID3v1
				$info['ape']['tag_offset_end'] = $info['filesize'];

			}

		} else {

			$this->fseek($this->overrideendoffset - $apetagheadersize);
			if ($this->fread(8) == 'APETAGEX') {
				$info['ape']['tag_offset_end'] = $this->overrideendoffset;
			}

		}
		if (!isset($info['ape']['tag_offset_end'])) {

			// APE tag not found
			unset($info['ape']);
			return false;

		}

		// shortcut
		$thisfile_ape = &$info['ape'];

		$this->fseek($thisfile_ape['tag_offset_end'] - $apetagheadersize);
		$APEfooterData = $this->fread(32);
		if (!($thisfile_ape['footer'] = $this->parseAPEheaderFooter($APEfooterData))) {
			$this->error('Error parsing APE footer at offset '.$thisfile_ape['tag_offset_end']);
			return false;
		}

		if (isset($thisfile_ape['footer']['flags']['header']) && $thisfile_ape['footer']['flags']['header']) {
			$this->fseek($thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize'] - $apetagheadersize);
			$thisfile_ape['tag_offset_start'] = $this->ftell();
			$APEtagData = $this->fread($thisfile_ape['footer']['raw']['tagsize'] + $apetagheadersize);
		} else {
			$thisfile_ape['tag_offset_start'] = $thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize'];
			$this->fseek($thisfile_ape['tag_offset_start']);
			$APEtagData = $this->fread($thisfile_ape['footer']['raw']['tagsize']);
		}
		$info['avdataend'] = $thisfile_ape['tag_offset_start'];

		if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] < $thisfile_ape['tag_offset_end'])) {
			$this->warning('ID3v1 tag information ignored since it appears to be a false synch in APEtag data');
			unset($info['id3v1']);
			foreach ($info['warning'] as $key => $value) {
				if ($value == 'Some ID3v1 fields do not use NULL characters for padding') {
					unset($info['warning'][$key]);
					sort($info['warning']);
					break;
				}
			}
		}

		$offset = 0;
		if (isset($thisfile_ape['footer']['flags']['header']) && $thisfile_ape['footer']['flags']['header']) {
			if ($thisfile_ape['header'] = $this->parseAPEheaderFooter(substr($APEtagData, 0, $apetagheadersize))) {
				$offset += $apetagheadersize;
			} else {
				$this->error('Error parsing APE header at offset '.$thisfile_ape['tag_offset_start']);
				return false;
			}
		}

		// shortcut
		$info['replay_gain'] = array();
		$thisfile_replaygain = &$info['replay_gain'];

		for ($i = 0; $i < $thisfile_ape['footer']['raw']['tag_items']; $i++) {
			$value_size = getid3_lib::LittleEndian2Int(substr($APEtagData, $offset, 4));
			$offset += 4;
			$item_flags = getid3_lib::LittleEndian2Int(substr($APEtagData, $offset, 4));
			$offset += 4;
			if (strstr(substr($APEtagData, $offset), "\x00") === false) {
				$this->error('Cannot find null-byte (0x00) separator between ItemKey #'.$i.' and value. ItemKey starts '.$offset.' bytes into the APE tag, at file offset '.($thisfile_ape['tag_offset_start'] + $offset));
				return false;
			}
			$ItemKeyLength = strpos($APEtagData, "\x00", $offset) - $offset;
			$item_key      = strtolower(substr($APEtagData, $offset, $ItemKeyLength));

			// shortcut
			$thisfile_ape['items'][$item_key] = array();
			$thisfile_ape_items_current = &$thisfile_ape['items'][$item_key];

			$thisfile_ape_items_current['offset'] = $thisfile_ape['tag_offset_start'] + $offset;

			$offset += ($ItemKeyLength + 1); // skip 0x00 terminator
			$thisfile_ape_items_current['data'] = substr($APEtagData, $offset, $value_size);
			$offset += $value_size;

			$thisfile_ape_items_current['flags'] = $this->parseAPEtagFlags($item_flags);
			switch ($thisfile_ape_items_current['flags']['item_contents_raw']) {
				case 0: // UTF-8
				case 2: // Locator (URL, filename, etc), UTF-8 encoded
					$thisfile_ape_items_current['data'] = explode("\x00", $thisfile_ape_items_current['data']);
					break;

				case 1:  // binary data
				default:
					break;
			}

			switch (strtolower($item_key)) {
				// http://wiki.hydrogenaud.io/index.php?title=ReplayGain#MP3Gain
				case 'replaygain_track_gain':
					if (preg_match('#^([\\-\\+][0-9\\.,]{8})( dB)?$#', $thisfile_ape_items_current['data'][0], $matches)) {
						$thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
						$thisfile_replaygain['track']['originator'] = 'unspecified';
					} else {
						$this->warning('MP3gainTrackGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
					}
					break;

				case 'replaygain_track_peak':
					if (preg_match('#^([0-9\\.,]{8})$#', $thisfile_ape_items_current['data'][0], $matches)) {
						$thisfile_replaygain['track']['peak']       = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
						$thisfile_replaygain['track']['originator'] = 'unspecified';
						if ($thisfile_replaygain['track']['peak'] <= 0) {
							$this->warning('ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
						}
					} else {
						$this->warning('MP3gainTrackPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
					}
					break;

				case 'replaygain_album_gain':
					if (preg_match('#^([\\-\\+][0-9\\.,]{8})( dB)?$#', $thisfile_ape_items_current['data'][0], $matches)) {
						$thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
						$thisfile_replaygain['album']['originator'] = 'unspecified';
					} else {
						$this->warning('MP3gainAlbumGain value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
					}
					break;

				case 'replaygain_album_peak':
					if (preg_match('#^([0-9\\.,]{8})$#', $thisfile_ape_items_current['data'][0], $matches)) {
						$thisfile_replaygain['album']['peak']       = (float) str_replace(',', '.', $matches[1]); // float casting will see "0,95" as zero!
						$thisfile_replaygain['album']['originator'] = 'unspecified';
						if ($thisfile_replaygain['album']['peak'] <= 0) {
							$this->warning('ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")');
						}
					} else {
						$this->warning('MP3gainAlbumPeak value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
					}
					break;

				case 'mp3gain_undo':
					if (preg_match('#^[\\-\\+][0-9]{3},[\\-\\+][0-9]{3},[NW]$#', $thisfile_ape_items_current['data'][0])) {
						list($mp3gain_undo_left, $mp3gain_undo_right, $mp3gain_undo_wrap) = explode(',', $thisfile_ape_items_current['data'][0]);
						$thisfile_replaygain['mp3gain']['undo_left']  = intval($mp3gain_undo_left);
						$thisfile_replaygain['mp3gain']['undo_right'] = intval($mp3gain_undo_right);
						$thisfile_replaygain['mp3gain']['undo_wrap']  = (($mp3gain_undo_wrap == 'Y') ? true : false);
					} else {
						$this->warning('MP3gainUndo value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
					}
					break;

				case 'mp3gain_minmax':
					if (preg_match('#^[0-9]{3},[0-9]{3}$#', $thisfile_ape_items_current['data'][0])) {
						list($mp3gain_globalgain_min, $mp3gain_globalgain_max) = explode(',', $thisfile_ape_items_current['data'][0]);
						$thisfile_replaygain['mp3gain']['globalgain_track_min'] = intval($mp3gain_globalgain_min);
						$thisfile_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max);
					} else {
						$this->warning('MP3gainMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
					}
					break;

				case 'mp3gain_album_minmax':
					if (preg_match('#^[0-9]{3},[0-9]{3}$#', $thisfile_ape_items_current['data'][0])) {
						list($mp3gain_globalgain_album_min, $mp3gain_globalgain_album_max) = explode(',', $thisfile_ape_items_current['data'][0]);
						$thisfile_replaygain['mp3gain']['globalgain_album_min'] = intval($mp3gain_globalgain_album_min);
						$thisfile_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max);
					} else {
						$this->warning('MP3gainAlbumMinMax value in APEtag appears invalid: "'.$thisfile_ape_items_current['data'][0].'"');
					}
					break;

				case 'tracknumber':
					if (is_array($thisfile_ape_items_current['data'])) {
						foreach ($thisfile_ape_items_current['data'] as $comment) {
							$thisfile_ape['comments']['track_number'][] = $comment;
						}
					}
					break;

				case 'cover art (artist)':
				case 'cover art (back)':
				case 'cover art (band logo)':
				case 'cover art (band)':
				case 'cover art (colored fish)':
				case 'cover art (composer)':
				case 'cover art (conductor)':
				case 'cover art (front)':
				case 'cover art (icon)':
				case 'cover art (illustration)':
				case 'cover art (lead)':
				case 'cover art (leaflet)':
				case 'cover art (lyricist)':
				case 'cover art (media)':
				case 'cover art (movie scene)':
				case 'cover art (other icon)':
				case 'cover art (other)':
				case 'cover art (performance)':
				case 'cover art (publisher logo)':
				case 'cover art (recording)':
				case 'cover art (studio)':
					// list of possible cover arts from https://github.com/mono/taglib-sharp/blob/taglib-sharp-2.0.3.2/src/TagLib/Ape/Tag.cs
					if (is_array($thisfile_ape_items_current['data'])) {
						$this->warning('APEtag "'.$item_key.'" should be flagged as Binary data, but was incorrectly flagged as UTF-8');
						$thisfile_ape_items_current['data'] = implode("\x00", $thisfile_ape_items_current['data']);
					}
					list($thisfile_ape_items_current['filename'], $thisfile_ape_items_current['data']) = explode("\x00", $thisfile_ape_items_current['data'], 2);
					$thisfile_ape_items_current['data_offset'] = $thisfile_ape_items_current['offset'] + strlen($thisfile_ape_items_current['filename']."\x00");
					$thisfile_ape_items_current['data_length'] = strlen($thisfile_ape_items_current['data']);

					do {
						$thisfile_ape_items_current['image_mime'] = '';
						$imageinfo = array();
						$imagechunkcheck = getid3_lib::GetDataImageSize($thisfile_ape_items_current['data'], $imageinfo);
						if (($imagechunkcheck === false) || !isset($imagechunkcheck[2])) {
							$this->warning('APEtag "'.$item_key.'" contains invalid image data');
							break;
						}
						$thisfile_ape_items_current['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);

						if ($this->inline_attachments === false) {
							// skip entirely
							unset($thisfile_ape_items_current['data']);
							break;
						}
						if ($this->inline_attachments === true) {
							// great
						} elseif (is_int($this->inline_attachments)) {
							if ($this->inline_attachments < $thisfile_ape_items_current['data_length']) {
								// too big, skip
								$this->warning('attachment at '.$thisfile_ape_items_current['offset'].' is too large to process inline ('.number_format($thisfile_ape_items_current['data_length']).' bytes)');
								unset($thisfile_ape_items_current['data']);
								break;
							}
						} 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) || !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']);
								break;
							}
						}
						// 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) || 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)');
							}
							$thisfile_ape_items_current['data_filename'] = $destination_filename;
							unset($thisfile_ape_items_current['data']);
						} else {
							if (!isset($info['ape']['comments']['picture'])) {
								$info['ape']['comments']['picture'] = array();
							}
							$comments_picture_data = array();
							foreach (array('data', 'image_mime', 'image_width', 'image_height', 'imagetype', 'picturetype', 'description', 'datalength') as $picture_key) {
								if (isset($thisfile_ape_items_current[$picture_key])) {
									$comments_picture_data[$picture_key] = $thisfile_ape_items_current[$picture_key];
								}
							}
							$info['ape']['comments']['picture'][] = $comments_picture_data;
							unset($comments_picture_data);
						}
					} while (false); // @phpstan-ignore-line
					break;

				default:
					if (is_array($thisfile_ape_items_current['data'])) {
						foreach ($thisfile_ape_items_current['data'] as $comment) {
							$thisfile_ape['comments'][strtolower($item_key)][] = $comment;
						}
					}
					break;
			}

		}
		if (empty($thisfile_replaygain)) {
			unset($info['replay_gain']);
		}
		return true;
	}

	/**
	 * @param string $APEheaderFooterData
	 *
	 * @return array|false
	 */
	public function parseAPEheaderFooter($APEheaderFooterData) {
		// http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html

		// shortcut
		$headerfooterinfo = array();
		$headerfooterinfo['raw'] = array();
		$headerfooterinfo_raw = &$headerfooterinfo['raw'];

		$headerfooterinfo_raw['footer_tag']   =                  substr($APEheaderFooterData,  0, 8);
		if ($headerfooterinfo_raw['footer_tag'] != 'APETAGEX') {
			return false;
		}
		$headerfooterinfo_raw['version']      = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData,  8, 4));
		$headerfooterinfo_raw['tagsize']      = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 12, 4));
		$headerfooterinfo_raw['tag_items']    = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 16, 4));
		$headerfooterinfo_raw['global_flags'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 20, 4));
		$headerfooterinfo_raw['reserved']     =                              substr($APEheaderFooterData, 24, 8);

		$headerfooterinfo['tag_version']         = $headerfooterinfo_raw['version'] / 1000;
		if ($headerfooterinfo['tag_version'] >= 2) {
			$headerfooterinfo['flags'] = $this->parseAPEtagFlags($headerfooterinfo_raw['global_flags']);
		}
		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."
		// http://wiki.hydrogenaud.io/index.php?title=Ape_Tags_Flags
		$flags                      = array();
		$flags['header']            = (bool) ($rawflagint & 0x80000000);
		$flags['footer']            = (bool) ($rawflagint & 0x40000000);
		$flags['this_is_header']    = (bool) ($rawflagint & 0x20000000);
		$flags['item_contents_raw'] =        ($rawflagint & 0x00000006) >> 1;
		$flags['read_only']         = (bool) ($rawflagint & 0x00000001);

		$flags['item_contents']     = $this->APEcontentTypeFlagLookup($flags['item_contents_raw']);

		return $flags;
	}

	/**
	 * @param int $contenttypeid
	 *
	 * @return string
	 */
	public function APEcontentTypeFlagLookup($contenttypeid) {
		static $APEcontentTypeFlagLookup = array(
			0 => 'utf-8',
			1 => 'binary',
			2 => 'external',
			3 => 'reserved'
		);
		return (isset($APEcontentTypeFlagLookup[$contenttypeid]) ? $APEcontentTypeFlagLookup[$contenttypeid] : 'invalid');
	}

	/**
	 * @param string $itemkey
	 *
	 * @return bool
	 */
	public function APEtagItemIsUTF8Lookup($itemkey) {
		static $APEtagItemIsUTF8Lookup = array(
			'title',
			'subtitle',
			'artist',
			'album',
			'debut album',
			'publisher',
			'conductor',
			'track',
			'composer',
			'comment',
			'copyright',
			'publicationright',
			'file',
			'year',
			'record date',
			'record location',
			'genre',
			'media',
			'related',
			'isrc',
			'abstract',
			'language',
			'bibliography'
		);
		return in_array(strtolower($itemkey), $APEtagItemIsUTF8Lookup);
	}

}

Directory Contents

Dirs: 0 × Files: 20
Name Size Perms Modified Actions
54.07 KB lrw-r--r-- 2026-03-21 18:19:56
Edit Download
79.34 KB lrw-r--r-- 2026-03-21 18:19:56
Edit Download
1.36 KB lrw-r--r-- 2023-10-20 07:59:28
Edit Download
133.61 KB lrw-r--r-- 2025-11-17 16:52:34
Edit Download
26.50 KB lrw-r--r-- 2021-11-25 21:36:04
Edit Download
109.39 KB lrw-r--r-- 2026-03-21 18:19:56
Edit Download
168.59 KB lrw-r--r-- 2026-03-21 18:19:56
Edit Download
136.83 KB lrw-r--r-- 2026-03-21 18:19:56
Edit Download
38.46 KB lrw-r--r-- 2020-07-02 10:18:04
Edit Download
10.63 KB lrw-r--r-- 2020-07-02 10:18:04
Edit Download
19.33 KB lrw-r--r-- 2026-03-21 18:19:56
Edit Download
104.50 KB lrw-r--r-- 2026-03-21 18:19:56
Edit Download
42.74 KB lrw-r--r-- 2025-11-17 16:52:34
Edit Download
18.63 KB lrw-r--r-- 2025-11-17 16:52:34
Edit Download
14.82 KB lrw-r--r-- 2026-03-21 18:19:56
Edit Download
151.20 KB lrw-r--r-- 2026-03-21 18:19:56
Edit Download
11.75 KB lrw-r--r-- 2025-11-17 16:52:34
Edit Download
25.71 KB lrw-r--r-- 2023-10-20 07:59:28
Edit Download
2.74 KB lrw-r--r-- 2026-06-29 08:14:19
Edit Download
2.74 KB lrw-r--r-- 2026-06-29 08:14:19
Edit Download
If ZipArchive is unavailable, a .tar will be created (no compression).
© 2026 0xNothings — Secure File Manager. All rights reserved. Built with ❤️ & Tailwind x Dark UI