From 734ac1e1d2b3ce10a2da1a7e736a30bdf0bc5cf8 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Mon, 19 Oct 2009 01:58:31 +0000 Subject: [PATCH] deal with stream-specific crypt filters git-svn-id: svn+q:///qpdf/trunk@827 71b93d88-0707-0410-a8cf-f5a4172ac649 --- TODO | 14 +- include/qpdf/QPDFObjectHandle.hh | 7 +- libqpdf/QPDFObjectHandle.cc | 23 ++ libqpdf/QPDF_Stream.cc | 16 +- libqpdf/QPDF_encryption.cc | 25 +- qpdf/qpdf.testcov | 1 + qpdf/qtest/qpdf.test | 10 +- qpdf/qtest/qpdf/decrypted-crypt-filter.pdf | Bin 0 -> 14383 bytes qpdf/qtest/qpdf/metadata-crypt-filter.pdf | 411 +++++++++++++++++++++ 9 files changed, 483 insertions(+), 24 deletions(-) create mode 100644 qpdf/qtest/qpdf/decrypted-crypt-filter.pdf create mode 100644 qpdf/qtest/qpdf/metadata-crypt-filter.pdf diff --git a/TODO b/TODO index ee52b38f..1f63c646 100644 --- a/TODO +++ b/TODO @@ -1,9 +1,6 @@ 2.1 === - * Really need to handle /Crypt filter for Metadata. Search for crypt - below. - * Update documentation to reflect new command line flags and any other relevant changes. Should read through ChangeLog and the manual before releasing 2.1. @@ -83,10 +80,13 @@ General filters. There is an example in the spec of using a crypt filter on a metadata stream. - When we write encrypted files, we must remember to omit any - encryption filter settings from original streams. - - We need a way to test this. + For now, we notice /Crypt filters and decode parameters consistent + with the example in the PDF specification, and the right thing + happens for metadata filters that happen to be uncompressed or + otherwise compressed in a way we can filter. This should handle + all normal cases, but it's more or less just a guess since I don't + have any test files that actually use stream-specific crypt filters + in them. * The second xref stream for linearized files has to be padded only because we need file_size as computed in pass 1 to be accurate. If diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh index 348aef6b..0a277384 100644 --- a/include/qpdf/QPDFObjectHandle.hh +++ b/include/qpdf/QPDFObjectHandle.hh @@ -77,14 +77,14 @@ class DLL_EXPORT QPDFObjectHandle bool isNumber(); double getNumericValue(); - // Methods for name objects + // Methods for name objects; see also name and array objects std::string getName(); // Methods for string objects std::string getStringValue(); std::string getUTF8Value(); - // Methods for array objects + // Methods for array objects; see also name and array objects int getArrayNItems(); QPDFObjectHandle getArrayItem(int n); @@ -93,6 +93,9 @@ class DLL_EXPORT QPDFObjectHandle QPDFObjectHandle getKey(std::string const&); std::set getKeys(); + // Methods for name and array objects + bool isOrHasName(std::string const&); + // Mutator methods. Use with caution. // Recursively copy this object, making it direct. Throws an diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 08d648bd..c3a7167b 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -258,6 +258,29 @@ QPDFObjectHandle::getKeys() return dynamic_cast(obj.getPointer())->getKeys(); } +// Array and Name accessors +bool +QPDFObjectHandle::isOrHasName(std::string const& value) +{ + if (isName() && (getName() == value)) + { + return true; + } + else if (isArray()) + { + int n = getArrayNItems(); + for (int i = 0; i < n; ++i) + { + QPDFObjectHandle item = getArrayItem(0); + if (item.isName() && (item.getName() == value)) + { + return true; + } + } + } + return false; +} + // Dictionary mutators void diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index a9e2ec51..6642a06e 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -136,6 +136,13 @@ QPDF_Stream::filterable(std::vector& filters, filterable = false; } } + else if (((key == "/Type") || (key == "/Name")) && + decode_obj.getKey("/Type").isName() && + (decode_obj.getKey("/Type").getName() == + "/CryptFilterDecodeParms")) + { + // we handle this in decryptStream + } else { filterable = false; @@ -212,7 +219,8 @@ QPDF_Stream::filterable(std::vector& filters, iter != filters.end(); ++iter) { std::string const& filter = *iter; - if (! ((filter == "/FlateDecode") || + if (! ((filter == "/Crypt") || + (filter == "/FlateDecode") || (filter == "/LZWDecode") || (filter == "/ASCII85Decode") || (filter == "/ASCIIHexDecode"))) @@ -266,7 +274,11 @@ QPDF_Stream::pipeStreamData(Pipeline* pipeline, bool filter, iter != filters.rend(); ++iter) { std::string const& filter = *iter; - if (filter == "/FlateDecode") + if (filter == "/Crypt") + { + // Ignore -- handled by pipeStreamData + } + else if (filter == "/FlateDecode") { if (predictor == 12) { diff --git a/libqpdf/QPDF_encryption.cc b/libqpdf/QPDF_encryption.cc index fa16f55d..8962624d 100644 --- a/libqpdf/QPDF_encryption.cc +++ b/libqpdf/QPDF_encryption.cc @@ -600,18 +600,19 @@ QPDF::decryptStream(Pipeline*& pipeline, int objid, int generation, encryption_method_e method = e_unknown; std::string method_source = "/StmF from /Encrypt dictionary"; - // NOTE: the section in the PDF specification on crypt filters - // seems to suggest that there might be a /Crypt key in - // /DecodeParms whose value is a crypt filter (.e.g., << /Name - // /StdCF >>), but implementation notes suggest this can only - // happen for metadata streams, and emperical observation - // suggests that they are otherwise ignored. Not having been - // able to find a sample file that uses crypt filters in any - // way other than /StrF and /StmF, I'm not really sure what to - // do about this. If we were to override the encryption on a - // per-stream basis using crypt filters, set method_source to - // something useful in the error message for unknown - // encryption methods (search for method_source). + if (stream_dict.getKey("/Filter").isOrHasName("/Crypt") && + stream_dict.getKey("/DecodeParms").isDictionary()) + { + QPDFObjectHandle decode_parms = stream_dict.getKey("/DecodeParms"); + if (decode_parms.getKey("/Type").isName() && + (decode_parms.getKey("/Type").getName() == + "/CryptFilterDecodeParms")) + { + QTC::TC("qpdf", "QPDF_encryption stream crypt filter"); + method = interpretCF(decode_parms.getKey("/Name")); + method_source = "stream's Crypt decode parameters"; + } + } if (method == e_unknown) { diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index dd9ec5b1..6246e8e1 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -170,3 +170,4 @@ QPDFWriter forcing object stream disable 0 QPDFWriter forced version disabled encryption 0 qpdf-c called qpdf_set_r4_encryption_parameters 0 qpdf-c called qpdf_set_static_aes_IV 0 +QPDF_encryption stream crypt filter 0 diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index f1f2cc53..0c05121b 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -1079,7 +1079,7 @@ $td->runtest("make sure there is no xref stream", $td->NORMALIZE_NEWLINES); # Look at some actual V4 files -$n_tests += 8; +$n_tests += 10; foreach my $d (['--force-V4', 'V4'], ['--cleartext-metadata', 'V4-clearmeta'], ['--use-aes=y', 'V4-aes'], @@ -1094,6 +1094,14 @@ foreach my $d (['--force-V4', 'V4'], {$td->FILE => "a.pdf"}, {$td->FILE => "$out.pdf"}); } +# Crypt Filter +$td->runtest("decrypt with crypt filter", + {$td->COMMAND => "qpdf --decrypt --static-id" . + " metadata-crypt-filter.pdf a.pdf"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}); +$td->runtest("check output", + {$td->FILE => 'a.pdf'}, + {$td->FILE => 'decrypted-crypt-filter.pdf'}); show_ntests(); # ---------- diff --git a/qpdf/qtest/qpdf/decrypted-crypt-filter.pdf b/qpdf/qtest/qpdf/decrypted-crypt-filter.pdf new file mode 100644 index 0000000000000000000000000000000000000000..75e7f788296a99ee7056566da3375e00a379ca7a GIT binary patch literal 14383 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 RJZVw*EHrN4e(Qe6_#cu0%g6u# literal 0 HcmV?d00001 diff --git a/qpdf/qtest/qpdf/metadata-crypt-filter.pdf b/qpdf/qtest/qpdf/metadata-crypt-filter.pdf new file mode 100644 index 00000000..39ed3d81 --- /dev/null +++ b/qpdf/qtest/qpdf/metadata-crypt-filter.pdf @@ -0,0 +1,411 @@ +%PDF-1.5 +% +1 0 obj +<< /Metadata 3 0 R /Outlines 4 0 R /PageLabels << /Nums [ 0 << /P () >> 2 << /S /r /St 1 >> 7 << /P () >> 9 << /S /r /St 6 >> 11 << /P () >> 12 << /S /D /St 2 >> 15 << /S /D /St 6 >> 19 << /P () >> 20 << /S /D /St 12 >> 22 << /S /D /St 16059 >> 23 << /S /r /St 50 >> 29 << /S /r /St 54 >> ] >> /PageMode /UseOutlines /Pages 5 0 R /Type /Catalog >> +endobj +2 0 obj +<< /CreationDate /ModDate >> +endobj +3 0 obj +<< /Subtype /XML /Type /Metadata /DecodeParms << /Name /Identity /Type /CryptFilterDecodeParms >> /Filter /Crypt /Length 770 >> +stream + + + + + + 2003-10-10T18:04:32-03:00 + 2003-10-10T18:04:32-03:00 + + + + 2003-10-10T18:04:32-03:00 + 2003-10-10T18:04:32-03:00 + 2003-10-10T18:04:32-03:00 + + + +endstream +endobj +4 0 obj +<< /Count 6 /First 6 0 R /Last 7 0 R /Type /Outlines >> +endobj +5 0 obj +<< /Count 30 /Kids [ 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R 26 0 R 27 0 R 28 0 R 29 0 R 30 0 R 31 0 R 32 0 R 33 0 R 34 0 R 35 0 R 36 0 R 37 0 R ] /Type /Pages >> +endobj +6 0 obj +<< /Count 4 /Dest [ 13 0 R /XYZ null null null ] /First 38 0 R /Last 39 0 R /Next 7 0 R /Parent 4 0 R /Title <0bace566042e35f13ccb00496b6552b92c0c4c87ca4a8cbe11761a3c9718c8c0> /Type /Outline >> +endobj +7 0 obj +<< /Dest [ 23 0 R /XYZ 66 756 3 ] /Parent 4 0 R /Prev 6 0 R /Title /Type /Outline >> +endobj +8 0 obj +<< /Contents 40 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +9 0 obj +<< /Contents 43 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +10 0 obj +<< /Contents 44 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +11 0 obj +<< /Contents 45 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +12 0 obj +<< /Contents 46 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +13 0 obj +<< /Contents 47 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +14 0 obj +<< /Contents 48 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +15 0 obj +<< /Contents 49 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +16 0 obj +<< /Contents 50 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +17 0 obj +<< /Contents 51 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +18 0 obj +<< /Contents 52 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +19 0 obj +<< /Contents 53 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +20 0 obj +<< /Contents 54 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +21 0 obj +<< /Contents 55 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +22 0 obj +<< /Contents 56 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +23 0 obj +<< /Contents 57 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +24 0 obj +<< /Contents 58 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +25 0 obj +<< /Contents 59 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +26 0 obj +<< /Contents 60 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +27 0 obj +<< /Contents 61 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +28 0 obj +<< /Contents 62 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +29 0 obj +<< /Contents 63 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +30 0 obj +<< /Contents 64 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +31 0 obj +<< /Contents 65 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +32 0 obj +<< /Contents 66 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +33 0 obj +<< /Contents 67 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +34 0 obj +<< /Contents 68 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +35 0 obj +<< /Contents 69 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +36 0 obj +<< /Contents 70 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +37 0 obj +<< /Contents 71 0 R /CropBox [ 0 0 612 792 ] /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 41 0 R >> /ProcSet 42 0 R >> /Rotate 0 /Type /Page >> +endobj +38 0 obj +<< /Count -3 /Dest [ 19 0 R /Fit ] /First 72 0 R /Last 73 0 R /Next 39 0 R /Parent 6 0 R /Title <3fb30ac89234ff057e20814f60a034d2e5025f8cc58e> /Type /Outline >> +endobj +39 0 obj +<< /Count 2 /Dest [ 21 0 R /FitH 792 ] /First 74 0 R /Last 75 0 R /Parent 6 0 R /Prev 38 0 R /Title /Type /Outline >> +endobj +40 0 obj +<< /Length 50 /Filter /FlateDecode >> +stream + tv4Rnjaa-XjEB)s7DZJlendstream +endobj +41 0 obj +<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >> +endobj +42 0 obj +[ /PDF /Text ] +endobj +43 0 obj +<< /Length 50 /Filter /FlateDecode >> +stream +KCZX.WZhwwA'v jWY}endstream +endobj +44 0 obj +<< /Length 50 /Filter /FlateDecode >> +stream +ę|qsg:/IƸҐQ,V;Ukb{Ԝ,endstream +endobj +45 0 obj +<< /Length 50 /Filter /FlateDecode >> +stream +Cv=J@VޥI>Ht5y{7ݢK٪Py˨h_endstream +endobj +46 0 obj +<< /Length 50 /Filter /FlateDecode >> +stream +FKEnADov8 ,J;4J؇am"endstream +endobj +47 0 obj +<< /Length 50 /Filter /FlateDecode >> +stream +1'[1fi:l:S$GʮD1:]Ѩiendstream +endobj +48 0 obj +<< /Length 50 /Filter /FlateDecode >> +stream +2d#[ߑ)Oŵ j)^iNmOʢf}endstream +endobj +49 0 obj +<< /Length 50 /Filter /FlateDecode >> +stream +&;PG2fs@[Ԡy> +stream +7ۥsIT!ݔ%ÞXjIdMVQ+{65fendstream +endobj +51 0 obj +<< /Length 50 /Filter /FlateDecode >> +stream +l∿q kO vѪ[F3D{CAp,endstream +endobj +52 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +bǕM+|f.Ѥ8|{o#-&t%ca|Tendstream +endobj +53 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +Nc&fFuy4e.X\X"Kp;E[hzKcbendstream +endobj +54 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +}s+8QH}zM >i|v&&|!endstream +endobj +55 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +&hyu8iҐ̈́qSQ #.P5)I}+ˮendstream +endobj +56 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +X$Q$ B2.`e\tVw'q#E(~Yހd}endstream +endobj +57 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +_|Y9-n*k IAs}瑁L_9AsRendstream +endobj +58 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +_ZţH#!ެk39$/m?ڦl/Z/}@6@Vve7endstream +endobj +59 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +Fl+y'k`2orfY%1endstream +endobj +60 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +D%MXe=F( Iv_enҩVb! r!Iendstream +endobj +61 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +}Q[ULWh]"*ԶGt3~njoo{CD endstream +endobj +62 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +!Ӂ7aJ8c1[LܼPQl.bS)al L#+&sendstream +endobj +63 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +nqbv0X:V|b毕hmG0۔> +stream +@UYX#`[sS?*f( HuhByendstream +endobj +65 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +dq[!r09 F)hBQcGS`E)6k?mIendstream +endobj +66 0 obj +<< /Length 50 /Filter /FlateDecode >> +stream +p*-$ +>v_a.F!f2%endstream +endobj +67 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +WSX\,^Mʵ2A" p]>|/X,P3endstream +endobj +68 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +օU=MŢNSgϮݏX +#߀}`*?h6Pss{Vendstream +endobj +69 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +!h,s!/Ci"#mCAO$9Ⱦh${OM'endstream +endobj +70 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +7ZSL0=ƻ./ +|:&_! s*u#endstream +endobj +71 0 obj +<< /Length 51 /Filter /FlateDecode >> +stream +P+@Y( {?g]lvR9UŒ?-wOendstream +endobj +72 0 obj +<< /Count -2 /Dest [ 20 0 R /FitV 100 ] /First 76 0 R /Last 77 0 R /Next 73 0 R /Parent 38 0 R /Title /Type /Outline >> +endobj +73 0 obj +<< /Count 1 /Dest [ 20 0 R /XYZ null null null ] /First 78 0 R /Last 78 0 R /Parent 38 0 R /Prev 72 0 R /Title (輧:8\226v\)N\(\210\035NT\036mvj\tnl\212;o.\2113) /Type /Outline >> +endobj +74 0 obj +<< /Dest [ 9 0 R /FitR 66 714 180 770 ] /Next 75 0 R /Parent 39 0 R /Title <498fe6ebfb28be416edddb53c1a63ffee3887fce2a7a2e34043792493f5a7c1f8818fa24a81dbbd055212dae> /Type /Outline >> +endobj +75 0 obj +<< /Dest [ 8 0 R /XYZ null null null ] /Parent 39 0 R /Prev 74 0 R /Title <69fb82b1b1b8833e343e5f401879d3083e0cd738a3f54342e881ead5b6bc1816e7e3b431d48b1c0a14> /Type /Outline >> +endobj +76 0 obj +<< /Dest [ 26 0 R /XYZ null null null ] /Next 77 0 R /Parent 72 0 R /Title <1433a18038fcd41d81200f85f0f942caedcce35a9fddde851dd1b70def5f196aeac27ccf5f5b725ecc89be> /Type /Outline >> +endobj +77 0 obj +<< /Dest [ 27 0 R /XYZ null null null ] /Parent 72 0 R /Prev 76 0 R /Title <9028484736aaf8f0b5eedc521a7169cc9e2295cfd80eed0c2e41c44c26ba7c6ff586a290be701394f7e5ad> /Type /Outline >> +endobj +78 0 obj +<< /Dest [ 30 0 R /XYZ null null null ] /Parent 73 0 R /Title <6c21f1d776e7e20cadb7be7247c9856e4da1fbaded20b1596cc68c35e8c7f5c2ebd4a242796ea858837daa> /Type /Outline >> +endobj +79 0 obj +<< /CF << /StdCF << /AuthEvent /DocOpen /CFM /V2 >> >> /EncryptMetadata false /Filter /Standard /Length 128 /O <566fa873ee33c797cd3b904fdadf814afa34df9a38f6ed41b984e2c6da2aa6f5> /P -4 /R 4 /StmF /StdCF /StrF /StdCF /U <3a40816f776fccd39a9c505a9d4110e60122456a91bae5134273a6db134c87c4> /V 4 >> +endobj +xref +0 80 +0000000000 65535 f +0000000015 00000 n +0000000378 00000 n +0000000520 00000 n +0000001450 00000 n +0000001521 00000 n +0000001783 00000 n +0000001992 00000 n +0000002153 00000 n +0000002334 00000 n +0000002515 00000 n +0000002697 00000 n +0000002879 00000 n +0000003061 00000 n +0000003243 00000 n +0000003425 00000 n +0000003607 00000 n +0000003789 00000 n +0000003971 00000 n +0000004153 00000 n +0000004335 00000 n +0000004517 00000 n +0000004699 00000 n +0000004881 00000 n +0000005063 00000 n +0000005245 00000 n +0000005427 00000 n +0000005609 00000 n +0000005791 00000 n +0000005973 00000 n +0000006155 00000 n +0000006337 00000 n +0000006519 00000 n +0000006701 00000 n +0000006883 00000 n +0000007065 00000 n +0000007247 00000 n +0000007429 00000 n +0000007611 00000 n +0000007788 00000 n +0000007977 00000 n +0000008098 00000 n +0000008206 00000 n +0000008237 00000 n +0000008358 00000 n +0000008479 00000 n +0000008600 00000 n +0000008721 00000 n +0000008842 00000 n +0000008963 00000 n +0000009084 00000 n +0000009205 00000 n +0000009326 00000 n +0000009448 00000 n +0000009570 00000 n +0000009692 00000 n +0000009814 00000 n +0000009936 00000 n +0000010058 00000 n +0000010180 00000 n +0000010302 00000 n +0000010424 00000 n +0000010546 00000 n +0000010668 00000 n +0000010790 00000 n +0000010912 00000 n +0000011034 00000 n +0000011155 00000 n +0000011277 00000 n +0000011399 00000 n +0000011521 00000 n +0000011643 00000 n +0000011765 00000 n +0000011966 00000 n +0000012176 00000 n +0000012376 00000 n +0000012569 00000 n +0000012767 00000 n +0000012965 00000 n +0000013150 00000 n +trailer << /Info 2 0 R /Root 1 0 R /Size 80 /ID [<66d36a30a97e0f16f39955c6221e0c2a><31415926535897932384626433832795>] /Encrypt 79 0 R >> +startxref +13459 +%%EOF