• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

Services/MediaObjects/getid3/getid3/write.real.php

Go to the documentation of this file.
00001 <?php
00004 //  available at http://getid3.sourceforge.net                 //
00005 //            or http://www.getid3.org                         //
00007 // See readme.txt for more details                             //
00009 //                                                             //
00010 // write.real.php                                              //
00011 // module for writing RealAudio/RealVideo tags                 //
00012 // dependencies: module.tag.real.php                           //
00013 //                                                            ///
00015 
00016 class getid3_write_real
00017 {
00018         var $filename;
00019         var $tag_data     = array();
00020         var $warnings     = array(); // any non-critical errors will be stored here
00021         var $errors       = array(); // any critical errors will be stored here
00022         var $paddedlength = 512;     // minimum length of CONT tag in bytes
00023 
00024         function getid3_write_real() {
00025                 return true;
00026         }
00027 
00028         function WriteReal() {
00029                 // File MUST be writeable - CHMOD(646) at least
00030                 if (is_writeable($this->filename)) {
00031                         if ($fp_source = @fopen($this->filename, 'r+b')) {
00032 
00033                                 // Initialize getID3 engine
00034                                 $getID3 = new getID3;
00035                                 $OldThisFileInfo = $getID3->analyze($this->filename);
00036                                 if (empty($OldThisFileInfo['real']['chunks']) && !empty($OldThisFileInfo['real']['old_ra_header'])) {
00037                                         $this->errors[] = 'Cannot write Real tags on old-style file format';
00038                                         fclose($fp_source);
00039                                         return false;
00040                                 }
00041 
00042                                 if (empty($OldThisFileInfo['real']['chunks'])) {
00043                                         $this->errors[] = 'Cannot write Real tags because cannot find DATA chunk in file';
00044                                         fclose($fp_source);
00045                                         return false;
00046                                 }
00047                                 foreach ($OldThisFileInfo['real']['chunks'] as $chunknumber => $chunkarray) {
00048                                         $oldChunkInfo[$chunkarray['name']] = $chunkarray;
00049                                 }
00050                                 if (!empty($oldChunkInfo['CONT']['length'])) {
00051                                         $this->paddedlength = max($oldChunkInfo['CONT']['length'], $this->paddedlength);
00052                                 }
00053 
00054                                 $new_CONT_tag_data = $this->GenerateCONTchunk();
00055                                 $new_PROP_tag_data = $this->GeneratePROPchunk($OldThisFileInfo['real']['chunks'], $new_CONT_tag_data);
00056                                 $new__RMF_tag_data = $this->GenerateRMFchunk($OldThisFileInfo['real']['chunks']);
00057 
00058                                 if (@$oldChunkInfo['.RMF']['length'] == strlen($new__RMF_tag_data)) {
00059                                         fseek($fp_source, $oldChunkInfo['.RMF']['offset'], SEEK_SET);
00060                                         fwrite($fp_source, $new__RMF_tag_data);
00061                                 } else {
00062                                         $this->errors[] = 'new .RMF tag ('.strlen($new__RMF_tag_data).' bytes) different length than old .RMF tag ('.$oldChunkInfo['.RMF']['length'].' bytes)';
00063                                         fclose($fp_source);
00064                                         return false;
00065                                 }
00066 
00067                                 if (@$oldChunkInfo['PROP']['length'] == strlen($new_PROP_tag_data)) {
00068                                         fseek($fp_source, $oldChunkInfo['PROP']['offset'], SEEK_SET);
00069                                         fwrite($fp_source, $new_PROP_tag_data);
00070                                 } else {
00071                                         $this->errors[] = 'new PROP tag ('.strlen($new_PROP_tag_data).' bytes) different length than old PROP tag ('.$oldChunkInfo['PROP']['length'].' bytes)';
00072                                         fclose($fp_source);
00073                                         return false;
00074                                 }
00075 
00076                                 if (@$oldChunkInfo['CONT']['length'] == strlen($new_CONT_tag_data)) {
00077 
00078                                         // new data length is same as old data length - just overwrite
00079                                         fseek($fp_source, $oldChunkInfo['CONT']['offset'], SEEK_SET);
00080                                         fwrite($fp_source, $new_CONT_tag_data);
00081                                         fclose($fp_source);
00082                                         return true;
00083 
00084                                 } else {
00085 
00086                                         if (empty($oldChunkInfo['CONT'])) {
00087                                                 // no existing CONT chunk
00088                                                 $BeforeOffset = $oldChunkInfo['DATA']['offset'];
00089                                                 $AfterOffset  = $oldChunkInfo['DATA']['offset'];
00090                                         } else {
00091                                                 // new data is longer than old data
00092                                                 $BeforeOffset = $oldChunkInfo['CONT']['offset'];
00093                                                 $AfterOffset  = $oldChunkInfo['CONT']['offset'] + $oldChunkInfo['CONT']['length'];
00094                                         }
00095                                         if ($tempfilename = tempnam('*', 'getID3')) {
00096                                                 ob_start();
00097                                                 if ($fp_temp = fopen($tempfilename, 'wb')) {
00098 
00099                                                         rewind($fp_source);
00100                                                         fwrite($fp_temp, fread($fp_source, $BeforeOffset));
00101                                                         fwrite($fp_temp, $new_CONT_tag_data);
00102                                                         fseek($fp_source, $AfterOffset, SEEK_SET);
00103                                                         while ($buffer = fread($fp_source, GETID3_FREAD_BUFFER_SIZE)) {
00104                                                                 fwrite($fp_temp, $buffer, strlen($buffer));
00105                                                         }
00106                                                         fclose($fp_temp);
00107 
00108                                                         if (copy($tempfilename, $this->filename)) {
00109                                                                 unlink($tempfilename);
00110                                                                 fclose($fp_source);
00111                                                                 return true;
00112                                                         }
00113                                                         unlink($tempfilename);
00114                                                         $this->errors[] = 'FAILED: copy('.$tempfilename.', '.$this->filename.') - '.strip_tags(ob_get_contents());
00115 
00116                                                 } else {
00117 
00118                                                         $this->errors[] = 'Could not open '.$tempfilename.' mode "wb" - '.strip_tags(ob_get_contents());
00119 
00120                                                 }
00121                                                 ob_end_clean();
00122                                         }
00123                                         fclose($fp_source);
00124                                         return false;
00125 
00126                                 }
00127 
00128 
00129                         } else {
00130                                 $this->errors[] = 'Could not open '.$this->filename.' mode "r+b"';
00131                                 return false;
00132                         }
00133                 }
00134                 $this->errors[] = 'File is not writeable: '.$this->filename;
00135                 return false;
00136         }
00137 
00138         function GenerateRMFchunk(&$chunks) {
00139                 $oldCONTexists = false;
00140                 foreach ($chunks as $key => $chunk) {
00141                         $chunkNameKeys[$chunk['name']] = $key;
00142                         if ($chunk['name'] == 'CONT') {
00143                                 $oldCONTexists = true;
00144                         }
00145                 }
00146                 $newHeadersCount = $chunks[$chunkNameKeys['.RMF']]['headers_count'] + ($oldCONTexists ? 0 : 1);
00147 
00148                 $RMFchunk  = "\x00\x00"; // object version
00149                 $RMFchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['.RMF']]['file_version'], 4);
00150                 $RMFchunk .= getid3_lib::BigEndian2String($newHeadersCount,                                4);
00151 
00152                 $RMFchunk  = '.RMF'.getid3_lib::BigEndian2String(strlen($RMFchunk) + 8, 4).$RMFchunk; // .RMF chunk identifier + chunk length
00153                 return $RMFchunk;
00154         }
00155 
00156         function GeneratePROPchunk(&$chunks, &$new_CONT_tag_data) {
00157                 $old_CONT_length = 0;
00158                 $old_DATA_offset = 0;
00159                 $old_INDX_offset = 0;
00160                 foreach ($chunks as $key => $chunk) {
00161                         $chunkNameKeys[$chunk['name']] = $key;
00162                         if ($chunk['name'] == 'CONT') {
00163                                 $old_CONT_length = $chunk['length'];
00164                         } elseif ($chunk['name'] == 'DATA') {
00165                                 if (!$old_DATA_offset) {
00166                                         $old_DATA_offset = $chunk['offset'];
00167                                 }
00168                         } elseif ($chunk['name'] == 'INDX') {
00169                                 if (!$old_INDX_offset) {
00170                                         $old_INDX_offset = $chunk['offset'];
00171                                 }
00172                         }
00173                 }
00174                 $CONTdelta = strlen($new_CONT_tag_data) - $old_CONT_length;
00175 
00176                 $PROPchunk  = "\x00\x00"; // object version
00177                 $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['max_bit_rate'],    4);
00178                 $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['avg_bit_rate'],    4);
00179                 $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['max_packet_size'], 4);
00180                 $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['avg_packet_size'], 4);
00181                 $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['num_packets'],     4);
00182                 $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['duration'],        4);
00183                 $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['preroll'],         4);
00184                 $PROPchunk .= getid3_lib::BigEndian2String(max(0, $old_INDX_offset + $CONTdelta),              4);
00185                 $PROPchunk .= getid3_lib::BigEndian2String(max(0, $old_DATA_offset + $CONTdelta),              4);
00186                 $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['num_streams'],     2);
00187                 $PROPchunk .= getid3_lib::BigEndian2String($chunks[$chunkNameKeys['PROP']]['flags_raw'],       2);
00188 
00189                 $PROPchunk  = 'PROP'.getid3_lib::BigEndian2String(strlen($PROPchunk) + 8, 4).$PROPchunk; // PROP chunk identifier + chunk length
00190                 return $PROPchunk;
00191         }
00192 
00193         function GenerateCONTchunk() {
00194                 foreach ($this->tag_data as $key => $value) {
00195                         // limit each value to 0xFFFF bytes
00196                         $this->tag_data[$key] = substr($value, 0, 65535);
00197                 }
00198 
00199                 $CONTchunk  = "\x00\x00"; // object version
00200 
00201                 $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['title']), 2);
00202                 $CONTchunk .= @$this->tag_data['title'];
00203 
00204                 $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['artist']), 2);
00205                 $CONTchunk .= @$this->tag_data['artist'];
00206 
00207                 $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['copyright']), 2);
00208                 $CONTchunk .= @$this->tag_data['copyright'];
00209 
00210                 $CONTchunk .= getid3_lib::BigEndian2String(strlen(@$this->tag_data['comment']), 2);
00211                 $CONTchunk .= @$this->tag_data['comment'];
00212 
00213                 if ($this->paddedlength > (strlen($CONTchunk) + 8)) {
00214                         $CONTchunk .= str_repeat("\x00", $this->paddedlength - strlen($CONTchunk) - 8);
00215                 }
00216 
00217                 $CONTchunk  = 'CONT'.getid3_lib::BigEndian2String(strlen($CONTchunk) + 8, 4).$CONTchunk; // CONT chunk identifier + chunk length
00218 
00219                 return $CONTchunk;
00220         }
00221 
00222         function RemoveReal() {
00223                 // File MUST be writeable - CHMOD(646) at least
00224                 if (is_writeable($this->filename)) {
00225                         if ($fp_source = @fopen($this->filename, 'r+b')) {
00226 
00227                                 // Initialize getID3 engine
00228                                 $getID3 = new getID3;
00229                                 $OldThisFileInfo = $getID3->analyze($this->filename);
00230                                 if (empty($OldThisFileInfo['real']['chunks']) && !empty($OldThisFileInfo['real']['old_ra_header'])) {
00231                                         $this->errors[] = 'Cannot remove Real tags from old-style file format';
00232                                         fclose($fp_source);
00233                                         return false;
00234                                 }
00235 
00236                                 if (empty($OldThisFileInfo['real']['chunks'])) {
00237                                         $this->errors[] = 'Cannot remove Real tags because cannot find DATA chunk in file';
00238                                         fclose($fp_source);
00239                                         return false;
00240                                 }
00241                                 foreach ($OldThisFileInfo['real']['chunks'] as $chunknumber => $chunkarray) {
00242                                         $oldChunkInfo[$chunkarray['name']] = $chunkarray;
00243                                 }
00244 
00245                                 if (empty($oldChunkInfo['CONT'])) {
00246                                         // no existing CONT chunk
00247                                         fclose($fp_source);
00248                                         return true;
00249                                 }
00250 
00251                                 $BeforeOffset = $oldChunkInfo['CONT']['offset'];
00252                                 $AfterOffset  = $oldChunkInfo['CONT']['offset'] + $oldChunkInfo['CONT']['length'];
00253                                 if ($tempfilename = tempnam('*', 'getID3')) {
00254                                         ob_start();
00255                                         if ($fp_temp = fopen($tempfilename, 'wb')) {
00256 
00257                                                 rewind($fp_source);
00258                                                 fwrite($fp_temp, fread($fp_source, $BeforeOffset));
00259                                                 fseek($fp_source, $AfterOffset, SEEK_SET);
00260                                                 while ($buffer = fread($fp_source, GETID3_FREAD_BUFFER_SIZE)) {
00261                                                         fwrite($fp_temp, $buffer, strlen($buffer));
00262                                                 }
00263                                                 fclose($fp_temp);
00264 
00265                                                 if (copy($tempfilename, $this->filename)) {
00266                                                         unlink($tempfilename);
00267                                                         fclose($fp_source);
00268                                                         return true;
00269                                                 }
00270                                                 unlink($tempfilename);
00271                                                 $this->errors[] = 'FAILED: copy('.$tempfilename.', '.$this->filename.') - '.strip_tags(ob_get_contents());
00272 
00273                                         } else {
00274 
00275                                                 $this->errors[] = 'Could not open '.$tempfilename.' mode "wb" - '.strip_tags(ob_get_contents());
00276 
00277                                         }
00278                                         ob_end_clean();
00279                                 }
00280                                 fclose($fp_source);
00281                                 return false;
00282 
00283 
00284                         } else {
00285                                 $this->errors[] = 'Could not open '.$this->filename.' mode "r+b"';
00286                                 return false;
00287                         }
00288                 }
00289                 $this->errors[] = 'File is not writeable: '.$this->filename;
00290                 return false;
00291         }
00292 
00293 }
00294 
00295 ?>

Generated on Fri Dec 13 2013 17:56:59 for ILIAS Release_3_9_x_branch .rev 46835 by  doxygen 1.7.1