/** * Constructs the class with given parameters and reads object related data * from the Ogg bitstream. * * @param Zend_Io_Reader $reader The reader object. */ public function __construct($reader) { $this->_reader = $reader; $this->_capturePattern = $this->_reader->read(4); if ($this->_capturePattern != 'OggS') { require_once 'Zend/Media/Ogg/Exception.php'; throw new Zend_Media_Ogg_Exception('Not a valid Ogg bitstream'); } $this->_streamStructureVersion = $this->_reader->readUInt8(); if ($this->_streamStructureVersion != 0) { require_once 'Zend/Media/Ogg/Exception.php'; throw new Zend_Media_Ogg_Exception('Unsupported Ogg stream structure version'); } $this->_headerTypeFlag = $this->_reader->readUInt8(); $this->_granulePosition = $this->_reader->readInt64LE(); $this->_bitstreamSerialNumber = $this->_reader->readUInt32LE(); $this->_pageSequenceNumber = $this->_reader->readUInt32LE(); $this->_crcChecksum = $this->_reader->readUInt32LE(); $this->_numberPageSegments = $this->_reader->readUInt8(); $this->_segmentTable = array(); for ($i = 0; $i < $this->_numberPageSegments; $i++) { $this->_segmentTable[] = $this->_reader->readUInt8(); } $this->_headerSize = $this->_numberPageSegments + 27; $this->_pageSize = array_sum($this->_segmentTable); $this->_size = $this->_headerSize + $this->_pageSize; }
/** * Writes the possibly altered ID3v2 tag back to the file where it was read. * If the class was constructed without a file name, one can be provided * here as an argument. Regardless, the write operation will override * previous tag information, if found. * * If write is called on a tag without any frames to it, current tag is * removed from the file altogether. * * @param string|Zend_Io_Writer $filename The optional path to the file, use * null to save to the same file. */ public function write($filename) { if ($filename === null && ($filename = $this->_filename) === null) { throw new Zend_Media_Id3_Exception('No file given to write to'); } else { if ($filename !== null && $filename instanceof Zend_Io_Writer) { $this->_writeData($filename); return; } else { if ($filename !== null && $this->_filename !== null && realpath($filename) != realpath($this->_filename) && !copy($this->_filename, $filename)) { throw new Zend_Media_Id3_Exception('Unable to copy source to destination: ' . realpath($this->_filename) . '->' . realpath($filename)); } } } if (($fd = fopen($filename, file_exists($filename) ? 'r+b' : 'wb')) === false) { throw new Zend_Media_Id3_Exception('Unable to open file for writing: ' . $filename); } $hasNoFrames = true; foreach ($this->_frames as $identifier => $instances) { if (count($instances) > 0) { $hasNoFrames = false; break; } } if ($hasNoFrames === true) { $this->remove(new Zend_Io_Reader($fd)); return; } if ($this->_reader !== null) { $oldTagSize = 10 + $this->_header->getSize(); } else { $reader = new Zend_Io_Reader($fd); if ($reader->read(3) == 'ID3') { $header = new Zend_Media_Id3_Header($reader); $oldTagSize = 10 + $header->getSize(); } else { $oldTagSize = 0; } } $tag = new Zend_Io_StringWriter(); $this->_writeData($tag); $tagSize = $tag->getSize(); if ($tagSize > $oldTagSize) { fseek($fd, 0, SEEK_END); $oldFileSize = ftell($fd); ftruncate($fd, $newFileSize = $tagSize - $oldTagSize + $oldFileSize); for ($i = 1, $cur = $oldFileSize; $cur > 0; $cur -= 1024, $i++) { if ($cur >= 1024) { fseek($fd, -($i * 1024 + ($newFileSize - $oldFileSize)), SEEK_END); $buffer = fread($fd, 1024); fseek($fd, -($i * 1024), SEEK_END); $bytes = fwrite($fd, $buffer, 1024); } else { fseek($fd, 0); $buffer = fread($fd, $cur); fseek($fd, $newFileSize - $oldFileSize); $bytes = fwrite($fd, $buffer, $cur); } } if (($remaining = $oldFileSize % 1024) != 0) { // huh? } fseek($fd, 0, SEEK_END); } fseek($fd, 0); for ($i = 0; $i < $tagSize; $i += 1024) { fseek($tag->getFileDescriptor(), $i); $bytes = fwrite($fd, fread($tag->getFileDescriptor(), 1024)); } fclose($fd); $this->_filename = $filename; }
/** * Writes the possibly altered ID3v1 tag back to the file where it was read. * If the class was constructed without a file name, one can be provided * here as an argument. Regardless, the write operation will override * previous tag information, if found. * * @param string $filename The optional path to the file. * @throws Zend_Media_Id3_Exception if there is no file to write the tag to */ public function write($filename = null) { if ($filename === null && ($filename = $this->_filename) === null) { require_once 'Zend/Media/Id3/Exception.php'; throw new Zend_Media_Id3_Exception('No file given to write the tag to'); } require_once 'Zend/Io/FileWriter.php'; try { $writer = new Zend_Io_FileWriter($filename); $offset = $writer->getSize(); if ($this->_reader !== null) { $offset = -128; } else { $reader = new Zend_Io_Reader($writer->getFileDescriptor()); $reader->setOffset(-128); if ($reader->read(3) == 'TAG') { $offset = -128; } } $writer->setOffset($offset); $writer->writeString8('TAG')->writeString8(substr($this->_title, 0, 30), 30)->writeString8(substr($this->_artist, 0, 30), 30)->writeString8(substr($this->_album, 0, 30), 30)->writeString8(substr($this->_year, 0, 4), 4); if ($this->_track) { $writer->writeString8(substr($this->_comment, 0, 28), 28)->writeInt8(0)->writeInt8($this->_track); } else { $writer->writeString8(substr($this->_comment, 0, 30), 30); } $writer->writeInt8($this->_genre); $writer->flush(); } catch (Zend_Io_Exception $e) { require_once 'Zend/Media/Id3/Exception.php'; throw new Zend_Media_Id3_Exception($e->getMessage()); } $this->_filename = $filename; }
/** * Writes the possibly altered ID3v2 tag back to the file where it was read. * If the class was constructed without a file name, one can be provided * here as an argument. Regardless, the write operation will override * previous tag information, if found. * * If write is called without setting any frames to the tag, the tag is * removed from the file. * * @param string|Zend_Io_Writer $filename The optional path to the file, use * null to save to the same file. */ public function write($filename) { if ($filename === null && ($filename = $this->_filename) === null) { require_once 'Zend/Media/Id3/Exception.php'; throw new Zend_Media_Id3_Exception('No file given to write to'); } else { if ($filename !== null && $filename instanceof Zend_Io_Writer) { require_once 'Zend/Io/Writer.php'; $this->_writeData($filename); return; } else { if ($filename !== null && $this->_filename !== null && realpath($filename) != realpath($this->_filename) && !copy($this->_filename, $filename)) { require_once 'Zend/Media/Id3/Exception.php'; throw new Zend_Media_Id3_Exception('Unable to copy source to destination: ' . realpath($this->_filename) . '->' . realpath($filename)); } } } if (($fd = fopen($filename, file_exists($filename) ? 'r+b' : 'wb')) === false) { require_once 'Zend/Media/Id3/Exception.php'; throw new Zend_Media_Id3_Exception('Unable to open file for writing: ' . $filename); } if ($this->_reader !== null) { $oldTagSize = 10 + $this->_header->getSize(); } else { $reader = new Zend_Io_Reader($fd); if ($reader->read(3) == 'ID3') { $header = new Zend_Media_Id3_Header($reader); $oldTagSize = 10 + $header->getSize(); } else { $oldTagSize = 0; } } require_once 'Zend/Io/StringWriter.php'; $tag = new Zend_Io_StringWriter(); $this->_writeData($tag); $tagSize = empty($this->_frames) ? 0 : $tag->getSize(); if ($tagSize > $oldTagSize || $tagSize == 0) { fseek($fd, 0, SEEK_END); $oldFileSize = ftell($fd); ftruncate($fd, $newFileSize = $tagSize - $oldTagSize + $oldFileSize); for ($i = 1, $cur = $oldFileSize; $cur > 0; $cur -= 1024, $i++) { if ($cur >= 1024) { fseek($fd, $off = -($i * 1024 + ($newFileSize - $oldFileSize)), SEEK_END); $buffer = fread($fd, 1024); fseek($fd, $off = -($i * 1024), SEEK_END); $bytes = fwrite($fd, $buffer, 1024); } else { fseek($fd, 0); $buffer = fread($fd, $cur); fseek($fd, $off = $newFileSize % 1024 - $cur); $bytes = fwrite($fd, $buffer, $cur); } } if (($remaining = $oldFileSize % 1024) != 0) { } fseek($fd, 0, SEEK_END); } fseek($fd, 0); for ($i = 0; $i < $tagSize; $i += 1024) { fseek($tag->getFileDescriptor(), $i); $bytes = fwrite($fd, fread($tag->getFileDescriptor(), 1024)); } fclose($fd); $this->_filename = $filename; }
/** * Constructs the class with given filename. * * @param string|resource|Zend_Io_Reader $filename The path to the file, * file descriptor of an opened file, or a {@link Zend_Io_Reader} instance. * @throws Zend_Io_Exception if an error occur in stream handling. * @throws Zend_Media_Flac_Exception if an error occurs in vorbis bitstream reading. */ public function __construct($filename) { if ($filename instanceof Zend_Io_Reader) { $this->_reader =& $filename; } else { $this->_filename = $filename; require_once 'Zend/Io/FileReader.php'; try { $this->_reader = new Zend_Io_FileReader($filename); } catch (Zend_Io_Exception $e) { $this->_reader = null; require_once 'Zend/Media/Flac/Exception.php'; throw new Zend_Media_Flac_Exception($e->getMessage()); } } $capturePattern = $this->_reader->read(4); if ($capturePattern != 'fLaC') { require_once 'Zend/Media/Flac/Exception.php'; throw new Zend_Media_Flac_Exception('Not a valid FLAC bitstream'); } while (true) { $offset = $this->_reader->getOffset(); $last = ($tmp = $this->_reader->readUInt8()) >> 7 & 0x1; $type = $tmp & 0x7f; $size = $this->_reader->readUInt24BE(); $this->_reader->setOffset($offset); switch ($type) { case self::STREAMINFO: // 0 require_once 'Zend/Media/Flac/MetadataBlock/Streaminfo.php'; $this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Streaminfo($this->_reader); break; case self::PADDING: // 1 require_once 'Zend/Media/Flac/MetadataBlock/Padding.php'; $this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Padding($this->_reader); break; case self::APPLICATION: // 2 require_once 'Zend/Media/Flac/MetadataBlock/Application.php'; $this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Application($this->_reader); break; case self::SEEKTABLE: // 3 require_once 'Zend/Media/Flac/MetadataBlock/Seektable.php'; $this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Seektable($this->_reader); break; case self::VORBIS_COMMENT: // 4 require_once 'Zend/Media/Flac/MetadataBlock/VorbisComment.php'; $this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_VorbisComment($this->_reader); break; case self::CUESHEET: // 5 require_once 'Zend/Media/Flac/MetadataBlock/Cuesheet.php'; $this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Cuesheet($this->_reader); break; case self::PICTURE: // 6 require_once 'Zend/Media/Flac/MetadataBlock/Picture.php'; $this->_metadataBlocks[] = new Zend_Media_Flac_MetadataBlock_Picture($this->_reader); break; default: // break intentionally omitted } $this->_reader->setOffset($offset + 4 + $size); // Jump off the loop if we reached the end of metadata blocks if ($last === 1) { break; } } }
/** * Reads 1 record from the file. */ protected function readRecord() { $record_header = $this->readRecordHeader(); $local_msg_type = $record_header['Local Message Type']; if ($record_header['Message Type'] === true) { //this is a definition message $def = $this->readRecordDefinition(); $this->message_type_definitions[$local_msg_type] = $def; } else { $def = $this->message_type_definitions[$local_msg_type]; $data = array(); /* * Architecture Type * 0: Definition and Data Messages are Little Endian * 1: Definition and Data Message are Big Endian */ $big_endian = $def['architecture'] === 1; if ($this->file_type === null) { //default filetype, file_id is overal hetzelfde $this->file_type = \Fit\FileType::activity; } foreach ($def['fields'] as $field_def) { $profile_field_def = $this->profile->findFieldDefinition($this->file_type, $def['global_msg_number'], $field_def['field_def_number']); if ($profile_field_def) { $field_name = $profile_field_def[\Fit\Field::NAME]; $field_factor = (double) $profile_field_def[\Fit\Field::FACTOR]; $field_unit = $profile_field_def[\Fit\Field::UNIT]; } else { $field_name = 'no:' . $field_def['field_def_number']; $field_factor = 1; $field_unit = ''; } switch ($field_def['base_type']['base_type_definition']['name']) { case 'string': $value = $this->reader->readString8($field_def['size']); break; case 'sint8': $value = $this->reader->readInt8(); break; case 'enum': case 'uint8z': case 'uint8': $value = $this->reader->readUInt8(); break; case 'sint16': $value = $big_endian ? $this->reader->readInt16BE() : $this->reader->readInt16LE(); break; case 'uint16z': case 'uint16': $value = $big_endian ? $this->reader->readUInt16BE() : $this->reader->readUInt16LE(); break; case 'sint32': $value = $big_endian ? $this->reader->readInt32BE() : $this->reader->readInt32LE(); break; case 'uint32z': case 'uint32': $value = $big_endian ? $this->reader->readUInt32BE() : $this->reader->readUInt32LE(); break; case 'float32': $value = $big_endian ? $this->reader->readFloatBE() : $this->reader->readFloatLE(); break; case 'float64': $value = $big_endian ? $this->reader->readDoubleBE() : $this->reader->readDoubleLE(); break; case 'byte': default: $value = $this->reader->read($field_def['size']); } if (is_numeric($value) && $field_factor > 0) { $value *= $field_factor; } $data[$field_name] = array('value' => $value, 'unit' => $field_unit); if ($def['global_msg_number'] === 0 && $field_name === 'type') { $this->file_type = $value; } } $this->records[] = $data; } }
/** * Reads 1 record from the file. */ protected function readRecord() { $record_header = $this->readRecordHeader(); $local_msg_type = $record_header['Local Message Type']; if ($record_header['Message Type'] === true) { //this is a definition message $def = $this->readRecordDefinition(); $this->message_type_definitions[$local_msg_type] = $def; } else { //this is a data message $def = $this->message_type_definitions[$local_msg_type]; $data = array(); /* * Architecture Type * 0: Definition and Data Messages are Little Endian * 1: Definition and Data Message are Big Endian */ $big_endian = $def['architecture'] === 1; if ($this->file_type === null) { //default filetype, file_id is overal hetzelfde $this->file_type = \Fit\FileType::activity; } foreach ($def['fields'] as $field_def) { $profile_field_def = $this->profile->findFieldDefinition($this->file_type, $def['global_msg_number'], $field_def['field_def_number']); if ($profile_field_def) { $field_name = $profile_field_def[\Fit\Field::NAME]; $field_factor = (double) $profile_field_def[\Fit\Field::FACTOR]; $field_unit = $profile_field_def[\Fit\Field::UNIT]; } else { $field_name = 'no:' . $field_def['field_def_number']; $field_factor = 1; $field_unit = ''; } switch ($field_def['base_type']['base_type_definition']['name']) { case 'string': $value = $this->reader->readString8($field_def['size']); break; case 'sint8': $value = $this->reader->readInt8(); break; case 'enum': case 'uint8z': case 'uint8': $value = $this->reader->readUInt8(); break; case 'sint16': $value = $big_endian ? $this->reader->readInt16BE() : $this->reader->readInt16LE(); break; case 'uint16z': case 'uint16': $value = $big_endian ? $this->reader->readUInt16BE() : $this->reader->readUInt16LE(); break; case 'sint32': $value = $big_endian ? $this->reader->readInt32BE() : $this->reader->readInt32LE(); break; case 'uint32z': case 'uint32': $value = $big_endian ? $this->reader->readUInt32BE() : $this->reader->readUInt32LE(); break; case 'float32': $value = $big_endian ? $this->reader->readFloatBE() : $this->reader->readFloatLE(); break; case 'float64': $value = $big_endian ? $this->reader->readDoubleBE() : $this->reader->readDoubleLE(); break; case 'byte': default: $value = $this->reader->read($field_def['size']); } if (is_numeric($value) && $field_factor > 0) { $value *= $field_factor; } $data[$field_name] = array('value' => $value, 'unit' => $field_unit); if ($def['global_msg_number'] === 0 && $field_name === 'type') { $this->file_type = $value; } } $this->records[] = $data; } if ($this->debug) { $style = 'padding:1px 3px;background:white;'; $style2 = 'padding:1px 3px;background:lightgrey;'; $style3 = 'padding:1px 3px;background:darkgrey;'; static::$log->add(' <tr> <td style="' . $style . '">' . intval($this->headerbits[7]) . '</td> <td style="' . $style2 . '">' . intval($this->headerbits[6]) . '</td> <td style="' . $style . '">' . intval($this->headerbits[5]) . '</td> <td style="' . $style . '">' . intval($this->headerbits[4]) . '</td> <td style="' . $style2 . '">' . intval($this->headerbits[3]) . '</td> <td style="' . $style2 . '">' . intval($this->headerbits[2]) . '</td> <td style="' . $style2 . '">' . intval($this->headerbits[1]) . '</td> <td style="' . $style2 . '">' . intval($this->headerbits[0]) . '</td> <td style="' . $style3 . '">' . $local_msg_type . '</td> <td style="' . $style3 . '">' . $def['global_msg_number'] . '</td> <td style="' . $style3 . '">' . $this->file_type . '</td> '); if (isset($data)) { foreach ($data as $k => $d) { $v = $d['value']; if (stripos($k, 'time') !== false && stripos($k, 'total') === false) { $v = strftime('%FT%H:%M:%S%z', \Fit\Data::timeToUnix($v)); } elseif ($d['unit'] === 'deg') { $v = \Fit\Data::positionToDegrees($v); } static::$log->add('<td style="' . $style . '">' . $k . ': ' . $v . $d['unit'] . '</td>'); } } static::$log->add('</tr>'); } }
/** * Overwrite the method to read bytes within the Ogg bitstream. * * @param integer $length The amount of bytes to read within the Ogg bitstream. * @return string * @throws Zend_Io_Exception if an I/O error occurs */ public function read($length) { $currentPageSize = $this->_pages[$this->_currentPageNumber]['page']->getPageSize(); if ($this->_currentPagePosition + $length >= $currentPageSize) { $buffer = parent::read($currentPageSize - $this->_currentPagePosition); parent::skip($this->_pages[++$this->_currentPageNumber]['page']->getHeaderSize()); return $buffer . parent::read($this->_currentPagePosition = $length - ($currentPageSize - $this->_currentPagePosition)); } else { $buffer = parent::read($length); $this->_currentPagePosition += $length; return $buffer; } }