26 static function enarmor($data, $marker =
'MESSAGE', array $headers = array()) {
27 $text = self::header($marker) .
"\n";
28 foreach ($headers as $key => $value) {
29 $text .= $key .
': ' . (string)$value .
"\n";
31 $text .=
"\n" . base64_encode($data);
32 $text .=
"\n".
'=' . base64_encode(substr(pack(
'N', self::crc24($data)), 1)) .
"\n";
33 $text .= self::footer($marker) .
"\n";
41 static function unarmor($text, $header =
'PGP PUBLIC KEY BLOCK') {
42 $header = self::header($header);
43 $text = str_replace(array(
"\r\n",
"\r"), array(
"\n",
''), $text);
44 if (($pos1 = strpos($text, $header)) !== FALSE &&
45 ($pos1 = strpos($text,
"\n\n", $pos1 += strlen($header))) !== FALSE &&
46 ($pos2 = strpos($text,
"\n=", $pos1 += 2)) !== FALSE) {
47 return base64_decode($text = substr($text, $pos1, $pos2 - $pos1));
55 return '-----BEGIN ' . strtoupper((
string)$marker) .
'-----';
62 return '-----END ' . strtoupper((
string)$marker) .
'-----';
71 for ($i = 0; $i < strlen($data); $i++) {
72 $crc ^= (ord($data[$i]) & 255) << 16;
73 for ($j = 0; $j < 8; $j++) {
75 if ($crc & 0x01000000) {
80 return $crc & 0x00ffffff;
87 return (strlen($data) - 1) * 8 + (int)floor(log(ord($data[0]), 2)) + 1;
91 return ((
int)16 + ($c & 15)) << (($c >> 4) + 6);
95 if($iterations >= 65011712)
return 255;
97 $count = $iterations >> 6;
100 $count = $count >> 1;
103 $result = ($c << 4) | ($count - 16);
124 $s2k =
new OpenPGP_S2k();
125 switch($s2k->type = ord($input{0})) {
127 $s2k->hash_algorithm = ord($input{1});
128 $input = substr($input, 2);
131 $s2k->hash_algorithm = ord($input{1});
132 $s2k->salt = substr($input, 2, 8);
133 $input = substr($input, 10);
136 $s2k->hash_algorithm = ord($input{1});
137 $s2k->salt = substr($input, 2, 8);
139 $input = substr($input, 11);
147 $bytes = chr($this->type);
148 switch($this->type) {
150 $bytes .= chr($this->hash_algorithm);
153 $bytes .= chr($this->hash_algorithm);
157 $bytes .= chr($this->hash_algorithm);
171 while(strlen($hash) < $size) {
176 return substr($hash, 0, $size);
180 if(strlen($s) >= $this->count)
return $s;
181 $s = str_repeat($s, ceil($this->count / strlen($s)));
182 return substr($s, 0, $this->count);
186 switch($this->type) {
190 return $this->
sized_hash($this->salt . $pass, $size);
210 if (($msg = self::parse(file_get_contents($path)))) {
211 $msg->uri = preg_match(
'!^[\w\d]+://!', $path) ? $path :
'file://' . realpath($path);
221 if (is_resource($input)) {
222 return self::parse_stream($input);
224 if (is_string($input)) {
225 return self::parse_string($input);
230 return self::parse_string(stream_get_contents($input));
235 while (($length = strlen($input)) > 0) {
239 if ($length == strlen($input)) {
252 foreach($this as $p) {
253 $bytes .= $p->to_bytes();
273 $final_sigs = array();
275 foreach($msg as $idx => $p) {
277 return array(array($p, array_values(array_filter($msg->packets,
function($p) {
282 array_push($final_sigs, array($key, $userid, $sigs));
285 array_push($final_sigs, array($key, $subkey, $sigs));
292 array_push($final_sigs, array($key, $userid, $sigs));
295 array_push($final_sigs, array($key, $subkey, $sigs));
298 array_push($final_sigs, array($key, $sigs));
305 array_push($final_sigs, array($key, $userid, $sigs));
308 array_push($final_sigs, array($key, $sigs));
318 array_push($final_sigs, array($key, $userid, $sigs));
320 array_push($final_sigs, array($key, $subkey, $sigs));
322 array_push($final_sigs, array($key, $sigs));
333 $signed = $this->signatures();
336 foreach($signed as $sign) {
337 $signatures = array_pop($sign);
340 foreach($signatures as $sig) {
341 $verifier = $verifiers[$sig->key_algorithm_name()][$sig->hash_algorithm_name()];
342 if($verifier && $this->verify_one($verifier, $sign, $sig)) {
346 array_push($sign, $vsigs);
355 $sign[0]->normalize();
356 $raw = $sign[0]->data;
358 $raw = implode(
'', array_merge($sign[0]->fingerprint_material(), array(chr(0xB4),
359 pack(
'N', strlen($sign[1]->body())), $sign[1]->body())));
361 $raw = implode(
'', array_merge($sign[0]->fingerprint_material(), $sign[1]->fingerprint_material()));
363 $raw = implode(
'', $sign[0]->fingerprint_material());
367 return call_user_func($verifier, $raw.$sig->trailer, $sig);
373 return new ArrayIterator($this->packets);
379 return isset($this->packets[$offset]);
383 return $this->packets[$offset];
387 return is_null($offset) ? $this->packets[] = $value : $this->packets[$offset] = $value;
391 unset($this->packets[$offset]);
408 return isset(self::$tags[
$tag]) && class_exists(
409 $class =
'OpenPGP_' . self::$tags[$tag] .
'Packet') ? $class : __CLASS__;
419 if (strlen($input) > 0) {
420 $parser = ord($input[0]) & 64 ?
'parse_new_format' :
'parse_old_format';
421 list(
$tag, $head_length, $data_length) = self::$parser($input);
422 $input = substr($input, $head_length);
423 if (
$tag && ($class = self::class_for(
$tag))) {
424 $packet =
new $class();
426 $packet->input = substr($input, 0, $data_length);
427 $packet->length = $data_length;
429 unset($packet->input);
430 unset($packet->length);
432 $input = substr($input, $data_length);
443 $tag = ord($input[0]) & 63;
444 $len = ord($input[1]);
446 return array(
$tag, 2, $len);
448 if($len > 191 && $len < 224) {
449 return array(
$tag, 3, (($len - 192) << 8) + ord($input[2]) + 192);
452 $unpacked = unpack(
'N', substr($input, 2, 4));
453 return array(
$tag, 6, reset($unpacked));
464 $len = (
$tag = ord($input[0])) & 3;
469 $data_length = ord($input[1]);
473 $data_length = unpack(
'n', substr($input, 1, 2));
474 $data_length = $data_length[1];
478 $data_length = unpack(
'N', substr($input, 1, 4));
479 $data_length = $data_length[1];
483 $data_length = strlen($input) - $head_length;
486 return array(
$tag, $head_length, $data_length);
490 $this->tag = array_search(substr(substr(get_class($this), 8), 0, -6), self::$tags);
502 $body = $this->
body();
503 $tag = chr($this->tag | 0xC0);
504 $size = chr(255).pack(
'N', strlen($body));
505 return array(
'header' =>
$tag.$size,
'body' => $body);
510 return $data[
'header'].$data[
'body'];
525 $length = (int)floor(($length + 7) / 8);
533 $unpacked = unpack($format, $this->
read_bytes($count));
534 return reset($unpacked);
538 return ($bytes = $this->
read_bytes()) ? $bytes[0] : NULL;
542 $bytes = substr($this->input, 0, $count);
543 $this->input = substr($this->input, $count);
548 1 =>
'AsymmetricSessionKey',
550 3 =>
'SymmetricSessionKey',
551 4 =>
'OnePassSignature',
555 8 =>
'CompressedData',
556 9 =>
'EncryptedData',
561 14 =>
'PublicSubkey',
562 17 =>
'UserAttribute',
563 18 =>
'IntegrityProtectedData',
564 19 =>
'ModificationDetectionCode',
565 60 =>
'Experimental',
566 61 =>
'Experimental',
567 62 =>
'Experimental',
568 63 =>
'Experimental',
581 parent::__construct();
583 $this->keyid = substr(
$keyid, -16);
589 switch($this->version = ord($this->
read_byte())) {
593 for($i = 0; $i < strlen($rawkeyid); $i++) {
594 $this->keyid .= sprintf(
'%02X',ord($rawkeyid{$i}));
597 $this->key_algorithm = ord($this->
read_byte());
599 $this->encrypted_data = $this->input;
602 throw new Exception(
"Unsupported AsymmetricSessionKeyPacket version: " . $this->version);
607 $bytes = chr($this->version);
609 for($i = 0; $i < strlen($this->keyid); $i += 2) {
610 $bytes .= chr(hexdec($this->keyid{$i}.$this->keyid{$i+1}));
613 $bytes .= chr($this->key_algorithm);
630 parent::__construct();
633 $this->hash_algorithm = array_search($this->hash_algorithm, self::$hash_algorithms);
642 $this->signature_type = (
$data->format ==
'b') ? 0x00 : 0x01;
647 $key = implode(
'',
$data[0]->fingerprint_material());
648 $user_id =
$data[1]->body();
649 $data = $key . chr(0xB4) . pack(
'N', strlen($user_id)) . $user_id;
661 $this->data = call_user_func($signer, $this->data.$this->trailer);
662 $unpacked = unpack(
'n', substr(implode(
'',$this->data), 0, 2));
663 $this->hash_head = reset($unpacked);
667 switch($this->version = ord($this->
read_byte())) {
671 $this->signature_type = ord($this->
read_byte());
675 for($i = 0; $i < strlen($keyid); $i++) {
676 $keyidHex .= sprintf(
'%02X',ord($keyid{$i}));
679 $this->hashed_subpackets = array();
680 $this->unhashed_subpackets = array(
685 $this->key_algorithm = ord($this->
read_byte());
686 $this->hash_algorithm = ord($this->
read_byte());
688 $this->data = array();
689 while(strlen($this->input) > 0) {
694 $this->signature_type = ord($this->
read_byte());
695 $this->key_algorithm = ord($this->
read_byte());
696 $this->hash_algorithm = ord($this->
read_byte());
697 $this->trailer = chr(4).chr($this->signature_type).chr($this->key_algorithm).chr($this->hash_algorithm);
701 $this->trailer .= pack(
'n', $hashed_size).$hashed_subpackets;
704 $this->trailer .= chr(4).chr(0xff).pack(
'N', 6 + $hashed_size);
707 $this->unhashed_subpackets = self::get_subpackets($this->
read_bytes($unhashed_size));
711 $this->data = array();
712 while(strlen($this->input) > 0) {
722 return $body.chr(4).chr(0xff).pack(
'N', strlen($body));
726 $body = chr(4).chr($this->signature_type).chr($this->key_algorithm).chr($this->hash_algorithm);
729 foreach((array)$this->hashed_subpackets as $p) {
738 switch($this->version) {
741 $body = chr($this->version) . chr(5) . chr($this->signature_type);
743 foreach((array)$this->unhashed_subpackets as $p) {
745 $body .= pack(
'N', $p->data);
750 foreach((array)$this->unhashed_subpackets as $p) {
752 for($i = 0; $i < strlen($p->data); $i += 2) {
753 $body .= chr(hexdec($p->data{$i}.$p->data{$i+1}));
759 $body .= chr($this->key_algorithm);
760 $body .= chr($this->hash_algorithm);
761 $body .= pack(
'n', $this->hash_head);
763 foreach($this->data as $mpi) {
770 $body = substr($this->trailer, 0, -6);
773 foreach((array)$this->unhashed_subpackets as $p) {
778 $body .= pack(
'n', $this->hash_head);
780 foreach((array)$this->data as $mpi) {
793 return self::$hash_algorithms[$this->hash_algorithm];
797 foreach($this->hashed_subpackets as $p) {
800 foreach($this->unhashed_subpackets as $p) {
810 $subpackets = array();
811 while(($length = strlen($input)) > 0) {
812 $subpackets[] = self::get_subpacket($input);
813 if($length == strlen($input)) {
821 $len = ord($input[0]);
822 $length_of_length = 1;
824 if($len > 190 && $len < 255) {
825 $length_of_length = 2;
826 $len = (($len - 192) << 8) + ord($input[1]) + 192;
829 $length_of_length = 5;
830 $unpacked = unpack(
'N', substr($input, 1, 4));
831 $len = reset($unpacked);
833 $input = substr($input, $length_of_length);
834 $tag = ord($input[0]);
835 $class = self::class_for($tag);
837 $packet =
new $class();
839 $packet->input = substr($input, 1, $len-1);
840 $packet->length = $len-1;
842 unset($packet->input);
843 unset($packet->length);
845 $input = substr($input, $len);
849 static $hash_algorithms = array(
859 static $subpacket_types = array(
862 2 =>
'SignatureCreationTime',
863 3 =>
'SignatureExpirationTime',
864 4 =>
'ExportableCertification',
865 5 =>
'TrustSignature',
866 6 =>
'RegularExpression',
869 9 =>
'KeyExpirationTime',
871 11 =>
'PreferredSymmetricAlgorithms',
872 12 =>
'RevocationKey',
880 20 =>
'NotationData',
881 21 =>
'PreferredHashAlgorithms',
882 22 =>
'PreferredCompressionAlgorithms',
883 23 =>
'KeyServerPreferences',
884 24 =>
'PreferredKeyServer',
885 25 =>
'PrimaryUserID',
888 28 =>
'SignersUserID',
889 29 =>
'ReasonforRevocation',
891 31 =>
'SignatureTarget',
892 32 =>
'EmbeddedSignature',
896 if(!isset(self::$subpacket_types[$tag]))
return 'OpenPGP_SignaturePacket_Subpacket';
897 return 'OpenPGP_SignaturePacket_'.self::$subpacket_types[$tag].
'Packet';
904 parent::__construct(
$data);
909 $body = $this->
body();
910 $size = chr(255).pack(
'N', strlen($body)+1);
911 $tag = chr($this->tag);
912 return array(
'header' =>
$size.$tag,
'body' => $body);
917 $this->data = $this->input;
934 return pack(
'N', $this->data);
944 return pack(
'N', $this->data);
950 $this->data = (ord($this->input) != 0);
954 return chr($this->data ? 1 : 0);
960 $this->depth = ord($this->input{0});
961 $this->trust = ord($this->input{1});
965 return chr($this->depth) . chr($this->trust);
971 $this->data = substr($this->input, 0, -1);
975 return $this->data . chr(0);
981 $this->data = (ord($this->input) != 0);
985 return chr($this->data ? 1 : 0);
995 return pack(
'N', $this->data);
1001 $this->data = array();
1002 while(strlen($this->input) > 0) {
1003 $this->data[] = ord($this->
read_byte());
1009 foreach($this->data as $algo) {
1010 $bytes .= chr($algo);
1022 $this->sensitive = $bitfield & 0x40 == 0x40;
1023 $this->key_algorithm = ord($this->
read_byte());
1025 $this->fingerprint =
'';
1026 while(strlen($this->input) > 0) {
1027 $this->fingerprint .= sprintf(
'%02X',ord($this->
read_byte()));
1033 $bytes .= chr(0x80 | ($this->sensitive ? 0x40 : 0x00));
1034 $bytes .= chr($this->key_algorithm);
1036 for($i = 0; $i < strlen($this->fingerprint); $i += 2) {
1037 $bytes .= chr(hexdec($this->fingerprint{$i}.$this->fingerprint{$i+1}));
1049 for($i = 0; $i < 8; $i++) {
1050 $this->data .= sprintf(
'%02X',ord($this->
read_byte()));
1056 for($i = 0; $i < strlen($this->data); $i += 2) {
1057 $bytes .= chr(hexdec($this->data{$i}.$this->data{$i+1}));
1070 $this->human_readable = ord($flags[0]) & 0x80 == 0x80;
1076 return chr($this->human_readable ? 0x80 : 0x00) .
"\0\0\0" .
1077 pack(
'n', strlen($this->name)) . pack(
'n', strlen($this->data)) .
1084 $this->data = array();
1085 while(strlen($this->input) > 0) {
1086 $this->data[] = ord($this->
read_byte());
1092 foreach($this->data as $algo) {
1093 $bytes .= chr($algo);
1101 $this->data = array();
1102 while(strlen($this->input) > 0) {
1103 $this->data[] = ord($this->
read_byte());
1109 foreach($this->data as $algo) {
1110 $bytes .= chr($algo);
1120 $flags = ord($this->input);
1121 $this->no_modify = $flags & 0x80 == 0x80;
1125 return chr($this->no_modify ? 0x80 : 0x00);
1131 $this->data = $this->input;
1141 $this->data = (ord($this->input) != 0);
1145 return chr($this->data ? 1 : 0);
1152 $this->data = $this->input;
1162 parent::__construct();
1163 $this->flags = $flags;
1167 $this->flags = array();
1168 while($this->input) {
1169 $this->flags[] = ord($this->
read_byte());
1175 foreach($this->flags as $f) {
1184 $this->data = $this->input;
1197 $this->data = $this->input;
1214 $this->key_algorithm = ord($this->
read_byte());
1215 $this->hash_algorithm = ord($this->
read_byte());
1216 $this->data = $this->input;
1220 return chr($this->key_algorithm) . chr($this->hash_algorithm) .
$this->data;
1228 parent::__construct(
$data);
1233 $body = $this->
body();
1234 $size = chr(255).pack(
'N', strlen($body)+1);
1235 $tag = chr($this->tag);
1236 return array(
'header' =>
$size.$tag,
'body' => $body);
1249 parent::__construct();
1257 $this->version = ord($this->
read_byte());
1258 $this->symmetric_algorithm = ord($this->
read_byte());
1259 $this->s2k = OpenPGP_S2k::parse($this->input);
1260 $this->encrypted_data = $this->input;
1264 return chr($this->version) . chr($this->symmetric_algorithm) .
1277 $this->version = ord($this->
read_byte());
1278 $this->signature_type = ord($this->
read_byte());
1279 $this->hash_algorithm = ord($this->
read_byte());
1280 $this->key_algorithm = ord($this->
read_byte());
1281 for($i = 0; $i < 8; $i++) {
1282 $this->key_id .= sprintf(
'%02X',ord($this->
read_byte()));
1284 $this->nested = ord($this->
read_byte());
1288 $body = chr($this->version).chr($this->signature_type).chr($this->hash_algorithm).chr($this->key_algorithm);
1289 for($i = 0; $i < strlen($this->key_id); $i += 2) {
1290 $body .= chr(hexdec($this->key_id{$i}.$this->key_id{$i+1}));
1292 $body .= chr((
int)$this->nested);
1311 parent::__construct();
1313 if(is_string($this->algorithm =
$algorithm)) {
1314 $this->algorithm = array_search($this->algorithm, self::$algorithms);
1319 if(count($this->key) > 0) {
1327 $keyid16 = strtoupper(substr($this->
fingerprint, -16));
1328 foreach($message as $p) {
1330 if(strtoupper($p->issuer()) == $keyid16) {
1333 foreach(array_merge($p->hashed_subpackets, $p->unhashed_subpackets) as $s) {
1340 }
else if(count($sigs))
break;
1348 foreach(array_merge($p->hashed_subpackets, $p->unhashed_subpackets) as $s) {
1350 return $this->timestamp + $s->data;
1361 switch ($this->version = ord($this->
read_byte())) {
1365 $this->algorithm = ord($this->
read_byte());
1370 $this->algorithm = ord($this->
read_byte());
1379 foreach (self::$key_fields[$this->algorithm] as $field) {
1380 $this->key[$field] = $this->
read_mpi();
1386 switch ($this->version) {
1388 $material = array();
1389 foreach (self::$key_fields[$this->algorithm] as $i) {
1391 $material[] = $this->key[$i];
1397 chr($this->version), pack(
'N', $this->timestamp),
1398 chr($this->algorithm),
1400 $material = array();
1401 foreach (self::$key_fields[$this->algorithm] as $i) {
1403 $material[] = $this->key[$i];
1405 $material = implode(
'', $material);
1406 $head[1] = pack(
'n', 6 + strlen($material));
1407 $head[] = $material;
1417 switch ($this->version) {
1427 switch ($this->version) {
1430 return implode(
'', array_merge(array(
1431 chr($this->version) . pack(
'N', $this->timestamp) .
1432 pack(
'n', $this->v3_days_of_validity) . chr($this->algorithm)
1441 1 => array(
'n',
'e'),
1442 16 => array(
'p',
'g',
'y'),
1443 17 => array(
'p',
'q',
'g',
'y'),
1483 $this->s2k_useage = ord($this->
read_byte());
1484 if($this->s2k_useage == 255 || $this->s2k_useage == 254) {
1485 $this->symmetric_algorithm = ord($this->
read_byte());
1486 $this->s2k = OpenPGP_S2k::parse($this->input);
1487 }
else if($this->s2k_useage > 0) {
1490 if($this->s2k_useage > 0) {
1491 $this->encrypted_data = $this->input;
1499 1 => array(
'd',
'p',
'q',
'u'),
1500 2 => array(
'd',
'p',
'q',
'u'),
1501 3 => array(
'd',
'p',
'q',
'u'),
1507 foreach(self::$secret_key_fields[$this->algorithm] as $field) {
1508 $this->key[$field] = $this->
read_mpi();
1513 $bytes = parent::body() . chr($this->s2k_useage);
1514 $secret_material = NULL;
1515 if($this->s2k_useage == 255 || $this->s2k_useage == 254) {
1516 $bytes .= chr($this->symmetric_algorithm);
1517 $bytes .= $this->s2k->to_bytes();
1519 if($this->s2k_useage > 0) {
1522 $secret_material =
'';
1523 foreach(self::$secret_key_fields[$this->algorithm] as $f) {
1524 $f = $this->key[$f];
1526 $secret_material .= $f;
1528 $bytes .= $secret_material;
1532 for($i = 0; $i < strlen($secret_material); $i++) {
1533 $chk = ($chk + ord($secret_material[$i])) % 65536;
1535 $bytes .= pack(
'n', $chk);
1561 static $algorithms = array(0 =>
'Uncompressed', 1 =>
'ZIP', 2 =>
'ZLIB', 3 =>
'BZip2');
1563 $this->algorithm = ord($this->
read_byte());
1564 $this->data = $this->
read_bytes($this->length);
1565 switch($this->algorithm) {
1584 $body = chr($this->algorithm);
1585 switch($this->algorithm) {
1587 $body .= $this->data->to_bytes();
1590 $body .= gzdeflate($this->data->to_bytes());
1593 $body .= gzcompress($this->data->to_bytes());
1596 $body .= bzcompress($this->data->to_bytes());
1607 return new ArrayIterator($this->data->packets);
1613 return isset($this->data[$offset]);
1617 return $this->data[$offset];
1621 return is_null($offset) ? $this->data[] = $value : $this->data[$offset] = $value;
1625 unset($this->data[$offset]);
1637 $this->data = $this->input;
1663 parent::__construct();
1664 $this->data =
$data;
1665 $this->format = isset($opt[
'format']) ? $opt[
'format'] :
'b';
1666 $this->filename = isset($opt[
'filename']) ? $opt[
'filename'] :
'data';
1667 $this->timestamp = isset($opt[
'timestamp']) ? $opt[
'timestamp'] : time();
1671 if($this->format ==
'u' || $this->format ==
't') {
1672 $this->data = str_replace(
"\n",
"\r\n", str_replace(
"\r",
"\n", str_replace(
"\r\n",
"\n", $this->data)));
1677 $this->size = $this->length - 1 - 4;
1679 $filename_length = ord($this->
read_byte());
1680 $this->size -= $filename_length;
1681 $this->filename = $this->
read_bytes($filename_length);
1683 $this->data = $this->
read_bytes($this->size);
1687 return $this->format.chr(strlen($this->filename)).$this->filename.pack(
'N', $this->timestamp).$this->data;
1698 $this->data = $this->input;
1716 parent::__construct();
1718 $this->input =
$name;
1721 $this->name =
$name;
1728 $this->data = $this->input;
1730 if (preg_match(
'/^([^\(]+)\(([^\)]+)\)\s+<([^>]+)>$/', $this->data, $matches)) {
1731 $this->name = trim($matches[1]);
1732 $this->comment = trim($matches[2]);
1733 $this->email = trim($matches[3]);
1736 else if (preg_match(
'/^([^<]+)\s+<([^>]+)>$/', $this->data, $matches)) {
1737 $this->name = trim($matches[1]);
1738 $this->comment = NULL;
1739 $this->email = trim($matches[2]);
1742 else if (preg_match(
'/^([^<]+)$/', $this->data, $matches)) {
1743 $this->name = trim($matches[1]);
1744 $this->comment = NULL;
1745 $this->email = NULL;
1748 else if (preg_match(
'/^<([^>]+)>$/', $this->data, $matches)) {
1750 $this->comment = NULL;
1751 $this->email = trim($matches[2]);
1758 if ($this->comment) { $text[] =
"({$this->comment})"; }
1759 if ($this->email) { $text[] =
"<{$this->email}>"; }
1760 return implode(
' ', $text);
1789 parent::__construct();
1791 $this->data =
$data;
1795 $this->version = ord($this->
read_byte());
1796 $this->data = $this->input;
1811 parent::__construct();
1812 $this->data = $sha1;
1816 $this->data = $this->input;
1817 if(strlen($this->input) != 20)
throw new Exception(
"Bad ModificationDetectionCodePacket");
1821 $body = $this->
body();
1822 if(strlen($body) != 20)
throw new Exception(
"Bad ModificationDetectionCodePacket");
1823 return array(
'header' =>
"\xD3\x14",
'body' => $body);