Merge pull request #9 from adecaneda/Partial-body-lengths

Support for Partial body lengths
This commit is contained in:
Stephen Paul Weber 2015-08-14 13:15:15 -05:00
commit f4fabd04e7

View File

@ -412,24 +412,41 @@ class OpenPGP_Packet {
/** /**
* Parses an OpenPGP packet. * Parses an OpenPGP packet.
* *
* Partial body lengths based on https://github.com/toofishes/python-pgpdump/blob/master/pgpdump/packet.py
*
* @see http://tools.ietf.org/html/rfc4880#section-4.2 * @see http://tools.ietf.org/html/rfc4880#section-4.2
*/ */
static function parse(&$input) { static function parse(&$input) {
$packet = NULL; $packet = NULL;
if (strlen($input) > 0) { if (strlen($input) > 0) {
$parser = ord($input[0]) & 64 ? 'parse_new_format' : 'parse_old_format'; $parser = ord($input[0]) & 64 ? 'parse_new_format' : 'parse_old_format';
list($tag, $head_length, $data_length) = self::$parser($input);
$input = substr($input, $head_length); $header_start0 = 0;
$consumed = 0;
$packet_data = "";
do {
list($tag, $data_offset, $data_length, $partial) = self::$parser($input, $header_start0);
$data_start0 = $header_start0 + $data_offset;
$header_start0 = $data_start0 + $data_length - 1;
$packet_data .= substr($input, $data_start0, $data_length);
$consumed += $data_offset + $data_length;
if ($partial) {
$consumed -= 1;
}
} while ($partial === true && $parser === 'parse_new_format');
if ($tag && ($class = self::class_for($tag))) { if ($tag && ($class = self::class_for($tag))) {
$packet = new $class(); $packet = new $class();
$packet->tag = $tag; $packet->tag = $tag;
$packet->input = substr($input, 0, $data_length); $packet->input = $packet_data;
$packet->length = $data_length; $packet->length = strlen($packet_data);
$packet->read(); $packet->read();
unset($packet->input); unset($packet->input);
unset($packet->length); unset($packet->length);
} }
$input = substr($input, $data_length); $input = substr($input, $consumed);
} }
return $packet; return $packet;
} }
@ -439,20 +456,21 @@ class OpenPGP_Packet {
* *
* @see http://tools.ietf.org/html/rfc4880#section-4.2.2 * @see http://tools.ietf.org/html/rfc4880#section-4.2.2
*/ */
static function parse_new_format($input) { static function parse_new_format($input, $header_start = 0) {
$tag = ord($input[0]) & 63; $tag = ord($input[0]) & 63;
$len = ord($input[1]); $len = ord($input[$header_start + 1]);
if($len < 192) { // One octet length if($len < 192) { // One octet length
return array($tag, 2, $len); return array($tag, 2, $len, false);
} }
if($len > 191 && $len < 224) { // Two octet length if($len > 191 && $len < 224) { // Two octet length
return array($tag, 3, (($len - 192) << 8) + ord($input[2]) + 192); return array($tag, 3, (($len - 192) << 8) + ord($input[$header_start + 2]) + 192, false);
} }
if($len == 255) { // Five octet length if($len == 255) { // Five octet length
$unpacked = unpack('N', substr($input, 2, 4)); $unpacked = unpack('N', substr($input, $header_start + 2, 4));
return array($tag, 6, reset($unpacked)); return array($tag, 6, reset($unpacked), false);
} }
// TODO: Partial body lengths. 1 << ($len & 0x1F) // Partial body lengths
return array($tag, 2, 1 << ($len & 0x1f), true);
} }
/** /**
@ -483,7 +501,7 @@ class OpenPGP_Packet {
$data_length = strlen($input) - $head_length; $data_length = strlen($input) - $head_length;
break; break;
} }
return array($tag, $head_length, $data_length); return array($tag, $head_length, $data_length, false);
} }
function __construct($data=NULL) { function __construct($data=NULL) {