/usr/share/php/Horde/Crypt/Pgp/Parse.php is in php-horde-crypt 2.4.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | <?php
/**
* Copyright 2002-2013 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (LGPL). If you
* did not receive this file, see http://www.horde.org/licenses/lgpl21.
*
* @category Horde
* @copyright 2002-2013 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Crypt
*/
/**
* Provides method to parse PGP armored text data.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2002-2013 Horde LLC
* @license http://www.horde.org/licenses/lgpl21 LGPL 2.1
* @package Crypt
* @since 2.4.0
*/
class Horde_Crypt_Pgp_Parse
{
/**
* Armor Header Lines - From RFC 2440:
*
* An Armor Header Line consists of the appropriate header line text
* surrounded by five (5) dashes ('-', 0x2D) on either side of the header
* line text. The header line text is chosen based upon the type of data
* that is being encoded in Armor, and how it is being encoded.
*
* All Armor Header Lines are prefixed with 'PGP'.
*
* The Armor Tail Line is composed in the same manner as the Armor Header
* Line, except the string "BEGIN" is replaced by the string "END."
*/
/* Used for signed, encrypted, or compressed files. */
const ARMOR_MESSAGE = 1;
/* Used for signed files. */
const ARMOR_SIGNED_MESSAGE = 2;
/* Used for armoring public keys. */
const ARMOR_PUBLIC_KEY = 3;
/* Used for armoring private keys. */
const ARMOR_PRIVATE_KEY = 4;
/* Used for detached signatures, PGP/MIME signatures, and natures
* following clearsigned messages. */
const ARMOR_SIGNATURE = 5;
/* Regular text contained in an PGP message. */
const ARMOR_TEXT = 6;
/**
* Metadata names for signature data.
*/
const SIG_CHARSET = 'pgp_sig_charset';
const SIG_RAW = 'pgp_sig_raw';
/**
* Strings in armor header lines used to distinguish between the different
* types of PGP decryption/encryption.
*
* @var array
*/
protected $_armor = array(
'MESSAGE' => self::ARMOR_MESSAGE,
'SIGNED MESSAGE' => self::ARMOR_SIGNED_MESSAGE,
'PUBLIC KEY BLOCK' => self::ARMOR_PUBLIC_KEY,
'PRIVATE KEY BLOCK' => self::ARMOR_PRIVATE_KEY,
'SIGNATURE' => self::ARMOR_SIGNATURE
);
/**
* Parses a message into text and PGP components.
*
* @param mixed $text Either the text to parse or a Horde_Stream object.
*
* @return array An array with the parsed text, returned in blocks of
* text corresponding to their actual order. Keys:
* <pre>
* - data: (array) The data for each section. Each line has been
* stripped of EOL characters.
* - type: (integer) The type of data contained in block. Valid types
* are the class ARMOR_* constants.
* </pre>
*/
public function parse($text)
{
$data = array();
$temp = array(
'type' => self::ARMOR_TEXT
);
if ($text instanceof Horde_Stream) {
$stream = $text;
$stream->rewind();
} else {
$stream = new Horde_Stream_Temp();
$stream->add($text, true);
}
while (!$stream->eof()) {
$val = rtrim($stream->getToChar("\n", false), "\r");
if (preg_match('/^-----(BEGIN|END) PGP ([^-]+)-----\s*$/', $val, $matches)) {
if (isset($temp['data'])) {
$data[] = $temp;
}
$temp = array();
if ($matches[1] == 'BEGIN') {
$temp['type'] = $this->_armor[$matches[2]];
$temp['data'][] = $val;
} elseif ($matches[1] == 'END') {
$temp['type'] = self::ARMOR_TEXT;
$data[count($data) - 1]['data'][] = $val;
}
} else {
$temp['data'][] = $val;
}
}
if (isset($temp['data']) &&
((count($temp['data']) > 1) || !empty($temp['data'][0]))) {
$data[] = $temp;
}
return $data;
}
/**
* Parses an armored message into a Horde_Mime_Part object.
*
* @param mixed $text Either the text to parse or a Horde_Stream object.
*
* @return mixed Either null if no PGP data was found, or a
* Horde_Mime_Part object. For detached signature data:
* the full contents of the armored text (data + sig) is
* contained in the SIG_RAW metadata, and the charset is
* contained in the SIG_CHARSET metadata, within the
* application/pgp-signature part.
*/
public function parseToPart($text, $charset = 'UTF-8')
{
$parts = $this->parse($text);
if (empty($parts) ||
((count($parts) == 1) && ($parts[0]['type'] == self::ARMOR_TEXT))) {
return null;
}
$new_part = new Horde_Mime_Part();
$new_part->setType('multipart/mixed');
foreach ($parts as $val) {
switch ($val['type']) {
case self::ARMOR_TEXT:
$part = new Horde_Mime_Part();
$part->setType('text/plain');
$part->setCharset($charset);
$part->setContents(implode("\n", $val['data']));
$new_part->addPart($part);
break;
case self::ARMOR_PUBLIC_KEY:
$part = new Horde_Mime_Part();
$part->setType('application/pgp-keys');
$part->setContents(implode("\n", $val['data']));
$new_part->addPart($part);
break;
case self::ARMOR_MESSAGE:
$part = new Horde_Mime_Part();
$part->setType('multipart/encrypted');
$part->setMetadata(IMP_Mime_Viewer_Pgp::PGP_ARMOR, true);
$part->setContentTypeParameter('protocol', 'application/pgp-encrypted');
$part1 = new Horde_Mime_Part();
$part1->setType('application/pgp-encrypted');
$part1->setContents("Version: 1\n");
$part2 = new Horde_Mime_Part();
$part2->setType('application/octet-stream');
$part2->setContents(implode("\n", $val['data']));
$part2->setDisposition('inline');
$part->addPart($part1);
$part->addPart($part2);
$new_part->addPart($part);
break;
case self::ARMOR_SIGNED_MESSAGE:
if (($sig = current($parts)) &&
($sig['type'] == self::ARMOR_SIGNATURE)) {
$part = new Horde_Mime_Part();
$part->setType('multipart/signed');
// TODO: add micalg parameter
$part->setContentTypeParameter('protocol', 'application/pgp-signature');
$part1 = new Horde_Mime_Part();
$part1->setType('text/plain');
$part1->setCharset($charset);
$part1_data = implode("\n", $val['data']);
$part1->setContents(substr($part1_data, strpos($part1_data, "\n\n") + 2));
$part2 = new Horde_Mime_Part();
$part2->setType('application/pgp-signature');
$part2->setContents(implode("\n", $sig['data']));
$part2->setMetadata(self::SIG_CHARSET, $charset);
$part2->setMetadata(self::SIG_RAW, implode("\n", $val['data']) . "\n" . implode("\n", $sig['data']));
$part->addPart($part1);
$part->addPart($part2);
$new_part->addPart($part);
next($parts);
}
}
}
return $new_part;
}
}
|