public function parseFromFile($fp) { $header_bin = fread($fp, 8); $length_read = strlen($header_bin); if ($length_read == 0) { L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Reached EOF; no more to read", array()); return false; // if we read an exact chunk, it's not an 'eof'. } if ($length_read < 8) { throw new OutOfBoundsException("No more data (read {$length_read} bytes)"); } if ($header_bin === false) { throw new RuntimeException("Read error; failed to read 8 bytes of chunk header"); } list($chunk_type, $chunk_size) = $this->parseHeader($header_bin); if ($chunk_size > 1048576) { // a chunk larger than 1Mb!? $chunk_size = number_format($chunk_size / 1024 / 1024, 2); throw new RuntimeException("Found chunk claiming to be enormous ({$chunk_size} MiB); are you reading the right file?"); } $body_bin = fread($fp, $chunk_size); $chunk = $this->chunk_factory->newChunk($chunk_type, $body_bin); L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Read %s chunk from file", array($chunk_type)); return $chunk; }
public function parseFromFile($fp) { // It looks like newer Serato sometimes allocates large chunks of free space in the file at the end. // This doesn't count as data, so we skip it, using str_pad() to make sure we also skip any run of // nulls that is shorter than 8 bytes. do { $header_bin = fread($fp, 8); if ($header_bin === false) { throw new RuntimeException("Read error; failed to read 8 bytes of chunk header"); } $length_read = strlen($header_bin); if ($length_read == 0) { L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Reached EOF; no more to read", array()); return false; // if we read an exact chunk, it's not an 'eof'. } $just_blank_bytes = str_pad($header_bin, 8, "") == ""; if ($just_blank_bytes) { L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, "Hit unallocated blank space in file.", array()); // argh. Attempt to resync the stream to the next oent. // it looks like Serato sometimes has junk after the free space! if (!$this->resync($fp)) { // eof. return false; } } } while ($just_blank_bytes); if ($length_read < 8) { throw new OutOfBoundsException("No more data (read {$length_read} bytes)"); } list($chunk_type, $chunk_size) = $this->parseHeader($header_bin); if ($chunk_size > 1048576) { // a chunk larger than 1Mb!? $chunk_size = number_format($chunk_size / 1024 / 1024, 2); $dumper = new Hexdumper(); throw new RuntimeException(sprintf("Found chunk claiming to be enormous ({$chunk_size} MiB); are you reading the right file?\n%s", $dumper->hexdump($header_bin))); } if ($chunk_size > 0) { $body_bin = fread($fp, $chunk_size); $chunk = $this->chunk_factory->newChunk($chunk_type, $body_bin); L::level(L::DEBUG) && L::log(L::DEBUG, __CLASS__, "Read %s chunk from file (size: %d)", array($chunk_type, $chunk_size)); } else { $chunk = ''; L::level(L::WARNING) && L::log(L::WARNING, __CLASS__, "Read 0-byte %s chunk from file. This is unusual.", array($chunk_type)); } return $chunk; }