/** * Parses the SRR data and stores a list of valid blocks locally. * * @return boolean false if parsing fails */ protected function analyze() { // Find the SRR MARKER block, or abort if none is found if (($startPos = $this->findMarker()) === false) { $this->error = 'Could not find Marker block, not a valid SRR file'; return false; } // Start at the SRR MARKER block $this->seek($startPos); // Analyze all valid blocks while ($this->offset < $this->length) { try { // Get the next block header $block = $this->getNextBlock(); // Block type: SRR MARKER if ($block['head_type'] == self::SRR_BLOCK_MARK) { if ($block['head_flags'] & self::APP_NAME_PRESENT) { $block += self::unpack('vapp_name_size', $this->read(2), false); $block['app_name'] = $this->read($block['app_name_size']); $this->client = $block['app_name']; } if ($block['head_flags'] > 1 || $this->offset != $block['next_offset']) { $this->error = 'Could not find Marker block, not a valid SRR file'; return false; } // Block type: STORED FILE } elseif ($block['head_type'] == self::SRR_STORED_FILE) { $block += self::unpack('vname_size', $this->read(2), false); $block['file_name'] = $this->read($block['name_size']); $block['file_data'] = $this->read(isset($block['add_size']) ? $block['add_size'] : 0); // Block type: OSO HASH } elseif ($block['head_type'] == self::SRR_OSO_HASH) { $block += self::unpack(self::FORMAT_SRR_OSO_HASH, $this->read(18)); $block['file_hash'] = strrev($block['file_hash']); $block['file_size'] = self::int64($block['file_size'], $block['file_size_high']); $block['file_name'] = $this->read($block['name_size']); // Block type: SRR RAR FILE } elseif ($block['head_type'] == self::SRR_RAR_FILE) { $block += self::unpack('vname_size', $this->read(2), false); $block['file_name'] = $this->read($block['name_size']); // Default to RAR block processing } else { parent::processBlock($block); } // Add current block to the list $this->blocks[] = $block; // Skip to the next block, if any if ($this->offset != $block['next_offset']) { $this->seek($block['next_offset']); } // Sanity check if ($block['offset'] == $this->offset) { $this->error = 'Parsing seems to be stuck'; $this->close(); return false; } // No more readable data, or read error } catch (Exception $e) { if ($this->error) { $this->close(); return false; } break; } } // Analysis was successful return true; }