($tagwriter->overwrite_tags = false) broken in v1.8.x

Post Reply
James Heinrich
getID3() v1 developer
Posts: 1475
Joined: Fri May 04, 2001 4:00 pm
Are you a spambot?: no
Location: Northern Ontario, Canada
Contact:

($tagwriter->overwrite_tags = false) broken in v1.8.x

Post by James Heinrich » Thu Feb 17, 2011 12:44 am

$tagwriter->overwrite_tags=false with id3v2.3 doesn't work properly. Generates errors similar to:
Failed to write tags!
WriteID3v2() failed with message(s):

* Invalid Text Encoding in TITLE (M) for ID3v2.3
* $this->GenerateID3v2FrameData() failed for "TITLE"
* $this->GenerateID3v2Tag() failed
Is broken for all versions of ID3v2. It may (or may not) be OK for other tag formats (ID3v1, APE, Real, Lyrics3), but I'm going to disable overwrite_tags=false for v1.8.5 pending a full review of how the data is pre-processed. Hopefully I'll have it fixed properly for v1.8.6. I will post an update in this thread when it is resolved.

Transmitter
User
Posts: 1
Joined: Fri Nov 11, 2011 1:11 pm
Are you a spambot?: no

Re: ($tagwriter->overwrite_tags = false) broken in v1.8.x

Post by Transmitter » Fri Nov 11, 2011 2:04 pm

I'm using the latest stable version (1.9.1) of getID3.
But unfortunately the overwrite_tags Bug seems to be still inside.

Is there a fix available or any workaround for this Problem, ?
I tried several other ID3 Libaries, to handle ID3 Informations,
but everytime I fail at editing Tags.

James Heinrich
getID3() v1 developer
Posts: 1475
Joined: Fri May 04, 2001 4:00 pm
Are you a spambot?: no
Location: Northern Ontario, Canada
Contact:

Re: ($tagwriter->overwrite_tags = false) broken in v1.8.x

Post by James Heinrich » Sun Nov 13, 2011 7:49 pm

Just confirming it is not yet fixed as of the current version (v1.9.1).
Rewriting the tag-writing code to fix all known issues is on the priority to-do list, but a fixed version will not likely be out until around the end of 2011.

Plastic Soul
User
Posts: 1
Joined: Mon Jan 23, 2012 9:58 pm
Are you a spambot?: no

Re: ($tagwriter->overwrite_tags = false) broken in v1.8.x

Post by Plastic Soul » Mon Jan 23, 2012 10:14 pm

Hello,
I'm new IdTag3 user for my personal developement...

Great tools James !!!

Ok I'm try to update my Tags from my audio library and with the "demo.write.php" document after "update" a cover and went i want to change "again" somes orthers informations ... my cover was deleted...

After lot of work... I see this comment... aarg ! :-p

but... here i have a solution... and it work fine !

I give you my edit of the "demo.write.php" document...

let me know if this edit help you ... at gildc@yahoo.fr

cya

Plastic Soul

Code: Select all

<?php
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org>               //
//  available at http://getid3.sourceforge.net                 //
//            or http://www.getid3.org                         //
/////////////////////////////////////////////////////////////////
//                                                             //
// /demo/demo.write.php - part of getID3()                     //
// sample script for demonstrating writing ID3v1 and ID3v2     //
// tags for MP3, or Ogg comment tags for Ogg Vorbis            //
// See readme.txt for more details                             //
//                                                            ///
/////////////////////////////////////////////////////////////////


//die('Due to a security issue, this demo has been disabled. It can be enabled by removing line '.__LINE__.' in '.$_SERVER['PHP_SELF']);

$TaggingFormat = 'UTF-8';

header('Content-Type: text/html; charset='.$TaggingFormat);
echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">';
echo '<html><head><title>getID3() - Sample tag writer</title></head><style type="text/css">BODY,TD,TH { font-family: sans-serif; font-size: 9pt;" }</style><body>';

require_once('../getid3/getid3.php');
// Initialize getID3 engine
$getID3 = new getID3;
$getID3->setOption(array('encoding'=>$TaggingFormat));

getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'write.php', __FILE__, true);

$browsescriptfilename = 'demo.browse.php';

$Filename = (isset($_REQUEST['Filename']) ? $_REQUEST['Filename'] : '');


if (isset($_POST['WriteTags'])) {

	$TagFormatsToWrite = (isset($_POST['TagFormatsToWrite']) ? $_POST['TagFormatsToWrite'] : array());
	if (!empty($TagFormatsToWrite)) {
		echo 'starting to write tag(s)<BR>';

		$tagwriter = new getid3_writetags;
		$tagwriter->filename       = $Filename;
		$tagwriter->tagformats     = $TagFormatsToWrite;
		$tagwriter->overwrite_tags = true;
		$tagwriter->tag_encoding   = $TaggingFormat;
		if (!empty($_POST['remove_other_tags'])) {
			$tagwriter->remove_other_tags = true;
		}

		$commonkeysarray = array('Title', 'Artist', 'Album', 'Year', 'Comment');
		foreach ($commonkeysarray as $key) {
			if (!empty($_POST[$key])) {
				$TagData[strtolower($key)][] = $_POST[$key];
			}
		}
		if (!empty($_POST['Genre'])) {
			$TagData['genre'][] = $_POST['Genre'];
		}
		if (!empty($_POST['GenreOther'])) {
			$TagData['genre'][] = $_POST['GenreOther'];
		}
		if (!empty($_POST['Track'])) {
			$TagData['track'][] = $_POST['Track'].(!empty($_POST['TracksTotal']) ? '/'.$_POST['TracksTotal'] : '');
		}
		
//If Cover exist
		
		$getID3 = new getID3;
		$OldThisFileInfo = $getID3->analyze($Filename);
		getid3_lib::CopyTagsToComments($OldThisFileInfo);
		
		
			$imagepic = $OldThisFileInfo['comments']['picture'];
			$img_mime = $imagepic [0]['image_mime'];
			$data_img = $imagepic[0]['data'];
			$img_name = $OldThisFileInfo ['id3v2']['APIC'][0]['description'];
			$path = ('data:').$img_mime.(';base64,').base64_encode($data_img);
	
		 	
			if (!empty($path) && empty($_FILES['userfile']['tmp_name'])) {
		
				if (in_array('id3v2.4', $tagwriter->tagformats) || in_array('id3v2.3', $tagwriter->tagformats) || in_array('id3v2.2', $tagwriter->tagformats)) {
				
						ob_start();
					if ($fd = fopen($path, 'rb')) {
						ob_end_clean();
						$APICdata = fread($fd, filesize($path));
						fclose ($fd);

						list($APIC_width, $APIC_height, $APIC_imageTypeID) = GetImageSize($path);
						$imagetypes = array(1=>'gif', 2=>'jpeg', 3=>'png');
						if (isset($imagetypes[$APIC_imageTypeID])) {

							$TagData['attached_picture'][0]['data']          = $data_img;
							$TagData['attached_picture'][0]['picturetypeid'] = $_POST['APICpictureType'];
							$TagData['attached_picture'][0]['description']   = $img_name;
							$TagData['attached_picture'][0]['mime']          = 'image/'.$imagetypes[$APIC_imageTypeID];
							

						} else {
							echo '<b>invalid image format (only GIF, JPEG, PNG)</b><br>';
						}
					} else {
						$errormessage = ob_get_contents();
						ob_end_clean();
						echo '<b>cannot open '.$path.'</b><br>';
					}
				} else {
					echo '<b>!is_uploaded_file('.$path.')</b><br>';
				}
			} else {
				echo '<b>WARNING:</b> Can only embed images for ID3v2<br>';
		}
		  
//If Add new Cover

		  
		if (!empty($_FILES['userfile']['tmp_name'])) {
			if (in_array('id3v2.4', $tagwriter->tagformats) || in_array('id3v2.3', $tagwriter->tagformats) || in_array('id3v2.2', $tagwriter->tagformats)) {
				if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
					ob_start();
					if ($fd = fopen($_FILES['userfile']['tmp_name'], 'rb')) {
						ob_end_clean();
						$APICdata = fread($fd, filesize($_FILES['userfile']['tmp_name']));
						fclose ($fd);

						list($APIC_width, $APIC_height, $APIC_imageTypeID) = GetImageSize($_FILES['userfile']['tmp_name']);
						$imagetypes = array(1=>'gif', 2=>'jpeg', 3=>'png');
						if (isset($imagetypes[$APIC_imageTypeID])) {

							$TagData['attached_picture'][0]['data']          = $APICdata;
							$TagData['attached_picture'][0]['picturetypeid'] = $_POST['APICpictureType'];
							$TagData['attached_picture'][0]['description']   = $_FILES['userfile']['name'];
							$TagData['attached_picture'][0]['mime']          = 'image/'.$imagetypes[$APIC_imageTypeID];


						} else {
							echo '<b>invalid image format (only GIF, JPEG, PNG)</b><br>';
						}
					} else {
						$errormessage = ob_get_contents();
						ob_end_clean();
						echo '<b>cannot open '.$_FILES['userfile']['tmp_name'].'</b><br>';
					}
				} else {
					echo '<b>!is_uploaded_file('.$_FILES['userfile']['tmp_name'].')</b><br>';
				}
			} else {
				echo '<b>WARNING:</b> Can only embed images for ID3v2<br>';
			}
		}

		$tagwriter->tag_data = $TagData;
		if ($tagwriter->WriteTags()) {
			echo 'Successfully wrote tags<BR>';
			if (!empty($tagwriter->warnings)) {
				echo 'There were some warnings:<BLOCKQUOTE STYLE="background-color:#FFCC33; padding: 10px;">'.implode('<BR><BR>', $tagwriter->warnings).'</BLOCKQUOTE>';
			}
		} else {
			echo 'Failed to write tags!<BLOCKQUOTE STYLE="background-color:#FF9999; padding: 10px;">'.implode('<BR><BR>', $tagwriter->errors).'</BLOCKQUOTE>';
		}

	} else {

		echo 'WARNING: no tag formats selected for writing - nothing written';

	}
	echo '<HR>';

}


echo '<div><span style="font-size: 1.2em; font-weight: bold;">Sample tag editor/writer</span><span style=" color:#777; font-size: 1em; font-weight: bold;"><br />Edited by Plastic Soul</span></div>';
echo '<a href="'.htmlentities($browsescriptfilename.'?listdirectory='.rawurlencode(realpath(dirname($Filename))), ENT_QUOTES).'">Browse current directory</a><br>';
if (!empty($Filename)) {
	
		$getID3 = new getID3;
		$OldThisFileInfo = $getID3->analyze($Filename);
		getid3_lib::CopyTagsToComments($OldThisFileInfo);
		
	echo '<a href="'.htmlentities($_SERVER['PHP_SELF'], ENT_QUOTES).'">Start Over</a><br><br>';
	echo '<form action="'.htmlentities($_SERVER['PHP_SELF'], ENT_QUOTES).'" method="post" enctype="multipart/form-data">';
	echo '<div><table border="3" cellspacing="0" cellpadding="4">';
	echo '<tr><th align="right">File Name</th><td >'.$OldThisFileInfo['filename'].'</td></tr>';
	
	echo '<tr><th align="right">File Path</th><td ><input type="hidden" name="Filename" value="'.htmlentities($Filename, ENT_QUOTES).'"><a href="'.htmlentities($browsescriptfilename.'?filename='.rawurlencode($Filename), ENT_QUOTES).'" target="_blank">'.$Filename.'</a></td></tr>';
	if (file_exists($Filename)) {

		// Initialize getID3 engine
		$getID3 = new getID3;
		$OldThisFileInfo = $getID3->analyze($Filename);
		getid3_lib::CopyTagsToComments($OldThisFileInfo);

		switch ($OldThisFileInfo['fileformat']) {
			case 'mp3':
			case 'mp2':
			case 'mp1':
				$ValidTagTypes = array('id3v1', 'id3v2.3', 'ape');
				break;

			case 'mpc':
				$ValidTagTypes = array('ape');
				break;

			case 'ogg':
				if (!empty($OldThisFileInfo['audio']['dataformat']) && ($OldThisFileInfo['audio']['dataformat'] == 'flac')) {
					//$ValidTagTypes = array('metaflac');
					// metaflac doesn't (yet) work with OggFLAC files
					$ValidTagTypes = array();
				} else {
					$ValidTagTypes = array('vorbiscomment');
				}
				break;

			case 'flac':
				$ValidTagTypes = array('metaflac');
				break;

			case 'real':
				$ValidTagTypes = array('real');
				break;

			default:
				$ValidTagTypes = array();
				break;
		}

					
		echo '<tr><th align="right">Title</th> <td><input class="input_form_in" type="text" size="32" name="Title"  value="'.htmlentities((!empty($OldThisFileInfo['comments']['title'])  ? implode(', ', $OldThisFileInfo['comments']['title'] ) : ''), ENT_QUOTES).'"></td></tr>';
		echo '<tr><th align="right">Artist</th><td><input type="text" size="32" name="Artist" value="'.htmlentities((!empty($OldThisFileInfo['comments']['artist']) ? implode(', ', $OldThisFileInfo['comments']['artist']) : ''), ENT_QUOTES).'"></td></tr>';
		echo '<tr><th align="right">Album</th> <td><input type="text" size="32" name="Album"  value="'.htmlentities((!empty($OldThisFileInfo['comments']['album'])  ? implode(', ', $OldThisFileInfo['comments']['album'] ) : ''), ENT_QUOTES).'"></td></tr>';
		echo '<tr><th align="right">Year</th>  <td><input type="text" size="4"  name="Year"   value="'.htmlentities((!empty($OldThisFileInfo['comments']['year'])   ? implode(', ', $OldThisFileInfo['comments']['year']  ) : ''), ENT_QUOTES).'"></td></tr>';

		$TracksTotal = '';
		$TrackNumber = '';
		if (!empty($OldThisFileInfo['comments']['track_number']) && is_array($OldThisFileInfo['comments']['track_number'])) {
			$RawTrackNumberArray = $OldThisFileInfo['comments']['track_number'];
		} elseif (!empty($OldThisFileInfo['comments']['track']) && is_array($OldThisFileInfo['comments']['track'])) {
			$RawTrackNumberArray = $OldThisFileInfo['comments']['track'];
		} else {
			$RawTrackNumberArray = array();
		}
		foreach ($RawTrackNumberArray as $key => $value) {
			if (strlen($value) > strlen($TrackNumber)) {
				// ID3v1 may store track as "3" but ID3v2/APE would store as "03/16"
				$TrackNumber = $value;
			}
		}
		if (strstr($TrackNumber, '/')) {
			list($TrackNumber, $TracksTotal) = explode('/', $TrackNumber);
		}
		echo '<tr><th align="right">Track</th><td><input type="text" size="2" name="Track" value="'.htmlentities($TrackNumber, ENT_QUOTES).'"> of <input type="text" size="2" name="TracksTotal" value="'.htmlentities($TracksTotal, ENT_QUOTES).'"></TD></TR>';

		$ArrayOfGenresTemp = getid3_id3v1::ArrayOfGenres();   // get the array of genres
		foreach ($ArrayOfGenresTemp as $key => $value) {      // change keys to match displayed value
			$ArrayOfGenres[$value] = $value;
		}
		unset($ArrayOfGenresTemp);                            // remove temporary array
		unset($ArrayOfGenres['Cover']);                       // take off these special cases
		unset($ArrayOfGenres['Remix']);
		unset($ArrayOfGenres['Unknown']);
		$ArrayOfGenres['']      = '- Unknown -';              // Add special cases back in with renamed key/value
		$ArrayOfGenres['Cover'] = '-Cover-';
		$ArrayOfGenres['Remix'] = '-Remix-';
		asort($ArrayOfGenres);                                // sort into alphabetical order
		echo '<tr><th align="right">Genre</th><td><select name="Genre" style="width:120px">';
		$AllGenresArray = (!empty($OldThisFileInfo['comments']['genre']) ? $OldThisFileInfo['comments']['genre'] : array());
		foreach ($ArrayOfGenres as $key => $value) {
			echo '<option value="'.htmlentities($key, ENT_QUOTES).'"';
			if (in_array($key, $AllGenresArray)) {
				echo ' selected="selected"';
				unset($AllGenresArray[array_search($key, $AllGenresArray)]);
				sort($AllGenresArray);
			}
			echo '>'.htmlentities($value).'</option>';
		}
		echo '</select>  <input type="text" name="GenreOther" size="10" value="'.htmlentities((!empty($AllGenresArray[0]) ? $AllGenresArray[0] : ''), ENT_QUOTES).'"></td></tr>';

		echo '<tr><th align="right">Write Tags</th><td>';
		foreach ($ValidTagTypes as $ValidTagType) {
			echo '<input type="checkbox" name="TagFormatsToWrite[]" value="'.$ValidTagType.'"';
			if (count($ValidTagTypes) == 1) {
				echo ' checked="checked"';
			} else {
				switch ($ValidTagType) {
					case 'id3v2.2':
					case 'id3v2.3':
					case 'id3v2.4':
						if (isset($OldThisFileInfo['tags']['id3v2'])) {
							echo ' checked="checked"';
						}
						break;

					default:
						if (isset($OldThisFileInfo['tags'][$ValidTagType])) {
							echo ' checked="checked"';
						}
						break;
				}
			}
			echo '>'.$ValidTagType;
		}
		if (count($ValidTagTypes) > 1) {
			echo '<hr><input type="checkbox" name="remove_other_tags" value="1"> <span style="font-size:9px">Remove non-selected tag formats when writing new...</span><br>';
		}
		echo '</td></tr>';

		echo '<tr><th align="right">Comment</th><td><textarea cols="28" rows="3" name="Comment" wrap="virtual">'.((isset($OldThisFileInfo['comments']['comment']) && is_array($OldThisFileInfo['comments']['comment'])) ? implode("\n", $OldThisFileInfo['comments']['comment']) : '').'</textarea></td></tr>';

		echo '<tr><th align="right"><span>Picture</span><br /><span style="font-size:9px">(ID3v2 only)</span></th><td>';
		
		// Show Cover
		
		$imagepic = $OldThisFileInfo['comments']['picture'];
		$img_mime = $imagepic [0]['image_mime'];
		$data_img = $imagepic[0]['data'];
	echo '<img src="data:'.$img_mime.';base64,'.base64_encode($data_img).'" style="'.'max-width:150px">';
	echo'<br />';
		
				echo '<input type="file" name="userfile" accept="image/jpeg, image/gif, image/png"><br>';
		echo '<select name="APICpictureType">';
		$APICtypes = getid3_id3v2::APICPictureTypeLookup('', true);
		foreach ($APICtypes as $key => $value) {
			echo '<option value="'.htmlentities($key, ENT_QUOTES).'">'.htmlentities($value).'</option>';
		}
		echo '</select><br /></td></tr>';
		echo '<tr><td align="center" colspan="2"><input type="submit" name="WriteTags" value="Save Changes"> ';
		echo '<input type="reset" value="Reset"></td></tr>';

	} else {

		echo '<tr><td align="right"><b>Error</b></td><td>'.htmlentities($Filename).' does not exist</td></tr>';

	}
	echo '</table></div>';
	echo '</form>';

}

?>

</body>
</html>

Falko
User
Posts: 1
Joined: Wed May 23, 2012 9:34 am
Are you a spambot?: no

Re: ($tagwriter->overwrite_tags = false) broken in v1.8.x

Post by Falko » Wed May 23, 2012 10:05 am

Hi Plastic Soul,

I tried your Solution and recognized a problem on writing the data back to the mp3 file:

Code: Select all

Warning: filesize() [function.filesize]: stat failed for data:image/jpeg;base64,/9j/4AAQSkZJRg...
In your code sample I saw the following line:

Code: Select all

$path = ('data:').$img_mime.(';base64,').base64_encode($data_img);
and a few lines later:

Code: Select all

 if ($fd = fopen($path, 'rb')) {
                      ob_end_clean();
                      $APICdata = fread($fd, filesize($path));
                      fclose ($fd);
which looks strange, cause $path does not really contain a file path here. What went wrong?

Is there any other solution for the problem of writing data without deleting other tags?

Regards
Falko

Post Reply