From f8306913ba6eb751cd7f408d04f2d65d8cd3b341 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Mon, 31 Dec 2012 06:47:11 -0500 Subject: [PATCH] Update "C" API with functions for new features --- ChangeLog | 9 ++++ include/qpdf/qpdf-c.h | 26 +++++++++++ libqpdf/qpdf-c.cc | 48 +++++++++++++++++++- qpdf/qpdf-ctest.c | 40 +++++++++++++++- qpdf/qpdf.testcov | 3 ++ qpdf/qtest/qpdf.test | 47 ++++++++++++++----- qpdf/qtest/qpdf/c-decrypt-R5-with-user.pdf | Bin 0 -> 9731 bytes qpdf/qtest/qpdf/c-decrypt-R6-with-owner.pdf | Bin 0 -> 9731 bytes qpdf/qtest/qpdf/c-min-version.out | 4 ++ qpdf/qtest/qpdf/c-r5-in.pdf | Bin 0 -> 11195 bytes qpdf/qtest/qpdf/c-r5.out | 20 ++++++++ qpdf/qtest/qpdf/c-r6-in.pdf | Bin 0 -> 11195 bytes qpdf/qtest/qpdf/c-r6.out | 20 ++++++++ 13 files changed, 202 insertions(+), 15 deletions(-) create mode 100644 qpdf/qtest/qpdf/c-decrypt-R5-with-user.pdf create mode 100644 qpdf/qtest/qpdf/c-decrypt-R6-with-owner.pdf create mode 100644 qpdf/qtest/qpdf/c-min-version.out create mode 100644 qpdf/qtest/qpdf/c-r5-in.pdf create mode 100644 qpdf/qtest/qpdf/c-r5.out create mode 100644 qpdf/qtest/qpdf/c-r6-in.pdf create mode 100644 qpdf/qtest/qpdf/c-r6.out diff --git a/ChangeLog b/ChangeLog index c85b27a5..c68c4ceb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2012-12-31 Jay Berkenbilt + + * Add new methods qpdf_get_pdf_extension_level, + qpdf_set_r5_encryption_parameters, + qpdf_set_r6_encryption_parameters, + qpdf_set_minimum_pdf_version_and_extension, and + qpdf_force_pdf_version_and_extension to support new functionality + from the C API. + 2012-12-30 Jay Berkenbilt * Fix long-standing bug that could theoretically have resulted in diff --git a/include/qpdf/qpdf-c.h b/include/qpdf/qpdf-c.h index 57100839..ee4fa58c 100644 --- a/include/qpdf/qpdf-c.h +++ b/include/qpdf/qpdf-c.h @@ -213,6 +213,10 @@ extern "C" { QPDF_DLL char const* qpdf_get_pdf_version(qpdf_data qpdf); + /* Return the extension level of the PDF file. */ + QPDF_DLL + int qpdf_get_pdf_extension_level(qpdf_data qpdf); + /* Return the user password. If the file is opened using the * owner password, the user password may be retrieved using this * function. If the file is opened using the user password, this @@ -358,15 +362,37 @@ extern "C" { enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify, QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes); + QPDF_DLL + void qpdf_set_r5_encryption_parameters( + qpdf_data qpdf, char const* user_password, char const* owner_password, + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, + enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify, + QPDF_BOOL encrypt_metadata); + + QPDF_DLL + void qpdf_set_r6_encryption_parameters( + qpdf_data qpdf, char const* user_password, char const* owner_password, + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, + enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify, + QPDF_BOOL encrypt_metadata); + QPDF_DLL void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value); QPDF_DLL void qpdf_set_minimum_pdf_version(qpdf_data qpdf, char const* version); + QPDF_DLL + void qpdf_set_minimum_pdf_version_and_extension( + qpdf_data qpdf, char const* version, int extension_level); + QPDF_DLL void qpdf_force_pdf_version(qpdf_data qpdf, char const* version); + QPDF_DLL + void qpdf_force_pdf_version_and_extension( + qpdf_data qpdf, char const* version, int extension_level); + /* Do actual write operation. */ QPDF_DLL QPDF_ERROR_CODE qpdf_write(qpdf_data qpdf); diff --git a/libqpdf/qpdf-c.cc b/libqpdf/qpdf-c.cc index 0312ae50..a46df63e 100644 --- a/libqpdf/qpdf-c.cc +++ b/libqpdf/qpdf-c.cc @@ -288,6 +288,12 @@ char const* qpdf_get_pdf_version(qpdf_data qpdf) return qpdf->tmp_string.c_str(); } +int qpdf_get_pdf_extension_level(qpdf_data qpdf) +{ + QTC::TC("qpdf", "qpdf-c called qpdf_get_pdf_extension_level"); + return qpdf->qpdf->getExtensionLevel(); +} + char const* qpdf_get_user_password(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_get_user_password"); @@ -566,6 +572,32 @@ void qpdf_set_r4_encryption_parameters( encrypt_metadata, use_aes); } +void qpdf_set_r5_encryption_parameters( + qpdf_data qpdf, char const* user_password, char const* owner_password, + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, + qpdf_r3_print_e print, qpdf_r3_modify_e modify, + QPDF_BOOL encrypt_metadata) +{ + QTC::TC("qpdf", "qpdf-c called qpdf_set_r5_encryption_parameters"); + qpdf->qpdf_writer->setR5EncryptionParameters( + user_password, owner_password, + allow_accessibility, allow_extract, print, modify, + encrypt_metadata); +} + +void qpdf_set_r6_encryption_parameters( + qpdf_data qpdf, char const* user_password, char const* owner_password, + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, + qpdf_r3_print_e print, qpdf_r3_modify_e modify, + QPDF_BOOL encrypt_metadata) +{ + QTC::TC("qpdf", "qpdf-c called qpdf_set_r6_encryption_parameters"); + qpdf->qpdf_writer->setR6EncryptionParameters( + user_password, owner_password, + allow_accessibility, allow_extract, print, modify, + encrypt_metadata); +} + void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_linearization"); @@ -573,15 +605,27 @@ void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value) } void qpdf_set_minimum_pdf_version(qpdf_data qpdf, char const* version) +{ + qpdf_set_minimum_pdf_version_and_extension(qpdf, version, 0); +} + +void qpdf_set_minimum_pdf_version_and_extension( + qpdf_data qpdf, char const* version, int extension_level) { QTC::TC("qpdf", "qpdf-c called qpdf_set_minimum_pdf_version"); - qpdf->qpdf_writer->setMinimumPDFVersion(version); + qpdf->qpdf_writer->setMinimumPDFVersion(version, extension_level); } void qpdf_force_pdf_version(qpdf_data qpdf, char const* version) +{ + qpdf_force_pdf_version_and_extension(qpdf, version, 0); +} + +void qpdf_force_pdf_version_and_extension( + qpdf_data qpdf, char const* version, int extension_level) { QTC::TC("qpdf", "qpdf-c called qpdf_force_pdf_version"); - qpdf->qpdf_writer->forcePDFVersion(version); + qpdf->qpdf_writer->forcePDFVersion(version, extension_level); } QPDF_ERROR_CODE qpdf_write(qpdf_data qpdf) diff --git a/qpdf/qpdf-ctest.c b/qpdf/qpdf-ctest.c index 072e5a7c..58fcb002 100644 --- a/qpdf/qpdf-ctest.c +++ b/qpdf/qpdf-ctest.c @@ -106,6 +106,10 @@ static void test01(char const* infile, { qpdf_read(qpdf, infile, password); printf("version: %s\n", qpdf_get_pdf_version(qpdf)); + if (qpdf_get_pdf_extension_level(qpdf) > 0) + { + printf("extension level: %d\n", qpdf_get_pdf_extension_level(qpdf)); + } printf("linearized: %d\n", qpdf_is_linearized(qpdf)); printf("encrypted: %d\n", qpdf_is_encrypted(qpdf)); if (qpdf_is_encrypted(qpdf)) @@ -304,7 +308,7 @@ static void test14(char const* infile, qpdf_read(qpdf, infile, password); qpdf_init_write(qpdf, outfile); qpdf_set_static_ID(qpdf, QPDF_TRUE); - qpdf_set_minimum_pdf_version(qpdf, "1.6"); + qpdf_set_minimum_pdf_version_and_extension(qpdf, "1.7", 8); qpdf_write(qpdf); qpdf_init_write(qpdf, outfile2); qpdf_set_static_ID(qpdf, QPDF_TRUE); @@ -374,6 +378,38 @@ static void test16(char const* infile, report_errors(); } +static void test17(char const* infile, + char const* password, + char const* outfile, + char const* outfile2) +{ + qpdf_read(qpdf, infile, password); + qpdf_init_write(qpdf, outfile); + qpdf_set_static_ID(qpdf, QPDF_TRUE); + qpdf_set_static_aes_IV(qpdf, QPDF_TRUE); + qpdf_set_r5_encryption_parameters( + qpdf, "user3", "owner3", QPDF_TRUE, QPDF_TRUE, + qpdf_r3p_low, qpdf_r3m_all, QPDF_TRUE); + qpdf_write(qpdf); + report_errors(); +} + +static void test18(char const* infile, + char const* password, + char const* outfile, + char const* outfile2) +{ + qpdf_read(qpdf, infile, password); + qpdf_init_write(qpdf, outfile); + qpdf_set_static_ID(qpdf, QPDF_TRUE); + qpdf_set_static_aes_IV(qpdf, QPDF_TRUE); + qpdf_set_r6_encryption_parameters( + qpdf, "user4", "owner4", QPDF_TRUE, QPDF_TRUE, + qpdf_r3p_low, qpdf_r3m_all, QPDF_TRUE); + qpdf_write(qpdf); + report_errors(); +} + int main(int argc, char* argv[]) { char* p = 0; @@ -430,6 +466,8 @@ int main(int argc, char* argv[]) (n == 14) ? test14 : (n == 15) ? test15 : (n == 16) ? test16 : + (n == 17) ? test17 : + (n == 18) ? test18 : 0); if (fn == 0) diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 0263f312..a0578f28 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -256,3 +256,6 @@ QPDF_encryption skip 0x28 0 QPDF_encrypt crypt array 0 QPDF_encryption CFM AESV3 0 QPDFWriter remove Crypt 0 +qpdf-c called qpdf_get_pdf_extension_level 0 +qpdf-c called qpdf_set_r5_encryption_parameters 0 +qpdf-c called qpdf_set_r6_encryption_parameters 0 diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 0e164be7..bf62ceea 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -315,8 +315,8 @@ $td->runtest("C API: min/force versions", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); $td->runtest("C check version 1", - {$td->COMMAND => "qpdf --check a.pdf"}, - {$td->FILE => "min-version.out", + {$td->COMMAND => "qpdf-ctest 1 a.pdf '' ''"}, + {$td->FILE => "c-min-version.out", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); $td->runtest("C check version 2", @@ -1472,29 +1472,52 @@ $td->runtest("C API: invalid password", $td->NORMALIZE_NEWLINES); my @cenc = ( - [11, 'hybrid-xref.pdf', "''", 'r2', ""], - [12, 'hybrid-xref.pdf', "''", 'r3', ""], - [15, 'hybrid-xref.pdf', "''", 'r4', ""], + [11, 'hybrid-xref.pdf', "''", 'r2', "", ""], + [12, 'hybrid-xref.pdf', "''", 'r3', "", ""], + [15, 'hybrid-xref.pdf', "''", 'r4', "", ""], + [17, 'hybrid-xref.pdf', "''", 'r5', "", "owner3"], + [18, 'hybrid-xref.pdf', "''", 'r6', "", "user4"], [13, 'c-r2.pdf', 'user1', 'decrypt with user', - "user password: user1\n"], + "user password: user1\n", ""], [13, 'c-r3.pdf', 'owner2', 'decrypt with owner', - "user password: user2\n"], + "user password: user2\n", ""], + [13, 'c-r5-in.pdf', 'user3', 'decrypt R5 with user', + "user password: user3\n", ""], + [13, 'c-r6-in.pdf', 'owner4', 'decrypt R6 with owner', + "user password: \n", ""], ); $n_tests += 2 * @cenc; foreach my $d (@cenc) { - my ($n, $infile, $pass, $description, $output) = @$d; + my ($n, $infile, $pass, $description, $output, $checkpass) = @$d; my $outfile = $description; $outfile =~ s/ /-/g; - $outfile = "c-$outfile.pdf"; + my $pdf_outfile = "c-$outfile.pdf"; + my $check_outfile = "c-$outfile.out"; $td->runtest("C API encryption: $description", {$td->COMMAND => "qpdf-ctest $n $infile $pass a.pdf"}, {$td->STRING => $output, $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); - $td->runtest("check $description", - {$td->FILE => "a.pdf"}, - {$td->FILE => $outfile}); + if (-f $pdf_outfile) + { + $td->runtest("check $description content", + {$td->FILE => "a.pdf"}, + {$td->FILE => $pdf_outfile}); + } + else + { + # QPDF doesn't provide any way to make the random bits in + # /Perms static, so we have no way to predictably create a + # /V=5 encrypted file. It's not worth adding this...the test + # suite is adequate without having a statically predictable + # file. + $td->runtest("check $description", + {$td->COMMAND => + "qpdf --check a.pdf --password=$checkpass"}, + {$td->FILE => $check_outfile, $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + } } # Test combinations of linearization and encryption. Note that we do diff --git a/qpdf/qtest/qpdf/c-decrypt-R5-with-user.pdf b/qpdf/qtest/qpdf/c-decrypt-R5-with-user.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e3ff67ee6134a16fd219626544cc95d535955dd9 GIT binary patch literal 9731 zcmc&)3sh9q8YT?HQ_3T8A!=<9?5f1fdCUwWD#&939}LW>ScozVM;h)hgL4iKM?;A+ z)FQ0tY1Xx_-2_tyN(o)0w+FerrD?eCT`p9v)ZClay;%9K_Bm(ZoZ3^(tOe_=1?$Y5 z*=K*>{`dcX=imSO<8w1~_u+{eEWYc?jvp}`D1p7W44XY0C^BnU+QwMyHU@BC=Vhd2 z@*mPn484?gaK8Wrd{i=WAzejV0SV^L<^B}o}O~tg80k}%M zwa8vV1H}@C9vaV&goD(=pv7w{;DB@!YqHu);mjCqE8$oY61Kt^eQ}wQEeDE)w5^nV z2&i!-Q0OdHmUh6a)x^>nw3$cC0XWJ1Z>rlGGQqVlASUIl+hc1Js%OVN);})mubY!!JGFF5*d8bT zO4@+4^X$cCc*ld0{f%wlOzJ@5S6A9=yKY@R2iA0*-JL%v|A=)$tFdYMtZ}!FK2rJJ zo1d*LYFoLd{+qWWPuJDlRePzndefI{&Mz~nE%}}A)VJ;LKN}H}xT-0q?EAW#*EZ}8 zvUa$(FZi?4x}&wBujKNPTV?ClK6CZmiqLENuq9<>%zo^t_}zsaO%FQ@wyfA)btv?K zbM<4_DYu5=pSIjs*VbLP!l`JOwu0G~&PD|$KcOjVbw7|5tbC&}yoO=3$inyfBi6LU zl=XdiV0wl*JSaAC?9t^rZtBiVI5S@J^~bjkUQj)9IxBDemY}ZA+8o#0$6nTc`a1RX zW#`|ui+euU_gs7PN7jQA>c*UU@qb%GvEXS%4+RFr@7o&V+^gE(|KH@U)p;+u8nP8B zD<;i)KRQ{v?&(pftM5FTKYi`wTz13bo3)R6hkqKl;9S3w7@hV#{&*X+{ankQ>(>La4?kS_ubN{S z;p)cYUqpS|r+jo)^MZS(-Ykj^?YX0T+mwGt4b1#7wUOG{qwjtpJ~L$&xR6qD_o0^B zA5y-%Z_)zjydGckxH0eMgHe}mue7m%gnqlgQo?`&KnOuV2mwQA_>drygo~EH;KEJ# z5Eo`77sT+wMF+eHu}4zENZ|oO7(#d+5T?e3IY|MJ^Z*I75T02)Lp-wxb5g=AlrSeH zJU|H#P@W+I0wqjc2oyrJa(ci>;+bEEXb2nBAC>`>z(lc#F0q)>>^0CP9HJU0fJRFI zI9smC0Y?tWg@I=5l@2qUn$sx;VK*CT7Er=kxLYDADJSj`gp*2G zvs|1w&L}5g17zaF`x44Y@CLa!aTY;2dEQ3y_!Gfd1mz^eiClK#EP`_KyrN~Y6K4^W zlP4pPi4$iLl#{Ib#J?U;PJ+r<%Eig6j;m$Wal)&Pt7X-3K8Zl~PA#jB z^BE1wNmd=_(<_vdtUAu;dMGDZb(~K;QBJbzIO$c#)w1e1pLU~ml2ym~GXTm-Rvjn3 z>bOQ$9Vfl&xJFhT=TBwG-f3jjasG&ia*|cY`SU8uNmd=_56>tkS#_L0$)lWP)p5$J zj%#GqalXcZ+DTR&=PM|KoV=DpJ@ryp){s_08SK0v_jonASV`oCWRG(F@|9mK4*8_dG4_05K(7v)f>gHnddna%S2yO1F^VkOT1B%Kvk8`tZLl6| zv6TWvzQr~VmYc;JIi_-0_0{1(VXQ1>`4TW!p@H9pLJdEcSPbS1IUH62Ebe6J;3&F= z1%-pPV!mQCNac5Jfct3!N;HDI1j|8;ppsT0h8OwNkon!I*nAXOT5A|yHqGU{Z$rm$-S}IM0Cm0G;mmf#a-^5h()2m(p+y?fkjjI&cvb-V7^r0(%VKWSp82lQ5SgsGi1*sE|k{OgIQGGtjGsT7Hs#tK&!L z{DG|kV%qDRPS7`~gic}?OHCmD&lPEQzrbsf0Bs5yp+&>;s_>04)xi}zjnl89D zcv|qrO7Pswh7aG*O8oz;9sjxGu2EC(JwE=U>EQL9MXrkZx%ZE`?NBpVI z))@y|=O0iXNeI*}IUH$zJ}BU=s<>+I==;k~6NWW8*cu1D3e%EW5{r+|)a$UH0dNrG AivR!s literal 0 HcmV?d00001 diff --git a/qpdf/qtest/qpdf/c-decrypt-R6-with-owner.pdf b/qpdf/qtest/qpdf/c-decrypt-R6-with-owner.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8e5d9b81a198fd6f896e5d8636ab49b6def07694 GIT binary patch literal 9731 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 AkN^Mx literal 0 HcmV?d00001 diff --git a/qpdf/qtest/qpdf/c-min-version.out b/qpdf/qtest/qpdf/c-min-version.out new file mode 100644 index 00000000..94558ace --- /dev/null +++ b/qpdf/qtest/qpdf/c-min-version.out @@ -0,0 +1,4 @@ +version: 1.7 +extension level: 8 +linearized: 0 +encrypted: 0 diff --git a/qpdf/qtest/qpdf/c-r5-in.pdf b/qpdf/qtest/qpdf/c-r5-in.pdf new file mode 100644 index 0000000000000000000000000000000000000000..19c67a30dbf07af2c8e3e1314e9ecc707421652b GIT binary patch literal 11195 zcmc(lc~lcu8^*O27b-~I7i_1kh@hCstQnz*5Yj5EL@ArgWHNzh2$+P;PtmGXiVDc4 zf>tVSMJ$R)5x0U?+FBLd>H>nLwpw?vij~&y&I}6Q8GF9JNX~&XOYZWUckX@W-sijy zfpUe5bRuc(aO~;Uf2^et48^GCS-ZJG67NJ4t2b(6^hSugoFe!1=1)9nBOA;bxL+U% zsM@8ZFB{M5AQW1)vGy5qzkQ3CO|b$X^Ms1bsyTrT9+?rsQE!5|7eEiU%4lT z9?Ne(={dhN%AK~(z8*IFe)0X%8BM7b(hsr?>LU;B_xBpxmKqkad2P?4sf|@1yq6kj zcWP?i%H9QQ8gKsIlJjopxXm9aMo;~vIArzZ=#fXVe*C-O&ea`_#zP7u^_~g1~9;+U@Y9E}VssBT_=vGT{e(Xi~ z-LEc9EeH)m2GDI6rYf;WWR3T-yseEvryY;4uO-GEu8%n!@Bg%HlN?=nC`&yesn5?x z{+{aclfOgCp~a`O*6%x`>sy=T4?T1}-D(rRYp8$g#N_%_ntMZzjST8Jxh&-Nz?As` zo2jgyOk=A^mY#T7f-_N_g9(fNmh z{o8jx%r;$GSr}lLKjmJ3EV|YHx!;v(?Q^$f{D_8;D{i0ux;(X?ec8I${AZf1IlfDi z(`rgiW`2jI_rJf`y**-uQ%1t&#%#?HtAX{iH$MNes?q)Z{%*asGorj2mxRr~)m*UQ z4SM77Hy2Fe_T%H&>8J_$~_l?q1`bOI|eyF30}@gub4Q!2|~fB_R*@1P&kAL zQv?yF6GHM629XH|ia$t&o1hXm2~lo}g9A5rz(JUqC?=E?Dj-4;q@#k+v{Yyl75YOv zIucqzI$G%{($R|0CYXU-N0`tiCRD(L3Rp)Gp$AN8dKM%R<}#-i#xAp+e~!*T=z%(! zj1VS}Nc>o}miCNE1To=yB%}yLQV0ZE3#1L8!zfu3gbB~W-Rgwu%EVO>G2y~9TZ)Ne7BdMiz(P#?SQ0Y{qrp;4Ttvi79p5U; zj35iygX zw3cFet&S5G)p6vtI!;(r$N5Es=-m+()p34BBWALwj`PbaF_T4goL}pSnJlW~{K8Yr zWKkVQU#sJUMRlBCc8lX=Q61;^0AePK>NxsZ9VacSw(;>NxLlh~s2Y9p@dCmrNbTsq9~T z(|`9#Fa0`Y`hrv6)YeU(JKR`~ACEj*m+O=F=c3SMR=>@%e>2QJ(nZOTqaXP?tXq5E z`$GHRJs!PIJlP%W(h%!XT3Z|=^1XOB<|P*AIrCPH1f~>E2NM_8K*Mw_A%$*fNR0V;oIsol6jkl>nj{sKXL^q#U`4dSucHN z-p_f7(rpp4e*22{psQ8$i`46W^vNNT&`o&*AEdc2E1H1Y1y87H6-5Z|YG8C5*5m03 z`3@%z2Y46%(!Qu<@1AMMudP;R`jwv_N2J^=V(Z0NT|JC$!}?&`mBwx1@+C!A6PESy zO{qN;e@E+3dcSQ+`dhhARxE50V|BGLx(zF2*S8ms49fb#KXOCQdXPyC%G!s6YYZXa7` zLNQ{ol04wCdQ8L+r}%4Lg?s)?Sl_hdd-lu1yzvz$#8_rg`QVh~S<%XivBwi!hdJn_ zfwD9d(T*IPlGbapI+YlnEygm7$`{uw-%>j%Cm)kt9q-wEx##5c@*~sxC%pIVlGP(} z&sOgeW0^(e$Ny0%`L1s3*oGFjyMvDY>G)|=S>WEb%+iLURi~WEq)aiESyVnYvZ8Wn zm{ZBB=)4Ur3ah)#SM94#+I{)yEY}x-8ChX%Vl1<${E;)6zwM-4`^t@oW^GjX9@~rw z2V6)$D+LA;wcYQpAoxjs#WuD%{6`sTZ0EVHQmy25Aef4U?_ zSwF0>>UFAK625EpW<_z-h}~}6p@17`n)`LfX5 z{_`A%Kkn%_d`wl;wVIH!eJvZUTn~hZqh%JAe_HqRXSPbRCTs8l$EEs5ze}UDZ#MLK zxZ=*J+9+w@oD?yZSyaAmBfH?X_S%Pg!bT2QHTD(EY@H1~pXW%fB6F;-WV z_fqhwG)j}Y<7`TtDat#Z%f6AwW0-(g7Gw;1Df~b(p|>*lRhr<-1U;pR)~jiQ`c?WK zf)gN#5OTw17>%Pi%3uh_NHr9Jst6UXfoYgR)Fc9HU{a-#A~35$5sFr;Wdwn0SQMpY zxC~q~v>MYeG(zAgNug?(qA&`RX-EyBK|vcR&ZR1X+(sN$A(#|rWoib2F$BdK8A`G; zTt(0*O3>hpRG|dHs#%Jq7=~1%FoBb56%4~D$}%XIHw3vLFphu|)({OcjARrkr5F}L z2%1D;29e4rihxxr97Qo4rq!TI5QGDl$`lP;Cn0d)VCcM<3Aw3Bl2OZK2(3XVmQ=9} ziIbERC#5oykP-}vU^GF)Fe_70AQTi%v4jeiYGfz{Vng68gR4je!=;E+gM-*%D6G-2 zFiOJ&jUXs21rRgAxV zdynnCG7icepYq+eA5VO=C8=uI*xm~N0;e@f4~1Wqdfmh+qaEz-o9xE-Igz=_xU+C? xZH4^fz^%j9o*Hw!M~}RP^ltdi9UqlG~*%70}ta}Y)HG0mKbr4#KP-G@-BNNw`0B?Vh5kDmHD$3YVgZ&hsn zxhVKfxv_Bf)c)6Rn-?jE7q6Z5zDG@V*Xx(=M#CBI~rCflLR_NMnLyC=SBIjmi6 zT-LFQ<>m;_4N&EP)ab)Anl_rZ{1!N(__jl)tZPgB-iV7UdbL#ERW5z;WOVoFT^n}C zmtCk`=zQXz19m@kbGtW%h|Rq2TkpC$$FCr%=4n;+?x@FZqs&KMa;G5E{`L-G1tdAZ!H`Qr#A;}x_v0~uI=cO%QeS+oE9+0uNHNmdii3f zk)0RWAn!N^^i(vQ8&-d4)uTo`s>n7{4mb6iIyd!6%!zw`?n{pjjqk!;cXzGq_-Idm z*K_A&iFFMVjaZ+z`&ai5*Uo8*tJ&rL_nw%X zU85c>^hDim=NXREsw|rm-~DiUL3+3J^-ro_&g%n5&U6Z^Ughr867a<49&)kV99puW zv~Q^M=E;Bcc<_B-cC6QR_o*Ap=H0E>3$2 zO;P9f_E39%wU#+Fw0Qif1+^q{Q0Aq~Txz;FVresyJKgc!!`~+7G$-`Fstw!MePf5K zBg~nud5#6u{qj<~oI1d1yfR%kOh0nGY2-Nnl-Z6-1M}ISIlVfRtLF^)LQ_;VZW1+r z<*yZ*Z4<(Oh+I=Px7UuYLHPICV@ko&Ze5A3i(J?Qul8h+F(rwEP_U{;8yGV*8A8M@ zf{5D*A%zWtP~t@)Tww7-(23uKD8I$Qh2J~iBJNBS6I+TM5U~l;+CdBri!o7gJhXKn zF$&TerL{?G6fq{)f&4(27!wmaU}6WXwTUq0YjL`&nuVO zWYlR`4#LE_@E^T_YRklTkuc%noUO&gGfSDoAHYgX!dj9tiL1d{OngS9Os)4S>#Qe) z&xn*s+$Yw`6Q2<&Q|k@fN_pZlB4rX4#9DdcGa_ZOsy+#~2Pu;%bk@ofpAjjOsI=B% zdaI5TR@HIjtvXIvRmX)xgygp)tg7R}iAKs~RUH?OS5hXc>bP*$lQLOV$AyEZl*y_( zj=ojL39IV3aO{@m$*MXoJOfCXtg7SaTXmeYs*a;?)p63QIxakwNq#%hsyZ$_B1)O8 zs^h}*s+7s9IxajsOPQ>y@QKEVip<4B>4JjCRAqLR_7V z$1XLkn^IBu<3}qZZz_FmJU<*8RUX{4S9FVEiWIA@htY0WEvGIe2mJX*@coeYd)nC@ zFnIUw?t*@>DXo7_n8PVHTqeb8Yh$z<)`FYg-p#@fzOTR2^dSG}`9`CS`r~`=hS#hZ zc4kMX83WU#SZ$q*cEj2-nY)yj;(7m4w+_3HjaoJ!;`1--9A3V6SGId6?z*QkUy9XM zJlhScHvQSv#eJd&_s~H@=G6u`g@67|Cl5A0JZ|0njKgfN52aZA9i`oOV)E&#h|d@H z5A)iV-NQf0qq*L5=k}BV34@+3zH5k(tvMmZYHMkSh3daW~lSobsg_S z%sCm;ebh;3m-mX4?>al(kYcqx4YwOs-$`Ru7B@_D8U9SxyHi5%W{;R2o5P3RVwDe9 zK62Ur86?GOdmwH%tbB(Zn!3cH#~VW?vMayr_Y+rsD=Ow$#iPR!54ocb%hpJ+1h=Q% z*VdHa<@QV6_Uy=dyym-TpDV+TO)NC;z4m3+?bzvaXTX2%kz!dyaI$^ z=(MWBiBs<^bo=D+Y3d@eFSQ!t^%C$hkosp`)JG#ukBA#cHWxZ4PMvv+O577{s+pANwF-V@?57! z#Df9cg_gRah7yOXF0%(In_6Or8y1C*b??}~Y?fkKMCGr({OxH`SaX%bAFL1i>}2rw zEn&q2OA|bh3CAXde=WEo;f>u zuFp^^N{VF>mA8%bjy+fVccb^|{KyqCwj}|R2fT3QRLg(wml%1cb8japmPJ(FJ2Szn z*YxkUKkwjgGxBV7y~CjU@~o1EQGI>p`~G>U;H(tOA}a4%G5y7{sqRd!=X*Dm1B@?f zKmF76$npA~&3CWN+g=iKRElL0l|Px;ZJzVA?60GkWf#pCW?ijwUO+-?{YO_=aBu%`dp!7n;-3GNlKnYu5$#QVLv8AQ*%4rHY`oQI6|%Ivq*D7-+1+ zaZ;xxQH-MGB%-4zJxyXbtWz*Jsl{jn(`!+jBp5=+P^4Z@VhA5b4Gl%)I09a&Bxdh=!+lObhxdV3dYw1WXTf)8h(E3sQ@L zY-=fyBm!qi7}Zlc2G)`Y2s0kS+Z0Cu6YD)Gvp}7fjx(AdP~gQco(Z7f3x*Kz4@$kp8jYaP3ycbiO*MuYEJOjv zZ=@2M?2p12j4KcVM{$rv1&W{)Mj!-+q7;gd3OwNdw*c{h!Dz}z=0IhcFvc4