22 if (!defined(
'GETID3_INCLUDEPATH')) {
23 die(
'getid3.php MUST be included before calling getid3_writetags');
25 if (!include_once(GETID3_INCLUDEPATH.
'getid3.lib.php')) {
26 die(
'write.php depends on getid3.lib.php, which is missing.');
73 if (empty($this->filename)) {
74 $this->errors[] =
'filename is undefined in getid3_writetags';
76 } elseif (!file_exists($this->filename)) {
77 $this->errors[] =
'filename set to non-existant file "'.$this->filename.
'" in getid3_writetags';
81 if (!is_array($this->tagformats)) {
82 $this->errors[] =
'tagformats must be an array in getid3_writetags';
86 $TagFormatsToRemove = array();
87 if (filesize($this->filename) == 0) {
91 $this->ThisFileInfo = array(
'fileformat'=>
'');
92 $AllowedTagFormats = array(
'id3v1',
'id3v2.2',
'id3v2.3',
'id3v2.4',
'ape',
'lyrics3');
98 $this->ThisFileInfo = $getID3->analyze($this->filename);
101 switch (@$this->ThisFileInfo[
'fileformat']) {
106 $AllowedTagFormats = array(
'id3v1',
'id3v2.2',
'id3v2.3',
'id3v2.4',
'ape',
'lyrics3');
110 $AllowedTagFormats = array(
'ape');
114 $AllowedTagFormats = array(
'metaflac');
118 $AllowedTagFormats = array(
'real');
122 switch (@$this->ThisFileInfo[
'audio'][
'dataformat']) {
125 $this->errors[] =
'metaflac is not (yet) compatible with OggFLAC files';
129 $AllowedTagFormats = array(
'vorbiscomment');
132 $this->errors[] =
'metaflac is not (yet) compatible with Ogg files other than OggVorbis';
139 $AllowedTagFormats = array();
142 foreach ($this->tagformats as $requested_tag_format) {
143 if (!in_array($requested_tag_format, $AllowedTagFormats)) {
144 $errormessage =
'Tag format "'.$requested_tag_format.
'" is not allowed on "'.@$this->ThisFileInfo[
'fileformat'];
145 if (@$this->ThisFileInfo[
'fileformat'] != @$this->ThisFileInfo[
'audio'][
'dataformat']) {
146 $errormessage .=
'.'.@$this->ThisFileInfo[
'audio'][
'dataformat'];
148 $errormessage .=
'" files';
149 $this->errors[] = $errormessage;
155 if ($this->remove_other_tags) {
156 foreach ($AllowedTagFormats as $AllowedTagFormat) {
157 switch ($AllowedTagFormat) {
161 if (!in_array(
'id3v2', $TagFormatsToRemove) && !in_array(
'id3v2.2', $this->tagformats) && !in_array(
'id3v2.3', $this->tagformats) && !in_array(
'id3v2.4', $this->tagformats)) {
162 $TagFormatsToRemove[] =
'id3v2';
167 if (!in_array($AllowedTagFormat, $this->tagformats)) {
168 $TagFormatsToRemove[] = $AllowedTagFormat;
176 $WritingFilesToInclude = array_merge($this->tagformats, $TagFormatsToRemove);
179 foreach ($WritingFilesToInclude as $tagformat) {
180 switch ($tagformat) {
190 case 'vorbiscomment':
210 $this->errors[] =
'unknown tag format "'.$tagformat.
'" in $tagformats in WriteTags()';
218 if (!is_array($this->tag_data)) {
219 $this->errors[] =
'$tag_data is not an array in WriteTags()';
223 foreach ($this->tag_data as $tag_key => $tag_array) {
224 if (strtoupper($tag_key) !== $tag_key) {
225 $this->tag_data[strtoupper($tag_key)] = $this->tag_data[$tag_key];
226 unset($this->tag_data[$tag_key]);
230 if (!empty($this->ThisFileInfo[
'tags'])) {
231 foreach ($this->ThisFileInfo[
'tags'] as $tag_format => $tag_data_array) {
232 foreach ($tag_data_array as $tag_key => $tag_array) {
233 if (strtoupper($tag_key) !== $tag_key) {
234 $this->ThisFileInfo[
'tags'][$tag_format][strtoupper($tag_key)] = $this->ThisFileInfo[
'tags'][$tag_format][$tag_key];
235 unset($this->ThisFileInfo[
'tags'][$tag_format][$tag_key]);
242 if (isset($this->tag_data[
'TRACK']) && !isset($this->tag_data[
'TRACKNUMBER'])) {
243 $this->tag_data[
'TRACKNUMBER'] = $this->tag_data[
'TRACK'];
244 unset($this->tag_data[
'TRACK']);
248 if ($this->remove_other_tags) {
253 foreach ($this->tagformats as $tagformat) {
255 switch ($tagformat) {
258 if (($ape_writer->tag_data = $this->FormatDataForAPE()) !==
false) {
260 if ((
$success = $ape_writer->WriteAPEtag()) ===
false) {
261 $this->errors[] =
'WriteAPEtag() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $ape_writer->errors)).
'</LI></UL></PRE>';
264 $this->errors[] =
'FormatDataForAPE() failed';
270 if (($id3v1_writer->tag_data = $this->FormatDataForID3v1()) !==
false) {
272 if ((
$success = $id3v1_writer->WriteID3v1()) ===
false) {
273 $this->errors[] =
'WriteID3v1() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $id3v1_writer->errors)).
'</LI></UL></PRE>';
276 $this->errors[] =
'FormatDataForID3v1() failed';
284 $id3v2_writer->majorversion = intval(substr($tagformat, -1));
286 if (($id3v2_writer->tag_data = $this->FormatDataForID3v2($id3v2_writer->majorversion)) !==
false) {
288 if ((
$success = $id3v2_writer->WriteID3v2()) ===
false) {
289 $this->errors[] =
'WriteID3v2() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $id3v2_writer->errors)).
'</LI></UL></PRE>';
292 $this->errors[] =
'FormatDataForID3v2() failed';
296 case 'vorbiscomment':
298 if (($vorbiscomment_writer->tag_data = $this->FormatDataForVorbisComment()) !==
false) {
300 if ((
$success = $vorbiscomment_writer->WriteVorbisComment()) ===
false) {
301 $this->errors[] =
'WriteVorbisComment() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $vorbiscomment_writer->errors)).
'</LI></UL></PRE>';
304 $this->errors[] =
'FormatDataForVorbisComment() failed';
310 if (($metaflac_writer->tag_data = $this->FormatDataForMetaFLAC()) !==
false) {
312 if ((
$success = $metaflac_writer->WriteMetaFLAC()) ===
false) {
313 $this->errors[] =
'WriteMetaFLAC() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $metaflac_writer->errors)).
'</LI></UL></PRE>';
316 $this->errors[] =
'FormatDataForMetaFLAC() failed';
322 if (($real_writer->tag_data = $this->FormatDataForReal()) !==
false) {
324 if ((
$success = $real_writer->WriteReal()) ===
false) {
325 $this->errors[] =
'WriteReal() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $real_writer->errors)).
'</LI></UL></PRE>';
328 $this->errors[] =
'FormatDataForReal() failed';
333 $this->errors[] =
'Invalid tag format to write: "'.$tagformat.
'"';
347 foreach ($TagFormatsToDelete as $DeleteTagFormat) {
349 switch ($DeleteTagFormat) {
353 if ((
$success = $id3v1_writer->RemoveID3v1()) ===
false) {
354 $this->errors[] =
'RemoveID3v1() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $id3v1_writer->errors)).
'</LI></UL></PRE>';
361 if ((
$success = $id3v2_writer->RemoveID3v2()) ===
false) {
362 $this->errors[] =
'RemoveID3v2() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $id3v2_writer->errors)).
'</LI></UL></PRE>';
369 if ((
$success = $ape_writer->DeleteAPEtag()) ===
false) {
370 $this->errors[] =
'DeleteAPEtag() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $ape_writer->errors)).
'</LI></UL></PRE>';
374 case 'vorbiscomment':
377 if ((
$success = $vorbiscomment_writer->DeleteVorbisComment()) ===
false) {
378 $this->errors[] =
'DeleteVorbisComment() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $vorbiscomment_writer->errors)).
'</LI></UL></PRE>';
385 if ((
$success = $metaflac_writer->DeleteMetaFLAC()) ===
false) {
386 $this->errors[] =
'DeleteMetaFLAC() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $metaflac_writer->errors)).
'</LI></UL></PRE>';
393 if ((
$success = $lyrics3_writer->DeleteLyrics3()) ===
false) {
394 $this->errors[] =
'DeleteLyrics3() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $lyrics3_writer->errors)).
'</LI></UL></PRE>';
401 if ((
$success = $real_writer->RemoveReal()) ===
false) {
402 $this->errors[] =
'RemoveReal() failed with message(s):<PRE><UL><LI>'.trim(implode(
'</LI><LI>', $real_writer->errors)).
'</LI></UL></PRE>';
407 $this->errors[] =
'Invalid tag format to delete: "'.$tagformat.
'"';
421 if ($this->overwrite_tags) {
424 if (!isset($this->ThisFileInfo[
'tags'][$TagFormat])) {
427 $tag_data = array_merge_recursive(
$tag_data, $this->ThisFileInfo[
'tags'][$TagFormat]);
433 $ape_tag_data = array();
434 foreach ($this->tag_data as $tag_key => $valuearray) {
436 case 'ATTACHED_PICTURE':
438 $this->warnings[] =
'$data['.$tag_key.
'] is assumed to be ID3v2 APIC data - NOT written to APE tag';
442 foreach ($valuearray as $key => $value) {
443 if (is_string($value) || is_numeric($value)) {
446 $this->warnings[] =
'$data['.$tag_key.
']['.$key.
'] is not a string value - all of $data['.$tag_key.
'] NOT written to APE tag';
447 unset($ape_tag_data[$tag_key]);
455 return $ape_tag_data;
460 $tag_data_id3v1[
'genreid'] = 255;
461 if (!empty($this->tag_data[
'GENRE'])) {
462 foreach ($this->tag_data[
'GENRE'] as $key => $value) {
470 $tag_data_id3v1[
'title'] =
getid3_lib::iconv_fallback($this->tag_encoding,
'ISO-8859-1', @implode(
' ', @$this->tag_data[
'TITLE']));
471 $tag_data_id3v1[
'artist'] =
getid3_lib::iconv_fallback($this->tag_encoding,
'ISO-8859-1', @implode(
' ', @$this->tag_data[
'ARTIST']));
472 $tag_data_id3v1[
'album'] =
getid3_lib::iconv_fallback($this->tag_encoding,
'ISO-8859-1', @implode(
' ', @$this->tag_data[
'ALBUM']));
473 $tag_data_id3v1[
'year'] =
getid3_lib::iconv_fallback($this->tag_encoding,
'ISO-8859-1', @implode(
' ', @$this->tag_data[
'YEAR']));
474 $tag_data_id3v1[
'comment'] =
getid3_lib::iconv_fallback($this->tag_encoding,
'ISO-8859-1', @implode(
' ', @$this->tag_data[
'COMMENT']));
476 $tag_data_id3v1[
'track'] = intval(
getid3_lib::iconv_fallback($this->tag_encoding,
'ISO-8859-1', @implode(
' ', @$this->tag_data[
'TRACKNUMBER'])));
477 if ($tag_data_id3v1[
'track'] <= 0) {
478 $tag_data_id3v1[
'track'] =
'';
482 return $tag_data_id3v1;
486 $tag_data_id3v2 = array();
488 $ID3v2_text_encoding_lookup[2] = array(
'ISO-8859-1'=>0,
'UTF-16'=>1);
489 $ID3v2_text_encoding_lookup[3] = array(
'ISO-8859-1'=>0,
'UTF-16'=>1);
490 $ID3v2_text_encoding_lookup[4] = array(
'ISO-8859-1'=>0,
'UTF-16'=>1,
'UTF-16BE'=>2,
'UTF-8'=>3);
491 foreach ($this->tag_data as $tag_key => $valuearray) {
493 switch ($ID3v2_framename) {
495 foreach ($valuearray as $key => $apic_data_array) {
496 if (isset($apic_data_array[
'data']) &&
497 isset($apic_data_array[
'picturetypeid']) &&
498 isset($apic_data_array[
'description']) &&
499 isset($apic_data_array[
'mime'])) {
500 $tag_data_id3v2[
'APIC'][] = $apic_data_array;
502 $this->errors[] =
'ID3v2 APIC data is not properly structured';
509 $this->errors[] =
'ID3v2: Skipping "'.$tag_key.
'" because cannot match it to a known ID3v2 frame type';
515 foreach ($valuearray as $key => $value) {
516 if (isset($ID3v2_text_encoding_lookup[$id3v2_majorversion][$this->tag_encoding])) {
518 $tag_data_id3v2[$ID3v2_framename][$key][
'encodingid'] = $ID3v2_text_encoding_lookup[$id3v2_majorversion][
$this->tag_encoding];
519 $tag_data_id3v2[$ID3v2_framename][$key][
'data'] = $value;
522 if ($id3v2_majorversion < 4) {
524 $tag_data_id3v2[$ID3v2_framename][$key][
'encodingid'] = 1;
529 $tag_data_id3v2[$ID3v2_framename][$key][
'encodingid'] = 3;
535 $tag_data_id3v2[$ID3v2_framename][$key][
'description'] =
'';
542 return $tag_data_id3v2;
550 foreach ($tag_data_vorbiscomment as $tag_key => $valuearray) {
551 foreach ($valuearray as $key => $value) {
552 str_replace(
"\r",
"\n", $value);
553 if (strstr($value,
"\n")) {
554 unset($tag_data_vorbiscomment[$tag_key][$key]);
555 $multilineexploded = explode(
"\n", $value);
556 foreach ($multilineexploded as $newcomment) {
557 if (strlen(trim($newcomment)) > 0) {
561 } elseif (is_string($value) || is_numeric($value)) {
564 $this->warnings[] =
'$data['.$tag_key.
']['.$key.
'] is not a string value - all of $data['.$tag_key.
'] NOT written to VorbisComment tag';
565 unset($tag_data_vorbiscomment[$tag_key]);
571 return $tag_data_vorbiscomment;
581 $tag_data_real[
'title'] =
getid3_lib::iconv_fallback($this->tag_encoding,
'ISO-8859-1', @implode(
' ', @$this->tag_data[
'TITLE']));
582 $tag_data_real[
'artist'] =
getid3_lib::iconv_fallback($this->tag_encoding,
'ISO-8859-1', @implode(
' ', @$this->tag_data[
'ARTIST']));
583 $tag_data_real[
'copyright'] =
getid3_lib::iconv_fallback($this->tag_encoding,
'ISO-8859-1', @implode(
' ', @$this->tag_data[
'COPYRIGHT']));
584 $tag_data_real[
'comment'] =
getid3_lib::iconv_fallback($this->tag_encoding,
'ISO-8859-1', @implode(
' ', @$this->tag_data[
'COMMENT']));
587 return $tag_data_real;