mirror of
https://github.com/roundcube/roundcubemail.git
synced 2026-03-11 18:46:51 +01:00
Fix regression in decoding mail parts FETCHed from IMAP (#9096)
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
- Fix regression where LDAP addressbook 'filter' option was ignored (#9061)
|
||||
- Fix wrong order of a multi-folder search result when sorting by size (#9065)
|
||||
- Fix so install/update scripts do not require PEAR (#9037)
|
||||
- Fix handling of mail parts that are encoded with x-uuencode (#9096)
|
||||
- Fix regression where some mail parts could have been decoded incorrectly, or not at all (#9096)
|
||||
|
||||
## Release 1.6.2
|
||||
|
||||
|
||||
@@ -2870,7 +2870,7 @@ class rcube_imap_generic
|
||||
$mode = 3;
|
||||
break;
|
||||
default:
|
||||
$mode = 0;
|
||||
$mode = $formatted ? 4 : 0;
|
||||
}
|
||||
|
||||
// Use BINARY extension when possible (and safe)
|
||||
@@ -2932,15 +2932,7 @@ class rcube_imap_generic
|
||||
}
|
||||
|
||||
if ($result !== false) {
|
||||
if ($mode == 1) {
|
||||
$result = base64_decode($result);
|
||||
}
|
||||
else if ($mode == 2) {
|
||||
$result = quoted_printable_decode($result);
|
||||
}
|
||||
else if ($mode == 3) {
|
||||
$result = convert_uudecode($result);
|
||||
}
|
||||
$result = $this->decodeContent($result, $mode, true);
|
||||
}
|
||||
}
|
||||
// response with string literal
|
||||
@@ -2954,67 +2946,37 @@ class rcube_imap_generic
|
||||
if (!$bytes) {
|
||||
$result = '';
|
||||
}
|
||||
// An optimal path for a case when we need the body as-is in a string
|
||||
else if (!$mode && !$file && !$print) {
|
||||
$result = $this->readBytes($bytes);
|
||||
}
|
||||
else while ($bytes > 0) {
|
||||
$line = $this->readBytes($bytes > $chunkSize ? $chunkSize : $bytes);
|
||||
$chunk = $this->readBytes($bytes > $chunkSize ? $chunkSize : $bytes);
|
||||
|
||||
if ($line === '') {
|
||||
if ($chunk === '') {
|
||||
break;
|
||||
}
|
||||
|
||||
$len = strlen($line);
|
||||
$len = strlen($chunk);
|
||||
|
||||
if ($len > $bytes) {
|
||||
$line = substr($line, 0, $bytes);
|
||||
$len = strlen($line);
|
||||
$chunk = substr($chunk, 0, $bytes);
|
||||
$len = strlen($chunk);
|
||||
}
|
||||
$bytes -= $len;
|
||||
|
||||
// BASE64
|
||||
if ($mode == 1) {
|
||||
$line = preg_replace('|[^a-zA-Z0-9+=/]|', '', $line);
|
||||
// create chunks with proper length for base64 decoding
|
||||
$line = $prev.$line;
|
||||
$length = strlen($line);
|
||||
if ($length % 4) {
|
||||
$length = floor($length / 4) * 4;
|
||||
$prev = substr($line, $length);
|
||||
$line = substr($line, 0, $length);
|
||||
}
|
||||
else {
|
||||
$prev = '';
|
||||
}
|
||||
$line = base64_decode($line);
|
||||
}
|
||||
// QUOTED-PRINTABLE
|
||||
else if ($mode == 2) {
|
||||
$line = rtrim($line, "\t\r\0\x0B");
|
||||
$line = quoted_printable_decode($line);
|
||||
}
|
||||
// UUENCODE
|
||||
else if ($mode == 3) {
|
||||
$line = preg_replace(
|
||||
['/\r?\n/', '/\nend$/', '/^begin\s+[0-7]{3}\s+[^\n]+\n/'],
|
||||
["\n", '', ''],
|
||||
$line
|
||||
);
|
||||
|
||||
$line = convert_uudecode($line);
|
||||
}
|
||||
// default
|
||||
else if ($formatted) {
|
||||
$line = rtrim($line, "\t\r\n\0\x0B") . "\n";
|
||||
}
|
||||
$chunk = $this->decodeContent($chunk, $mode, $bytes <= 0, $prev);
|
||||
|
||||
if ($file) {
|
||||
if (fwrite($file, $line) === false) {
|
||||
if (fwrite($file, $chunk) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ($print) {
|
||||
echo $line;
|
||||
echo $chunk;
|
||||
}
|
||||
else {
|
||||
$result .= $line;
|
||||
$result .= $chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3036,6 +2998,105 @@ class rcube_imap_generic
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a chunk of a message part content from a FETCH response.
|
||||
*
|
||||
* @param string $chunk Content
|
||||
* @param int $mode Encoding mode
|
||||
* @param bool $is_last Whether it is a last chunk of data
|
||||
* @param string $prev Extra content from the previous chunk
|
||||
*
|
||||
* @return string Encoded string
|
||||
*/
|
||||
protected static function decodeContent($chunk, $mode, $is_last = false, &$prev = '')
|
||||
{
|
||||
// BASE64
|
||||
if ($mode == 1) {
|
||||
$chunk = $prev . preg_replace('|[^a-zA-Z0-9+=/]|', '', $chunk);
|
||||
|
||||
// create chunks with proper length for base64 decoding
|
||||
$length = strlen($chunk);
|
||||
|
||||
if ($length % 4) {
|
||||
$length = floor($length / 4) * 4;
|
||||
$prev = substr($chunk, $length);
|
||||
$chunk = substr($chunk, 0, $length);
|
||||
}
|
||||
else {
|
||||
$prev = '';
|
||||
}
|
||||
|
||||
return base64_decode($chunk);
|
||||
}
|
||||
|
||||
// QUOTED-PRINTABLE
|
||||
if ($mode == 2) {
|
||||
if (!self::decodeContentChunk($chunk, $prev, $is_last)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$chunk = preg_replace('/[\t\r\0\x0B]+\n/', "\n", $chunk);
|
||||
|
||||
return quoted_printable_decode($chunk);
|
||||
}
|
||||
|
||||
// X-UUENCODE
|
||||
if ($mode == 3) {
|
||||
if (!self::decodeContentChunk($chunk, $prev, $is_last)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$chunk = preg_replace(
|
||||
['/\r?\n/', '/(^|\n)end$/', '/^begin\s+[0-7]{3}\s+[^\n]+\n/'],
|
||||
["\n", '', ''],
|
||||
$chunk
|
||||
);
|
||||
|
||||
if (!strlen($chunk)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return convert_uudecode($chunk);
|
||||
}
|
||||
|
||||
// Plain text formatted
|
||||
// TODO: Formatting should be handled outside of this class
|
||||
if ($mode == 4) {
|
||||
if (!self::decodeContentChunk($chunk, $prev, $is_last)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($is_last) {
|
||||
$chunk = rtrim($chunk, "\t\r\n\0\x0B");
|
||||
}
|
||||
|
||||
return preg_replace('/[\t\r\0\x0B]+\n/', "\n", $chunk);
|
||||
}
|
||||
|
||||
return $chunk;
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper for a new-line aware parsing. See self::decodeContent().
|
||||
*/
|
||||
private static function decodeContentChunk(&$chunk, &$prev, $is_last)
|
||||
{
|
||||
$chunk = $prev . $chunk;
|
||||
$prev = '';
|
||||
|
||||
if (!$is_last) {
|
||||
if (($pos = strrpos($chunk, "\n")) !== false) {
|
||||
$prev = substr($chunk, $pos + 1);
|
||||
$chunk = substr($chunk, 0, $pos + 1);
|
||||
} else {
|
||||
$prev = $chunk;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for IMAP APPEND command
|
||||
*
|
||||
|
||||
@@ -82,7 +82,7 @@ class Framework_ImapGeneric extends PHPUnit\Framework\TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for uncompressMessageSet
|
||||
* Test for uncompressMessageSet()
|
||||
*/
|
||||
function test_uncompressMessageSet()
|
||||
{
|
||||
@@ -100,7 +100,7 @@ class Framework_ImapGeneric extends PHPUnit\Framework\TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for tokenizeResponse
|
||||
* Test for tokenizeResponse()
|
||||
*/
|
||||
function test_tokenizeResponse()
|
||||
{
|
||||
@@ -121,4 +121,99 @@ class Framework_ImapGeneric extends PHPUnit\Framework\TestCase
|
||||
$result = rcube_imap_generic::tokenizeResponse($response, 1);
|
||||
$this->assertSame(['item1', 'item2'], $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for decodeContent() with no encoding
|
||||
*/
|
||||
function test_decode_content_plain()
|
||||
{
|
||||
$content = "test uuencode encoded content\ntest uuencode encoded content";
|
||||
|
||||
$this->runDecodeContent($content, $content, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for decodeContent() with base64 encoding
|
||||
*/
|
||||
function test_decode_content_base64()
|
||||
{
|
||||
$content = "test base64 encoded content\ntest base64 encoded content";
|
||||
$encoded = chunk_split(base64_encode($content), 10, "\r\n");
|
||||
|
||||
$this->runDecodeContent($content, $encoded, 1);
|
||||
|
||||
// Test some real-life example
|
||||
$content = file_get_contents(TESTS_DIR . "src/test.pdf");
|
||||
$encoded = file_get_contents(TESTS_DIR . "src/test.base64");
|
||||
|
||||
$this->runDecodeContent($content, $encoded, 1, 2000);
|
||||
$this->runDecodeContent($content, $encoded, 1, 4000);
|
||||
$this->runDecodeContent($content, $encoded, 1, 6000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for decodeContent() with quoted-printable encoding
|
||||
*/
|
||||
function test_decode_content_qp()
|
||||
{
|
||||
$content = "test quoted-printable\n\n żąśźć encoded content\ntest quoted-printable żąśźć encoded content";
|
||||
$encoded = Mail_mimePart::quotedPrintableEncode($content, 12);
|
||||
|
||||
$this->runDecodeContent($content, $encoded, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for decodeContent() with x-uuencode encoding
|
||||
*/
|
||||
function test_decode_content_uuencode()
|
||||
{
|
||||
$content = "test uuencode encoded content\ntest uuencode encoded content";
|
||||
$encoded = "begin 664 test.txt\r\n" . convert_uuencode($content) . "end";
|
||||
|
||||
$this->runDecodeContent($content, $encoded, 3);
|
||||
|
||||
// Test some real-life example
|
||||
$content = file_get_contents(TESTS_DIR . "src/test.pdf");
|
||||
$encoded = file_get_contents(TESTS_DIR . "src/test.uuencode");
|
||||
|
||||
$this->runDecodeContent($content, $encoded, 3, 2000);
|
||||
$this->runDecodeContent($content, $encoded, 3, 4000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for decodeContent() with no encoding, but formatted output
|
||||
*/
|
||||
function test_decode_content_formatted()
|
||||
{
|
||||
$content = "test \r\n plain text\tcontent\t\r\n test plain text content\t";
|
||||
$expected = "test \n plain text\tcontent\n test plain text content";
|
||||
|
||||
$this->runDecodeContent($expected, $content, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to execute decodeCOntent() method in multiple variations of an input
|
||||
* and assert with the expected output
|
||||
*/
|
||||
function runDecodeContent($expected, $encoded, $mode, $size = null)
|
||||
{
|
||||
$method = new ReflectionMethod('rcube_imap_generic', 'decodeContent');
|
||||
$method->setAccessible(true);
|
||||
|
||||
// Make sure the method works with any chunk size
|
||||
for ($x = 1; $x <= strlen($encoded); $x++) {
|
||||
if ($size && $size != $x) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$decoded = $prev = '';
|
||||
$chunks = str_split($encoded, $x);
|
||||
|
||||
foreach ($chunks as $idx => $chunk) {
|
||||
$decoded .= $method->invokeArgs(null, [$chunk, $mode, $idx == count($chunks)-1, &$prev]);
|
||||
}
|
||||
|
||||
$this->assertSame($expected, $decoded, "Failed on chunk size of $x");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
54
tests/src/test.base64
Normal file
54
tests/src/test.base64
Normal file
@@ -0,0 +1,54 @@
|
||||
JVBERi0xLjMNCiXi48/TDQoNCjEgMCBvYmoNCjw8DQovVHlwZSAvQ2F0YWxvZw0KL091dGxpbmVz
|
||||
IDIgMCBSDQovUGFnZXMgMyAwIFINCj4+DQplbmRvYmoNCg0KMiAwIG9iag0KPDwNCi9UeXBlIC9P
|
||||
dXRsaW5lcw0KL0NvdW50IDANCj4+DQplbmRvYmoNCg0KMyAwIG9iag0KPDwNCi9UeXBlIC9QYWdl
|
||||
cw0KL0NvdW50IDINCi9LaWRzIFsgNCAwIFIgNiAwIFIgXSANCj4+DQplbmRvYmoNCg0KNCAwIG9i
|
||||
ag0KPDwNCi9UeXBlIC9QYWdlDQovUGFyZW50IDMgMCBSDQovUmVzb3VyY2VzIDw8DQovRm9udCA8
|
||||
PA0KL0YxIDkgMCBSIA0KPj4NCi9Qcm9jU2V0IDggMCBSDQo+Pg0KL01lZGlhQm94IFswIDAgNjEy
|
||||
LjAwMDAgNzkyLjAwMDBdDQovQ29udGVudHMgNSAwIFINCj4+DQplbmRvYmoNCg0KNSAwIG9iag0K
|
||||
PDwgL0xlbmd0aCAxMDc0ID4+DQpzdHJlYW0NCjIgSg0KQlQNCjAgMCAwIHJnDQovRjEgMDAyNyBU
|
||||
Zg0KNTcuMzc1MCA3MjIuMjgwMCBUZA0KKCBBIFNpbXBsZSBQREYgRmlsZSApIFRqDQpFVA0KQlQN
|
||||
Ci9GMSAwMDEwIFRmDQo2OS4yNTAwIDY4OC42MDgwIFRkDQooIFRoaXMgaXMgYSBzbWFsbCBkZW1v
|
||||
bnN0cmF0aW9uIC5wZGYgZmlsZSAtICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAg
|
||||
NjY0LjcwNDAgVGQNCigganVzdCBmb3IgdXNlIGluIHRoZSBWaXJ0dWFsIE1lY2hhbmljcyB0dXRv
|
||||
cmlhbHMuIE1vcmUgdGV4dC4gQW5kIG1vcmUgKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjku
|
||||
MjUwMCA2NTIuNzUyMCBUZA0KKCB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBB
|
||||
bmQgbW9yZSB0ZXh0LiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDYyOC44NDgw
|
||||
IFRkDQooIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuIEFuZCBt
|
||||
b3JlIHRleHQuIEFuZCBtb3JlICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNjE2
|
||||
Ljg5NjAgVGQNCiggdGV4dC4gQW5kIG1vcmUgdGV4dC4gQm9yaW5nLCB6enp6ei4gQW5kIG1vcmUg
|
||||
dGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kICkgVGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1
|
||||
MDAgNjA0Ljk0NDAgVGQNCiggbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0
|
||||
LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRm
|
||||
DQo2OS4yNTAwIDU5Mi45OTIwIFRkDQooIEFuZCBtb3JlIHRleHQuIEFuZCBtb3JlIHRleHQuICkg
|
||||
VGoNCkVUDQpCVA0KL0YxIDAwMTAgVGYNCjY5LjI1MDAgNTY5LjA4ODAgVGQNCiggQW5kIG1vcmUg
|
||||
dGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1v
|
||||
cmUgKSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA1NTcuMTM2MCBUZA0KKCB0ZXh0
|
||||
LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBFdmVuIG1vcmUuIENvbnRpbnVlZCBvbiBw
|
||||
YWdlIDIgLi4uKSBUag0KRVQNCmVuZHN0cmVhbQ0KZW5kb2JqDQoNCjYgMCBvYmoNCjw8DQovVHlw
|
||||
ZSAvUGFnZQ0KL1BhcmVudCAzIDAgUg0KL1Jlc291cmNlcyA8PA0KL0ZvbnQgPDwNCi9GMSA5IDAg
|
||||
UiANCj4+DQovUHJvY1NldCA4IDAgUg0KPj4NCi9NZWRpYUJveCBbMCAwIDYxMi4wMDAwIDc5Mi4w
|
||||
MDAwXQ0KL0NvbnRlbnRzIDcgMCBSDQo+Pg0KZW5kb2JqDQoNCjcgMCBvYmoNCjw8IC9MZW5ndGgg
|
||||
Njc2ID4+DQpzdHJlYW0NCjIgSg0KQlQNCjAgMCAwIHJnDQovRjEgMDAyNyBUZg0KNTcuMzc1MCA3
|
||||
MjIuMjgwMCBUZA0KKCBTaW1wbGUgUERGIEZpbGUgMiApIFRqDQpFVA0KQlQNCi9GMSAwMDEwIFRm
|
||||
DQo2OS4yNTAwIDY4OC42MDgwIFRkDQooIC4uLmNvbnRpbnVlZCBmcm9tIHBhZ2UgMS4gWWV0IG1v
|
||||
cmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gKSBUag0KRVQNCkJUDQovRjEg
|
||||
MDAxMCBUZg0KNjkuMjUwMCA2NzYuNjU2MCBUZA0KKCBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0
|
||||
ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSB0ZXh0LiBBbmQgbW9yZSApIFRqDQpFVA0KQlQN
|
||||
Ci9GMSAwMDEwIFRmDQo2OS4yNTAwIDY2NC43MDQwIFRkDQooIHRleHQuIE9oLCBob3cgYm9yaW5n
|
||||
IHR5cGluZyB0aGlzIHN0dWZmLiBCdXQgbm90IGFzIGJvcmluZyBhcyB3YXRjaGluZyApIFRqDQpF
|
||||
VA0KQlQNCi9GMSAwMDEwIFRmDQo2OS4yNTAwIDY1Mi43NTIwIFRkDQooIHBhaW50IGRyeS4gQW5k
|
||||
IG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4gQW5kIG1vcmUgdGV4dC4g
|
||||
KSBUag0KRVQNCkJUDQovRjEgMDAxMCBUZg0KNjkuMjUwMCA2NDAuODAwMCBUZA0KKCBCb3Jpbmcu
|
||||
ICBNb3JlLCBhIGxpdHRsZSBtb3JlIHRleHQuIFRoZSBlbmQsIGFuZCBqdXN0IGFzIHdlbGwuICkg
|
||||
VGoNCkVUDQplbmRzdHJlYW0NCmVuZG9iag0KDQo4IDAgb2JqDQpbL1BERiAvVGV4dF0NCmVuZG9i
|
||||
ag0KDQo5IDAgb2JqDQo8PA0KL1R5cGUgL0ZvbnQNCi9TdWJ0eXBlIC9UeXBlMQ0KL05hbWUgL0Yx
|
||||
DQovQmFzZUZvbnQgL0hlbHZldGljYQ0KL0VuY29kaW5nIC9XaW5BbnNpRW5jb2RpbmcNCj4+DQpl
|
||||
bmRvYmoNCg0KMTAgMCBvYmoNCjw8DQovQ3JlYXRvciAoUmF2ZSBcKGh0dHA6Ly93d3cubmV2cm9u
|
||||
YS5jb20vcmF2ZVwpKQ0KL1Byb2R1Y2VyIChOZXZyb25hIERlc2lnbnMpDQovQ3JlYXRpb25EYXRl
|
||||
IChEOjIwMDYwMzAxMDcyODI2KQ0KPj4NCmVuZG9iag0KDQp4cmVmDQowIDExDQowMDAwMDAwMDAw
|
||||
IDY1NTM1IGYNCjAwMDAwMDAwMTkgMDAwMDAgbg0KMDAwMDAwMDA5MyAwMDAwMCBuDQowMDAwMDAw
|
||||
MTQ3IDAwMDAwIG4NCjAwMDAwMDAyMjIgMDAwMDAgbg0KMDAwMDAwMDM5MCAwMDAwMCBuDQowMDAw
|
||||
MDAxNTIyIDAwMDAwIG4NCjAwMDAwMDE2OTAgMDAwMDAgbg0KMDAwMDAwMjQyMyAwMDAwMCBuDQow
|
||||
MDAwMDAyNDU2IDAwMDAwIG4NCjAwMDAwMDI1NzQgMDAwMDAgbg0KDQp0cmFpbGVyDQo8PA0KL1Np
|
||||
emUgMTENCi9Sb290IDEgMCBSDQovSW5mbyAxMCAwIFINCj4+DQoNCnN0YXJ0eHJlZg0KMjcxNA0K
|
||||
JSVFT0YNCg==
|
||||
198
tests/src/test.pdf
Normal file
198
tests/src/test.pdf
Normal file
@@ -0,0 +1,198 @@
|
||||
%PDF-1.3
|
||||
%âãÏÓ
|
||||
|
||||
1 0 obj
|
||||
<<
|
||||
/Type /Catalog
|
||||
/Outlines 2 0 R
|
||||
/Pages 3 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<<
|
||||
/Type /Outlines
|
||||
/Count 0
|
||||
>>
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<<
|
||||
/Type /Pages
|
||||
/Count 2
|
||||
/Kids [ 4 0 R 6 0 R ]
|
||||
>>
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<<
|
||||
/Type /Page
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 9 0 R
|
||||
>>
|
||||
/ProcSet 8 0 R
|
||||
>>
|
||||
/MediaBox [0 0 612.0000 792.0000]
|
||||
/Contents 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Length 1074 >>
|
||||
stream
|
||||
2 J
|
||||
BT
|
||||
0 0 0 rg
|
||||
/F1 0027 Tf
|
||||
57.3750 722.2800 Td
|
||||
( A Simple PDF File ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 688.6080 Td
|
||||
( This is a small demonstration .pdf file - ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 664.7040 Td
|
||||
( just for use in the Virtual Mechanics tutorials. More text. And more ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 652.7520 Td
|
||||
( text. And more text. And more text. And more text. ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 628.8480 Td
|
||||
( And more text. And more text. And more text. And more text. And more ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 616.8960 Td
|
||||
( text. And more text. Boring, zzzzz. And more text. And more text. And ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 604.9440 Td
|
||||
( more text. And more text. And more text. And more text. And more text. ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 592.9920 Td
|
||||
( And more text. And more text. ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 569.0880 Td
|
||||
( And more text. And more text. And more text. And more text. And more ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 557.1360 Td
|
||||
( text. And more text. And more text. Even more. Continued on page 2 ...) Tj
|
||||
ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<<
|
||||
/Type /Page
|
||||
/Parent 3 0 R
|
||||
/Resources <<
|
||||
/Font <<
|
||||
/F1 9 0 R
|
||||
>>
|
||||
/ProcSet 8 0 R
|
||||
>>
|
||||
/MediaBox [0 0 612.0000 792.0000]
|
||||
/Contents 7 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
<< /Length 676 >>
|
||||
stream
|
||||
2 J
|
||||
BT
|
||||
0 0 0 rg
|
||||
/F1 0027 Tf
|
||||
57.3750 722.2800 Td
|
||||
( Simple PDF File 2 ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 688.6080 Td
|
||||
( ...continued from page 1. Yet more text. And more text. And more text. ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 676.6560 Td
|
||||
( And more text. And more text. And more text. And more text. And more ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 664.7040 Td
|
||||
( text. Oh, how boring typing this stuff. But not as boring as watching ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 652.7520 Td
|
||||
( paint dry. And more text. And more text. And more text. And more text. ) Tj
|
||||
ET
|
||||
BT
|
||||
/F1 0010 Tf
|
||||
69.2500 640.8000 Td
|
||||
( Boring. More, a little more text. The end, and just as well. ) Tj
|
||||
ET
|
||||
endstream
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
[/PDF /Text]
|
||||
endobj
|
||||
|
||||
9 0 obj
|
||||
<<
|
||||
/Type /Font
|
||||
/Subtype /Type1
|
||||
/Name /F1
|
||||
/BaseFont /Helvetica
|
||||
/Encoding /WinAnsiEncoding
|
||||
>>
|
||||
endobj
|
||||
|
||||
10 0 obj
|
||||
<<
|
||||
/Creator (Rave \(http://www.nevrona.com/rave\))
|
||||
/Producer (Nevrona Designs)
|
||||
/CreationDate (D:20060301072826)
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0000000000 65535 f
|
||||
0000000019 00000 n
|
||||
0000000093 00000 n
|
||||
0000000147 00000 n
|
||||
0000000222 00000 n
|
||||
0000000390 00000 n
|
||||
0000001522 00000 n
|
||||
0000001690 00000 n
|
||||
0000002423 00000 n
|
||||
0000002456 00000 n
|
||||
0000002574 00000 n
|
||||
|
||||
trailer
|
||||
<<
|
||||
/Size 11
|
||||
/Root 1 0 R
|
||||
/Info 10 0 R
|
||||
>>
|
||||
|
||||
startxref
|
||||
2714
|
||||
%%EOF
|
||||
71
tests/src/test.uuencode
Normal file
71
tests/src/test.uuencode
Normal file
@@ -0,0 +1,71 @@
|
||||
begin 664 test.pdf
|
||||
M)5!$1BTQ+C,-"B7BX\_3#0H-"C$@,"!O8FH-"CP\#0HO5'EP92`O0V%T86QO
|
||||
M9PT*+T]U=&QI;F5S(#(@,"!2#0HO4&%G97,@,R`P(%(-"CX^#0IE;F1O8FH-
|
||||
M"@T*,B`P(&]B:@T*/#P-"B]4>7!E("]/=71L:6YE<PT*+T-O=6YT(#`-"CX^
|
||||
M#0IE;F1O8FH-"@T*,R`P(&]B:@T*/#P-"B]4>7!E("]086=E<PT*+T-O=6YT
|
||||
M(#(-"B]+:61S(%L@-"`P(%(@-B`P(%(@72`-"CX^#0IE;F1O8FH-"@T*-"`P
|
||||
M(&]B:@T*/#P-"B]4>7!E("]086=E#0HO4&%R96YT(#,@,"!2#0HO4F5S;W5R
|
||||
M8V5S(#P\#0HO1F]N="`\/`T*+T8Q(#D@,"!2(`T*/CX-"B]0<F]C4V5T(#@@
|
||||
M,"!2#0H^/@T*+TUE9&EA0F]X(%LP(#`@-C$R+C`P,#`@-SDR+C`P,#!=#0HO
|
||||
M0V]N=&5N=',@-2`P(%(-"CX^#0IE;F1O8FH-"@T*-2`P(&]B:@T*/#P@+TQE
|
||||
M;F=T:"`Q,#<T(#X^#0IS=')E86T-"C(@2@T*0E0-"C`@,"`P(')G#0HO1C$@
|
||||
M,#`R-R!49@T*-3<N,S<U,"`W,C(N,C@P,"!49`T**"!!(%-I;7!L92!01$8@
|
||||
M1FEL92`I(%1J#0I%5`T*0E0-"B]&,2`P,#$P(%1F#0HV.2XR-3`P(#8X."XV
|
||||
M,#@P(%1D#0HH(%1H:7,@:7,@82!S;6%L;"!D96UO;G-T<F%T:6]N("YP9&8@
|
||||
M9FEL92`M("D@5&H-"D54#0I"5`T*+T8Q(#`P,3`@5&8-"C8Y+C(U,#`@-C8T
|
||||
M+C<P-#`@5&0-"B@@:G5S="!F;W(@=7-E(&EN('1H92!6:7)T=6%L($UE8VAA
|
||||
M;FEC<R!T=71O<FEA;',N($UO<F4@=&5X="X@06YD(&UO<F4@*2!4:@T*150-
|
||||
M"D)4#0HO1C$@,#`Q,"!49@T*-CDN,C4P,"`V-3(N-S4R,"!49`T**"!T97AT
|
||||
M+B!!;F0@;6]R92!T97AT+B!!;F0@;6]R92!T97AT+B!!;F0@;6]R92!T97AT
|
||||
M+B`I(%1J#0I%5`T*0E0-"B]&,2`P,#$P(%1F#0HV.2XR-3`P(#8R."XX-#@P
|
||||
M(%1D#0HH($%N9"!M;W)E('1E>'0N($%N9"!M;W)E('1E>'0N($%N9"!M;W)E
|
||||
M('1E>'0N($%N9"!M;W)E('1E>'0N($%N9"!M;W)E("D@5&H-"D54#0I"5`T*
|
||||
M+T8Q(#`P,3`@5&8-"C8Y+C(U,#`@-C$V+C@Y-C`@5&0-"B@@=&5X="X@06YD
|
||||
M(&UO<F4@=&5X="X@0F]R:6YG+"!Z>GIZ>BX@06YD(&UO<F4@=&5X="X@06YD
|
||||
M(&UO<F4@=&5X="X@06YD("D@5&H-"D54#0I"5`T*+T8Q(#`P,3`@5&8-"C8Y
|
||||
M+C(U,#`@-C`T+CDT-#`@5&0-"B@@;6]R92!T97AT+B!!;F0@;6]R92!T97AT
|
||||
M+B!!;F0@;6]R92!T97AT+B!!;F0@;6]R92!T97AT+B!!;F0@;6]R92!T97AT
|
||||
M+B`I(%1J#0I%5`T*0E0-"B]&,2`P,#$P(%1F#0HV.2XR-3`P(#4Y,BXY.3(P
|
||||
M(%1D#0HH($%N9"!M;W)E('1E>'0N($%N9"!M;W)E('1E>'0N("D@5&H-"D54
|
||||
M#0I"5`T*+T8Q(#`P,3`@5&8-"C8Y+C(U,#`@-38Y+C`X.#`@5&0-"B@@06YD
|
||||
M(&UO<F4@=&5X="X@06YD(&UO<F4@=&5X="X@06YD(&UO<F4@=&5X="X@06YD
|
||||
M(&UO<F4@=&5X="X@06YD(&UO<F4@*2!4:@T*150-"D)4#0HO1C$@,#`Q,"!4
|
||||
M9@T*-CDN,C4P,"`U-3<N,3,V,"!49`T**"!T97AT+B!!;F0@;6]R92!T97AT
|
||||
M+B!!;F0@;6]R92!T97AT+B!%=F5N(&UO<F4N($-O;G1I;G5E9"!O;B!P86=E
|
||||
M(#(@+BXN*2!4:@T*150-"F5N9'-T<F5A;0T*96YD;V)J#0H-"C8@,"!O8FH-
|
||||
M"CP\#0HO5'EP92`O4&%G90T*+U!A<F5N="`S(#`@4@T*+U)E<V]U<F-E<R`\
|
||||
M/`T*+T9O;G0@/#P-"B]&,2`Y(#`@4B`-"CX^#0HO4')O8U-E="`X(#`@4@T*
|
||||
M/CX-"B]-961I84)O>"!;,"`P(#8Q,BXP,#`P(#<Y,BXP,#`P70T*+T-O;G1E
|
||||
M;G1S(#<@,"!2#0H^/@T*96YD;V)J#0H-"C<@,"!O8FH-"CP\("],96YG=&@@
|
||||
M-C<V(#X^#0IS=')E86T-"C(@2@T*0E0-"C`@,"`P(')G#0HO1C$@,#`R-R!4
|
||||
M9@T*-3<N,S<U,"`W,C(N,C@P,"!49`T**"!3:6UP;&4@4$1&($9I;&4@,B`I
|
||||
M(%1J#0I%5`T*0E0-"B]&,2`P,#$P(%1F#0HV.2XR-3`P(#8X."XV,#@P(%1D
|
||||
M#0HH("XN+F-O;G1I;G5E9"!F<F]M('!A9V4@,2X@665T(&UO<F4@=&5X="X@
|
||||
M06YD(&UO<F4@=&5X="X@06YD(&UO<F4@=&5X="X@*2!4:@T*150-"D)4#0HO
|
||||
M1C$@,#`Q,"!49@T*-CDN,C4P,"`V-S8N-C4V,"!49`T**"!!;F0@;6]R92!T
|
||||
M97AT+B!!;F0@;6]R92!T97AT+B!!;F0@;6]R92!T97AT+B!!;F0@;6]R92!T
|
||||
M97AT+B!!;F0@;6]R92`I(%1J#0I%5`T*0E0-"B]&,2`P,#$P(%1F#0HV.2XR
|
||||
M-3`P(#8V-"XW,#0P(%1D#0HH('1E>'0N($]H+"!H;W<@8F]R:6YG('1Y<&EN
|
||||
M9R!T:&ES('-T=69F+B!"=70@;F]T(&%S(&)O<FEN9R!A<R!W871C:&EN9R`I
|
||||
M(%1J#0I%5`T*0E0-"B]&,2`P,#$P(%1F#0HV.2XR-3`P(#8U,BXW-3(P(%1D
|
||||
M#0HH('!A:6YT(&1R>2X@06YD(&UO<F4@=&5X="X@06YD(&UO<F4@=&5X="X@
|
||||
M06YD(&UO<F4@=&5X="X@06YD(&UO<F4@=&5X="X@*2!4:@T*150-"D)4#0HO
|
||||
M1C$@,#`Q,"!49@T*-CDN,C4P,"`V-#`N.#`P,"!49`T**"!";W)I;F<N("!-
|
||||
M;W)E+"!A(&QI='1L92!M;W)E('1E>'0N(%1H92!E;F0L(&%N9"!J=7-T(&%S
|
||||
M('=E;&PN("D@5&H-"D54#0IE;F1S=')E86T-"F5N9&]B:@T*#0HX(#`@;V)J
|
||||
M#0I;+U!$1B`O5&5X=%T-"F5N9&]B:@T*#0HY(#`@;V)J#0H\/`T*+U1Y<&4@
|
||||
M+T9O;G0-"B]3=6)T>7!E("]4>7!E,0T*+TYA;64@+T8Q#0HO0F%S949O;G0@
|
||||
M+TAE;'9E=&EC80T*+T5N8V]D:6YG("]7:6Y!;G-I16YC;V1I;F<-"CX^#0IE
|
||||
M;F1O8FH-"@T*,3`@,"!O8FH-"CP\#0HO0W)E871O<B`H4F%V92!<*&AT='`Z
|
||||
M+R]W=W<N;F5V<F]N82YC;VTO<F%V95PI*0T*+U!R;V1U8V5R("A.979R;VYA
|
||||
M($1E<VEG;G,I#0HO0W)E871I;VY$871E("A$.C(P,#8P,S`Q,#<R.#(V*0T*
|
||||
M/CX-"F5N9&]B:@T*#0IX<F5F#0HP(#$Q#0HP,#`P,#`P,#`P(#8U-3,U(&8-
|
||||
M"C`P,#`P,#`P,3D@,#`P,#`@;@T*,#`P,#`P,#`Y,R`P,#`P,"!N#0HP,#`P
|
||||
M,#`P,30W(#`P,#`P(&X-"C`P,#`P,#`R,C(@,#`P,#`@;@T*,#`P,#`P,#,Y
|
||||
M,"`P,#`P,"!N#0HP,#`P,#`Q-3(R(#`P,#`P(&X-"C`P,#`P,#$V.3`@,#`P
|
||||
M,#`@;@T*,#`P,#`P,C0R,R`P,#`P,"!N#0HP,#`P,#`R-#4V(#`P,#`P(&X-
|
||||
M"C`P,#`P,#(U-S0@,#`P,#`@;@T*#0IT<F%I;&5R#0H\/`T*+U-I>F4@,3$-
|
||||
M"B]2;V]T(#$@,"!2#0HO26YF;R`Q,"`P(%(-"CX^#0H-"G-T87)T>')E9@T*
|
||||
-,C<Q-`T*)25%3T8-"@``
|
||||
`
|
||||
end
|
||||
Reference in New Issue
Block a user