From 23fd0f657dec0c64cac17211c24028a51a37e03f Mon Sep 17 00:00:00 2001 From: n1481 Date: Tue, 17 May 2011 07:57:29 +0000 Subject: [PATCH] =?UTF-8?q?=E3=82=A2=E3=82=AF=E3=82=BB=E3=82=B9=E3=83=AD?= =?UTF-8?q?=E3=82=B0=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=92=E5=85=A5?= =?UTF-8?q?=E5=8A=9B=E3=81=99=E3=82=8B=E3=81=A8=E3=80=81=E8=A9=B2=E5=BD=93?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E6=83=85?= =?UTF-8?q?=E5=A0=B1=E3=82=92=E4=BB=98=E5=8A=A0=E3=81=97=E3=81=A6=E5=87=BA?= =?UTF-8?q?=E5=8A=9B=E3=81=99=E3=82=8B=E6=A9=9F=E8=83=BD=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlToolsRED@560 7061adef-622a-194b-ae81-725974e89856 --- build/tools/TamperDetectorForSrl/checker.cpp | 108 ++++++++++++++---- build/tools/TamperDetectorForSrl/checker.h | 6 + build/tools/TamperDetectorForSrl/entry.cpp | 18 +++ build/tools/TamperDetectorForSrl/entry.h | 4 + build/tools/TamperDetectorForSrl/main.cpp | 22 +++- .../tools/TamperDetectorForSrl/searcharg.cpp | 10 ++ build/tools/TamperDetectorForSrl/searcharg.h | 2 +- .../TamperDetectorForSrl/tamperdetector.exe | Bin 157785 -> 161070 bytes 8 files changed, 142 insertions(+), 28 deletions(-) diff --git a/build/tools/TamperDetectorForSrl/checker.cpp b/build/tools/TamperDetectorForSrl/checker.cpp index f610366..280ee58 100644 --- a/build/tools/TamperDetectorForSrl/checker.cpp +++ b/build/tools/TamperDetectorForSrl/checker.cpp @@ -21,10 +21,10 @@ void Checker::Initialize( FILE* myGfp, FILE* myMfp, void* myGbuf, void* myMbuf, bool Checker::LoadHeader( void* gHeaderBuf, void* mHeaderBuf) { size_t readed; - + fseek( gfp, 0, SEEK_SET); readed = fread( gHeaderBuf, sizeof(RomHeader), 1, gfp); - if( readed == 1) + if( (readed == 1)&&(mHeaderBuf)) { fseek( mfp, 0, SEEK_SET); readed = fread( mHeaderBuf, sizeof(RomHeader), 1, mfp); @@ -46,7 +46,7 @@ bool Checker::Diff( u32 g_offset, u32 g_size, u32 m_offset, u32 m_size, bool isD check_size = (g_size < m_size)? g_size : m_size; rest_size = check_size; - + if( !isDataOnly) { /* 指定アドレスとサイズのチェック */ @@ -63,7 +63,7 @@ bool Checker::Diff( u32 g_offset, u32 g_size, u32 m_offset, u32 m_size, bool isD printf( " offset:0x%x ---> offset:0x%x(改竄されている)\n", g_offset, m_offset); } } - + if( g_size == m_size) { if( (print_enable)&&(print_enable < PRINT_LEVEL_2)) { @@ -82,7 +82,7 @@ bool Checker::Diff( u32 g_offset, u32 g_size, u32 m_offset, u32 m_size, bool isD bool filled = true; int totalResult = 0; int j; - + nowgfp = ftell( gfp); nowmfp = ftell( mfp); /* メモリ内容のチェック(サイズが異なる場合は小さいサイズで) */ @@ -194,7 +194,7 @@ void Checker::AnalyzeBanner( RomHeader* gHeaderBuf, RomHeader* mHeaderBuf) { printf( " invalid banner version!\n"); return; - } + } printf( "------- Banner Body -------\n"); Diff( (u32)(gHeaderBuf->banner_offset) + sizeof(BannerHeader), banner_size[gBannerHeader.version], (u32)(mHeaderBuf->banner_offset) + sizeof(BannerHeader), banner_size[mBannerHeader.version], @@ -218,11 +218,10 @@ bool Checker::AnalyzeFNT( RomHeader* headerBuf, FILE* fp, Entry* entry, PrintLev printf( "invalid FNT! directory count over 4096.\n"); return false; } - + // ディレクトリテーブル全体を読む fseek( fp, (u32)(headerBuf->fnt_offset), SEEK_SET); fread( &fntBuf, sizeof(ROM_FNTDir) * currentDir.parent_id, 1, fp); - // ルートディレクトリのparent_idは総ディレクトリ数を表す for( i=0; iCopyEntry( pDirEntry, &tmpDirEntry); entry->addDirEntry( pDirEntry); } - + if( !FindEntry( fntBuf[i].entry_start, fntBuf[i].entry_file_id, headerBuf, fp, entry, tmpDirEntry.self_id, @@ -272,7 +271,7 @@ bool Checker::FindEntry( u32 fnt_offset, u16 entry_id, RomHeader* headerBuf, FIL u16 dir_id; MyDirEntry* dirEntry; MyFileEntry* fileEntry; - + fseek( fp, (u32)(headerBuf->fnt_offset) + fnt_offset, SEEK_SET); while( 1) { @@ -300,7 +299,7 @@ bool Checker::FindEntry( u32 fnt_offset, u16 entry_id, RomHeader* headerBuf, FIL fileEntry->parent_id = parent_id; entry->SetName( fileEntry, entryNames, entryInfo.entry_name_length); entry->addFileEntry( fileEntry); - + FindAllocation( entry_id, headerBuf, fp, entry, print_enable); entry_id++; } @@ -337,9 +336,9 @@ void Checker::FindAllocation( u16 entry_id, RomHeader* headerBuf, FILE* fp, Entr SEEK_SET); fread( ¤tRomFat, sizeof(ROM_FAT), 1, fp); if( print_enable) { - printf( " fat top:0x%x, bottom:0x%x, len:0x%x\n", + printf( " fat top:0x%lx, bottom:0x%lx, len:0x%lx\n", (u32)(currentRomFat.top), (u32)(currentRomFat.bottom), - (u32)(currentRomFat.bottom) - (u32)(currentRomFat.top)); + (u32)((u32)(currentRomFat.bottom) - (u32)(currentRomFat.top))); } Diff( (u32)(currentRomFat.top), (u32)(currentRomFat.bottom) - (u32)(currentRomFat.top), (u32)(currentRomFat.top), (u32)(currentRomFat.bottom) - (u32)(currentRomFat.top), @@ -349,7 +348,7 @@ void Checker::FindAllocation( u16 entry_id, RomHeader* headerBuf, FILE* fp, Entr MyFileEntry* fileEntry = entry->FindFileEntry( entry_id); fileEntry->top = (u32)(currentRomFat.top); fileEntry->bottom = (u32)(currentRomFat.bottom); - + // ファイルポインタを戻す fseek( fp, nowfp, SEEK_SET); } @@ -362,12 +361,11 @@ void Checker::ExportGenuineBmpFiles( Entry* gEntry, PrintLevel print_enable) { int i; MyFileEntry *currentEntry = gEntry->fileEntry; - MyFileEntry *hisEntry; // u32* tmpBuf = (u32*)malloc( BMP_BUFFER_SIZE); u32 file_size, rest_size; int loop_num; FILE* fp; - + while( currentEntry) { if( currentEntry->name_length > 4) @@ -376,10 +374,10 @@ void Checker::ExportGenuineBmpFiles( Entry* gEntry, PrintLevel print_enable) { file_size = (currentEntry->bottom - currentEntry->top); rest_size = file_size; - + loop_num = file_size / BMP_BUFFER_SIZE; fp = fopen( currentEntry->name, "w"); - + fseek( gfp, currentEntry->top, SEEK_SET); if( rest_size > BMP_BUFFER_SIZE) { @@ -413,12 +411,12 @@ void Checker::CheckAllEntries( Entry* gEntry, Entry* mEntry) MyDirEntry *currentEntry = gEntry->dirEntry; MyDirEntry *hisEntry; bool isExistAll = true; - + printf( "------- directory check -------\n"); while( currentEntry) { printf( "- %s", currentEntry->full_path_name); - + hisEntry = mEntry->FindDirEntry( currentEntry->full_path_name); if( hisEntry) { @@ -429,7 +427,7 @@ void Checker::CheckAllEntries( Entry* gEntry, Entry* mEntry) printf( " --->(存在していない)\n"); isExistAll = false; } - + currentEntry = (MyDirEntry*)(currentEntry->next); } @@ -437,9 +435,9 @@ void Checker::CheckAllEntries( Entry* gEntry, Entry* mEntry) { printf( "\n"); printf( "(以上の ディレクトリは 全て マジコン側にも存在している)\n"); - } + } } - + printf( "\n\n"); MyFileEntry *currentEntry = gEntry->fileEntry; MyFileEntry *hisEntry; @@ -447,7 +445,7 @@ void Checker::CheckAllEntries( Entry* gEntry, Entry* mEntry) while( currentEntry) { printf( "- %s", currentEntry->full_path_name); - + hisEntry = mEntry->FindFileEntry( currentEntry->full_path_name); if( hisEntry) { @@ -463,12 +461,72 @@ void Checker::CheckAllEntries( Entry* gEntry, Entry* mEntry) { printf( " --->(存在していない)\n"); } - + currentEntry = (MyFileEntry*)(currentEntry->next); } } +u32 Checker::GetOctValue( char* hex_char) +{ + u8 num = (u32)(*(u8*)hex_char); + + if( (num >= '0')&&(num <= '9')) + { + return num - 0x30; + } + else if( (num >= 'a')&&(num <= 'f')) + { + return (num - 0x61) + 10; + } + else if( (num >= 'A')&&(num <= 'F')) + { + return (num - 0x41) + 10; + } + return 0; +} + +char logBuf[0x46]; +void Checker::FindAccessLogFile( Entry* entry, FILE* lfp) +{ + int i = 0; + u32 log_start_adr, log_end_adr; + + while( fread( logBuf, 6, 1, lfp)) + { + if( memcmp( logBuf, "Read: ", 4) == 0) + { + fread( logBuf, 0x25, 1, lfp); + log_start_adr = (GetOctValue(&logBuf[0x9]) + + (GetOctValue(&logBuf[0x8]) * 0x10) + + (GetOctValue(&logBuf[0x7]) * 0x100) + + (GetOctValue(&logBuf[0x6]) * 0x1000) + + (GetOctValue(&logBuf[0x5]) * 0x10000) + + (GetOctValue(&logBuf[0x4]) * 0x100000) + + (GetOctValue(&logBuf[0x3]) * 0x1000000) + + (GetOctValue(&logBuf[0x2]) * 0x10000000)); + + log_end_adr = (GetOctValue(&logBuf[0x14]) + + (GetOctValue(&logBuf[0x13]) * 0x10) + + (GetOctValue(&logBuf[0x12]) * 0x100) + + (GetOctValue(&logBuf[0x11]) * 0x1000) + + (GetOctValue(&logBuf[0x10]) * 0x10000) + + (GetOctValue(&logBuf[0x0F]) * 0x100000) + + (GetOctValue(&logBuf[0x0E]) * 0x1000000) + + (GetOctValue(&logBuf[0x0D]) * 0x10000000)); + printf( "%d 0x%lx - 0x%lx", i, log_start_adr, log_end_adr); + + entry->FindFileLocation( log_start_adr, log_end_adr); + } + else + { + printf( "<>\n"); + fread( logBuf, 12, 1, lfp); + } + i++; + }; +} + void Checker::Finalize( void) { } diff --git a/build/tools/TamperDetectorForSrl/checker.h b/build/tools/TamperDetectorForSrl/checker.h index 5947d1c..ad0e240 100644 --- a/build/tools/TamperDetectorForSrl/checker.h +++ b/build/tools/TamperDetectorForSrl/checker.h @@ -59,6 +59,12 @@ class Checker /* ROM内のBMPファイルを全て切り出して出力する */ void ExportGenuineBmpFiles( Entry* gEntry, PrintLevel print_enable); + + + + u32 GetOctValue( char* hex_char); + void FindAccessLogFile( Entry* entry, FILE* lfp); + }; #endif diff --git a/build/tools/TamperDetectorForSrl/entry.cpp b/build/tools/TamperDetectorForSrl/entry.cpp index 6e0182d..92f17b0 100644 --- a/build/tools/TamperDetectorForSrl/entry.cpp +++ b/build/tools/TamperDetectorForSrl/entry.cpp @@ -155,6 +155,24 @@ MyFileEntry* Entry::FindFileEntry( char* my_full_path_name) } +/* アドレスの範囲に該当するファイルを表示する */ +MyFileEntry* Entry::FindFileLocation( u32 start_adr, u32 end_adr) +{ + MyFileEntry *currentEntry = fileEntry; + while( currentEntry) + { + if( ((currentEntry->top <= start_adr)&&(currentEntry->bottom >= start_adr)) || + ((currentEntry->top <= end_adr)&&(currentEntry->bottom >= end_adr))) + { + printf( " %s,", currentEntry->full_path_name); + } + currentEntry = (MyFileEntry*)(currentEntry->next); + } + printf( "\n"); + return NULL; +} + + void Entry::AutoSetFullPath( void) { MyDirEntry *currentDirEntry = dirEntry; diff --git a/build/tools/TamperDetectorForSrl/entry.h b/build/tools/TamperDetectorForSrl/entry.h index beb7234..7179896 100644 --- a/build/tools/TamperDetectorForSrl/entry.h +++ b/build/tools/TamperDetectorForSrl/entry.h @@ -63,6 +63,10 @@ class Entry MyDirEntry* FindDirEntry( char* my_full_path_name); MyFileEntry* FindFileEntry( char* my_full_path_name); + /* アドレスの範囲に該当するファイルを表示する */ + MyFileEntry* FindFileLocation( u32 start_adr, u32 end_adr); + + /* parent リンクを繋げる */ void FollowParent( void); diff --git a/build/tools/TamperDetectorForSrl/main.cpp b/build/tools/TamperDetectorForSrl/main.cpp index 7bff090..d6dcabb 100644 --- a/build/tools/TamperDetectorForSrl/main.cpp +++ b/build/tools/TamperDetectorForSrl/main.cpp @@ -10,6 +10,7 @@ extern char* output_fname; extern char* genuine_fname; extern char* magicon_fname; +extern char* log_fname; #define BUFFER_SIZE (0x4000) @@ -67,7 +68,14 @@ int main (int argc, char *argv[]) printf("[output_fname]%s\n", output_fname); printf("[genuine_fname]%s\n", genuine_fname); printf("[magicon_fname]%s\n", magicon_fname); + printf("[log_fname]%s\n", log_fname); + if( !genuine_fname) + { + SA_Usage(); + } + + if( magicon_fname) { FILE* gfp; FILE* mfp; @@ -159,8 +167,18 @@ int main (int argc, char *argv[]) // AnalyzeFNT( mHeaderBuf, mfp); - fclose( gfp); - fclose( mfp); + if( log_fname) + { + FILE* lfp; + + lfp = fopen( log_fname, "r"); + printf( "\n\n\nACCESS LOG\n"); + checker.FindAccessLogFile( &gEntry, lfp); + printf( "------------------\n"); + } + + fclose( gfp); + fclose( mfp); } return 0; diff --git a/build/tools/TamperDetectorForSrl/searcharg.cpp b/build/tools/TamperDetectorForSrl/searcharg.cpp index a58b9d4..4a56cb9 100644 --- a/build/tools/TamperDetectorForSrl/searcharg.cpp +++ b/build/tools/TamperDetectorForSrl/searcharg.cpp @@ -21,12 +21,14 @@ char* output_fname = NULL; char* genuine_fname = NULL; char* magicon_fname = NULL; +char* log_fname = NULL; void SA_Usage( void) { fprintf( stderr, "Analyzing Tool\n"); fprintf( stderr, "Usage: makelst [-o output-file] [--g genuine-srl-file] [--m magicon-srl-file]\n\n"); + fprintf( stderr, "Usage: makelst [-o output-file] [--g genuine-srl-file] [--l access-log-file]\n\n"); exit( 1); } @@ -38,6 +40,7 @@ void SA_searchopt( int argc, char* argv[]) struct option optionInfo[] = { { "genuine", required_argument, NULL, 'g'}, { "magicon", required_argument, NULL, 'm'}, + { "log", required_argument, NULL, 'l'}, { NULL, 0, NULL, 0} }; @@ -73,6 +76,13 @@ void SA_searchopt( int argc, char* argv[]) } magicon_fname = optarg; break; + case 'l': // "--log" + if( log_fname != NULL) { + fprintf( stderr, "ERROR! redefined log filename.\n"); + SA_Usage(); + } + log_fname = optarg; + break; case 'h': SA_Usage(); break; diff --git a/build/tools/TamperDetectorForSrl/searcharg.h b/build/tools/TamperDetectorForSrl/searcharg.h index cf1489f..73a596d 100644 --- a/build/tools/TamperDetectorForSrl/searcharg.h +++ b/build/tools/TamperDetectorForSrl/searcharg.h @@ -15,7 +15,7 @@ #define __SEARCH_ARG__ - +void SA_Usage( void); /*引数を解析する*/ void SA_searchopt( int argc, char* argv[]); diff --git a/build/tools/TamperDetectorForSrl/tamperdetector.exe b/build/tools/TamperDetectorForSrl/tamperdetector.exe index eb6dd2dda2f5a82fd4204eec0496ec98b8c9be07..9c3ab3f6a645dd744805dc41a2bec4a9668a49cd 100755 GIT binary patch delta 22507 zcmaic4O~=J-v2pw1{h$30fu*w;Y~mgLC_FM2XqY6jC?m=0C^FVw_qsU(xIpnSyMc= z(^k7-xz(1Y8?9E>Mr)h3Yn%2|PyN^Jy(dg7YwhLfvHX93=iZq+gYNU(k9W>F-`~sm zo!|MLbI&>V;=3n;pZGj@=hg&s${W|P0)@S;F!lip;-OrzvOLDv^nnMb7&`A(2LAE8 zkPW#2EV%Q;Ha>PrNf5Gj+$P)wxP2}=s~MhHtO8BY$*OQ0ahHhqctYUt?U1P%NR1Iz zC7zdwd?hQVLgm(f?G+OzO_jxFlC%Uf7Kn6~*sLT>sauAu4bb&Sug2|nSt=$@zCt1+ zWLyvULXhqie~0M5#vr>BP#DrDaQj^lEh&=7Sp$+m@KNp0iLr)+DbWNS)SzMH{Vs?W z7RYL^B14D4N438s+6-CzxcHS}chK29I~z&P6otkFrBF>W)g)d`#$<{;#$=^&ycjk{ zFIqaDvEH+$JBFQA$7W?1S&f|?GiI?PQYa4&0_)@}CfZHWL+k;<0c+fG&S#nOlVv+-@}V z9ewd*BT+MS>QkVC1O|iSl$T+g&LF%D+l@h9hHRJ4(dokx2tQH{#X5N*$ZD%5>ELt% zWvdEwFo!_L2PB`bqfvw&C2)cc{_Ohcl2%RB$sd5~Y1Ic_qYHJ07rYFm&G(J7iQxgL|MB3fMwU=vdVCoDXB zdOMdxBm9uvRAvmnbGcgVx1hy@g&!L39YL5Wq}Ve!{)T3gl1WfZ10zEdsv;@zOki^S z*?wuk361e&iZqv~Uj-&wo8!XA)EV>%QPz(Y-KLZv zQ#taEvEn{cnyZZRNsu^`@v`GP=(I6sLcb$U?QrT)3WXZt`YxHVmmS~pV~!ultJ0fB zGG;#reU5ij_Y!cw1WxrYMpVJ&G%{s}^exJe0>1>ke=%k`Q?yTad8qBl;=17Lm1)Uh ze{i-Eku3f**rvRnB)$lV6_${@mGUIgE);WxXgJ$MW0$chrLMimF`rTnQ#VYE&OdWZ4{B1O41dDc2b&PTg3eL71$ zwiiW8+tms%k!wwm^}J;uH~AuHj&(S;2ak*qgc!McE9Jq*UOhT=bM!_f#W)K!ejkQt zNP&y>XiX#h^)L|?myuFT`KSI3&o9HolDGn8TbS4ySFPlPiPLfGBA&-u5WVqb?=UA1 z%pN1^<8zdo$A}&A16El^6hDgvVK^F^^Rb1%%GoE8xt4yyR#cHVcY@9ZmIWC-;D;s2< z<}lwBDzg@3yD-n9nLsT!rFu|Hr;2)J-(}R`cFYEn0kbbXn^^Y&I8aUzEg>wJJx$$> zMVLrSN>gTsh}lVVmH!SFA}L4Nxl=rsG&87%)YJ!yz~u6v+bN$EEaoR?Wrt%9?b|+# z_0fn8p*>QB!O(k-qo2c%-SHA&1PnVpK0y2?Inni40AqUwKdxjHQ83{5r070q*t1s$ zj}Uk#fsg9o-wC{dzV>392XDv)Mc&77NMcgbg?5dxT@ zB$q~z_*v{#u<`(8Wp)JEtPIQGLsHf}SVxOS-}T1!J5Hc&6c1V7UAzchlWmP!&mf{w zr*8T$P>mVikfle*pav8I94H(P5@KxeG>?|;BRXHJ$`(UxwaD+82i1Ll-eafa#XZMS zLEq6m!(uok(Z$*=&-D8D2TC)`NPZ9U{n7Q1 z+*2dP`;$L`{GJc|q}zR@uT`bzk@QR{-9pk$n)F$c9`Tco@R9x+5ds&jA?Z(%?~itp zbcZH=o}|zDNe}sWSg6w7B)vsS-$K$GH0cW@{R2t6JndfWBRyG_-b&Irl>fKAy8Vpw z)=uKQh#;d_p%H}COfwV~I*4#u@)`ZZ;iYp@u!olOBL&~81$G`ExXgej}!&*-YxB zH}aOKNlOmhM|!UY%gBDQH7(io9F^0kd@9Q_-ZM+Jb@DJpK2PaM#c>q@V7@kI| z;Zs?mF{6VFw}NHF4b6KhzeWVGhiJAu{SR=;iA<_l#uf2idQ$Fg5_pYFsqzt^`R?>? z5}@f*3PebL*VDv*C-DdS@DtaWDo;;OkP3Z_#OmJH$Wx@Ff^_@^n;?&o6eefPBToW4 z6EN~P60}Q>i0zK&JpGh=0kX7DLzD4fqi(+*iqr?vMQv+!J1nE;P<6(2VqeCcg$!QU zx$|OXww4xXX_A(fY3V#IwTZgS#}?I0Lod%PXpxEaAgt@_%04!;vS%{k^LEOlYEUMN z4$36sDdI95n;ADO%SnT!#A|z0CbJHfirR5j{(67g4mdT@*nf76EZPrcI zvP!#JrCnCp-?JCK>$@TQSh-qpxvaQP>36VWiq$}Kl;!)@mx-)!aflN<6|hP9KR}m?OWK^KQ#_aG=Nr}{vPF>>V>EL zMLXO}7v-y_*~N$Bw+ETwJmX}$h~QI&J+Ef`f`;1qQX9*xx7ln38!}rq*e0kcD=TYv zHZ^qGYU}D6y1J%M7Z2pcE6gUo%u5`4Gw)NL(6S-Vwx-?bY;P@PW{oOb_&STLkVVPo7O0&f3$uYspK$wziXWb+<rh0^n zLtnJzP>_eJcAmn*i#&8P%oaGBzF>iePBrf$ziF4Mf5u`D-8$K>u)?7mCavc=H2tZp zRR3(8cg$>Rs9WFASz3BkgY()t=aSl%?gqAdtgzUvQ=j#v&u(t3FP9@{Ui;eFh*~xc zGqqQIUVCkQC5B!@C)=JPrrT2s^KCxlSHsaB6fZHdpTnd%4xXOeRrY99Us6(%Sm^SHbrsRvB{o+i%pArxPUBnH;GBCmlJFD5~o?1PEOw0b(D9UY=Dir_C0jDJGcEG(~H+$A>5jK20(Ano1G zj&5glBh8EKegJD5+Pa(D8Z_i-Ag#4)o9o)!G~`Vn=xnV-{XI!m5xYeEedeU0(kX(Q zPNMI@#>B~8xuR&+T4hIuxPR7#G4}v7h0LM=33_Jeca8)@*fW661+P&qV${XnGxS>J z`<&l1wEt>rAiqcaxvCJq=c}e#Fv3{c+y~%XB|VS@-XpHOE*GTc>vqT7K%|3@Nm3FE zGv19H7@`&|0mHflPJV-Uf5ET$)S-Y% zg(rEmgAss%4n*iwUtRl-|LDfAguJm(zxF|kuh7>G)WxaW=YA9 z^|TVa<=xJ9jPKdqEiF~G&L);INBqyWu~F-F9vcs)9=X~*yh6#0=fC$-Je?xRbBP=; zZdnnQIihn&7pHO0WaOROGOiH^R-~A-;8WG#EKPjaAEji>7hkQg&1=%}OumCWyujOt z5_m(-c8(hv*Mu<)mLQ(Pj1<*j##?df7kCfExFzfpv0~*k*SNCUw)VD-t?k`iHVpXI z>C9+}%8zF(t7^fV`HQOOIhHu)RTqpZ7c%ZgpM+7Ktv!}lQjaAm5mQo5v-crU&n#mJ zLWmo3);4x9OG>&dt}q&MTB&SP%O;R%#bQ_B`Z&YJGV#)i)7E_(J@ z($(Q^HRLq5IVEF8j#M0H$Ppc@5-@`LR~2Oz;AA?r6a;Ridek4%Xq7)QIx@t^tMU@b zN`8~h?qx!-k6)c@mh_V{3Eak(x z7CG|A%Yp5`w6W00_Nuvp#&&s~i?$8g;>S^?j{B;q)zw|I=gf0VDQ4W)cJdsehAV5@ z+glLseW*I*8~jk$=hBntVmM$5?=WLi7(QR1*73LbV1%6+BJCv2c7S&R);co7UCIE< zZ)(_3UDs6GNvv{OA23eDSYiAfF6Z@un^*!>kw<~SBNZc51>??x7Fy5g>Y$C~ku&(` zoHh!7wA$G+aM7~PkEx7E@5vl@D(+6k&*ZAEZy3w7rL6=*MVwmWNE7JyAW zTW59^tz&$VsuMj;(+a`4 zWy+^`sMKQEtWFA*F3pJ+bpTazHKME&>$*E>2ehEQb#^VH=4w6-`!1Rw5Lu*XE>}aX zshHN8e5K~@7M4fPAbjdY#{snM|0T$CF$elvI+cV%`C~3=s+-&XhrA7Ic<&YjE~`ivhUkf5c@3` zcCI{(e=ndDL*iuZ3YHrb@q(g0Ogw|Tj1oTAauTewkOyg-Zi#E4@ zjh!U>;WaHfCX@GG)8^hu**T>CH8qmW>ZpEA?E?!9zt`2F(o!TM)>>Uf*c^M8cl;zR z$CQD2MLyUYYH)Y3!ng5c;=yFp4&0x>uqN!F{0y7iy74NqCRnw`i1IZ)Wz0?+ufh@u z4C-8+fyrs(HNJ>tvN~46>_R3zUT1gKH4iXVDdiOJyuhP4tw}u)H_KC+muW-vNcQ zF?@=!tuKz0r7+?q2nJY$ZCRfAZUbXxmG*}C?fNUVJn@Ac7oV-48l(w|td?0?{teOD zGRKSmxurr={st)z$KWL8CzdBBkrqBRz*_@30}Q()12$lBB*AaEgkhz)wbiCd|6V7O zZ@kj9@siRXjbgA|y77|Bv;S@5B^4C}dhP5)O=0xILj5;hmeCupz_n6Jq_)Lzb(gi* zs|J4FNGk9xa@3Erk&AuvvgACr#<>}l8Gm;9ty=s)p;-5;Q1? zB3?t%Ipgf?EHo4ZkFq+JCh8hFo(Jkx`88e(D9Cxoc*u6*jx#V9qeDKwW=jPfehNCh z22k|zZ%Ozo+_T_CIt=uak7=e>f3Mcr5%VsUe)cGk!N8~UbCCWPx2ppx=1&gCt z;xU{Ky-Ty~?0#^WaeC;-6))Wz$Gy5KF1d-5z$VB>iEwo!N{y0>BBTU$wE=Jgmi8hj;el z?@F^>1ICzV$wU7j5yQZLZHk$VUgf7$|2L}cdrxg*Q$mM4fYl#%@2eKIu*Ahs5(5=U zS0HndMbh}@!ymz(pK|PM9&B=5&L$U(($x)X4OC6~vue`knn_1hlh&#I`xj5mkuK8dL+J@IC6%JW@t4M@~Q?9Txj5lp{6IrM1|jG0#t9o>wDH-~6|v z?Qz@}pz+9Pjj=u(#NX1aj7cNbyEoJjlR6>?)rL5kE0UfZe8)a${cqgaC|ww>IXZ$u zVuxy)QPnWu(U45fCEoKRglQ$P2qpi9O5q+q;oHUc{^I4d{v@imUTN0( ztlx`Aw@wYx05P(4mX`lX6!p#V;=O$pnsTxQ=SmBuax81&s5agl?Xks5?gztW5wgve zOx%3WB}6GL&y*8!vLrRUt22?)q=sK?OLa*NkvIlcn`)KB^h=jD>HpVxvQ$)~E23Di z(hp1ZU)H3LUe=_zy;9&EeV&}Iu5{kic~W={dB?NTiG&X{Td8*ShuEz0NA_sCczAnWBAL$b*V(;H7#3e_&n=Yn?{vC1B4k*oKg44V z#vsFhdPU5+D>*0?M-r%CwBA)7)1~IgmIh*^A1Ht6uBuF_d}I_|8cbtNRhcfP?x-q| zoGsYOYORuH&?r)M>M{}wjuX%9Se<%C=f4~)xJq`~W3R-)g{D>3Nr>RROJ%(={=aO&j_h4cTfLt$UrE0e_+J7Znc^Wy^$`tk^P zAsQ5BT#8etT<(4A$`h-vFY%OaWaM9Z+|Y*zJ$P=>OWC}-_HMjl=E*<9A<95YUUwHZ z{9{LCsWY#;1*McM)Iw*X6S#bb%S*xRl4|J5wGXNm;D{t2OD?R_h{yuEhc9jlBm}Q+ zN{JdIk#u98JR+=;<7J>ePo586rd11|?H3EJA7%~KZ&?{`Uvu3dTLODn9m{5QuT}RS1%6Y5@ zdZ-d#ACuSFZgFDQKrs3F$6`BMIkZmXa2NHfeA`{Sw&6y(e4uYdzCuR?bKqSKwVicM z?H%aX%pd+T5<)d2~oQ)(?GM>a)H*-UUQy$o_(C#zgxY6Qk9x858SYdz_{-z|)u_#^U|$O+Zoe7uAx;`J5at*8HBhOB{H(o_{5*k4#8;ca!rL(>x_DN=dUS znNdon^?7ARly3pbOa28M|LBfXcaF#k{Qvnxv^;g*RCT+ z6a_QTilHALnXf22GsM-8&EY?Y-H(koiOpqArUAnN@$zGp%J-Xv7ZOf45i3v(6%@>9Q-h?Kr|6XWQI;;=uHT`1%EOOyPuh5$NPRNuN_zi?$;JCs8=iCW@_ZWT`PNVSGLTs{y83A# zG$?J+V*Zmc3G}k+9qd3n0`wTB>wJRP{A7Z%ElJ#qByy}c^yJtCdy4uk-)QC^Q^l9y zs>l!_L*rakh#oq%B2^wvs-JK=qndXaoX)LkE`!ry)9lOObcTc(>Jt4p8FI0!E<>Or zpUVl*NzSIr@YDH>uY)}ekY6EQhM&${W=hrh^=(v6hTA2yM|b5fsjBl7TTgd<^kJXaRP}=*!awqz!SROT7q${GlVC z0y&Q^*O4%2-G+|Uk*U`MilhZE^HfitS=z&Wk-q@>5gTot$AoaM!1z;~_bkP_!aQYm# zPnLausx%%n3Ow0HcSp8jk|8J>k6?29E+;?QYLjq5}kh?mrYLiSB|T#b|j@V}eV;w355;%2(p}M)%2V zB_(h_h&!$B{rjbj}Yt3FJFJoF6Ne#zjP3J7vVi>PMLbcrQ+km)fIgK^_C{TX(!<;* zW+({*1;%iSxH8;o#O-lMWGK-xXl9{WCn+ZWickK8PyQV}?>>FPWT}lF)-|hgaheO)oAO9Od#j{ zcnW}Yj2}G+)XFI+a}bmf?ygd0Du3F&zZ6FHjHmXg?Fp=c_|EZa2p~m|rMYbt3jX@a z{rU{}`GpcCNEwt8Y09HodeBz`Ex?Ay%UQ~8E>lcacDtvYo+%3C>@o%Kac_5bl%WS$ zu8#$qA#cf5EkJq-j0jV`a+_pMQ?hg2EmtaOpzXL)S*{d#i({rM%lTFs6N&EIrYm_$ zNv`|gbdQ!acl-=x4*!)(|5FJ%&5yo=KkTly!!3SjA|5nyQ1!UKvMVV?G}dC5cxH)t z81Lx5Q5OxoHcWBqz`MgU%M}^jE6ZVbq1#oiq)gm~=GH@=qCky=UjxyXl%(`wAog56 zeBzD(s8Rt4dE9Exb^l!MX=kFlrb00VNY(Cv3MDoqe_dTCX~VMht_o#rIK3dPmr5uu zjB=_8d>>#(?%}s9ls1#gGR_l6BzG1hy2whJ;P5cS6sftY1FE%8^K4jF z=)6wwcuK1D4j}X`ifU7JL)(qbo$YN0{p|i7cy95t;&~ties;fJ3drBv9|ECeo8H`W zemvFMU#AVaSIt*athBsa7n!B5X~q=(K0bVaYbZ@5m0c0KCnfMA>v zFxj;>t+SJWl=x{M4}`Wlx|JnBsOxp**8s8l@zelW=7+QcxnP5suIM&E=lzh~?#u;B zy6Y7XHuy<@1cW}NSA`K?6isY6(|1&S3m)GGPF+iTR|6aI<1t`OKg+8Jb+ZT{NnWHH ze}U29TF=-!UNJdL@l-nJMMx|~ZVoIyPADP7I|hj7YRO~w;aLiVhN$kk1|alj3;{sZ z@zxdYp1n{>yJ9OS7C*`Zq|dL0eL!rQq$>TQ`+-SxHZ(h-y2LvjkOfzP$EJ8Dy6O)4^X*3VgV(p!+RNx3@0?Cj3n4|9Zq#-SQDOEI~`k7uSUqi(yNywjoQLu;f}-WHB~Sb+&)=S>7k2Bh$1ASt8n= zEKXa(BW$EDI!i2xoV0ZG%iB0(gH@xkPrEI%%&|AGP{l!;fyF*O(m!gx&8)$23-vrT zV7Fn@woC@oV{ghcglb7j{4p{keRNPVK5Q^90VB)-b|`D*TJ|7ezXvAOnW;0-7bu;erVlvsMsG?He~d}fT2sWS zn9M6ji2qvBarI!;=|Q*8LnjGeDE0Wz!73RL)tC_ms?PMIPdqWGkp|jmDQU2w^f}3; zrHIDZTG{7lM!g#2KYl`5+m1;Z=?j{^MiMd%9YC~3y8B|kb!8fTcX zG?vUb)xY@^^K9^$ajWD!CH;6xm~29zj**7NB#Tbla_#mc@w&~awI_*DTduYw z2@#(gGa*S@dnFk&J4wv8Hzo8@{_R9)sE3B_RC+B@9JH_3;u6J#xS|LK+F+GKWG5zy zuDCGmiv+PDZhXW(;(RMX{5tMxUMRHqDOzTNm=-@*d(R<$7Vp$vbcp*<`l&;F5?_(| zHgPX-FxGOz^X+4}zTJ?F>P88^*dZz$iHRS?8^hu(_2OVvI)&QJqQg-Y|0rf13ibg0 zj(E+{piPYzg$d4T>s)9lfOzb|sxz?%M}qjaV3ZD2{m{Sp2iCU;6~a?&^iZ4x2djPv z;!G8{B}_2iV`5C)>PU?aCjCu(k}zGH9w#co6G|x5ZmT*)#$`ees{DJ)C1bH05}-Yg z3@HNodetA;m+xUB5IiwOd*3d8nm9=twu`-q>8T$Broie;?cbcN0(ue2-DeknO)QV_ zQ2r{rNKKj+@d)Mf?c&O$jHGr=PA|JgZXEH<^tEKKO$;Wb#=i@z{jG73Y4?a{l15UT z4K-}k4uip8M0uLRkG`^F$ME*#O{UQi~bKD zOSD**=F)z&ihI-Qwfn5%|EI09ms+J){-=M0lO@kZiH+&wwQr-ugXu2qwJ7o5>Fcx= zQKBNFN_%vi*p@L>dwZOCF~gBFud|4q&Weadl($*L z`_97XF+9TtZX5BAjg49@A|^XUd&n%tXQz38M7->Ae_F#RGT^oKB(yyOU}XU8C-A2P z)&#&i32gRp(t}|y5b^+q5MuDOWDdq{5@oTTKXJ?+px@XDSB@j_0%U;gdUfc$tR{|U)wko;LCe_F|3 zujIQ)eul69-XQs-2uqm!J;^_h{9uB4bq(9Y@H6nzV8)G*-?KGDIw45D$4(#omzHEO3f$EG{s44Rv9WZ$W@G3px~TnSofV2 zbb7%wdg6OkpnToGk+012YoY1E2sqM0u@#7^d}zV6GYw6Z)5vzENakaeA`2BrlFSK6 zeokSAX3a3HJ%?QJnY2g-Yn7bDPE&+Wkl8bo%@Q>Q&T%_-{AA$s{!_`LRie8fBWfA> z;rEyjM>E7-1sSzXRQ?spFp#6B(T|Xq5_Lzajy(nHk*ecFI8ybFG^FapT3Pz=u%w+- zw9gc6v_s4<%=elBj!wm+>dXHJ91~>!XwyK|;r`8sqhf#Y2|+(OJZQdSdNmfVC*_=h zRqCYCrKlR~It*DWH9Uvvfm>t^=Db(Q(i5clgCEDn_SAd_ud@ef!ufI+IOQxO)mX(h zg&9So#6CpqyMowhD*C!s&L@)h4KDttFumCdOGXzHb8QeaO;KN4M=t^Nb=c@MBrr#I z`)yUnd{(+3im8<58LX+u?>~VawPqfRy#vpj*qiuwO=PQ0#OR_Rt%x@DDv zTOWe22i6xIsZbSH$chKF!76s7Le*ZOYOheW^CK0i_6k*dg{r-RYJaVGXZ%(&5xu>q zTV>3cE!Rz28@q#w@MbQ&c_eIyI5}xyX#=n$VZ;cK4J454gLMSL`v=P1j8?<#Aoc$M z*T3@M4zaSNN8A0WI9`%S$!N(nB@yqBjotQC0hlPvulZ6(d55|Xuw%R78oDTdV48cl zapoi*(GB0Wy4=FfX9%~eA*Ez>M>o5UO>*Y({Imz;G-!yRJF^hB=**^iRk?2cfz%6=0m+=1JZ z;$~EVUj=B`)UbWH&!)QBq+nWAzxig&OC);?_k?sedk$mWFN-YEMsa_Z>1H(=6Y(?b zku>s)v)ybl87|y2qA%34PjcO?k{H6NWd(U+%ZxM*ir?Uhi%=v<+KT_v z%*5?4ri$p9jtf;)SK?-?sj37Lcn+n9gIhVw-5>BLXF0;X?_u-dyV8--SahB`tzhhW zG{_y{qcW!G_q%*_vhi-}5aUwxqnG*UWJClxFNA*IbB0t_O_okvl}zSs>(#|&lzGvWwzsHY^VJ^m2E98?CmV^SY_Ib z4bC7!1!OnN{i^&cmL2pwr z*@>-%!PD5(RN2-e3#?HbuS!b&Re(s=`Kg~+1g}m?$-#=)kge{5<=53V_B3~T*cwq< z9q%0oP-}bIIz4Dxbz6J0(*MHwM8Ed$0<^hZ-J6s^872v%uBFYM>b~~&+D1<+d;P-j zvblXQk%wrQ)J_*4=22%A$S9cBt%2gw`}SHZ}K9PrOf*K+z0sYY9(6ro-1&jp#6qQFOk8Kzjilx3r@E zC%xj`c?lI;fpqnGy8Ar!EuCcaJphck&Oi8CQ84RYnXCKfEy26f+FybmVG{wkSzEhu^&Hubl53{%x%z zobMDbFE7RKndLKVOTd=1@BxIDmK)B(cZy4{oCs3emAewJCDMUMB`KZ7nD0Oi4Dof# z!LY8*!><*8t@|Y}8{V|y3eH~>$F4dB!n0RhJ9Yi5Ic*)u$eEL;5V2HbugcI*w`f)ePjN7oEvXJt zKrAAC)zkb8>4l;w~@~PrjeO3ll z!0AlHsF1n<#D~fJOZ1_&T3QD2^XccYOeK~}#h>bvowaM2)YBbcA~*T;xJggScyLKo zd(Yv@;UQx@Z?4!X(y~taxmXUb=<{?156--5QM(~CJ_F}J%5M0`L~fiXZrD(ee6=6< zIZzU7#1oB$`F971(i1t{H;MS?iM$2+k88Ee9R8l47e@Hl0&`8?Lj9w)T9$*S!bOH5 zd3=BzvqW^SPRdbTjG$eP=!-E^491vmh^GJs6Su|ODfX_uI5B@#V`o?ArjD*YtX(?$ zI%YGoE&ik^x#QAhw)7H=`Jy)eEZf9vnFJxMOhs#3x|uC&nk<@4MIBUhs-gu{nh|W- zGvOF5*9x*M=gbr@-Qmcv<*Fg&Fcr0QdL$)pmQ<8%DiSZONe%l3CfbDk&dK?o;HWTr zF^Jqj%GD34b;uu5#Kw!#rs6cRjE~3BsKM@M0)1oCM60CtE4tXDES1Dd zsE>F8ttqd>O0pOXe+KLgVV%4MFi(&HF=U?nLr}@$>Y=Ah6XQuggGJhqhZR%XcpImc zX_&*!>cCEGkr0)oUyzbEP7TzC%%yWwk$O}cvP|)|F@7!o5}-D;vJ9h%@pewbP8(_{ zLkk)2Fp5o6TJQ|7@1^w*@8U8zhg!?VBg*{6_OjVj>^2m3PeHu%^;`x#3@)L-{?0t(@=mACa)HhLPDbhdAT zCW|t4*WiK^ixs_Ts`P+SYIU{rb*`aBUA<4wBxOmb3*Ky}?z}<)T`o_Tr?LGCqq?O^ zUAJo;Ew76sZ0j^rni$JHjf$yWe4((|^ zgo!_%YodzteKb=bCRLmpC5ubcw4e`KZtW>)6gSc*J`M*ce7r5L2XS5m!OhT1Kl4 zevRSqc2-O?B)4+f;?Y*FoTGkP{f8P`Mp9N|;F*=}R%yFw=(8=#cqy~-BC*GIVhu+n}$wqQEjmrZAqWvm5rU>+0w;$48KA~K-Uxr(o(vY@mT(els&a& zN>f`;eH$X#W;n9Fj22hiZbVMEYHys;UQ7e@#NcmIQ)#E#fOgelGZWleFPkho<4q$( z%E^Ims(HjxZuG>Psw1pwP`|1A!A67ek7~rUyNo`;!h!MQG?QyXO)l)3{3{9mCwlU0 zLyKHN*nhdbvc=u3WE;)ek!0p3+_%Ei*UvGPm3M5KN9IK;^UNqO4k}}^+B9!99`rm? z&Fh$|HZ2YYY~^a^id55ygH8WJtm|?X(hhH?eCmv$-iwXR9&hEJg22N}&IUK$4Ozvz zT{~lGhfKTRf14Ql`3ffN_bn2yc5k1afzgm`i#8##$i=lSW(kyGaS}=Ua9gY@nIpfa zlIr*o%cUlN{dVt&BGaKBsJs0I~!Oqiyh^UgI#Ws=3 zsLetT4+AT{QS9p}i@609&Z4;sw%G#9>tucf+F+H`7?Sp}2m32wjiROZk|4gA zEn-`NV7OJ- z`H_E?E_KyLZT1`jrI5g3Ei*Q|+%GJU-g)fy5 zHJ#bG|NO&7tLH?oVK56bZ-zBtW{R>f^CS4R{{=rhf}(O4?q@*$9hAh;&XY27T@+8< zV7H-1c{FjI#Qhlp@hw?cuJ4oNOh=@O$-rQvc_ zf(8v;&l^ZOAs2puhEL8_kVx}r1H~OCDkZ<#ZvjOn?@om5D%>NQ7yItWb1aYwxP%`9js%o$xl5zVRtYqG;fg_=k}GIM?lE$><0=>buQ4aaH&mmqr%?7-1 z9r$m>O&=T4VNr-oVpDT3EhUwZIkC5AjlX1Jb{aeU4U&E{-_72DhNsWd;A!kxi-RZs z1jgS`MtjW(PmzCqPa>wFFE%H*;Zptw<^2}ryf+nZYf85~A@dJ9{+6<+ou$&d4?4|C zy9k*vW~Xt^_rC>uzASLFGq4GVTIaNiZ1OgH0_ye~4OAvQp-lS9FzHEU(mK_3JHXsN=RP1!fgyL&{(eOQ%VnZ|#OKJzWL}88%oIsb#$ zzI7jdXWgL3w19j%YPDuYWl5h7e|!VZ=RO^NssG0?{;3!lD8=vJ2WHsb1DkWL*cNzRR)iS>{= zhs%w55%UurkKGJXZmcSq?N3w5Mr!CB?hbMG_ALIMNZ(!peG9jzW=QU|5bpE<_s_S_ z2KP(bFPgF!+s#P-QXzLDm1$uTSSsWe@0XZ4i$6w{ijkhwcy~P7^E=?2W$}L!99TSv ztvkZwB+WtEd<=5w@S0!Fv0ohDafvm+=h!P!hGs+2fRc`Q6bIhjT!?M1)b_`gazY1#t->=LKuQkp6Z2(^>-(D zQ|qsq?tAyMfl&)+x~BJ>XEE>7%b?;lU43}d#nXR8l{g0}?(4;lGh(|j;FM;Pam#g=;#y^}-VA91T9x{UW* z-1b*I1mq60hPiy_M|K0GFK=8y@4R^Yl{gv#H+>l93VQp+9R`8E?in`>577HCc)T1g zzZ5!XNbrPzpsggmhNLBw=z|`tVeB}$lJ!N%=jToLHpkY%h4n5siyem}ohUAz*nGR# zx+h=kyRTbzpM06txVCu%BTjnbOrLB;a^StqjXi5xySmYRx%F3-P6>wEYO#MKZqlto zg66t$s*7^z^#q>uR7CgW5(z7hD6Cxa70D9?t!)Keo$Ab_ph0p}GP9XJ>b9=KPdA|G z3Q{CqzQ2gO#n<WSmx^Z( zrHNlX@H5^hGIt-1yla}9(VaAWdiUkrN#CJF*4I}qTXIGHqWMdg)z>rrn1#a#sKy5| zc-vjUpM2=gTs-&a72>0ZEyDHdS>6&pFMej!#Zh)1$KBx^kIczo%oIb={CEu>ca<}f zB~UCis9}ma#h@C+G89SHD3*gcNOr10H8f8HHH^q%!>4~efqQ46wf6JviK80l$Cq2l zn)m`XA2vD+D-2Bup^6hjt4%U=h6UP~9BO9@ik6H(BU3q_A5XqW%SLsy7*8KQ_Q(ld zCH?XXe7p}+@y(UV5*0;K#F}3O9qBj$EYJuK^WlZjejiL9HwCJS#Gf8c5I;V8t(|IB zm0oHkjjrMT$2M!i$+IH9#~My!%f#d-2Znb%{%4-`u8Ge!9lCzjI?GY5D85zx?riHf zy{gS>Ge!PcJau3^-yuFa(8RwJbDx;R-xceh$lzmQ`x8s;H+xI2w;a-P9J>$gLOMA? z{Nssy``G4|)*)Ow4;|7p%oOv7$3JMweK2XdirX z<<7%S9wxF6$A_u!bdXE+eWT<1M8|=_Ll?f!x&LtDOy9RTK5}KhiDA~1m+#x0U>ZI2 z=sKG!{^xL}HX&WaJfE0td~M_Z9)`5|DpFtG%zrW0n~X6`#~-BMr<1q{r^Aj#7r^NN zq~QX%I|sXk3*a{c#}sj%ejG7)*}Mx7=c&Q zExrIhZRLXfZvzi~yT%z8^)E)}m`&=j|4@)@9`c0KL;Rm+eDO4;xDG`M;?+THWGdml z51o8nkI&$mc8-h}|9QzeeDTOp(~v7%m|sm^PTs}S4b!{2upwvI=>hZ5j*sC8gz^?j z56XOi_ZgI*Rdh3@hg9Bjh>2T{lz3-DSFma-Un((=nbHcCw@~^v>I&w42j%~kn8!@% zyDD#?bR}#F=B4sA67!fTtyg)kg)#$}q=T7nL3vPO9y6u4sl0{KN_t-syhDQ#AH3#Ig}8S$dmtDZczW(EJ-!KQqE$&)Xr=ybsW#V}iV^W^-1za^MfB$j0pv>{XW{JtQVOjT;I07DmjviDTGcUM_0Iq)w(F;+XsKcJ zsorLN&opgDv=f%W1V*bM%TRW__JyXmlxaC-XTVPvMYf4YWBAYnbIyfFbi2Vff4yBjr}z3Y3+wcJ=bPo@h#0CBngK{@`Sa)bVTxt0}v4QSWf^#jwj)FGGI zy8*>rcoi9N%x)kjLy$iJanl0Y@4WAT+#G_Wz-e!VAmu<3v2X}T)dE=+f?Vqb^kE2e z1CUQbkUc;OFb@S3jR08}f_wqw))0igXMGFj4gsk$AYb7GAb?yRwt}$**lGo!4PbgY z1flORbMVv)@Eiov?MF&H%^N*%^!3tbcm`!R z%BZ4PQc*=;I$k)c=rx#%s>QyjT6>XJ81)Wt3QQAUHk6$p!;6ASh1V(M3S@X`>0G~l zmX>LwSb7Gqils`5Nf}CMz*H!m@Q2c+(~VG~S3)Y3{-qDO5K6i}I31z%HvDinnL;Ti zy8)YR%n)~sJPQ_GB{ zvGfl}DhG7x_IVh#bM>K_T5cE(rN#QQ$nrPzzmVj|XiZ(FZvf?gi{f)IHnj0|5~0S^ z)R`$8ALZ`17;}pioh1XJ4|OUhoB$+!K;Ka+AJEs7^pV0j7c8Q!qVhqD-v?2%w8H#l zutxd7VRTxkFu9~ozjBtAtG%N_B8)t7t^U9)ElWD05k=*QX6cBqxd0mU-`j$DG zMQd>C)=RW?TB}pvNNKlI{|qU=PG2$`I;b1zLuA#26Z*%P-DFc~%cq*^z#n;2zx3&c zX2Xz;PW|L;ty){u?;9(!&aG5uR(KemC^SQzI-O6&?rHlTN++ zQY}YAT02k6(Vb;lUXbQ+9452V1`pB;@|1&zWh*^MFUV5`9-F~~^jw}a-8)B%(45)& z>A47l?)bsADx z?`|V~M5d|w)<(@7PH$xnWJ|}wzUnHinlI9Ct3rny$kU&!(w2pH5J#T=<6fUHhyC?J0-|Aob1lysAp+^FsXUtn7G zZx?8n@LC;5>1p~%4aUn>DU_paE6|+_GAHi2MQR8z=aEo&~l1GGFtu!hV2Ik^aDCm~5pc{qjXx5|$?6t0Dbrfo@%5cs#rd z!102E06Hz+?rdMkP_5U4L>E~G199C0q{iq~g*%oyO{0dYYR_)Ua6b zyaArW2tiD&kgD(X^sK?({cQAxRR2DhTK!C<<6l%6_F+nlkZ^Q?HH0UN=15#)V?Kix z5VAEGSxpG^1bBWXrSPsi0R0Bg?hu2Xl1$DZp0|MD0U3mRMLZ!Uo;?qV!Hm7psiIr? zBbnxK8$Rd?w5$k_Z)n0r_}0G{Jgp%H%?8ib5XUYAQW?@gR{<%4WI*$JAlpKuZUWK` zgCgXV!jt4Ps^DIrO(DKL1cWYXvNHT=r2fnbt=xNxC?Os-<5BA4Q@mL~-asrFo!;EJ zp{=K@b5V%3Q^9k6NS%v;>89!RK**T(^>4H4U_Z@&s-%&k9sm6o+~2k6T}==YKm zT&ln8TdwPA^E9*C?BMu+Lh`tSdUpf}Ed>M4JT^{uUajSHd;&^Q2<2NKZalG-6Y4vf zJJxh>V%tJ$_z!sKZ?OXUVz90{nICLL7Ok}WmQrq^zW-`1!Mim?RU6o_Ru59;1w#LI z40&Jmz^y<=q%VEQ-9YI7i1GCl_LD#Y-mR~%m+vNa`0J{#Z~yStF}wwgL>+z!R_liXI6t z)wgtXHK990VrvRjk1JqMD-b6S_8A?Xhw?lQ!s-m5vnU0aBCx_f6N04Z-c?#|=VA~xhUi-h zq}-1n+Nd$inH}7_KLtNd57uj0-e{bL*g}YTKtd}i z1>yu4h>&XH!DV!Hi>DdiQL~~D^S#6qqM1&!@ZgFTIt?%LL^U7nnav=2KRiMKc0I7)yX=a^%!)k2S zibAxv>JP8h=H+Y#yDNly5J