00001 <?php
00004
00005
00007
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00021
00022 if (!defined('GETID3_INCLUDEPATH')) {
00023 die('getid3.php MUST be included before calling getid3_writetags');
00024 }
00025 if (!include_once(GETID3_INCLUDEPATH.'getid3.lib.php')) {
00026 die('write.php depends on getid3.lib.php, which is missing.');
00027 }
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 class getid3_writetags
00048 {
00049
00050 var $filename;
00051 var $tagformats = array();
00052 var $tag_data = array(array());
00053 var $tag_encoding = 'ISO-8859-1';
00054 var $overwrite_tags = true;
00055 var $remove_other_tags = false;
00056
00057 var $id3v2_tag_language = 'eng';
00058 var $id3v2_paddedlength = 4096;
00059
00060 var $warnings = array();
00061 var $errors = array();
00062
00063
00064 var $ThisFileInfo;
00065
00066 function getid3_writetags() {
00067 return true;
00068 }
00069
00070
00071 function WriteTags() {
00072
00073 if (empty($this->filename)) {
00074 $this->errors[] = 'filename is undefined in getid3_writetags';
00075 return false;
00076 } elseif (!file_exists($this->filename)) {
00077 $this->errors[] = 'filename set to non-existant file "'.$this->filename.'" in getid3_writetags';
00078 return false;
00079 }
00080
00081 if (!is_array($this->tagformats)) {
00082 $this->errors[] = 'tagformats must be an array in getid3_writetags';
00083 return false;
00084 }
00085
00086 $TagFormatsToRemove = array();
00087 if (filesize($this->filename) == 0) {
00088
00089
00090
00091 $this->ThisFileInfo = array('fileformat'=>'');
00092 $AllowedTagFormats = array('id3v1', 'id3v2.2', 'id3v2.3', 'id3v2.4', 'ape', 'lyrics3');
00093
00094 } else {
00095
00096 $getID3 = new getID3;
00097 $getID3->encoding = $this->tag_encoding;
00098 $this->ThisFileInfo = $getID3->analyze($this->filename);
00099
00100
00101 switch (@$this->ThisFileInfo['fileformat']) {
00102 case 'mp3':
00103 case 'mp2':
00104 case 'mp1':
00105 case 'riff':
00106 $AllowedTagFormats = array('id3v1', 'id3v2.2', 'id3v2.3', 'id3v2.4', 'ape', 'lyrics3');
00107 break;
00108
00109 case 'mpc':
00110 $AllowedTagFormats = array('ape');
00111 break;
00112
00113 case 'flac':
00114 $AllowedTagFormats = array('metaflac');
00115 break;
00116
00117 case 'real':
00118 $AllowedTagFormats = array('real');
00119 break;
00120
00121 case 'ogg':
00122 switch (@$this->ThisFileInfo['audio']['dataformat']) {
00123 case 'flac':
00124
00125 $this->errors[] = 'metaflac is not (yet) compatible with OggFLAC files';
00126 return false;
00127 break;
00128 case 'vorbis':
00129 $AllowedTagFormats = array('vorbiscomment');
00130 break;
00131 default:
00132 $this->errors[] = 'metaflac is not (yet) compatible with Ogg files other than OggVorbis';
00133 return false;
00134 break;
00135 }
00136 break;
00137
00138 default:
00139 $AllowedTagFormats = array();
00140 break;
00141 }
00142 foreach ($this->tagformats as $requested_tag_format) {
00143 if (!in_array($requested_tag_format, $AllowedTagFormats)) {
00144 $errormessage = 'Tag format "'.$requested_tag_format.'" is not allowed on "'.@$this->ThisFileInfo['fileformat'];
00145 if (@$this->ThisFileInfo['fileformat'] != @$this->ThisFileInfo['audio']['dataformat']) {
00146 $errormessage .= '.'.@$this->ThisFileInfo['audio']['dataformat'];
00147 }
00148 $errormessage .= '" files';
00149 $this->errors[] = $errormessage;
00150 return false;
00151 }
00152 }
00153
00154
00155 if ($this->remove_other_tags) {
00156 foreach ($AllowedTagFormats as $AllowedTagFormat) {
00157 switch ($AllowedTagFormat) {
00158 case 'id3v2.2':
00159 case 'id3v2.3':
00160 case 'id3v2.4':
00161 if (!in_array('id3v2', $TagFormatsToRemove) && !in_array('id3v2.2', $this->tagformats) && !in_array('id3v2.3', $this->tagformats) && !in_array('id3v2.4', $this->tagformats)) {
00162 $TagFormatsToRemove[] = 'id3v2';
00163 }
00164 break;
00165
00166 default:
00167 if (!in_array($AllowedTagFormat, $this->tagformats)) {
00168 $TagFormatsToRemove[] = $AllowedTagFormat;
00169 }
00170 break;
00171 }
00172 }
00173 }
00174 }
00175
00176 $WritingFilesToInclude = array_merge($this->tagformats, $TagFormatsToRemove);
00177
00178
00179 foreach ($WritingFilesToInclude as $tagformat) {
00180 switch ($tagformat) {
00181 case 'ape':
00182 $GETID3_ERRORARRAY = &$this->errors;
00183 if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'write.apetag.php', __FILE__, false)) {
00184 return false;
00185 }
00186 break;
00187
00188 case 'id3v1':
00189 case 'lyrics3':
00190 case 'vorbiscomment':
00191 case 'metaflac':
00192 case 'real':
00193 $GETID3_ERRORARRAY = &$this->errors;
00194 if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'write.'.$tagformat.'.php', __FILE__, false)) {
00195 return false;
00196 }
00197 break;
00198
00199 case 'id3v2.2':
00200 case 'id3v2.3':
00201 case 'id3v2.4':
00202 case 'id3v2':
00203 $GETID3_ERRORARRAY = &$this->errors;
00204 if (!getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'write.id3v2.php', __FILE__, false)) {
00205 return false;
00206 }
00207 break;
00208
00209 default:
00210 $this->errors[] = 'unknown tag format "'.$tagformat.'" in $tagformats in WriteTags()';
00211 return false;
00212 break;
00213 }
00214
00215 }
00216
00217
00218 if (!is_array($this->tag_data)) {
00219 $this->errors[] = '$tag_data is not an array in WriteTags()';
00220 return false;
00221 }
00222
00223 foreach ($this->tag_data as $tag_key => $tag_array) {
00224 if (strtoupper($tag_key) !== $tag_key) {
00225 $this->tag_data[strtoupper($tag_key)] = $this->tag_data[$tag_key];
00226 unset($this->tag_data[$tag_key]);
00227 }
00228 }
00229
00230 if (!empty($this->ThisFileInfo['tags'])) {
00231 foreach ($this->ThisFileInfo['tags'] as $tag_format => $tag_data_array) {
00232 foreach ($tag_data_array as $tag_key => $tag_array) {
00233 if (strtoupper($tag_key) !== $tag_key) {
00234 $this->ThisFileInfo['tags'][$tag_format][strtoupper($tag_key)] = $this->ThisFileInfo['tags'][$tag_format][$tag_key];
00235 unset($this->ThisFileInfo['tags'][$tag_format][$tag_key]);
00236 }
00237 }
00238 }
00239 }
00240
00241
00242 if (isset($this->tag_data['TRACK']) && !isset($this->tag_data['TRACKNUMBER'])) {
00243 $this->tag_data['TRACKNUMBER'] = $this->tag_data['TRACK'];
00244 unset($this->tag_data['TRACK']);
00245 }
00246
00247
00248 if ($this->remove_other_tags) {
00249 $this->DeleteTags($TagFormatsToRemove);
00250 }
00251
00252
00253 foreach ($this->tagformats as $tagformat) {
00254 $success = false;
00255 switch ($tagformat) {
00256 case 'ape':
00257 $ape_writer = new getid3_write_apetag;
00258 if (($ape_writer->tag_data = $this->FormatDataForAPE()) !== false) {
00259 $ape_writer->filename = $this->filename;
00260 if (($success = $ape_writer->WriteAPEtag()) === false) {
00261 $this->errors[] = 'WriteAPEtag() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $ape_writer->errors)).'</LI></UL></PRE>';
00262 }
00263 } else {
00264 $this->errors[] = 'FormatDataForAPE() failed';
00265 }
00266 break;
00267
00268 case 'id3v1':
00269 $id3v1_writer = new getid3_write_id3v1;
00270 if (($id3v1_writer->tag_data = $this->FormatDataForID3v1()) !== false) {
00271 $id3v1_writer->filename = $this->filename;
00272 if (($success = $id3v1_writer->WriteID3v1()) === false) {
00273 $this->errors[] = 'WriteID3v1() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $id3v1_writer->errors)).'</LI></UL></PRE>';
00274 }
00275 } else {
00276 $this->errors[] = 'FormatDataForID3v1() failed';
00277 }
00278 break;
00279
00280 case 'id3v2.2':
00281 case 'id3v2.3':
00282 case 'id3v2.4':
00283 $id3v2_writer = new getid3_write_id3v2;
00284 $id3v2_writer->majorversion = intval(substr($tagformat, -1));
00285 $id3v2_writer->paddedlength = $this->id3v2_paddedlength;
00286 if (($id3v2_writer->tag_data = $this->FormatDataForID3v2($id3v2_writer->majorversion)) !== false) {
00287 $id3v2_writer->filename = $this->filename;
00288 if (($success = $id3v2_writer->WriteID3v2()) === false) {
00289 $this->errors[] = 'WriteID3v2() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $id3v2_writer->errors)).'</LI></UL></PRE>';
00290 }
00291 } else {
00292 $this->errors[] = 'FormatDataForID3v2() failed';
00293 }
00294 break;
00295
00296 case 'vorbiscomment':
00297 $vorbiscomment_writer = new getid3_write_vorbiscomment;
00298 if (($vorbiscomment_writer->tag_data = $this->FormatDataForVorbisComment()) !== false) {
00299 $vorbiscomment_writer->filename = $this->filename;
00300 if (($success = $vorbiscomment_writer->WriteVorbisComment()) === false) {
00301 $this->errors[] = 'WriteVorbisComment() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $vorbiscomment_writer->errors)).'</LI></UL></PRE>';
00302 }
00303 } else {
00304 $this->errors[] = 'FormatDataForVorbisComment() failed';
00305 }
00306 break;
00307
00308 case 'metaflac':
00309 $metaflac_writer = new getid3_write_metaflac;
00310 if (($metaflac_writer->tag_data = $this->FormatDataForMetaFLAC()) !== false) {
00311 $metaflac_writer->filename = $this->filename;
00312 if (($success = $metaflac_writer->WriteMetaFLAC()) === false) {
00313 $this->errors[] = 'WriteMetaFLAC() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $metaflac_writer->errors)).'</LI></UL></PRE>';
00314 }
00315 } else {
00316 $this->errors[] = 'FormatDataForMetaFLAC() failed';
00317 }
00318 break;
00319
00320 case 'real':
00321 $real_writer = new getid3_write_real;
00322 if (($real_writer->tag_data = $this->FormatDataForReal()) !== false) {
00323 $real_writer->filename = $this->filename;
00324 if (($success = $real_writer->WriteReal()) === false) {
00325 $this->errors[] = 'WriteReal() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $real_writer->errors)).'</LI></UL></PRE>';
00326 }
00327 } else {
00328 $this->errors[] = 'FormatDataForReal() failed';
00329 }
00330 break;
00331
00332 default:
00333 $this->errors[] = 'Invalid tag format to write: "'.$tagformat.'"';
00334 return false;
00335 break;
00336 }
00337 if (!$success) {
00338 return false;
00339 }
00340 }
00341 return true;
00342
00343 }
00344
00345
00346 function DeleteTags($TagFormatsToDelete) {
00347 foreach ($TagFormatsToDelete as $DeleteTagFormat) {
00348 $success = false;
00349 switch ($DeleteTagFormat) {
00350 case 'id3v1':
00351 $id3v1_writer = new getid3_write_id3v1;
00352 $id3v1_writer->filename = $this->filename;
00353 if (($success = $id3v1_writer->RemoveID3v1()) === false) {
00354 $this->errors[] = 'RemoveID3v1() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $id3v1_writer->errors)).'</LI></UL></PRE>';
00355 }
00356 break;
00357
00358 case 'id3v2':
00359 $id3v2_writer = new getid3_write_id3v2;
00360 $id3v2_writer->filename = $this->filename;
00361 if (($success = $id3v2_writer->RemoveID3v2()) === false) {
00362 $this->errors[] = 'RemoveID3v2() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $id3v2_writer->errors)).'</LI></UL></PRE>';
00363 }
00364 break;
00365
00366 case 'ape':
00367 $ape_writer = new getid3_write_apetag;
00368 $ape_writer->filename = $this->filename;
00369 if (($success = $ape_writer->DeleteAPEtag()) === false) {
00370 $this->errors[] = 'DeleteAPEtag() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $ape_writer->errors)).'</LI></UL></PRE>';
00371 }
00372 break;
00373
00374 case 'vorbiscomment':
00375 $vorbiscomment_writer = new getid3_write_vorbiscomment;
00376 $vorbiscomment_writer->filename = $this->filename;
00377 if (($success = $vorbiscomment_writer->DeleteVorbisComment()) === false) {
00378 $this->errors[] = 'DeleteVorbisComment() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $vorbiscomment_writer->errors)).'</LI></UL></PRE>';
00379 }
00380 break;
00381
00382 case 'metaflac':
00383 $metaflac_writer = new getid3_write_metaflac;
00384 $metaflac_writer->filename = $this->filename;
00385 if (($success = $metaflac_writer->DeleteMetaFLAC()) === false) {
00386 $this->errors[] = 'DeleteMetaFLAC() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $metaflac_writer->errors)).'</LI></UL></PRE>';
00387 }
00388 break;
00389
00390 case 'lyrics3':
00391 $lyrics3_writer = new getid3_write_lyrics3;
00392 $lyrics3_writer->filename = $this->filename;
00393 if (($success = $lyrics3_writer->DeleteLyrics3()) === false) {
00394 $this->errors[] = 'DeleteLyrics3() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $lyrics3_writer->errors)).'</LI></UL></PRE>';
00395 }
00396 break;
00397
00398 case 'real':
00399 $real_writer = new getid3_write_real;
00400 $real_writer->filename = $this->filename;
00401 if (($success = $real_writer->RemoveReal()) === false) {
00402 $this->errors[] = 'RemoveReal() failed with message(s):<PRE><UL><LI>'.trim(implode('</LI><LI>', $real_writer->errors)).'</LI></UL></PRE>';
00403 }
00404 break;
00405
00406 default:
00407 $this->errors[] = 'Invalid tag format to delete: "'.$tagformat.'"';
00408 return false;
00409 break;
00410 }
00411 if (!$success) {
00412 return false;
00413 }
00414 }
00415 return true;
00416 }
00417
00418
00419 function MergeExistingTagData($TagFormat, &$tag_data) {
00420
00421 if ($this->overwrite_tags) {
00422
00423 } else {
00424 if (!isset($this->ThisFileInfo['tags'][$TagFormat])) {
00425 return false;
00426 }
00427 $tag_data = array_merge_recursive($tag_data, $this->ThisFileInfo['tags'][$TagFormat]);
00428 }
00429 return true;
00430 }
00431
00432 function FormatDataForAPE() {
00433 $ape_tag_data = array();
00434 foreach ($this->tag_data as $tag_key => $valuearray) {
00435 switch ($tag_key) {
00436 case 'ATTACHED_PICTURE':
00437
00438 $this->warnings[] = '$data['.$tag_key.'] is assumed to be ID3v2 APIC data - NOT written to APE tag';
00439 break;
00440
00441 default:
00442 foreach ($valuearray as $key => $value) {
00443 if (is_string($value) || is_numeric($value)) {
00444 $ape_tag_data[$tag_key][$key] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $value);
00445 } else {
00446 $this->warnings[] = '$data['.$tag_key.']['.$key.'] is not a string value - all of $data['.$tag_key.'] NOT written to APE tag';
00447 unset($ape_tag_data[$tag_key]);
00448 break;
00449 }
00450 }
00451 break;
00452 }
00453 }
00454 $this->MergeExistingTagData('ape', $ape_tag_data);
00455 return $ape_tag_data;
00456 }
00457
00458
00459 function FormatDataForID3v1() {
00460 $tag_data_id3v1['genreid'] = 255;
00461 if (!empty($this->tag_data['GENRE'])) {
00462 foreach ($this->tag_data['GENRE'] as $key => $value) {
00463 if (getid3_id3v1::LookupGenreID($value) !== false) {
00464 $tag_data_id3v1['genreid'] = getid3_id3v1::LookupGenreID($value);
00465 break;
00466 }
00467 }
00468 }
00469
00470 $tag_data_id3v1['title'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', @implode(' ', @$this->tag_data['TITLE']));
00471 $tag_data_id3v1['artist'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', @implode(' ', @$this->tag_data['ARTIST']));
00472 $tag_data_id3v1['album'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', @implode(' ', @$this->tag_data['ALBUM']));
00473 $tag_data_id3v1['year'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', @implode(' ', @$this->tag_data['YEAR']));
00474 $tag_data_id3v1['comment'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', @implode(' ', @$this->tag_data['COMMENT']));
00475
00476 $tag_data_id3v1['track'] = intval(getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', @implode(' ', @$this->tag_data['TRACKNUMBER'])));
00477 if ($tag_data_id3v1['track'] <= 0) {
00478 $tag_data_id3v1['track'] = '';
00479 }
00480
00481 $this->MergeExistingTagData('id3v1', $tag_data_id3v1);
00482 return $tag_data_id3v1;
00483 }
00484
00485 function FormatDataForID3v2($id3v2_majorversion) {
00486 $tag_data_id3v2 = array();
00487
00488 $ID3v2_text_encoding_lookup[2] = array('ISO-8859-1'=>0, 'UTF-16'=>1);
00489 $ID3v2_text_encoding_lookup[3] = array('ISO-8859-1'=>0, 'UTF-16'=>1);
00490 $ID3v2_text_encoding_lookup[4] = array('ISO-8859-1'=>0, 'UTF-16'=>1, 'UTF-16BE'=>2, 'UTF-8'=>3);
00491 foreach ($this->tag_data as $tag_key => $valuearray) {
00492 $ID3v2_framename = getid3_write_id3v2::ID3v2ShortFrameNameLookup($id3v2_majorversion, $tag_key);
00493 switch ($ID3v2_framename) {
00494 case 'APIC':
00495 foreach ($valuearray as $key => $apic_data_array) {
00496 if (isset($apic_data_array['data']) &&
00497 isset($apic_data_array['picturetypeid']) &&
00498 isset($apic_data_array['description']) &&
00499 isset($apic_data_array['mime'])) {
00500 $tag_data_id3v2['APIC'][] = $apic_data_array;
00501 } else {
00502 $this->errors[] = 'ID3v2 APIC data is not properly structured';
00503 return false;
00504 }
00505 }
00506 break;
00507
00508 case '':
00509 $this->errors[] = 'ID3v2: Skipping "'.$tag_key.'" because cannot match it to a known ID3v2 frame type';
00510
00511 break;
00512
00513 default:
00514
00515 foreach ($valuearray as $key => $value) {
00516 if (isset($ID3v2_text_encoding_lookup[$id3v2_majorversion][$this->tag_encoding])) {
00517
00518 $tag_data_id3v2[$ID3v2_framename][$key]['encodingid'] = $ID3v2_text_encoding_lookup[$id3v2_majorversion][$this->tag_encoding];
00519 $tag_data_id3v2[$ID3v2_framename][$key]['data'] = $value;
00520 } else {
00521
00522 if ($id3v2_majorversion < 4) {
00523
00524 $tag_data_id3v2[$ID3v2_framename][$key]['encodingid'] = 1;
00525 $tag_data_id3v2[$ID3v2_framename][$key]['data'] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-16', $value);
00526
00527 } else {
00528
00529 $tag_data_id3v2[$ID3v2_framename][$key]['encodingid'] = 3;
00530 $tag_data_id3v2[$ID3v2_framename][$key]['data'] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $value);
00531 }
00532 }
00533
00534
00535 $tag_data_id3v2[$ID3v2_framename][$key]['description'] = '';
00536 $tag_data_id3v2[$ID3v2_framename][$key]['language'] = $this->id3v2_tag_language;
00537 }
00538 break;
00539 }
00540 }
00541 $this->MergeExistingTagData('id3v2', $tag_data_id3v2);
00542 return $tag_data_id3v2;
00543 }
00544
00545 function FormatDataForVorbisComment() {
00546 $tag_data_vorbiscomment = $this->tag_data;
00547
00548
00549
00550 foreach ($tag_data_vorbiscomment as $tag_key => $valuearray) {
00551 foreach ($valuearray as $key => $value) {
00552 str_replace("\r", "\n", $value);
00553 if (strstr($value, "\n")) {
00554 unset($tag_data_vorbiscomment[$tag_key][$key]);
00555 $multilineexploded = explode("\n", $value);
00556 foreach ($multilineexploded as $newcomment) {
00557 if (strlen(trim($newcomment)) > 0) {
00558 $tag_data_vorbiscomment[$tag_key][] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $newcomment);
00559 }
00560 }
00561 } elseif (is_string($value) || is_numeric($value)) {
00562 $tag_data_vorbiscomment[$tag_key][$key] = getid3_lib::iconv_fallback($this->tag_encoding, 'UTF-8', $value);
00563 } else {
00564 $this->warnings[] = '$data['.$tag_key.']['.$key.'] is not a string value - all of $data['.$tag_key.'] NOT written to VorbisComment tag';
00565 unset($tag_data_vorbiscomment[$tag_key]);
00566 break;
00567 }
00568 }
00569 }
00570 $this->MergeExistingTagData('vorbiscomment', $tag_data_vorbiscomment);
00571 return $tag_data_vorbiscomment;
00572 }
00573
00574 function FormatDataForMetaFLAC() {
00575
00576
00577 return $this->FormatDataForVorbisComment();
00578 }
00579
00580 function FormatDataForReal() {
00581 $tag_data_real['title'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', @implode(' ', @$this->tag_data['TITLE']));
00582 $tag_data_real['artist'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', @implode(' ', @$this->tag_data['ARTIST']));
00583 $tag_data_real['copyright'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', @implode(' ', @$this->tag_data['COPYRIGHT']));
00584 $tag_data_real['comment'] = getid3_lib::iconv_fallback($this->tag_encoding, 'ISO-8859-1', @implode(' ', @$this->tag_data['COMMENT']));
00585
00586 $this->MergeExistingTagData('real', $tag_data_real);
00587 return $tag_data_real;
00588 }
00589
00590 }
00591
00592 ?>