[or-cvs] r11280: added new tests for proposal 114 (in puppetor/trunk: . doc lib src/de/uniba/wiai/lspi/puppetor src/de/uniba/wiai/lspi/puppetor/diststorage src/de/uniba/wiai/lspi/puppetor/examples src/de/uniba/wiai/lspi/puppetor/impl)

kloesing at seul.org kloesing at seul.org
Sun Aug 26 21:18:53 UTC 2007


Author: kloesing
Date: 2007-08-26 17:18:53 -0400 (Sun, 26 Aug 2007)
New Revision: 11280

Added:
   puppetor/trunk/lib/
   puppetor/trunk/lib/bcpg-jdk16-137.jar
   puppetor/trunk/lib/bcprov-jdk16-137.jar
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/AdvertisingAndAccessingV2HiddenServiceOverPrivateTorNetwork.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/DistributedStorage.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/HidServDirectoryTest.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/HidServRoutingTable.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/RendezvousServiceDescriptor.java
Removed:
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/DistributedStorage.java
Modified:
   puppetor/trunk/LICENSE
   puppetor/trunk/doc/howto.pdf
   puppetor/trunk/doc/howto.tex
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java
   puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java
Log:
added new tests for proposal 114

Modified: puppetor/trunk/LICENSE
===================================================================
--- puppetor/trunk/LICENSE	2007-08-26 21:03:54 UTC (rev 11279)
+++ puppetor/trunk/LICENSE	2007-08-26 21:18:53 UTC (rev 11280)
@@ -64,3 +64,27 @@
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+===============================================================================
+The Bouncy Castle Crypto Package is distributed under this license:
+
+Copyright (c) 2000-2006 The Legion Of The Bouncy Castle
+(http://www.bouncycastle.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE. 

Modified: puppetor/trunk/doc/howto.pdf
===================================================================
--- puppetor/trunk/doc/howto.pdf	2007-08-26 21:03:54 UTC (rev 11279)
+++ puppetor/trunk/doc/howto.pdf	2007-08-26 21:18:53 UTC (rev 11280)
@@ -3,100 +3,88 @@
 5 0 obj
 <</Length 6 0 R/Filter /FlateDecode>>
 stream
-xœÅ\I“·
-Îyâñny/¥×"	®>%Îf9KÙɤrHå idÉ¥ñŒlK²•_€Àn¶4Š£¸\eõt7Iëý¾9¨EýWÿ}üõÅý¿†ÃÓï.ò݃>ü±_=¿øæB×?T}ûðÉ%H£=\~y¡ëë&èżwøÃå×ÿ<~~RKt	R<¾:™Eiáø"_9ðêlÜAûãºu´ÇËSp‹ÖŽ·§³^,Äã·t>%ø×åggoR8œÆÁ).¯p­_ŸÎ -qÏOù…äÑ>Q„ÞøD$©ÅÛ-F9Ü£K¥¥È)0H>¾YÆhëœ8™'rÊØãS¦äWyŸÑ»á.JlIÆ‚=þ€3Eo -Ï3IL¥ ˜ƒòÑFòECL©ÊŠk¼x5£åU›v`	€&k:j~Q\Þ£%
-ßU›Kåí1ô»U~pÐvë«üp0‡³Å½»f_¸”Ö(Ù`ÁR©›Ð5íUÒëŠLG®ù,Ò)$™®a,í/_j$å1±=ð®Î`µCY*š²$TT´`­Ç•Ú˜J³;$T}ã³B6bóåŸ..IŽçìq†ÌH²èkøêlÈzQO²ÌU­9zD2:¥HVòm¾4Jźf8x=DGkZô6MßX¤äo3
-=ñ2 ×ꯓFk\v5ÆG$XgÛè5QwэÙEÙ˜-9„FtcŽ^D†Ð›xqЗ¨&”7b㲕Ñ>bÈJlLp¾mØD8~BôÕpê‹bôsœ7¨€$KE+:>ËL4.‰É_íÝ­dðãÇeEgbݯMAg³-[g&ð2rrºçl’”gn…%E?%í	=öèÙc[œ•M&ÚuÓUá£~õ”³Î°ø+Iù9¯É´3IMyì —ü’hB£0©Øé⤙ɓSöè “óL³~tÎڝ©
-•ÊKÔ5ã¡íYÁ@t5GP”ѸÐY×ÀQ´ß­•ß¡ø Œ§²Dƒnk:×…Lv$LŠ·'7*БtÓª,ò&, Â®˜ÑOÑî…nü=›åÚ]Ò<¡,]Ö-¡˜ƒš`pu覅t‰ù=eˆBI_uš˜ÎÛ‰ñ½C‡Óz¨Ör»b•‡<š('樀¦íK,#ƈ™®&»©ÌÖ´zÑÅ„Ù¦‹ß…!²X‹0ÜFW4†¹¦+è¥~>áË·èÊøxÁ«hOÃâTÅg}M“½í¢+:³ûæ„سËÌ£ì…nÖ‡ÝÃÐ㍵u­|s+wŽ¾3vQú¢YpŒêE%<HO÷üDHN½Í¼„Ñ9âM\'X)€¹¨y”xµYs^zpü™84¦«5/Ie^uøæ°úõÄýÕàêÃzñWˆ7:-QùÑZ
-odÔº™^òM1tœæßLfg]j-šyxûEQr‹± )y£Í 5åmD=è»_IoÜÄÒØÞ-ž“Ò@"0#%(¨cc®©°K¹$
-«Ž÷ÊÉ»•9ˆqŠÔm"€C¨…™SÞíÍZÐ6˵ÙaBQñ˜9"|-1°Måd˜5ˆLl”eƒvU@ˆ6ɍ轅¾uú:-𘥔¦j?ä؇
-°q=ì(,5z±^Šx•ÕHӐÿI7âæôŒ2G`júJÒBÕ1¦wVc†8Ûöý=glálÂϪÄ-í§À”zÎ#<-	1jéÉ”êÒ^d…ñSï¥ç‚ßgš5™dã6ÒÒMÄhË™Oà÷PuÞs.èOpÕ¶N@“Î3Û©/ᛟΞ\±›ì¹,…|ÒiˆRoNÑP	6R”A²DëVä
-yü¹æŽf"Ø–v#gf˜N‚ßìD¬ž‡P^þ¶è¥G¨zd„”Íi _w”£¥Äx×HŸröÐŒô`!\6KЋ6W2G+ã4¦­Í
-~	¾‹_]MÞ@wHÓð1“=§˜W¡Ÿ¯Éìd“ä±<ôWq™†K'È£¥gÃÁ)#éú³k›*V»§“ÉïÕrIx'²zCä’m
-ª8-)¬`z~À^k)¸
-•ç/ÝOæ°a´§"ë®oä<cmªÌ‹àú¢w’nÅ<	ã{¹è÷Q@~Á›÷IÎÎ&ºõ¤³3àM|ò^V4iEís・miŽ¤†RÆä@cuL~X]¿ÇÛ5uŸ.Ú
-(É͝ëæèe­š_Ó\ÿðs…=~ÓÍèÕ̏¯%Ò
-Uù^uíeݵojk+S[˜æí–Q©žà£Ï…ò±´›”GÈŒ®Šøà™#š¡·)Ÿg<  €”hW+07“²Ù`É	#k_lB÷ê¦Öçw9‡·é-è:9Ìvj&ïy‘«àS[fo% )ðR	qԔÝ+8·Òë´ÕpžÅÝ	­$uËV&R²MF„‘'Sç¿®ª2»6\,<¤§TÐk¤[oG'VKD.<<3G@ò™‰LËŽ-Q3åMëgò¤!zQ­l'T׃™g@ˆ+²{·É
-ªÖ-ám!$׆µ!|žËÓ—Ò0@<ÛÙݦäËdü»¢jU“%½ru‡Ú`ÞÙP8àÂI¡ÌÅ(_jZ•/úQw³òAšyçõqW¥{D%¿?ÑIU~^ Y#Åz$¶
-oô&•´Y`v(ªšè»•ÂÿϸcE‘3r°aD>jí&Åê?ãìÔìköˍ?Þ¼LÂlƁ?SRæ^¤- ¾¼·ê|èÛž?@{Eš¡:^wÖ½ûž®’Ec0ÞibŒ»ÉÂnåeÛé#|¿x“aÍõ¯
-a-Ý*fm£‘n5'j˜¶ž©¨J]¦gíÛ›7jS8·Mé·yz>5ÜI`Úãìÿ(#²¹ªðÓ7œ¿˜xލ—’ ®‚¡NK”ºénq6	m™õ¾ë(¹E,3="W‰$éÒ¯×ÃÈwŸ…ü?ÔaJ-oÅÔs c÷ñªÃЁÐáœÐÚ÷šŒòÞ„k ÈæN5<K
-†´yÓQVâN9½÷;ꝿ_°NËãIù$/k|¹C=!„Ò5/W
-¶ÔmÓí7§pHõvÛmj.ÿ_÷QîV¶&ùqCwðûäƒûñ-G9xE³âf*/ûÙUH«>Ò¡¶›,ê®ME98['ÃÓ{6å³FYïé[ÛÝl>&õ†‰Ÿm¯ö“H?O‡VR‹nÓ…½Cü&àµñtV–Q@ù´6¹AèYñC¿f‘Ë̏¦Õ›y’ÚÚ)ôÿàT«©¯úæj£ÂÞ‰t>ðh©j†ÝQf´D&%NxuÓà‡er;­Î<|šoRiÔåêQË2íüèþLQÀΡ׮êÙíé¹ëzO0ø`‚c‡hÎX#zðén¼n°˜b4À¼^(ɬwéjæàÈ­Bv‡SXÂnå~D„«ƒ±[Á„iÆ–>“s·Ý(áêû¬I5¯«#5Kâ†|Apv¨”lð(‡n‡zCN/‰¯óÌOºkÇ/c#áD«ã3!•\_ ïž¦ÊêŸkö?XÃ05ÐÆý€_†çëÌœD[6§¿'&ûèÕ|¢2ë[Kz5)·?Öªw 2€«Þ¥-Å•üEÍóÜö§ßEƒù&é“
-”J=$zÈ·$1Ï«~•ï%ÊÇN˜ë$¿¦&„Å=¾¢•1çªyêëÂGÆ„'œFÛ&‡uã]>«jž6K9Ã)CŸOó›LU14ä¹•l€0 ˆ^–»íê»}”tóÒÏO„S²¬SMªèŠ«4èÓ\’ówÀ]Pâìé7btµÊ-–MFƒ"m*ó-:Çwu§‰³fªËÚÅû¢í`Nå0÷úœ¶£Kø™½ÊJәщ†¦h&ÐàEúîñÊéBXè§
-Ä ±[iæEãƒÜáMK¿Ña¥¨^uk{Úéä+&©Óž³0Â=^º§GÅT}Κ=°µñ?mŒÊÆÂêqÕ5Cnòïv9³±bZ•o£iMmcé7kÅ{vº¼=ÈïãBòém1NP’s}Â=ó›¸Ø^_–Žo=rLåVi}ߺsViàº!_itn¨h¬aÑS¹ù;ÿ7©n=ò½bã>ëÃ6\½,ß	ÄÜmÔì–Žþé‡;r;F(>Uo~ñªOþ†ˆDaŒ[ä7k8PF®øl‚Š·%„ðºy6wþµœ6B3͇wÇn-Pïb«>"cÕG*¬õ‹ÎçBÍ6x¢"Óµ–lHÄ”Û	ÏÖbW=ˆ)ó'nÙuÅÁeß–
-õ§Ï‚$3²?­§Ãô#Cvek3ð4*8 ;‚-€w†@?84]Fí"Æ¥þÜ K”‰ïR¸ëZ'ÐÂ̦âxtW+\ÚãÙ™›ö©ýþMèÝ›ž|qñìêäendstream
+xœÅ\I“Gæ<øG¼ïz­ÚN`#†à@p4²äÐhF¶%Ùâ×óe­YÝÕÒȶ £žî®ª¬\¿ÌÊ~_Ä"‚þWþ}üââþßüáé·âðþ{zñõ…L/Ê?_>½ÄKñ ý¢¤5‡Ë//ò`yP^.êàœ]´;\¾¸ø×ñó“X‚:†ãë“Z„ÔÞ_¦++#®ÎÊ.AKw|B7ƒæxyòv‘Réãíé,£ÃñºÐ.FýïË?]œZ”þpVƒc8\^a­ßœÎZh¼/¼‹•^ÉãÓr‹1FßœŒ]l°¸U¦=cMi­ÇG¤ò0bÀ·˜Mº+LÅâµÊ„Šä@¨Šƒôñïm¿_ÑSfAÔ(#
+cÇuÜ({Õ6¼f‚—Ú,6h±uâAtBeü㤥5ÞžßùxüE_•^j	Ò?;á9þP…>âH!ß;‰Í×›mN¢åþߤ<HÐa­"}8Ë°˜ $ˆK”1f➟,øòhŸ¡S.IbqÆkëAˆY|T!Òþé.‡–Ò‹uÚªã
+¨‹&¨ãµŠ^	ëÀ=º,§´ùx3‘&”91öÑÞLY¡Ìñi§ä×iŸÁÙá.$¶De´9~™‚Sº.ßg"’:•Œvbä#•ÐàDCL)ÊŠµ¼/^Ïhy]§X¢µ$k:ªþ¢ë—÷è£Ôü±¹Î}»[ä§Ò,Ú¸"?Ì£Õál°w[íK‚?’õæø+-e	YûíZùŠóÌx
+K¤–uMk›ÉŽ˜IõíñòÇJx8’&pZµ‡ü…ò‹~WÌðS´{¦ß'Ï&´°õ.iÓƒ.Ý®[L15ApµpÓLºÄ|OéSÒ׍¦NçíÄøÞ£Ci=¨5ß.ÛCáaM”ST+³%­žu1â/Suqà;3Ä.Ö,»Ñ‰0WuΑëç“~ù]/¸
+fqä±f€3 ŠÏÚš}LRôº‹¦èÝ7'`Ï&3Ù3Ý,›‡¡ÇkÏêZøfWî¾34Qº¬YJƒpDõ¬NsO÷üDHNf½M¼Ô£sÄM¬ã
+À\Ô}{µZ³g^zpü‰8ÓÕš—¤2oˆ:¼9¬~=q%¸:¿^¼Æ⍌Kn´–̵n&Á¦/ù6:¦ùO'³±.VÔ<¼ý"+¹A,Õº*y¥MÁšÒ6‚ô‡¿+_qo\ÅRÙÞ,ž“ÒèH`†KQ׍™¹¦Ì.a#7¬2Þ	Ëïæ+‚¬£%©ü†ì <g#/Ô«B¤ŠvDï5ô­Ó×x¬†Acœªýc+$+ÄO¹—ž3~ŸiÖ¨¢	ÛHK|2q£-'>i·‡ªÓžSA‚«¶uštžÙN}I¿ù«ÓÙ‘+¶“=ç¥À'‡(õö•`E@%»"oÈãÇÈ5w„4Á¶¸9Ãddüî€ÅêyíËßf½t€:¾E6FHÞœÔäëΞr´¸“oà©ãÓž=TcÐr°	.›%èY›™£‡eŽqÓÖÀf¿˜Fßů®&¯ ÛÇiø˜É¾§˜WÁÏ—dHïd“䱜&é¯â2
+çN°æž
+ƒcB†Sõï®m
+¨ºÚ=L~¯”Kü{‘Õ["—lkPÅÐäý8½/Þ+ªýÌ‹«Ô’÷1¢–uâAºÇ’YÁôü {­%ã*(Ï_›ŸLaCIGEÖ³X_ñyÆÚT>˜gÁõeî:%ÝŠyÆß+{ÙàöQ at zÁ©IÎÎ*Øõ¤³3àM|rŽW4iEéR・3mqŽ¤†RÆä@cuL2~X\¿CŠm«ºO­”hçÎusô²VÍ4WÀn®°Ç¯›½žùñµDj¡*Ý+®=o£¹öMm`
+byj+4Ò¼Ý2*Õ\0ã¹P:–¶“ò™ÑuE=s„:ÓyÆ
+ DÚRAÜL–Éfƒ98'¯}uºW6µ>¿K9¼‰ï@×Ñ"Ø©™|àAFª‚Om}˜½–€¸Às%ÄRSNïDXÁ¹•^— -†ó¬ÞPK2AÖÌae"9,›¨Xy2uþëªj&³i3sÁÙÂ}pJ½Š»õztb$GäÌÃwæ0H>3‘)bÙ±%j梳¼iýŒŸ4¤C/ª•í„êr0óñ¸R	³çpë‘Ü êÚØÅ¿+„¤Ú°ä!¤Ÿçöési˜ žíìnSòídü§ jUã%½|u‡Ú`ÚÙP8è…“L™
+¿ÈÔ´(_p£î&åÓqæ×Ç]…î•üáD'UÞ»ydË‘Ø*¼Ñ›TjÑû°CPÕDÞ­þ?ÆÛÐÈŠœ¡›ŽÈG­Ý¤ØCýgœš}Õ~¹ñÇ›—ŠÈf¬fágJÊÜ‹d`‚y½]õn•g¨BRX4ƒ'f§fì.âûÇ{«Î‡&°íùƒ~¯H3TÇËΚwßÓU²hã&6¸Þ­¼l;}˜ïgovXs=ëLXK³ŠYÛ¨'D$toU'jÕzÚ6z¦¢*u™ž¥]LkÞ(5^¤pv›Òoóôtj¸“ÀÔÇÉÿQ²¹ª¼îOßöäøåÄón8—±
+Bä(uÓÝbMdÚ2ë}ßQrXjzD:¯qÒ¹_/‡‘ï?Ëø!|¬Ã0H^k½ëk]Uõºê³ò鲚Ú!óVúè:ˆûÕªCсÐáœÐê÷²+å½k+û!J¹©âÝ5íè•fÒ@$l'>ÌÄû˜yÍ •çMx«ŽÒ'÷ÞšòNÆsú‡nµ4ÈÝ1x‡ž
+¼CH=ì{ÂÖ¿ËúØÍË·K©E[¯Œ¼”䇮%ý@ÕRoì{†óh#(r3i?¢ôï//¾¸øú ©SF¥ÏÞÏf	ø[{lú TN
+ô!ý§.î?øËáÕ7¯Ÿ\ÜÿçA^Üÿ#ýߧŸÿÿ<øÝág¿pøb÷{÷6ð/ì%5™õ’D•?±—§@ðÇ—/T•<Ð'dBÊô…*ˆ€•ˆÀ°­ÅŸšdöx˜ŒÅéð†Üg½ù®B‘¾W¢I¢Ì&“Þ´ÿ/ôå6%ÐK::ˆ­Žê3•Ç
+Pÿ“tÓ§ÓRªg€ÒœÙrî$Čѕ¸ü"Ü%ﺂEÙð>&S¬ ä/Ûè>Ïm{úMöX4¸ß$}žR©‡Dù–Èæyݮҽ(|þØ	¹Ntkj¼÷ÝëW´2rPݧ¾Îì±d<šð„•°mrèAVÞ¥³ª:ài%0—3¬Pôùt³Ó@U©SßJ2
+
+àY/ËÝvõm†ƒ.pºûÒÏO„c4]§ªTኋ4èÓÜ>$åï» 
+ÄÙÑo4„+öÕÕÊæöúòŸJR[5*¦góÙZ½Ü<W	Ê!„Ó½K¦*Ý(F1À
+]ú¶`róaåH­3Ç-Aí
+ǍЍ㻺‹iÂÀ¬™êvíêû¢í §²È½>§íÈ~f¯v¥įŽDêªh*ÐÝ;é7zWJüB?UÀ±Ýr3ÏïùÖoúÃEõºYÛÓFg¿ê$5ÚSF¸Çq÷ô(›ªKùBµ‡nmýª?­H+&”…•ã,ªkúÔäßìrfcÙ´
+ßFÓšÚÆÒn–Š÷ìd)x»^ ¿CŒóÑÅwÅ8FIÊõ	÷ÌoöÀÕíõUîøFèác
+·rëû֝wÕ˜®ò•J¦†ŠÊš.zj"7!}çÿ–9Õ­G¾—mÜ%}؆«Wù;ºªÝÒÑ?ýpGjǨí„OÕ»¿xÕ&KDBãû›%ÅW|6Á+cÜ"Ó¹Pµ>QjZK6ÄbÊí„gk±‹Ä„	é·äºÂà²os…ŽúÓgA²3²=-§Ãô#Cfek3ð4*¸;<vWMÓ¯f#6šnÞ2€wÖž~phºŒØ5$ Æ¥üÜ‘K„
+ïS¸ëR'Ì̦âxtW+\êãÙ™›t±þþoY›–|qñ_fgé endobj
 6 0 obj
-4887
+4886
 endobj
 25 0 obj
 <</Length 26 0 R/Filter /FlateDecode>>
 stream
-xœí\[o·~ò#ôxNa­—w2oI¢I‹ÆuEÓ˲e׶¤Ø‘÷×w†×!whÇІ²Ù³ä’Ùo¾¹¬~>^q¼â¿üßǯŽî?tÇoŽâÝcqüçzõâèç#‘ÿgÍO}
-„9K°ÒêãÓ§G"?/Œ_àŽ[Ý"á‡WGÿܝî½Z¼q»«ý‰Y¼Aí^ïOT‹\Íîr/íͪwOö'pKêÕî~ÙK·»ÊÝ»½T‹Ur
-—r]ýîLdL wÒÞå)¥	»søÞV·{œf—^å©‚ôíçõê¦^å1FzXÌ$`Ãaw½?‘r1^„²dœ4/Jµ{º×‹V«­‹†5‘Ÿ_í%ŒqÆn–<¼fWN/v¥cÈ+µ}¼G—Uãe[>y'µ™
-_u¹—f1AHØ(ˆS» ËœÊîîáqÙÅÂMºxáÇñäG	Çv–$cVQÖnà÷çûuqz]q—ÿ:ýþHz³c at _NÏA?á“aE‚ñeédkiAF
-Ìî­·»gåAœï¤Lx"dš’èÊS˜]ÉÅAöC~Oû±*ªŸ’vÑðÊgQÖ:"ÌQSP½ˆ"Y6MÂ7Jó÷š Ôº8Š&ëguÎöàM7OZ9§1Û÷)ú>”€„0Bpk¯Yâ‘éàD0ú*,®DIÊ?àlB;_áaK ›)otEÖ^G,UÍI°x—¥chÇ]Õ
-n6Q\Wá]×_Ödýƒ£¡°Q0<…öä#g\¯³‹
-’ˆœœ;±AbÄdÃmúÞPÊš­œ€×öffB1X˜@PØëÍ=YŸ¡hÕ6ÕDß®ž7‰
-bÄ%“)ßíOVø}UT¶¿$Û6-\Ö’àÐ.w•T‚ê8lK*ŠâYn2ƒmIƒØ•v%ƒ
-Û]áy±ðŸ¼
-Í»\0 t0Tz—!5xæ`¨]ðúÖN§­©mãUÎ=ПJ¾ÝÃ(p!¸z¡‰á‘e]Ô{Óg›‚E)˜W‚CF-ìÝ°D}wTK‰Tˆ–·M‘›ÙE™°(QÕøE.ÉÛÉô¸l…¿Uyže|Q¯.8ƒàU:-t5ÝBóô¶R(Ÿ´;¯½zÃ/kŽœˆ¬x&¨úÔ¿€Ã2°{AÔ™@vƒ´g¥ÀÕPp'?‡kb8åD–~Yôw'ÀrAºƒ'mÙ`›:ÀPcvßá	Á{…1Ñ$­ˆ€y=ú"¡D:W$3o›™7ßÀ}Þv´Ï{ƒ¨ ÇšŠú%ã`2@[''t²½h¼DÀ&Þlr Á>·«Çß¿¨Ö»áçÙSI÷Õí¼ú?ðßæ’#.Hßžd¬Մ/©'’ <ZlwŽfKIЉFâdÅîÛý‰]`ŽþžÎ5kÂñšÿ"[{Yo¶«Ê “Ãa…k<#B
-<"%O¹æ'0gdq'
-œ§íBBµ’váL‘±ªÞŸ$À‰±œïê¯ÑEÀ˸%„•Æ'E\qvf9à¦Ð-4\PoÂ’ä·5®l÷Úپā4	ÏóâA:êFœ	¬œHïMä!ÞD­a¡!
-ñœ/"ò#ïœäª—5¤¸9+CQµv¡-—Ä	ë2 ã&
-„Mî¡áæúEL€•TÄž„peNL](>Æô‡‹R]J†<ÙÏd ˜Lt¡¸½MvU[¢¸Œ:l5‡ªÃ#®nJZœ—»1ì½èÐJŒs
-ý}LLUuÍ«¨êJxwÜC£µ oÔ<ÝG_d:fÚ;$úº£å¬èž ‡ÕXËTz†î´0ôFëßï=ìR(²ú!‰Ò[HŠ”3™ÔÆ­‹WšçMcœÝçj:Kˆ9S jÄ–¼ƒR GȺ(ÒÒSšOì`cÊnA-f|&†1Êë}J,k<".°=½ÊÛ°ù§}U!γEu8[Ü–ð˜›ÌŸ8Ñܳwr`“2HxÓœ%®°uî*7!ƒpšœÚ95xÒ/GLÙì!+†Zót–Ç'BcYî|28 Ë®ËU’J¢DxU$Û¿ÈN7rûfèmªD |¬ô¢0P¹É׍,¼¢PT80.L‹žÖX¢îë&-ñé}=`tvq¾ÿk#¡]Y44¢hî†Ñ£ÂmHwÒá
-j’c ¥=;»ñ²C’8«n€FOCšçMùÎ3@¹ ¶Û\ËÀØ’Ûã
-¾“
-’†R1zZ„/ÑõÏ)içhclRè{o^Ô+	ÕÁ …uD;nmÑ¢ |§EœÒÏ45ÖÛƒÔŒÓc.õ;‰è(vIkiôPÁ´òZ’
-@í<{;PÞ¢›ÖnãàÆR}j&+@]¸³öå¡òʹn±I¥(-feìrÒÕ3(bÒÛôI:Ÿ3Œ1Q1fŠ6A,1‰–ä™–)%›'¨Ò§ú±u€Gö
-aQ×oSgÚ°zÏÏS^û>¼ª/\Ϧù®”ˁж’_Ï=Ø…ó,£©¶&ÍE¥p8ðRa¶–YÐ4éeMwïeVæõLO“8íbJm–Þ‹iŸev
-D¹ç-A¢ºYD¿ýiù¬²ìÑáäF§´O37åܹ68¶ÈÏö Ý–`/iâW0^ŠUê>U•Û'ƃeK#9)p0©ìb&™w5rs3-Gè|D6ÿššÛp„Žü¬<w÷VN·¼EX×Ø}ÿ{0%œú ö‰áÌPH|B©
-¡È|ƒÏÿÜPôfP/<k¾?ã0ë—Üð#=h’7³$þìú~AÝdVËs¼­YÄ„òFǦ¹Wï£$›ÍÂÁ»÷Ìî{°P)cötRûØ
-‡¡c!VÕô´À\¶ûMƒkÊg·«lJ‡æKSœ€4˜!CQRéH•!¦ü u›}‡+vø0õ c@Q#ùn»Çs·Ã¬Ï ¢JNµ¥ÕU=Û˜øȍÀˆ1/	5Zy-|ƒ6'\*Ê&>²R6ÓT1{HýAÁú‚ž)N.>ýÈ ÕY=íY£qyÛCß:%Uø˜:ÎÚ3b{KŸ—êó‹Ù„[„À›Dj‚
-i|íêgó
-õ6Þ…PüŠm˜‘Šxþf­W~ÓŽœûËViïD»^qÆ«Ý+éI3‹±J LÖÌ÷’#¢›C.&9®ÁJ2ÍìÙpdMý-¶®‘=ç58Ö<|Šù_Š¤‘Y%§‡%´ŠÉimjc–ÃÌnÑÉì”À­öÝ’õrî”âü£W*¸|66ÔÆÈ €Æ:E_©!aÖÆ|L“¶2MH€†iì[“fŒ²ò'•×š¡ôƒ‚ LÞt£ŠàD~
-šZ¬¹s‹ÏòR&éíbåÖ~æì„ðˆ±­•A;tsŽ¢ÝÓ´¥Uðgb½oPŒ-3l5Hù]3Õdâ4~úÅ/Nœä÷ãVLLC-Bö¥\‘°•ÑfZ)ÄÚ¾™<ýæ;æš
-kãç&ˆ¶m
-íK½>“«Ù4™e„½Ô)\r^óÑ«ëC×8Ô±Áõg`7sF#2añë¬Ãæ²mû–Äežª+2ŒÝSLN Û‹y^„nGõ„ùìçµ·},@ú™øR&÷¥sVC–×ûy­ã—_³-Y`fA³
-Ή\Õ„»Ü¾³2šTÇ/ÇPHö«úHøôU1 Øfo?Ýö‡‘©h+xœí\[o·~ò#ôxNa­—w2oI¶	ŠÆuEÓ˲e7¶¤Ø–÷×w†×!whÇІd±gÉ%‡3ß|sYýr¼.âxÅùÿ_ÝèŽ/^­Ç‚ÿ.Ž~9ñãü¿Ç/¿>…‡„9K°ÒêãÓ§Gi´8Æ/pÇ­n‘ðÃË£îN÷^-Þ¸ÝÕþÄ,Þ‡ v¯ö'*ˆE®fw¹‹öfÕ»'û¸%õjwoöÒ-Æ®r÷n/Õb•FÃ¥\W¿û&²
+&»Géïò”Ò„Ý9üo«Û=N³K¯òTAúöózuS¯ò#=¬f°á°»ÞŸH¹/BY2Nš%Ú=ÝëE«ÕÖEÚÈÏ/÷Æ8c7KÞ	³+§»Ò1䕏Ú>^ã˪ñ²-Ÿ¼“ŒÚL…¯ºÜK³˜ $lÄ©]ÐeNew÷ð¸ìbá&]¼ð‹€ãxò€£„c;K’1«(k7ðûóýº8½®¸Ë~$½Y‚1 /§ç ðÉ°€"Áø²t²µ´ £ˆf÷ÖÛݳò ÎwR&<2MItå)Ì®äâ‚ û!¿§ýXÕOI»hxå³(
+kæ¨)¨^D‰,›&á¥Çù{MPj]E“õ³:g{ð¦›'­œÓ˜íû}J@Â	˜N!¸µ×,ñÈtp"
+
+}W"„$åp6¡Ž¯ð°%ЊÇ͈‰”7:‰"k¯#–ªæ$X¼ËÒ±N´ã®j7›(®«ð®ëƒ/ê²þÁÑPØ(žB{òŠ‘3®×ÙEIDNÎØ 1b²á6}o(eMˆVNÀkû
+33¡,L (ìõ枬ÏP´j›j¢oWÏ›ÄÎ1â’É”ïö'+ü¾**Û7ɶ
++\®^hbxdYõÁÞ´@Æ™EÀ¦`Q
+æ•àQ{7,QßÕR"¢åmSäfvQ&,JT5¾@QÁKòv2=î_Á+Æ'íÎk¯Þð‹Áš…„#'"+^£	ª>õ/à°ì^u&Ý íY)p5܉GàÏášN9‚¥_=ÃÝ	°\îà‰D[6ئ0Ô˜ÝwxBð^aL4I+"`^¾H(‘ÎÉÌÛfæMÁ7pŸ·íÇóÞ j'豦¢~Á8˜ÐÖÉ	l/š+â@ª&ºÿ¯Vñ9ÊÅvQ,Í],­ç: ÖwèÞP꺒º†óÍ!/ñID6ÜüDa”Ù Rò`ynq¾£o‰¨¸Ð©k&éÒ’áÅƵ NŸçìÉt9’~Öc,\’-SÀ£5 @Nú…Kâ„uÐŒq“€†@Â&÷PˆpsýÆ"&ÀJ*bOB¸2'¦.”cz‹ÃE©.%Cžìg2L&ºPÜÞˆ¦»ª-QÜÎ?F¶ÀšCÕáW7%-ÎËÝö…^tè%ƹ†þ>&¦ªºæUTu%¼…;î¡ÑZÐ7ê+Éà“›ì6žNÊV´·ÒJbï[åvFö0êòƒŸ@örá涹n©d1NØè¿T,´šGÿ.†‰¬á]”¢¨Ø¨Ã ÂEú]Uç*WŽµ»Î‹æº¶î9`Ra˜WUü"—æ¤:HEs½¦9æGI&ðqw3[Lïî+ë'—™s*-n¹ÊžŽ÷¬+ÝGÏ£ÍÍ”$JxÝ…Ò—-¬iÄëà—®$6Å—MM3'G$È+2¬gd½šŒÜ¿(ðw«¤I.6eœˆ€Ó‚Å›£ Q_×½k|®«kçYMÑY‚´…â²Õ%h™ø¤ç3å&›ÉdŠóÏ9W¦ïØã¹L?VËÙdIÍŽlNù>ïUk8Œ“wì£}>ZY(W|+­bZpDÒâå`‡z—³šTWØpケ©Þb“—<…øô¾0:»8ߍÿµ‘Ð.Ž,šQ4wÃèQá6¤;éð5I†±ÐÒžÝxÙ!IœU7 at H£§!Íó¦|çƒ
+ \PÛm®e`lÉíñßI†IC©Î=-—h„úç”´s416)ô½7/ê•„êàFÂ:¢·¶hÑF¾Ó"Nég‡ëíAjÆé1—úDt”다µ4z¨`Zy-É vž½(oÑMk·Žqpc©>5“ .ÜYûƒòPyå\·Ø¤ÒF”³2v9éjŒ1émú$ÏƘ¨3E› –DKòLË”‰ÍTéSýغÀ#{…°¨ë·ˆ©3mX
+½aŠÇç)¯}^ÕŽ®gÓ|WÊå@h[ɯçìÂy–ÑT[“揢R8x©0[Ë,hšôƒ2†¦»÷2+óz¦§I†v1¥6KïÅ´Ï2;¢Üs+	ìÈRˆ¦µ©Ú©sßÈ
+i9ì†4¶?–ëCáøÜVçS3¢t»?îÑžœ÷|Шñóé縷\QmVì<¬Îþ¦ÐÆãl4-%e\èM7i•?4
+E•?W%ÒŠªÎni¾²=͏5K¸ù^©¬–(2×Û:¤ÄëÁù›os<—‡ª°MàŽ=ûcüÀªØ(ô;N³/Ýö}!ûR®HØÊh3-ŠbíßLž‚‹þFósM…µˆñsDÛ‰¶†ö¥^ŸÉÕlšL2Â^ê.9¯ùhŠÕõ¡ÎkêØàú3°›Î9£™°øuÖasÙ¶}K
+â2OÕÆî)&'Ðíż	/B·£úFÂ|öóÚÛ> ýÌ|)“ûÒ9«!Ëëý¼Öñ˯ٖ,0³ Ù
+çD®j€]nßYMªã—c($
+Hûeýƒ$|ú@ªPl³·ŠnûÃÈT4€ßc“¥&‹Åú±óu0üø†¼Å0‰OHm؛푩§oU>ôßîÁòTüÆà+O7Ïš§3[S·w9³·Ý]#°Tà°yºÜ}ÜéB| endobj
 26 0 obj
 4713
@@ -104,48 +92,48 @@
 32 0 obj
 <</Length 33 0 R/Filter /FlateDecode>>
 stream
-xœí\[oGrÎ3a áÀ/á	ÄQß/ò°v´°v­½fà‡8”(ÉŠ$R–HYûïSÕ×êžšsHí:A€À€5왾U×å«KŸ_vb‘;ÿ•Ÿ½=yøg¿{ùá$µîäîíéõÉ/'²ü!Ê×»¯Ï¡ƒ
-»¸D§œÙ¿8‘å{iÍâÂο(xñöä?N·?3KÂûÓËôè£5§{ëóÞú¾·ÞôÖW½õÛzÕ[_æG/b™8µ’ÈÈÏö~!O­‘,ì¾÷f^vRR1ÀÇo[§WtþÚé’ÎÄŒôÃô>ôž’°vzE7Âtú×iEöôø]ëtÛŸ¶No¸Ý“9Ïûã5·æ'©Ñ+œþ?Ïÿp¢œ_ŒÀ;ç—À+ùЃ1æô×ô¥Ò
-"­Ý_·FæL…°hvgRå‘þ«sÇËuÐj¥XùYo%[yW>Ðöß> ¤¾ê­_õÖ…}|ØÙò†’ˆ;‚gì·oVƒå“™ÎYøj ‚=!42?$ú\²ò·ôÖ[v£¯æ©g
-“~e5mébÕ:‘ŠlôCÛÒ»^•ÅÈûÛÆ—¤‘<v±N¢vz?
-?ËʧþxÑFzKgbd…Õ$ËpLȸÿzrþÿ¯0ÿ¯*Ì÷ÜF?Nì’oX’·‘X÷„S˜Ï»Â¼i
-“ÞuëNV÷ºuÂþYê4‹6N¡)ïºT«Åäiô´‡‹7§ö
->>¢$-V®…¶‡'8ZG>ä–û&-ÂD8\Ü­@†dÂg™jË£
-ºÒ[ËPRÚô(ÈÊ_^<Ìð®ÍÚçÚ¶AæïôxVNÆü	@¨øÄÒãuƒ¼ŽÇÇÀÅ	Ú°X¨&V7‚ÙxÆ‰‡…–ZŽ{ÕÚ¦*H/¯¨!=æ\ª@†	ËÞ [éÅ[Ù9±r¹@Ã[ûTþs”¹¯°Ñ.^ú¹yZ»à…Ó/ڐ„ä8qE(ŠªÉý§Îcyõ¿M즅å¸§£%ü²´Ö2Lł꘸ë°]% 4V¾Ù+" T§Ýu'mÙž-M•hÂÎ×}#}øNž—ýõíL3”СS¿Ÿ
-•T˜]‚9RGgŸ5ØÈxdžÊcR1‡€ò
-dÒN“/_dSä#ß½p †e^QT ¸$\Ù2§«.w¾¡TÁAH!!ÀëÌ]Öâf“¼{»Ähª¼çþBøB|z’¥Š]^êAXW"Œ]2!u at G©´e“¤'“Tf?“À^Í$ý}c-ÎŽÁ£àQWüÝþ́٦ürÝ¦jkŒtEg£¼#çQ)erf$À²Z„(Ÿïý'¤Q‹
-2ŽÆªöi•-ûð¦ƒMÁa€-w x“­=G¿ ’«Ÿú6™èë­QV#7åLìí˜ÿ„J at lúô›®ÉÿØ[Ƚü65 ¨#ëT½qTp Ø$nx` Ç¸,P\ÒځËàåpÂD®”(€ìÅÞ-¼å’oJ´ƒ†~î¦÷²Çy¿lqÞŸöýƒšcº“g囡¼ô—BUŠ`˜P¦`X™U»±ð±ŠC`ÛB´¦|À›å®æ.›ÎÁã5àžh;`ƒø<ƒCƒN-Œ‰¬“¢©QUd½‚IkÀøÊ«®ŒGΨ*ö4›UpÕÐ&aÁ}ѧ¿k¼ŠßYɇcàe¥éµK4Ðû4ÏyEÂ	xE4¸ušîœiBFVÑ
-3î^®˜ÆIDžW\å-y!Ñ.Ü—0wr´M$¸C at -%´¢TäÂRäü¶<¨ƒXƒ|ÙãSýidþ„æõ<í‚vY}±æue6¦^ñŒ®jô»‘
-[Åê1(j …#àÊ4è¡0ÑMe¿xÊ­`«0Ÿs!Jtæ4’¥Q)àXóçÐì³ø(=(fãÔ5²	;Zû¬žÄúÛAüú*˨M†LtÕcì³¼~9=¥E¹ëíËr€©Œ {ÙJƒÂÖ
-êÎ$*˜0)›*©ÉçùØAçç’enžŽxó¬.+™x'Š*þÛ@ÅÒºBaó·Ï{ë[™@ÖðÝ„®R1\ŸŽ"8‡\ïöP;6éÿ-§«âëî€úytõ±î­›_àÙúø`2ÖñÒMFsð@%’ÜÉä¡_å<°cP‰—’©Ã‚¾ÅO¯ÿü¯°±èF‚AS
-Ð-‹K79Ù©ÅčÍ¢3õROyk”–Ô`‚R€Gnøø\ô«wî>ü½xj)ÈPÙØÛJ|¦!Ki=0d‹¼,á¨àØ´‡FE|´iL½Bª8öµ#9¾	í—
-h¿o¡i0ÎBoÆ€™uìÔ‰…
-ËÃACö`Ø!õ=ÔRmå““V½'à®ÚûÙìÉBg%æhØ”Ëu×d©]{z5œ‹“CH¸¿îUÇÅ®9q8W2
-1;Þªî:eM8/Ô²͹º&,Z6w«@1Ia7ŠŒša#ìŠò]+˜áªyÍž\Œñ{¯ÆÀoYnSâ[![†7sq†C#ù8Ö[¼;à¶km™n¤u^Ì,õääQ”qJ1iÔtÛ¼š\ªÀX§!éµ²M‰ª—TgâD>×Î
-À"ð*|à[Æ=¿%²
-;2`p'£ÒRÓ‘È’¸"=6¹Bf'j–óä/_G°öžðvœLQ—ã•’ÅÑK[ö@EqÑKõBrÑåT.8•Åq>.‹¸[—­Ìa¬EB_¶·	oÒý!Oç)-8_Þ¥š¼Å“ß”K½CïϤÔ8øîcj<çŽ1é±r]6Õ]×&g~,wÂ8µß(ÈÊ9”\õ[k>°y¯‹y„ùƒ'óläî+kžÓjˆœöÖj[ë:•ÿº¸Ksý~-W#/-ŠÌ;k¬?äx¡hµÖ #T¯q-Ee`tlӝw?O®„QËFh¡ÝÈ*¤­ÔÿÞˆP.­"g~YbaÚóN©R˜+îªSâ‰“â/Ñ;´ôˆú-ÇicB'Gê¸X>‹ß‰Ðr¶äÍ`_‘pFæ÷F²¢F‚§÷d@±°¼'à™p7W<ZsFÀ£cª—¦©Í™U ©l€wXPÓŦõ)U¦ye	¥øèçŠÆ;Õîîç7o%Zä2'Ÿ‡;çâPÐ@Ó
-Ûc…a¹À€S¸îךÀ]6òÒG¬äòsH«î÷^¨Ti–BwŒ£¼Àý|3v-Ç´©Æu¯ö˜Ë’jª(GLô-µ%cÖ’qRœ2àoù<k]úˆW¸i¥¢#=ȶû‡h„þÚ§§«èïI§>ÒƒÞ	ïó#	„Ïò!Á’äÓŸ5.Ú˜åæ3)Ï~D_é‹hßÐÙP£·_Z-iKH––mþ±-ù§Û¨ëéDåæK;ðÞçƒÇ_¨÷¦­P:´ñL+xœí\Yo]GrÎ3a áÂ/á
+Ä£Þy;š±²hì±?Äy HIVD‘²DÉšŸª^«ûÔ¹—ÔŒ›Ç}NoÕµ|µôýe'¹øOù{ñæäáŸüîåû±ûüûòä—™>Ø•?ov_?…TØÅ%:åÌîé‹“Ü[î¤5‹;/ü¢àÅ›“ÿ8ýÝþÌ,1ïO/Ó£Öœ~ì­Ï{ë»ÞzÛ[_õÖ÷lëuo}™½ˆeâÔJ> k \ìý"B4žZ#YØ{|ïͼ줤b€ß¶N¯èüµÓ%‰é‡é}é%aíôŠn„éôG®ÓŠìéñ»ÖéCo|Ö:]q»'s>í7ÜšŸ¤F¯púÿ|úÏ'ÊùÅø+ó·Ñ»¤Æ[–dOÛH¬Æ{Â)Ìç]aÞ6…Iï¦u'«{Ý:áˆÿ$õNšE§Ð”w]ªÕbò4zÚC†Å›ÓG{Ÿ
+Q+‹0áôÇ}”‹ŽJö…<ÃÑÝ¢¢I¯OˆÅ:iaC÷Z/Zy²‰wH
+½ØøÍ^ÛÅ*ÊwÂËá»:Lb³H%4¨ôÏçéÎL:^‰Zú(£]9fKÛYDÉÅËëHÐËiµ=ýy/áÑŠ|jÊ-éA.Já’ƒ£F‡…ÂD at 4L¢¬¢_ö×Àø*úÅ)
+Lªà [Ï÷ÀXJ}úgøNÚEk
+UŒÉFj-a#œX]OW†ÌëA/Á†„pi!Ñ_Ãð1±F]Úû|žj5Œ‹€£=oݯӌ
+æ¾!m
+Ê9ëU°r-,°=<ÁÑ:ò!·Ü«´ápq·"	/2Õ,4–Gt¥%¶–¡¤´éQ:;”¿¼x˜ám›µÏÿ¬mƒÌßéqQNÆü	@¨øÄÒãuƒ¼ŽÇÇÀÅ	Ú°X¨&V7‚ÙxÆ‰‡…–ZŽ{ÕÚ¦*H/¯¨!=æ\ª@†	ËÞ"[éÅ[Ù9±r¹@Ã[ûTþs”¹¯±Ñ.^ú¹yZ»à…Ó/ڐ„ä8qE(ŠªÉý§Îcyõ¿M즅å¸§£%ü²´Ö2Lł꘸ë°]% 4V¾Ý+" T§ÝM'mÙž-M•hÂÎ7}#}øNž—ýõ‡™f8(¡C§~?*©0»s¤ŽÎ>k°‘ñÈ<•Ç¤&båȤ&_¾È¦ÈG¾{á@
+˼¦¨@qI¸²)dNW]6î¼¢TÁAH!!ÀëÌ]Öâf“¼{»Ähª¼çþBøB|z’¥Š]^êAXW"Œ]2!u at G©´e“¤'“Tf?“À^Í$ýmc-ÎŽÁ£àQWüÝþ́٦ürÓ¦jkŒtEg£¼#çQ)erf$À²Z„(Ÿï}…“Ò	‡¨ÅGcUû´Ê–ýÎxÓÁ¦`‹0À–;¼ŠÎ€É…Öž£_ÉÕO}›Lôõ‹Ö(«Œ›Œ…ò&ö‡vÌÄ% 6}úM×äÿÒ[Ƚü65 ¨#ëT½qTp Ø$nx` Ç¸,P\ÒځËàåpÂD®”(€ìÅÞ+¼á’W%Ú‚AC?wÓ{Ùã¼_¶8ïOûþÁ?Ì1ÝɳrˆÍP^úK¡*E
+0L(S0¬ÌªÝXøXÅ!0‚m!Ú
+Ó@>àÍrWs—MçàñpO´
+°A|†ˆÁ¡A§@+ºAÂúþ‹6è
+"U{~Ç,Ïo“cR1.˜ßÞѦõµÿ,2fCS[ ­fµo‹…Õ‘¬*i•¸…ÓUñMwÀý<ºúX÷ÖÍ/ðl}|0™@ëxé&£9x IîdòЯsXÈ1¨DŽ‚KÉÔaÁG߈â§×€þWX‚Xt#Á ˆ)h+€‡?5s‡C£`’I¼Îk‘†ä¦—æ%4…gÆ•¥Æ÷¨®«wfëXŽ3Æ:Å%ôTÖ*æÒ.΄vÃÊY…AÍؾ_LxaÒ-$Y}×Ú…_¿ûÕ¸æßåZ(ãñqY„¤6ñ—pKÔÔ(ôM¬=Ì)÷3¸ÈëéÉœüNÆöÎÀsþ‡°Ö¯ì·¤œó–ø6’uÝ°Ö:VH¤³Ò’YÏéƘjÍ®0“”€f+£eÐA VÚ´äjµ‹â#E¥&X÷ѕ#
+µ+OoÚ$›¯êZ}K½wÑŽ—)"F6’Æ!âQz?¬µ$ΐRÉØ5t3d*zô+2F66¶„ŸiÈCZÙ"/K8*¸6-Á!‚Æ/¨ˆ6©WHgÁÞ#°v$Ç7¡ý²¡í÷-4
+ÆYèÍð!³Ž:±PayØ!hÈ;¤¾‡Zª­|rÒª÷ÜU{_Ìž\!tVbŽ†M¹\wM–Úµ§WÃY°89„„ûë^u\욇s%£³±ã­êŽ SÖ„“ñB-k1ܘ«k¢esG±
+“v£È¨6BÁ®(߶‚®‘×ìùÈÅèñ¿÷zü–å6%¾²ex3gø84’Oc½Å»n»Ö–éFZçÅÌROùANE§“FM·Í«É¥
+Œu’^+Û”¨zIu&NäsíŒÑ+›dpTÀÔ¸üü’¤Zð~^¶§†ò¦•„£’÷œ«TWu—L³©b¥;™žw
+Š§m(_^ájäÅ€ì)qŠ›Š9qtò¸öì­t{pÎ-®õ†‚Öd?%shCòG¹íœ^7ló2—­à}6úÏ!£Ò†ŒUùòˆ«î"UD+sÅ]u
+R<qRü%zǃ–QÿÀqÚ˜ÐÉ‘:.–Ïâw"´œ-¹ì+ÎèÁüãàÞHVÔHð”âžH"–÷<îæŠGkÎxtLµàÒ4µ9ó¯
+4•
+ðjºØ´>¥Ê4¯,¡ý\±Ãx§ÚÝÃýâæ­D‹\f#ðäópç\
+hºa{¬0,p
+÷ÀýZx ËF^úˆ•\~iÕýÞ+•*ÍRèŽq”·sø±ŸoÆ®å˜#Õx£îÕsYRM刉€~uÔÅÙ-è°Q¶X‰=mÄ¥­ÕS%™b.[´‘Ýø-¸Ñ?%ïk–kÌ÷ŒJ½\E=L®@xd¦ò»ìas×®Ë~¥9z¹”ë=Þ,(½¹ºg¬«À!lòš9_¿•G`#OlÑx·QCqò£§'ߟü²“˜öQé§!Ï@QÀÿk{ÝI"þ½xsòõ㓇ÿmwûîÃó“‡?îäÉÃoñ?_÷
+üyüO»¿9yôx÷ýæ¯Pʸ³XakÃð+”¨–L£ðwÒ¯Pê}À¸€%4$w`‹<ØÜty	­wB–ßIx”~ÛJ‰Ëï6%
+Z¼þn·âï˜ò›E`Ö\*xI¹]™@<0BúÙ­ËÖø<;>8òe3?ÁŠJ_2 endobj
 33 0 obj
 5168
@@ -153,206 +141,207 @@
 39 0 obj
 <</Length 40 0 R/Filter /FlateDecode>>
 stream
-xœÕ\Y·Îó"?bà§Ù@Ûâ}$ðCtØ–oYëAœyWZ+–W—e[òßSE²É"»zfv%;X½œn6YçWûÅFLr#ð¿òïُG7¿ò›‹WGit#7ŸÔ«Ž^Éò‡(wonÂ*lârfsúøH–û¥ÖSØxá'ã?ýc{y|b¦„÷ÛGéÒGk¶?µÑ_Úè³6ú²þÐF§6ú}}ÝFŸ·Ñ¯Ûååøâtù¤]>=ö“ÑÌO•¹pPIµývÛFm½ƒNMN›­l¿‹Å¥‘ÅËoÛõ_êÍÿ<ýè+mG_3… äæDIjsz´ýüXOJ
-…”“.Brje'g’ÓÂc1j ‘œL°Â aµ–“€
-œà–õôÆô³-îÔÈ4-í¤µ:‹Éx|û
-˜Twg[Ú%sÕncõ…Óü+ÒLÊ)øè7§Ÿþ‰§¬ß·ýõøDMJÈ “$Xƒô+4þPø»žŒq^‚¨Jà5r{–'U0ÓÓúx›èQûùòøaóé•FM2ø2»¦Ì®lÜ>¬ûš×‹~
-ø]hºÌüFaOñV7Eà'¿R“
-2Ò×R?>6“Ñ­ðìG\žžt¤ƒd¦™xZXÂ4ò;²wF;²;$¨	“	oÏ´Ÿ´\V:\à–àÉ:_ןÑ4è8!`ÇD¬ç'] Ë…ÙÀö7Ç( Ê›	t
-UÒ0&°B¸3l¿<>q“Á²Ê<yŒf&¬Q)Û:õÑzÖŸ(A-Ú:ð'*ÄÉy»9‘EeÏš,­Ë"ƒ#R÷°ýÌ)ÐPYC“;³éèM³›l4ó®o7³øt´…£•æíæ_›Y{>ZÞbMG‹÷žµÑ‡ûìñ³öX[g£¶´Í±JÙÔªÉÝL=먂}Ϙ³c`}°! ÇQN£Ò÷<l¼¿,7XVr*ÛWdÙ[ü]y1XãP!¥ö¸MzÞV׆Û ôq–a $•áÆag´
-ܝ—v¡¿BxøtMP‘¦”ÄLµ5'½܈ŒM/>ªÖú4óCZm»kÐQ
-,Cž|oðQ¹½›WâÚÁ w¡PÙ®i»’»2²'©v~’i’À°æ‘šàü|Œ¾Ūó0¥Ÿ¼óëf&Ÿöl`wY¥,<°°%O…à’Ì”_ޝ¸Öì·½E´ö¦·ßÀQ&û¯íÀ¬=ÖöçFabÕÛÞp"Ü´žHÍO8èa*×;ºd®c@·6ëv^¦5QÛ8é*,±ŒD#›P6™Ïv¹Ì}‚ UzERuxE!=±)ä÷‹Åe©¢íqK‚^ÔoeaÔ µ„ã,Çš„²b{'w“q‘5H}`wïBîŠR¬É¶-2i’†`)Èî‡Ä¯Žƒ~˜ì#ò„(ÔZ@ŽoÖÓgš„øÔõh²­­$Jy–õ„àk´”Б²R@vYƒÞ‹yçÄõÀÀ¬6E]HFi}0…³gÂèà‹[‹jÍ-’·pžÏ(½·
-i°ÄÃ)
-–‡¶Ï	 ÏÂkBUx‰ù!€¿‰_5d‘•É%1&3Í<Oµ$„ÕvÒ1È(+®®ì»!FIv4'ÈãË#™3€ë“a54=§Ø`ñ¬ƒ*VÙ
-|HR¹|:$3ÇL³‚ —l˜å“$"¬¨ û„Wz;˜§>dKÏïÉ# Œ5`Ͻ¤¹•çÕ¯°Ós)œ¦>OÆX/ø>ûf”™ì»¤¼¤—‡(TŽ0P@Ý,Ò«IYA’ÆaFÝ#@ö–W"l¤ñ÷H”bäq€E䊜 >F-f3WYÅx—5B»Ì‡bkuTƒ5ˆvŠÆuÚÎA2ÊI%¡rD_€!²&•ú$‘%>ìÝcöÈK1ÜfrÖÈÐDê_Æ<Š*/ß‹äÒL1Ø×þà&;¢OOKµ&ÚÖ‰v,}_Éç-ÂE-…°èðÒHÝ‹>:b u6nX1$²3šÐ¬—”‡µ¾ÙuŽÐsÈP#,R%!"‰ÀI ³zðòncÊ’U|M-x9aõЭÑϝ’z™n\HXn?-êaËü~µêzÊãl´f}
-2Þ.Zû¬]>dï%9»vÞÝILçºNß«4¶Î¬±<IbMø|À¶¥š@ÒR©*b-}¼Ýú4¿ÈW°á›Ú°="ÞZ‹Ð€ñdn©Ù?—Œ“Æ€À,
-|}ݬ¹4®–6ûÐU™¯”Î*Á¾ÒÖ¢í½k<EidbO¯_9áÆþDífµ}¾f9Ù|ÿØ¸£'qŸKÍöè­\êB§Æ{ÉèB§:?jLB§KU$~§‚ÎfûÄ¢J}bżÿV}büȼ‡¦â‡Ç>«YùŽ³«^£ÂÜÖû¾ÚSvp+Ø©kINPÞz
-Ï-`ŠU¤v}-÷›B¨-—¤íòáùM–F
-¥ÉNÀêÁH_ýÐ×بÒ'Oú£ÙìÚÓ®
-Î2k
-2*¸¦½Î+i/*[©c7°É®6ª˜2éÈ“:÷¬Ò3Å´5Rå¾×½Çù~êòÂÕ.‡\åÙt¹oï]NmÒÁõú5I®ù¡06ThÐVtx'èCI&Ó‰·²h ð~Xî]öõ¥‘×[S\ØaÖÈ÷Ö³mD,ÔEï"…Š:ˆd¹Tå¥AñÖ…j9à‹‡Ta¡Ïwd-÷@»VÑ")³À©ó‰­Ô+xˆÐ–¾¸æ4^sìçYö¡ÁÚ®5ý]·+I£"ù¹k1ê@#²ÛÇVך‚BrLÅG£äd¯ŽL=¥v¹Á™µâÙ¢‰…y&¸ö¬1/Æ8/ª¯£µÍ'÷:é+
-»
-Ƭ;Âô÷ÒÂEªärg¯zÂ7צµ_€{›±"SB%3‘Ëv„r^?xQ€°3»wŸB'û_)‹†w¶/tOó›ÔI1ìé,Ç_s™C—°)c$°´*Þ‘,ñØÔ-<½n~¦ž7»sŒ‡–°xÐâäGsGd$~¬©ê›;¨¢§sâa4]’õü’èìj¸O^¦6iTÿe’”>¨‡ÿÀC1ûÐM_÷4@]Þ±ËYœïñ\éJe<uÖ.÷•ö„\÷a‰_ëj/+k_TáÒ>$zà S{„œ¡Oô%v2O×ú:fŒ<ôŸ?ƒ´GDß>ð åƒâ+xœÕ\[“µÎó?bŠ§ÙÛÖý’±1`‚
+ÆK¨Tȃٵ‚½¾aÀ•ÊÏ9’Z:RŸž™]R)ʸ­éVKçú‹úÅFLr#ð¿ò÷ÙÓ£_ùÍÅ«#±ùþ\½8’é†Mùëìéææ)ܤÂ&NÑ)g6§òÓr#µžÂÆ?)zôíåñ‰™bÞo¥K­ÙþÔFi£ÏÚèË6úcÚè÷môu}ÞF¿n——ã‹ÓåíòɱŸDˆf~ªÌ…ƒJªí·Û6jëè0èÔä´ÙÊö»X\z™Q¼üö¸]ÿ¹ÞüÏÓÏ€¾Òvô5SBnN”„A¡6§ç@Û{ÇzRR(¤œpé’S+;9£œ‹Q‰äd‚	«µœlàô8+ד1ÎK5B	c¼FnÏò¤
+fzRo=j?_?¬s>½Ò¨I_f÷єٕÛ‡u_óÚ`ñÀO¿M—™ßh"¬ã	Þê¦üáWj²AFúzBêÇÇf2Z¸ž=ÅåéIG:Hfz‘‰§…%L#¿#{'a´#»C‚š09ðöL»ñ‡¶‘ËJ‡Üü#F²Î×õg4
+:N@Ø1ëyÅI$Èra6°ýÍ1
+ˆòf]C•´Œ	¬îÛ/OÜ$Dð¬2O£™	kATÊv…E}´žõ'JP‹¶|ã‰
+qrÞnNdQÙ³&‹D번ÄàˆÔ=l?sJ+ùýbqYÅ@ªh{Ü’ õ[Y5h-á8˱&¡¬Ø~€“»É¸Èš¤¾°»w!wE)ÖäN[+ìU›	&¢+ÞD%×JË.š[svÄü'íÍ
+á	y¨ý¾¸£+•B¯ú( ‰æ Õ¹´Dż£ È õ„™tJCØäüŠkâWǁ@Vö±yÂj-4Ç7
+ëé3	WB¤êz\ÙÖÎÀW¯<Ëš	¡Bð5nJ8IY)	4»¬áïżsâ—zH+ýô³^¼}
+	ÉÛN8Ïg¼Þ[…4X"ãR˃ÜçÚgáµ@¡*¼Äüèßį²ÈÊä’Γ™æP
+ž§ÚÂê;én”W§öÝ­$;šS
+äñÇÆå‹‘ÌÊõi1ŒšŒžS+ÖÎá«‹<>$©\>R–cÎYAøKB7Ì÷I‘VTÐÓÂ+½ÌS¼¥ç÷dаç^Ò,ËóêWØÇéιdNSŸƨ/ø>g”™ìŤ¥—‡(TŽ5P@Ý,Ò«éYA’ÆanÝ#@ö–W"l¤‘øH”bäq€E䊜 >F-f3WYÅx—5B»Ì‡bkuTƒ5ˆvŠÆuÚÎA2ÊI%¡rD_€!²¦—út‘%>+%±èðÒHÝ‹>:âhŠqÃ(ÈÎXrB³^’Öúf×9Bc|+CµHy”‹$?gƒ9ÂÝnLY²Š¯à½4tÜÉm2>—‚O­‘H‡MùÃo²«â$gìöª6Øií/‚ä³éÄ.ÎL	–G/œ{ï˜R_ÄF«ˆ³qÆ^K%‰-l<óC3vq#vIÐK®a—†©Rî…XhQîEÈ™|”ŒÍ'ó_B•ØeâK¨¢FŸvÁšBcøí&áâ«ýcë+^D«ss§Jì¨pÖ+ê‡L9ÈMгVð½å¿ÌÖø蓶¸+Ý4f3È(©àÓÜHÊrà6•ßþKU˜}ÛíŽeÔuÁk9W’ÿÓF+3=ä$FÚ¤!:•©C«Á·”º7æ@ÃÔÕD‘LÀJPº”šR~2\ú¹Ö¨“á“ç+dÐ.(ÔÖùýjÕõ”ÇÙhÍúd¼]´v·]>dï%9»vÞÝIL纞߫´¸Î¬±<IbMø|À¶¥š@ÒR©*b-}¼Ýú$¿ÈW°á›Úº="ÞZ‹Ð€ñdn©í?—Œ“Æ€À,
+|}ݬ¹4®–6ûÐU™¯”Î*Á¾ÒÖ¢¾k<EidbO×_9ëÆþDífµ‘¾f9Ù|ÿظ£;qŸKÍöè­\êB§Æ{ÉèB§:?jºÖžEú|ìÀZ*èlö±c,ªÔ1VÌûoÕ1ƯÌ{h*~xìnÍÊwd˜]õ掰Þ÷Õ[™øcO]sr‚òÖS|¾+
+É0Œ’3¾:"0õ”ÚågÖŠg‹&"æ™àڳƼ㼨¾ŽÖ66Ÿá뤯T(\ì*³îÓßK©’˝V¼êYß\›Ö~îmÆŠL	•ÌD.ÛaÊyýàEÂÎìÞ},dì¥,zÜÙ¾Ð=ÍclR$Å°ç´ÍAd]Â>¤Œ‘ÀÒv¾xG°hÄ#z(%'þ®yԐ
+{>¢éñ[3Û(ÿ1’úŠÃë/(Á˜ çžÐº€®AM	ZðÔ"9v•ïË|p\O-^§×ÍÏÔófã¡%,´8ùÑ܉«GªúæªèéÄxÍC—$F=¿$:»šîS§—ƒ©MÕ£$¥€êá?ðPÌ>tÓ×=
+PW…wìr§Å{<WºRÙOµË}¥=!×}bâ×z˜ÚË
+ÄÚ·U¸´‰8ÈÔ!g¨Æ}‰ÌÓµ¾Ž£ÿç"íÑ·<hù 8Àž¸(%ÑÍ^¼Èã̲·=DÃú†ä¦œÓ‹Ê‡(}ΫŸD™‹ÿ}§×Žc |oöwõˆ2óÃ!Ó¹yº}w£ûX@ÿmŠå¹T%ò·tò%²Ég˜=D—šD=Á†±6†;à,96ö¬'Húð+²¦³ãkÙGÜíµN–³5\Q¾ùŸv±_áFéb¯£÷º|9ßû762JŠß®÷ëùQã{&TˆõÞïûmôë6JH¿8ÐnxÐAú•>wLÎþ{
+ߨn¯_²{%ø˜å ¹á.KŒÝ-ïà«~Slõ_ê×¾0FŒ¾6úëó–iè“oÇÄV°Ñ,×û4%Ûý(]S·9»‘(f~}•ŸûGÿÒ3œendstream
 endobj
 40 0 obj
-4823
+4829
 endobj
 44 0 obj
 <</Length 45 0 R/Filter /FlateDecode>>
 stream
-xœÅÙn·µÏBþÂEžtßñp']ôÁŽÄMâUA’"°%[v%Ë«d»Eÿ½çCžCGòUœ"ú\®gßæÍjÄjÄÿ¦¿/w®?t«£w;º«ïÊèxçÍŽ˜þ1N³W·öaô«0+­^í?ÛÓ|¡ÔàWntƒø˝Ÿw_®7z~tn÷qº`ôîizDЧ}KЁ º;¼ è{~C^µûÆá͵F´›.Ÿ"P
-¹{€x@À3¾)üîtý‚ÓÞ"öû/»e›pRV½à«2Ýô=
-¯¥¡Ã?÷ÿ±#ÇÁûQ¬6B®ö{„”óö*:ÛµÅûM‚Þ'è}‚~OÐ;å2»_·;Äáþl.ïjÜ%à¯4|X°µGÀ1?ýþ¨,Úo€qѯü-¸ÇÏ,ÃoÊN÷š;ÅE?t¿]ý²&èßÊ©uý¡0\¨6vµ‘bð*øD½›ké5Ži£@ÔœC6§¥‘(è‚Ú}¿£V6΄MœP 2R
-VI¤·R~ÐÚ°‰Ï×Ò&ÀÎÖbÐÞŒº,–a÷°-¸÷ÇõFÂÞ
-žø‰†7âup"¡©Ö=¡'.‡«;N¬ÎTÌÓ.ShµB„2­pÜ€w}Þª€Vñv;ø´Çê¯
-/±õ$øï*ÅAãua±‹Ùª®›H!=Œî\f”ã ª½(ìªJRêÑrÎ;AFЃŸœ¡œ¥;ŒlϚᐯe¦ÕÞí>C \HI<SúŠUÒñAæ€ "bڙ擄OäCi½+pOøRi‰tÆNo‹hËI0¼íKÜSv¥òìÊÇxÈj0l&ÛþxÈp÷|£KçÙ°ªF+Ù1´7¿Š§Ôž‹'Qí´àú¨l³…|‘2zØ•¯7=ãÌ[ ïjYôT“ç2óª+–€P#Àš¤š iè`‚”ƒÚ¼lýÉœctҝ𮕵‚—+m%bA©Õþ÷;ûýyW
-À±C/aÂèr#øSJk
-ܨáà$¸È8XëaܸÁ©ÂâE@ã
-)"Z-xÑ
-þcd£¥ËDG(ëã8ÞÊAp͈ë‡5èP㣲µÇ…Mº¿Ü·’´ý$ÇÂ(3i_ÔÁIfÄŸ’Nfê™)b2è\$è¾¾ëMaš¸v6<Z•ðE45Dv(Š¨-©¡ª=ÙIoèQg-vZáÊ$FؾZ¨ÉFa%7öô3:°í¸ÄHk„ð|ÆD·]@{&=ã€Ø7cTë®›Âx/',X@Í™–	~>lÀ“ÄʶQ:³2²(^›D¥CNˆòŽ‹]Ÿ˜9»¢’I´–7jÙÁ;6“Ø:ñòtI°ýÌ”$ßѪŠd]ÍIÌÉ8:?ÕÍ„'¶ÂH>ä²ûM÷g$yU#ŒUMGÚ”|á†5²Œoœr	ËŒ^`장aû7Í</Î0mVX+óS°¿]qFW[šºWš¶G41Îgä¢]_³ˆ…$02³)1>33[M·*{ž¸?žÔä²ÁÇP@¹ß®G³NbØ©˜$oÿç&Zˆ?“(²M™€÷ëӍIü+MÃv' ZŠÊ¸ìÆ­¯RtRO‰J½^~¹Ž+òi
-æ¬ê¥½å™×¼Ú*ãé¢k«•T$Lr&sÕŒ}QŸÝÈ;¹–ªq-§6 O¸Òi£¿éù£04ÇäSï¯7ŒêS.h\zÇÆÉ­Y².ÆY-–‚ïL¹
-
-áà™{nÑ»›Eñ®ü>Ò‘cb’`´€YÙöLãÃéòr÷Q¡Ç=œ' dS˜òÌá÷w}4%Ê>ëšhqAÜ/¹¦$`£Y2k¢ÿ„ŽB1ûÓJ‡™FòÉX:þó
-Ä‚ŸÁHÝÏIp¢¤º*~ff5N•èAcŠ†
-;סÉ͉:¶œt¨ZpûÐÅ``™3P_é¨Î"Ùíô-¢jñÀš¢x_/Šß_91ó*ðgŠß
-y†5RLÉƸ|ÐdãRù€™06|8Áº„Â)WWûNyntþdPûS	¡Õ±9WÛ)¼@]÷jíž~¿®§æ0²Õ˜ÁM™©»_$å=¥ä¾LþB#üû”ıD÷lߘ›íÛVëŽi.«ì±*àAwßþfŸh8ÌvÀe©¢l…†Ç%ÿ¾ûœ»½2àû²hé‰yÑq[Œ«¾êU>v1ð²lõšg@“¼ƒ¢'£Îî—²©s˜_Åõäx^®òSöj“w*2ͪ€oÛFèÇïz·;÷°F,r%„Y¯·<ù ŒÿN»»"ÿÍY¦™û”æ>žÖÜáþl‡Ä¶™ÿª§eúóc×…*4u¸æ_ŸaÙŒàxEç#ÿ>ΆxAAÐkS–ìçlYä«1±`À+ð€€g|SøÝéú§½Eì÷ŸwË*6ḬzÁWe »é{^KC7†îÿ}GŽƒ÷£Xm„\í5ö)çíU"t¶k‹÷›½OÐûýŽ wÊev¿nwˆÃýÙ\Þ+Ô¸KÀÑðaÁÖÄü@@öû£²h¿ÆEÿâoÉÀ=~f~Svº×Ü).ú¾{üí²èç5AÿR†H­ë…áBµ±«ƒWÁ'êÝ\K7¨q4H¢æ²É88-D90@ïÔî;ø}µ²q&lâ„‘‘j°J"½•òƒÖ†M|¾–f0^p¶ƒöfÔe±»‡øj-ü ‘Ô ƒ#+hÏaWñ°ƒO{¬þªð[O‚ÿ®R4^»˜­ú躉ÒÃ(àþÀeF9N¢Ú‹Ân ªÄ ¥-ç¼cd=háñÉÊY
+¹ÃèÀö¬ùXfZíÝî3ÊÁ”Ä3¥¯X%„0`n+¯¶@ŒVÈÑR‚¡"ÈËÏ×À‚J kÀ>ÖZTY#l¢¤G’ƒÑ4û‹rÌ;¸†–q—€£ŽXÞAðØ„@–¡´žΆåxÜÉ(:;ä„6ý۝',IÂBûGE❁
+#ځU°ì%¯ÒýDg4|BÃ
+î¥Gc]ôô @E€ÿãGÎM`Ô^”ÜA/ZaÁ?ð`Œl´t™(ðeý`Ç[y"®B+#ùd,ÿùˆ†âÁÏ`¤îç$¸GQÒˆ]?3³‹§JtÈ 1EC…ëÐäæD
+[N:T-¸}è‹b0°Ì¨¯tTg‘‡ìvz-±h)´Ò íÿ)ÜŠyÇÐTÔÀ^Â."BDØʸiôÜ&Ñg·Öà˜š4À·ÒâªÉSÀðXeTX賐H¼&¸{s@‹ò+¥ã[M©;˜Óöÿ´ö@iéÅäjOáxW±Ф‡yà&PF3TÌE¸HLÌä	¥ûyÆ$çDž¥„HÂ@`ÅÀÊfÁ²ÖXl‹ƒ/R\,º¹~Ú½çÏ!³)ŠÕ×YîTÏ£®eï¼Ìíé-0µX¢j›ôxô`-ˆ÷ñ^HãšÚ„²àóÛY®²ÉXæåK¹e­Â ‚eÎ6ñb¡„Ÿ…(M
->çËG¾Q¡@*xÏaóÚ˜õHU!5ñ·XÍf©ü¾{}ÀÓQYiÎ(¡RRbB;VùÒJ©iÀ1æî}ÏÂ2péIGë5£ˆö8
-ÕŽ¦ªŽÓ݆†ÎnÀÞ%0Ïôm¬ÑÊð´;Z!
-ÇzÓ¦ÓYNW–Dkb}ɤ蔝¹$Â`º-%¨»ávNµxkHüù©*0%Üd?{¹Ù‘BüIǺ”‘óN=a#xxu²"eýO'ÆQ®kc»ùÚµö>!¯’9‚e›Ë´óK›¾‡	zƒ Ž c;ŒÈÏêé2§R†gÂüµÔZ Çy¬é³éå/fE³’‘GØ,†F†lØ3«Mv<ñ°{[:œ4ƒ¿,xu9çìO %`m«{7.Y_•PfP£2™“QOŸõì`®H)’ð`´wy¨ÝõmÖ/›|oÃÒ™ê.¯mçyûÛãn„vHÐo[£Íæö»Ò	W†JS\eÔsìrÎøìÆZ=ï5Ö6ç·Á{÷ü¯
-&+¬^0±¦k¢úî²áº-ÚúÌå½#SsE·”Ä,Qnéж›#fb;\7Ï&£<=.¥ÖWˆ…¨ _VfÝ´%é‚nµxÕxôŸB“èFóRõ¬2acÒ\ÕŠ•Ó £‹Noj¥0ÿ¯2š	jWå]¬Jù™„CùI9&ÒTMjc<álŽñ<:‹åFŸÍÂ¥Ï"7urLv+ÓB½ÚO¡h7ˆêËP{Kϳ/˜6#ÝYC捉2'UÜ”¡]-«±Ïû?¨õøCwnÿ›vð×íiMëñ³žB="àY²S«lVÖ—/øIêÖåí;âû:ŽU<å–¢Þ{ÒíýVůüûB¡I¹0Hs©6Û"­ó
-°äÚäuWWYâ#‚¹b½Œaa©…:}t›R Õëž«Îa·Shtu$Ü5Ÿ™Z÷œ¯ô;õV•nCYu«¥8Ä`ÇH–rjJ7MÕ	tZ‚–üx›ˆ)œaÊîyÏ«+÷г@÷¬i	êyt¶Ñ—1+õÁS¤@½¯ë4]œoŸ$ÓV
- U-ñ,ãnö;!«Š5`ZlO6=¸[œ“»¸3²fŸ^E÷®ÿASÿwi.ûòè6
-÷*å¹·¿ó`çÍJÉAǯóà7¿O‚0¿’ÀÏø÷àåέ;;×ïü°zÿöìéÎõŸVbçú·ø¿[÷¿†?wn¯þ´³wgõ`˵°]*<ø }
-ÈìÐJù?l
-U„þØ΍Ãý2aùlòñÀØ‘^?Qå>=e¯¥`½}¡ÍSØžJNŒå¤Œ’»eÆ)/·”L“˜,suGÎL§ürž;gzåg*0÷9&9›·ãèI¯­jf0ÒÇ6ÌZ²„iÔJ01þÝ»åèç;‡­»%ôïÕuÈ“QCs™f2#·Ž_J3E¾¾H3],¸ÊÎÁUò÷\
-‡-¬a)íQÀ²Í÷ÈìcýôS¬³ƒ–P
-S7Fðf‰Yz,JB¿n> œÛOn½oéçv?C[h8í§ÇbÁ¿Zº´×áú|*wEÑŸá?ÎýŒ›÷Ã0Ý|Ï:õ ˜ÝÿLiÏ;W®ÓÜëùE‚k¥Ø{˜ÀÁþï…ì›ZDp³/¯s[Áå­Ž±RíCÝ_ ô0kýÏ÷j1T,މЍ4ëÖç\¹Ý*²Š]_¯^p¹äÈw¾c™ÊšzTMM
-ÏQf)`Îeå«ÜÒƒmhÛpÝâ7³ð˜¥Åg Ì_¬@xiŠ¥â®eüø¥4VÍ•‘,†÷,4W²‚ùF†KxäïmÑáíGRÌsX¦½¤‘ËŠ>ÛEðSsû¥Lr7&²®ÙýW©”_V2_†AÉÕ¿°(Âlò¥‹Y°ó?“7Œ;endstream
+±h)´Ò íïnżch*j`/a‹N!"leÜ4zn“ˆè³[ë
+pLMà[iqÕä)`x¬2*,ôYÈ$^ܽ9 Eù•Òñ­¦Ô
+ÌéaÛZ{ ´ôbrµ§p¼«XhÒC‹<p(£*„æ"\$&fò„Òý¼?c’s"ÏRB$a °b`å
+³`Yk,6ˆE†Á).Ý\?íÞóg„ÙÅÀêë¬NwHªçQW2w^æötˆ˜Z,Q5‹Mz<z°ŽÄûx/$qMmBYðùí,WÙd¬óò¥Ü²VaPÁ2g›x±PÂÏB”&Ÿóå#ߨŠŠP ¼ç°ymÌz¤ªšø[¬f³T~ß½>à騬4g”P)©1¡«|i¥T4às÷¾Îga™¸ô¸£õŽšQD
+{…jGSUÇénCCg7`ï˜gú6V‡hexÚ­…c½ŒiÓé,§«	K¢‰5±¾dRtÊÎ\a0Ý–ÔÝp;§Z¼Ž5$þüT•
+˜n²Ÿ½ÜìH!þ¤Œc]ÊÈyŠ+Q}wYˆpÝm}æòÞ‘©¹¢[Jb–(·thÛÍ3±ÇŒG®›g“Qž—Rë+ĉÎBTÐ/+³îÚ’tA·Z	¼j<úO¡It£y©zV™°1i®jÅÊiÑE§7µR˜ß«Œf„ÚUy«R~D&áP~RŽ‰4U“ÚO8›c<ÎÇb¹Ñg³p©À³ÈM“ÝÊ´P¯öS(ڍ¢ú2ÔÞÒ3ÅìË+g˜²{ÞóêÊ=ô,ÐÆ=ë@Z‚zmôãeÌJ}Fð)Pïë:Í€@çÛ'ÉÅ´Uh@$>(Þò_¥+Û3Cɉ‚±œ”Qr·ŒÁÂ8åå–’i“e®îÈ™‰á”_ÎsçL¯üLæ>Ç$gó¶b=éµUÍFú؆YK–0šA	&Æ¿zסÝà|§â°uסÄâ€þµºyò jHc.ÓLfäÖñKi¦È×i¦‹W9Ðù ¸Jþº‚«áñ H,(M‚ËtÐ#zÊíÏP§ÆšßäÒê™ «K³rñté[ýŽ wÚÆá·WPG–g$uTÄf‘RW5¬#¥=
+X¶ù™}cÌ¢Ÿ~Šu–cbÐJaêÆÞ,1KEIè×Íç„sûÉ­÷-}âÜîghm§ýôX,ØãWK—ö:|X—Oå®(ú3üǹŸqór¦›ïY§³ûß)máyçÊuš{=¿Hp­4{Sc8Øÿ»½cS‹nöåun+¸¼Õ1Vª}¨û”f­ÿÙâ^-†ŠÅ;º‘fÝúœ+·[EV±KbáëÕ.—ùÎw,SYSª©Iá9Ê,̹¬|•»Sz°
+m› endobj
 45 0 obj
-4200
+4201
 endobj
 49 0 obj
 <</Length 50 0 R/Filter /FlateDecode>>
 stream
 xœí\[o\·~
-ô/,ú´dÞ/)úЦŠÄéÅV‡¸¶ä‹ ÙR"Kµûë;ÃÃː‡gWk;i~ðñr8óqnœõ+ÎÄŠãŸô÷ÉË£/¸Õóë£H]‰Õ7åéüèÇ#‘þÁÓèÕ_ŽáéW+­^?;i¼PŠù•ãŽI ¿<úa}o³Õ,xîÜú6>º`ôúi¥¾ªÔוúm¥>Ž%ÔçÃy‚G+™Õzý²ÿ,>¦É”:›,>âdÁ3äúO›­‘’y(;Oû]ÄyÿS©—ídéñ¼Žeûx óÞ«Ô™Pé޺ϾÝ8Æ]°®½rQ
-ø‘NMÄGëòÕ£M%ÿ±<þûøë#!WÇ÷Ž?û!) ªe¦€žú¼RŸö2‹T"(‚ÓJ=­Ô]è›
-·´[߯ij²Ïë~$Ç3íÙÕ—å«7•ø¶|ô9
-g&¸Åï‹¢›	Êã58v'jðñ~{V©×ñóɦ%2î¨<Ü ^¾x LcT4óž‹ÕV
-æUð«ãS0(Ç›-gÚ£ÌúÅFÀ£áqa¥<Ó
+ô/,ú´dÞ/)úЦAƒÖéÅV‡¸¶dË‚eKŽ,Õî¯ï/Cž]­/i†áƒ9<äpæãÜ8ëW+ÎÄŠãŸôïÉ‹£/î»ÕÙõ_ýþž½:qÀ*ýsòbõ§c$ý*°`¥Õ«ã§GÓ×b%”b~å¸cè/Ž~X½Ùj<wn}]0zý¤R_VêëJý¶R
+ÇêÙpÞáÑJfµ^¿è?‹i2Ç¥Î&‹8Yð̹þÃfk¤dÞÊΓ~qÞÿTêe;Yz|^Dz}<y¿®Ô™Pé޺ϾÝ8Æ]°®½rQ
+ø‘NMćëòÕÃM%ÿ¾<þûø¯GB®ŽïöCR at TËL=õ¬RŸô2‹T"(‚ÓJ=­Ô]è›
+·´[ß«Äó²Ïë~$Ç3íÙÕ—å«7•ø¶|ô9
+g&¸Åï‹¢›	Êã58v'jðñ^{^©×ñóɦ%2î¨<Ü ^¾¸/LcT4óž‹ÕV
+æUð«ãS0(Ç›-gÚ£ÌúÙFÀ£áqa¥<Ó
 !
-&¥æ%"™äŠdW™rÆã&ãZY *¦µu‚~tUfš3‘j€-÷ORW—–iîÈ”gÎœÖæ|¹Å¥3™(\_Ô×ÓœAƒ“*%…O,¹5‰`r*qÚ»4Qƒ
-¡[ÿ®pL¸K,áô¸w¦“2ïSzE…CX‰L+ÎE’.E˜Nßéã‰Ô ,€æ÷ï™Bh3×~DÖ?Å¡'î6­ï`gj2:´2CôH-ä£/Qf†hy’™pVÁêÂ3á½ÈÂ8¼žŒ¸ÞVÍ v‹v—LÐA‘ãÞ¤bÖë„«Ðnáì0îm•üx”Ì.Æp"¸lgGÉì=*ÈülX‚ÍëïðIp©×ÿÜl-ÀJHµþC‚dˆÖçU´u¥Šû‹aüZXSXß”¯6Ò0ã´ º¤¨‡µak6b>‘†ˆ‚q	°R
-¤”ß×û3•§Ô oq¢¸]§Ö'sõ#rRÈûÑôuC,Ó&»ÕC-U×'unâ¨+ø‰¼¤0ºoÈh‰ÄŸ¡G‘pDVLW=}þÛ‰¸·:ýM	·²ƒmb ²Yý¶„)³-'8EÉA:d‰Äˆ'•J”Pg½êÀ‘‚5Áæo*Ϭ÷ó¸åÃøˆqÈ*•ä)ÃHÉ€8†Öš7¹PLÂÖŸÕ2€Úíûi€Ótì!N€¤¡O
-ƒ1üŽ#'ُ[4ü1j—bwÀ	ï;8W_Dk&¨±&Óâ–¢0†Ú2yyLí¸ôÜ-¥<‘ÍYôÃeŽ¯IfóvãÁ†JîwoÛ&ëÔ\fÛø³që7}äÖœDndáW%Bi‚¼‹œRÐÊó-q¿–5ÅèSý>£JÇÂ[z«¿>%HW*OX>ÇuàüB<Ó{¶8ýyã ÓIÜ}lFÄÅ š§ÔžΪµjž—i¾Üië›ó5Y}Ì÷æ¤x6Ì`•íX7ô2r*ÎÚ²ëd-ê+>ZZ>£©Øã›þ´÷u.<@©4</.§r¤œyÕpó¤·}1Ž˜ŽÛ“8v°wHTêÃúø×Ê)ÞÌØÁy/†"9é}n;Δ.‡’$–†íxô*RÄU§£}ê¼gûŠÔÙ¾úø€d‹D§Y¶z­*ÕÏÂÜ"ñî:Á&cìbŸÄ¯ÓÞd¬g3<p“~6œ÷§¡J^§Õ¦-›x÷AÐ÷§Ó
-³4ô}¬by§¬¡…§iM'´¹Ûò-B«ü¬o_Ç]8ñèFðþ\Š
-|èX¬ªŒRWuÖš?Qç«¢c4œ"ĺqÇ@­Y»Ÿúf3\2ßÃ:Ý]$ppxÂÕKŽz'†ík6lï~CuÖ\z3ËÁöˆ1¤+Nñ8ñÀv´(NWçû¤òj‚±S*l†1aèd¤ÒpZqÒtD­Hª¿VûÒ2ø¤¿ÇAä÷ûˆv"¬jœ&d'η%¾ž5Øo½GBjšÞØÄOjµ\f½Êîë|Ñ}^•ø9Î)™žÎ^¾Ú{^\q÷~bÏÜAó±×±ëËÉMsû5>èØ¥f|ŸéšZpQ®‡†º^ú›^åËåw—9ßx¦…ÞÙ	âØ5£	ÄÓåXï¸bG(µ©‰VÒ;Š·Ïè½@ÀIRãÜwŒ-6S†H]S8v€œ––pCz©É'½U5Bi;“7ÃpÔÅ·Å)ƒ|$w ¼ã½éDŒ¾P›Vûm«WkƒO
-ÓŠ†:Ò…–¬Îå¶M×Ã6ÿ¤A/_¥8­Ý}ÿ“šÝµÐ“1؝–1| ÷˜`
-rÔ:
-ñýŽf9Äúø¬ô-l0r´¶;Øj—ßíg)‡D
-íÕ¼yõ^$¡¸é­NJò69ô·8¦F,ÑÅÔ’G.ÄÔ) :ÀªN‚ÓbÝ´'c—Ë͐ý¯}ªë(¿è$Í};ÑýO6Y£4
-L¿©‡ ÌÂY|:§»S3ÆÌõ“I¼ªôÞ$~ñ@u%ŒÄÓ"ñ B˜Xû}ܨ˹¼ô3Š¢Ô¿Ç{±§rŰლP;)lÏ~ÏÖ7ÉïÙD_šlWbÓ òÃö%êúËO–^û¶òGC“NZÖHÜ4ô$nwå=¯kòB9}
-û ù°àã8Phüªnþ›J}˜=ì]øLj;øŒ•	Y©l'Š€Ø	‹XWû¸±(ëX	ÅûbñÝìâÑw_ú
-y¯½Ã›‰ÉXrÏ[Ã%(RÎR½EÛ$ÖÄ=ë€9²nÝ»’ª»H_q³Ùg±ð¢«‘‹ ‰+ʶ`a g
-|)7¬-¦m•caãr1tÅÕ-†®-]DÉh9ó±QÄû£O @krR恟ú{Ô¥@´«c¤÷QtÜÍ#4†]µyµnÇ"uOhÇ
-è»FúîTiLH‚ŸSõ	ªïTâû~ßÐ8òÈy£Ï!ŽÜIûÓ&,?[wP#æÊà$~.3|7wA¬p®R·WD
-VùEyÈA½pXrÕÎÌ
-Óí¹È_Œ¨E’Ùÿ¡ïÜÉýü›J½»Ÿœ2
-49xD•%ÿÍ‚Â1÷ŽþþæS²!endstream
+&¥æ%"™äŠdW™rÆã&ãZY *¦µu‚~tUfš3‘j€-÷ORW—–iîÈ”çÎœÖæ|±Å¥3™(\_Ô×ÓœAƒ“*%…O,¹5‰`r*qÚ»4Qƒ
+¡[ÿ¦pL¸K,áô¸w¦“2ïSzE…CX‰L+ÎE’.E˜Nßéã‰Ô ,€æ÷ï™Bh3×~DÖ?Å¡'î6­ï`gj2:´2CôH+ä£/Qf†hy’™pVÁêÂ3á½ÈÂ8¼žŒ¸ÞVÍ v‹v—LÐA‘ãÞ¤bÖë„«Ðnáì0îm•ücx”Ì.Æp"¸lgGÉì>,Èü6,Áæ…õwø$¸Ôën¶`%¤Zÿ.Á	2DëYm]©âþ¢@¿ÄÖ7eàˍ4Ì8-ˆ.)êamØš
+„˜Od£!¢`\G¬”)å÷uÅþLå)5Æ[œ(nשõIÅ\ýˆœò~4}ÝË´ÉnµÁÀ.X^œqs3o©³(¡Ä/M”Ð;¿ëJ%øQ?C?àïØä´8¿'t…âäוj
+•Wbó˜ýØŽÐ@L¦ý#‹èY¥ÞTêU¥~·#Mþ¿<^}GçÚ-¢ÏS
+‡^,H«¸É±8©ó3ŽnºËw“}ç‹9@ðhϬÑÄõ=yÎt<8&[+0z`çÏ©ˆ3yj—PI*08+ÔÎßnГã™$ÄÉ^x1‰]K0'¨o´™Jɼ¦—ôp^VÛPÏi=ü+O<úùä2ƒ„Ùtv™IŠZóê;C\ù¢rëÉûª“èä€JhðŽù¨ã—ÕE>n‚«™#°K{í£cd+GœöÄ«Ù>@¡êú¤ÎMu?q€—ÔF÷
+-‘øSô(΁è‚ÀŠéê ¡Ï»#÷V§¿)áVv°MDÖ!«ß–0e¶å§(9A‡,‘ñ¤R‰ê¬W8R°F"ØüMå™áÞÁaW£ül˜1Î+7ÆÆû¤À÷kYSŒ>Õï3ªt,¼¥'±ú+àS‚t¥ò„å縜_ˆgzϧÞ8Ètw›Q q1È£¦Ã)µ§‡³j­†³2Í—;m}s¾&«€ù¾ÂœÔχ¡’ ë†ÞBFîQÅy@[v²E}ÅGKKÃçô {|ÓŸö¾Î…(•†çÅåTŽ4‚3¯n÷6 /ÆÓq;cÇö	òýJ}Pÿ\y ÅÛ;8ïÅP$'½ÏcÇ™ÒåP’ÄÒ°BåAŠx¿êt´¯@÷l_‘:ÛWl‘èá4ËV¯U¥úYx€[$Þ]'XÀdcŒ]ì“øuÚ›l€õt†ÇnÒÂO‡óþ8TÉë´Ú+É‹^-¤ž ?áäNöãäçWEç*5|BÈOiI~~n琜‘à&[oÞ7y†q“p n2Ü>nRT¶Œ›yTv5DÈ/Ïí…©iò…û™Ÿ2XîW€ÿ	7ÿSCÚ[Þô¼Ý=kžW¥Øˆšª?j…udm%fóJeV+»Dºš·Ì8a’Ä"”¶ë/£2v`m‰Y@,Š%~»QŠ)à€y¬œ«¤G1Hf´Ô¤—¹6´ô^»Dä:Š?Ïx†7ȁIaï>úþtºa–†¾U,ï”5ô±ð4­é„6w[@c%žÚL­ìŸ6œäDzR)^ôh¬|ªÕV8rCXè¥&±‚{[µ7­‹×IͶ¶Êf=Þ˜(ÃŒ")‚{ßÌ©¼aJ*ªð›úøxƒ*XR9¼þ_cw‰°±hœ‘³[p‘T|eñ×ÈYïí”fÆÇ¢ù¸€äyÙî¨Î¹-2lêÂãn¤©@âšz€i]ÚÚzû¬
+A(¡å+wn¤IxE룵ڸX Ën¥i/l'Žè¥ÖÛJ›á]&¹z=i=Øåf$°†&ºK3Τo_U€UyS{‰îdoW+V¦.Nø¬{¯2&õâéòƒÝ0<õ!æLéCÂÚ­U¸þà’šxâÜÑ*q%NÖJCŒå†ªø¢Œ|‹Ç$^à.wÑÄ«™©{)±Yº—Rÿ‘
+ìšK ­‚Å*?ëÂÁÛ×qNF<º¼?—bG:«*£TàUµæOÔù²è
+§±ƒnÜ1PkÖÃÙ—Ì÷°Nw	žpõ’£Þ‰aû‡
+Û»ßP7—ÞÌr°=béŠS<N<°-ŠÓÕù>©¼œ`lÁ”
+›aL:)…tœVœ4ÝQ+’ê¯Õ¾´>éïqùýÅ>¢«§	Ù‰óm‰¯'C
+vÁGï‘Ѐ‚¦7öñ“Z-—Y¯²û:_t?¯Jüç”LOg/ß
+í¿½G¯®¸{?±gî ùØëØõå䦹ýtìR3¾ÏÎtM-¸(×CC]/}‡M/óåò»ËŽœo<ÓBïìqìšÑâér¬w\±#”Ú…ÔD«éÅÛgôÞ	 à$©qî;F+¨°ª“à´X7íÉØe£År3dÿkŸê:Ê/:$	GsßNtÿ“MÖÀ(MÓoGê!³pŸžÓÎÝ©™ÇcæúÉ$^UzoH¿¸¯ºFâi‘x!L¬ý¶ endobj
 50 0 obj
-3580
+3581
 endobj
 54 0 obj
 <</Length 55 0 R/Filter /FlateDecode>>
 stream
-xœí\mU·îçU~Ä_zo•=¿û´êBHBK	›VU[U»Ø%Àò’ªÿ½3ö±=¶çÜ»»ì¦­T!ñõëxf<óÌøü´±ñÏüïã{7¿s«'¯÷BíJ¬þ˜K?îý´'æÿŒsëÕgÐA˜Õ4LVZ½:øaOÌí…öƒõ+7ºAÂ/öþº>Ø쏃öÂ(³~ºP4£^oö••ƒ‹bRvý~³/9
-¯Ö‡›}3x?Mjýb•Ò*½~™û?ߌƒÓÒ„îJùA+·~
-ÅaÔÊ®ßlÔ µ›tÇ»õ«P’Ò(ò3v10¼ó¤÷³0¸žœ˜çv&UâŒÏËÏqôIƒÃ+LdøSÞBÑ9#¤™ôD·FÖ9“F=ÞFҨѐ•œæ͝åî¸
-=ù=íþ¾t'k»Sã(æéqMdw¸<‡çôú]<ÅQ	2=Ý´œ/üúq™´ßɨ<Ìÿ÷ƒ?ìI‡àšƒ#à’8ÔóâŸäM=‰ÄBÑå—ߏðw78£Óü8Ó)×tyR£ÃUìKo8¡Õ¾q!ŸÐ9žµ‡#*:TëÔF-=‰’è&“H‰µ§…——I¹Ìê”hH)ë«…N*-$‘_4pR-^RÕB5PN§(ÂzóŽ}5ÕIÖgG‰ úb·‚/u§ÔŒô¬½öd#Í`œ¤½]àN£é<ϹŸO#‡Z_dý—âeÍWgíø"f4‚ü~ˆ
-Rî@Œ¥&<•tÃj¹~”ÆíLyéÀ¶ó*±”§Ž¬</1+ÙCQ£S”I
-ˆ“ßϵ%@D	‡Ôç¼ùôÔ@Á½˜É¯îíüæ¯ëû ¨ÃäqŸÇ¡ò¢ƒøεïJíi©}Uj„¢·°­¨?~°ÉÊõïaëR8÷~iЍ먭nÜPlƝÛ~QjKñ1;.?؇Rº°Û«ƒ#lE†C¬ô¨ß°Û¹:é–v©ÓÒS§KåßÖ¹×
-:Uª|ÏRàEêe©|%˃ä;—$‹¬OÅSÔ „7B	×ûß6¥ÁïrƒÙʈ#ÕºüË„C޷ĵ÷Ù¶G5u‘5ƒÁ|Ñ)BQÌüè
-åÇ“«äÇž…š¶Ç¥ía7[³†
-køI;º„÷™	È&_rùǯr¯j(B°ÔI4#…NŸ¢1-Í„pz‰oËöXù!'K\•êVNýf(·WqÙz
-¿FdÃZpP°cŽ+„_y7òåBQ;Ã-ÒÚ†³âj³’/»ý¹°Ñ÷»ð|  ?
-Ґôþ5¡ŸŒo¯-x±d.Ìú'¬rÛ’$`C åéîRæxⶳæJGÒ³WÄosï¥Àˆ3Ôp§x`o[‡÷ËBí׬Ç{ÂÖ>aÇ}5{f!y8)ž©íË0rO¹.üš_÷Å–xlŒëöuŽ§TdH¾ì’»OÖMpÑ- @f‚åXºhkŸ°XÁ:x¼‰ŒÀãM_ì:‹[Ùÿ'Ôû÷ùM©|œ+	ˆxFeBP'\§ã–¤ç0ør
-hlåä	!4¾_Ú|^ŠdŠ”¶ß•Ú‡l·”âƒ9q”ì-æ³@Ôz÷JåÝx´ x˜Cf_Ñe¥NŸ×”¡a4p圙ív7¹8³*Lsovë׿Iŵ-¿çÞÌÂ…‡M•†+Í^"›;?(´o#T.®þ(o)FY--6è/Ô’uw’lÓ:¡A'{y9TÁ‚2S«`}aC¢²SŠ!¸AŽm JmŸ]ªkõ¾³šÌ®
-ŸäÈÎ\¦êeIqé{÷†ý¹‰ÈŒ`½y× 1¦+(†Ïù Þ@õ|G	=(~Wb
-ž>û:´Šî׸L~@‰CÕAÆhEã}×¹Õ)ŒˆÁ å:W\×Y%ì“£“Ö¤–3ãU7Ñ+³•ßy¬–‰C¡„±C?Uå<ÕÅí$Ë~y7>¼¡ÂÃe<¡.øÞ¸'ÍïÍ;§'ÈÓO
-½Á”“	_¨Rv®-†²æ’hMÞÑÂ3¹°ŸËCRÛ`@]„ÓÉ3lÌðÁWkòŠ?ÄL*±ò&CV/ǐ)ïo?t™-f¬’“ƒJ‘ú≧Ey\·ô”1¤iYš«1k;åz¢aJRÛòLƒ]äd6UM¹Âìzï7GPâ~ê
-ѳó‰M¾V¾áÄ$åå¼VÖ™0!§4^2¨<´wm¨%CH±‹4ƒå6{[жÉ`!Á²ûÕmxç`ïÛ½ŸVJ:|ä-Äà¾Ó­7ýyGŠzSë/sÛåýMjF¿þýMäÎÑý}ÇîïÛ²¿ïÙ»ó]ˆÀÁÆœ˜ƒWsëãMHð>@J 5Ö5ÚyÔƒ°–Gõ«øQì÷î–¬š9?O‚Ñ_Ä­“è`S”¤qTºmG Á(r)›„2°¯,õÁv%A¢6ÄßðÀe›f‹xû½(Áß±Á(ˆ%ßÌó1Ù’ŸnÃâ&‡é“¢V_3ªÃùE;ƒò·JÛ+V_=Hnç9Ô—Â#AÌýt­â¢n…™_×$Þüþ¬°¸¯kߟÕ`MØÝû»]öw‡=¾?uÝjUÎi2^ d¼[“Íq¢Ê$‚Ú’Z,h‚)¸ûã¿rÑ"Ø_LÉZ›d2³F›ãn“ QŽb9Tª.ÒAHÆè<g#h†1Ƕ~#ÚIQ¡h|Í刣¸ˆBÉFuu+cvZ¿vaUÉQ±vs	—}Š{ÑX½`Ê“hǺ˜x^À‘ÿfÝv9ÓLJÝæܵʾMp¥³‹² Ž¡ö/çØ	Fž~‰(tUα“Ûlí6-l×b`Ž`¬Ü4X/ÐÄÁ®Õ™ƒ-ˆ©Bë‡QT9ÀÄÛær°³’ç±ç⤲ñXñ‡¶K«œ0ú+/íÁ;5 9Èêú:ò«Ã¼©*Ã<ô—z1Ù*l\z"uY½5ã<—NÍ/iFîµWü@’‘ìôÁâ“—°lH—ìæ
-
-,ðÍâG<iUQwǧM`.õ¸Úœd•Š•ÖÝO‹dî¿Óùã7Æ-س„I; ¨Â“ê«0†Æ{ÓÖã„ÏÃU-Î2ŒK>«ò¿,ÇdaÌÛˆN¤ñ™C%ÒDŠÒÛˆN¤±S—b•ÛR(æ…üŸ}yö½PÂóÕšÿ³ïu²oç*Jãâ ´GTú¤ÊýְềJ!Œ›¿Re´ˆ³ò¼…Môò…bÛ¡¡¦!K_H­½|P5å»ÖŠÑnžúWç³Åç$ØE«;å,&Ï¿ (o–>{€ïYÇ¥ŒË ÷Ý×e甁èZú`ÿ(y|C:¡òáêGS‚¡Nc5…6ùM¾wļ‚MÀöeø|-ÿ‘³æǧëW:)uÕW…%W@"š.qV¹¾Ýû75ßendstream
+xœí\[o7’Þg!?âÀ/{Î j7ïìöÁqœÄ3ŽãÄÊ3‹l)¶KrlË—,ö¿oÙ$‹dõ9’,Íöi³y-V«¾*ö¯«q«ÿÌ¿OOönÿèVÏÞ썫oàï³½_÷D¨°šžž¬¾<€J¬¦a²ÒêÕÁÏ{±µX	íëWntƒ„'{YlöÇA{a”Y?ßx4£^oö••ƒÅ ¥íúÃf_r^­7ûfð~šÔúd…Ò*½~•Û¿ÜŒƒÓÒ„æJùA+·~Ã¨•]¿Ý¨Ak7éԏwë×áIJ£Èklb {çIë¡s=91íL*Ä_–×±÷IƒÝ+L¤û3ìÞBÑ1#¤™ôD—Fæ9“F=ÞEҨѐ™œåŝçæ¸=ù=mþ¡4's«Sã(æáqNdu8=›çôú}ÜÅQ	2<]Ôœ/üúi´_ɨ<Œÿ?Ø“;6À5GÀ%±«Æ'Ä?Í‹z‰+„¢Ó/ïð½œÑi|錫ºÛ<©Ñá,ö¥7ìÐj_È8‘Ï蘉ÏÛͪyj#€­‘¥påûTƒUa·ÂK©úÝÆÏ6Âbª6ë#´…yéÉ(БáÓÖM
+—mdfd\ö°Ù÷
+˜ašÖwpt=h+‰–5Z2}žBkëaRTÊŽÙ­ž9u¤"C˜âWd¯yÿ»‡ÿT5Ùík÷'¼îög=ý®ÝÖ^ôÁÛH9&5 ºTC6@z'Øô³f ᬪÔNì´Z»Ã¡fÜaïEÚb ÒǍ—ÀØ°Þ!cLœ9¼/Ìwq‹Ú4©ÐÓ(‰n2‰”XzVxy™”ˬN‰†”²N°Zè´ÒBùeA'Õâ%U-¤QewŠÂ!¬7¯ØWCf}v”¢/'Ap*¨ñJgJÍxA/ÁÜaO7ÒÆiAÚÐÓ΄q0šŽó’{}9ÔBÿ"sèÏ8u/k¸:kÇ“H˜Ñòþ9¤ÜK1L¸+é„Õrý$WŒË™òԁmçYâS:²ò<Ŭd±G1ŒNQ&-4 RLÞŸ7jK€ˆ©9ŽyûG驁‚k1“_<Ø;øÝ_ÖAP‡Éã:Ã#È‹â;—¾/¥g¥ôu)ý½…eEÝøéMxT®ÿ–.åàs–
+]¿ÎÚêú
+M¿sݯKéay|ÊöËwö±<]ØìõÆÁ–N¶"Ã!zÔˆoÙå<tK»Ôhi‰©Ñ/¥ð¯ëÜê*~`)p’»zU
+_FÉò ùÎ%É"óSq5á­Ð^Âñþ×M©ðû\a¶2bOµ.Äòá-ñCéC¶îQM]dÍ`0_vˆð(f~ô†òãéuòcÏBMÝãR÷°­™Ã£†5ü¤Â‡Ìd‘À/ùùǯs«ª+B°ÔH4=…FŸ£1+h·4lÙ®®$Ç;·T´[J«-ÝÑŒŒ»¼‘YÄÓìòRJÉ‡vgBé«^¾-¥/Ø
+*šOó.>æ´3™ø»\ø‚UÇy?:­ž—ÂtV©ÕÅÇ¿Uí!n½ëc§4vë=Û,m2¶k6Y¦ý½))}ÏÖ%›ú–ø.«æËþþLûJ¤|V
+Ï9¢W:>íÔ:RjDŽ¡7­èG®X”››$æV£¶=´ºÓ¼0k æ1!‘€ò½É¥=3ÆÇÝtiôÉM‘èy)=oÕs(ý©<ž¶·òü2“è'Ú×v¡[9 –(¨•¥‘''CD¨]ŽÕ‘¨ûÙ÷À÷>z»àÎcÂåˆÞ墯Žžâä-ñ»‰oD0Ò
+ƒP“¦©Á!µtƒª¦
+‡Ô ¥¬ïq‹OÁ!ÁCŒ¸2Ìnš–¦d*t£#…ÔÿGÊy¹g´ÃXyðHÈŸg[Sˆ3·¾„»ê쮯%8ŽnýÙìf€Ç­d²ï%pÌG+.,…'cD°ýÔˆø©,¶uú)Ic€©éèqåÊWèáX?•Fåé獴œÔD:zÙ éø„¶n°ÈBkò/ìF˜¨rp’G¸(°1BÎ^ûƦ`2	ýFE+Ø1ÇŽ¯¼Àùj!¨¡ƒ+ŒØ1C
+÷Šö®…qx¿,”~Çz¼§lé3¶ß׳g¦’çPÓ♑Ү³#÷ñ”›Â¯ù9~ïQl‰ÇƸfßåxJE†äË.Q!¹ûdÞÝd&8)ÛÒm@[úŒÅ
+ÖÁãM¤oúz×^ÜÉþ?¡ÞǼÎïKáÓ\H@ÄsÚ)‚:å·$½`È€Á—kx8@‹Pa+§ Oð°¡ñÃR—à«òH†ø[©ûc)}Ì6û[y|4'ð Ž’½Â|(ƒZïA)¼·sÈì[:­Ôè«š24Œ®œ3³Ýî&GV…iÌÂnýúwéqmË{‚ã<˜Y8ð°ªÒp¤ÙKBdq…ömă‚ÊÅÙßå-Å(`2ªú|ÂDijX(»“QÍù–Úï0‡º#O:âM&SÄÿO°U€+O:÷l>”iŠ¢iUòM9%ŸpÐR•”ÖTѬ 	©#dJœ¥|ãÓÀ‰cݲK£G|¡wþQ¸&ð²¶Ã(¯«\ˆšQŸ™ž3Ø>o24Z‘ř蜟ÆAÀX6²y¶XKʬUê^Ø6I¥‚õt¾fLrB+ÈZWû¿N½Ða¬°[b9³¬†X±+"‡¼µÆ#Š;Ö€úM‘¾€õ™kIà£*·8)P|`bPâl¡}ôóí#«b™U»DÑ:1èežW,”Ch²Õ9‰2%ÕTKÚLÞÈÃóìjŸƒ°R±²_ep2¦np`sú¥€³*)jšƒGŸ1d
+'”•ný
+ôÃzÇ-°ÊèÇº˜ùˆ“¬\ìÀŸã2ß\}Õ¤M­¡ä È º^/¼ÿÏ*USY0Ômµ
+Æ=«Õ¬rœ‘¨#’£·=“HG^8e«ä¨q‹°§
+0ž©3'ҁ/Y’H§µHŒ1q×v'*ï’תä@†rDÎ8|&kÕ
+iHlùýI®£¿²ÖM`ÁüYNÅïè/Ç% ¤`iM|–8ÑG˜¼›§m
+ è<m^<YGэšqÒæ"ùèH>]ç„Î4­öVD[%(+à…R2ïNòB…mZ'Tèd/O‡*XPFbj¬/lHTvJ17ȱD)í³KCq­ÞwbVs€ÙUá“Ù™ËTÝ,).}ïÞ°¯›ˆÌÖ›w
+ƒaš±‚bøœâ
+T×w”Ѓ²á½SðôÙÛ¡Ut¿ÆeòJìª2F+ϻέNaD)×¹âºÎ*a¯¶ž µœ¯º‰^˜­¼ç±"˜&v…ÄýT•otrðTo´“,ëåÝøp‡
+7—ñ„ºà{ãž4ï›vN
+N«Ÿ6z‹)'ÞP¥ì\X1³H¨.é%ÜKjw©±·ŒÓ ;XsžczteÍÑš¼¢…kra=W‡
+¤¶Á€º§“kؘჷ֞䌙Tb!äMº¬nŽ!:Sîß~ì2[ÌX%%&”"õÅO‹r¹né*cHÓ²4WcÖvÊõ0DÔ¤´å™»ÈÉlª(r…ÙußoŽ ÄõÔ¢gç›|­|ÃŽIÊËy®¬3;aCNi¼bPyhÏÚPJ.†Ç.Ò–»ìi}@ë&ƒ…ËV§á½ƒ½ö~])9èð‘xçWÒà{¿R£øÁƒ§'{_Þß»}ÿ»ÕÛ×çÇ{·ÿ´{·¿Å¾|t~îµú½{÷W?,~O¡&`úž‚4p’)øø=bpßë挋þª#E½¨õ7¹îòú&5£ßüú&rçèú~d×÷CYßOl…ÇÝþ.Dà`aNL†Á«9„õé&$x %ëí<êAXË£úUü(6‡swKVÍœŸ'Áè/âÖIt°)JÒ8ªŽK¶#`”¹”MBØW–ú`»’ Q
+âoxà²M³E¼}á\”àïØ`Ä'ߌó)Ù’ŸoÃâ&‡é“¢V_3ªÃùE;ƒòwJÝkV_=HnçÔ—Â-AÌýt£â¢n…™_7$Þüú¬°¸®_ŸÕ`MØÝë»[ÖwÝ¾ÿîšÕªœÓd¼@Èx·&›ãD•Iµ%µXÐSpöÇå¢1D°½˜’µ6Édf6ÇÝ&A¢År¨T¤ƒŒÑyÁ GÐcŽlý.F´“¢BÑx?šËG…q…’êêTÆì´ÔíÂ&ª’­bíæ.û×¢±xÁ”'ÐŽu1ñ¼€#ÿ̺íj¦™•
+ºÍ¹•}=šà>Jge?@;)BéŸ/°Œ<ý=V¢ÐU¹ÀJî²¥Û´X¨°]‹9‚±rÓ`]¼@»Vg– ¦F­FQå+°›+4°dÀ7“kñ¤UEݯ6¹Ôãjs’Uz¬´î~š$sþÍ¿1nÁž%LÚAžT…14®Ø“¶î'|®PþA$^ê’î“!ÉÖòj+ê.T×Xï0¹)‰‚¿¬¼ß-ßñAl9qr%é
+N1ç–?iQÆnúH´= öÓþ÷:ÁÿW„sˆ@Bkoغ| ¯ItÀ€­Ÿ[ëMRDrú güÞÑÛ©	 endobj
 55 0 obj
-4873
+4876
 endobj
 59 0 obj
 <</Length 60 0 R/Filter /FlateDecode>>
 stream
-xœí\ÝsU·÷t¦ÿÂÍÛ½®¢ïô‰$d¦MZp§i'¶Ø&þﻫs¤]éèÚæ#„08ì9Ò®VûñÛ•./VR¨•Ä?óß'{_Þ«Çç{™ºR«ïëÓÓ½{jþ‡œ¿^}½t\%‘¼övµÿhOÍß+cD\„úÉÞÏëóÍÖŠeë£ü’³ë—D½ êQ_UõQ‰zNÔW=·üxJügÍž7ôü×é1Èôßý¿ï)½Úÿaoÿ/?¯®cÎuJÔWCñŸ_·ÔGD=~pB÷ødAȘlX¿ âëLÔJsÏ+ñÕX'?¸Þ¢“Â¥°¶ü}}”Ueå‘QñgHQ„è8·—\Ä:Ãѕۏ¸-_ÞS®±:+b”jµÕR-íÈÀì€!v*
-QÚð5€ojX>¬ð°MgÑ0p¾K b!çhhäoú(ѧí§C‡`ÐèIú@t8DŒñéÈôϪm±ñpêpQ1¹›ç_¹aR×mÜjùä×A8È«—”<(_‘1Î9ÎJßZã´Ó*òlÌM
-󌳉͹48WsyÄüD-BR<uýJÒ=èR¬‘°Œç5×·)vʦçT /òò1}ø˜¦œ#zžõÉ´g+Ö&2‘Ÿ"Ÿ LrL‘§ºì’ÈÎ|qNA<¤'”c¤×ŒÍÈõ'÷Ô6r÷…Çuš¯ª`×úלî
-ëQ_sËÝ…ù£AEî0gCŸm:©
-ÜDцãÔÆyX6‹2Ì·[”	Õ×g,üh$Îh†ò`Á‚ÍÛáæ./‘7î¶Ö"úF}¼”ç]äø^Þ/¸€¥Ò§°“¬Ra;ÉŠõíd‹3Ó”OšÅç}#èê"¶©,„o¿}9”‹Î`…÷v	£Ë¼E^¦I¹P*²0Eëi©¾hmc¥ÏˆÚ¨íÅ@dIίä.‘G1œß…éæoÙÚ/ˆz´Üm{—Èk·KWë%gÜÆú‹ú.q[Ö¸U
-ö:…Žþu¡Á®uÀ¨Œ#«u˜#ꜴÍ
-/ @AóŸ—µÁá!*4 èDœ(CBÉ$€>\êH%
-¤°¬W‚6…Ÿ*ºÂÒX«©¾t^8H„f-³B!®Úª0%ÎlBL„^kñ÷íÞÄWéÔ.kk¢>*°ˆD+5o„Œ±™ÓD'-¯Uà\.Íå¿4}ù	Ó‡á<LHf[ý–¢ϸ7”†æå¼2¨iÞ­{°µ?A%j ÈmÐÀ˶¸¡i2™vt946²£fFÊ…Éôt2XÂT at 5êÆ>@‰à‚RŽKŸ¿S¨Ši®]Oîm³	‡%r©=•HiüdóˆÕdÆm\½-BûÐëp··~áZZµÊ½ XsÌ«ëe¡W>DC X€çÑÊ&¤Y0ª´c÷GÅ8{}2)EË)¶`èIñ´èa*X)µ‡VЊ³z2ðÂÁ¯³å#V•Ü¢‡]&ýEµDÞ
-š"0ö j.)«5°S&Èl<žÒÄ:¾‰5´¶Qžï$F
-¼ý˜lPÏy*ÀývÊðÈ{Ú\9ÙZ
-k‘xD-,vTÇÕm]Ù)–°JRD¡ËT]ôÖ~9ÖDw³òBrd]A²ã…ÞaçÑX€±}¿ªÄªÅÃHϱ,§Ð7ÞåªGs®Zy¨ZÝÑb±AB˜±ïŸ‘@
-¬vÆÜ2ýŸ…­’Mº€„­77fŽE¡Rí‰4;Ú¶
-¯¶N
-GŠeF¹ãb…tæ=o†`ªÀÃÄ9.&éZŒ÷6>h1hÙð6ö>å›(¤©Ž™¯Ša»o>gú˜0öÈðHÅañªùf
-xò-€ËI¹.i¼îÕêâk<œ^ï¾&}>U[bk4c¦ø]”÷ÃdŠ²èØ*aǵ1¿òšiÌžÀÞ"Ì.¸—°‚ܵZ@ä^ôdÝxdǍ·å!Sx†¤2-‹ÿi9¹·Ñ”îÇÃÚœeR¼Ð"%$-K7ÞÌiÃeK‘Wà'ÿ¦
-¨¼Ô¼CÚ€eð3÷m‘½ßÔqc-Þ+`ª×¡¾—ÄSW¢""ÞÞ¢€ëûu;îâ{¨t Q|Cýž¨÷qÈ>¤Tº•
-WC‘Å«ˆwP«Þ¤Â6n‡·W¶vf›?XðͽÃÏUQöò€€#ÆÆËÇ9—1}äR:e©²›J³£Ìa¹‰¡×hËQt÷ZïÝâ³TØNxü™º¯þÜÝ×|’îKR}\÷5H÷%mýß}[÷5Ÿ»ûÚOÒ}Iªë¾ö龤­ê¾ßnœ/¹,Îè»3ÙÞ×)N=^ëe½:3òok…Iɳ–ÞàÒ#»ÉJwGëÁ+AŠ„×»ï|9áý½·”ž7ñ“„×f¼ón‡÷æùãÛ:/v
-¢¿‰PF&®©sÝüÛ¼Ô¹.j4ÜÌs3O©wx®»çz<Š¡ëýîîK{7÷µVêÏÓ}õgî¾þÓs_飺¯[÷­wªw÷%}T÷½ß7»vss(ÈÞ[¼`bǧCíñ “Z€ºÆ?=L4×€X›¾ˆÞ2sÄc“¤…©a­67+xœí\[o·~
+ô/œ¼Sø0¼_Ò''qŠ¶iØ*ú-ɶ`K²-[Žþ}g¸KΐË#É—8ŽQ†Ü%g8×o†<~±’B­$þ™ÿ=8Ùûò^X=>ß“«¿ÀßÇ{/öTþ`5ÿsp²úz>Òq•DòÚÛÕþ£½i¶Z)cD\„†ñ“½ŸÖç›­)ÊÖGù1$g×/iô‚Fhô%
+}F£Ç4zN£¯zjùñ”>øÏš=oèùÏÓcé¿ûÛSzµÿýÞþŸ~Z\Gœmê”F_
+Ù~ÝVÑèÙðƒz¼ÇBÆdÃú
+¾ÎƒZiÎây|5–‰Ã‚ª·`ÐIáRX[þ¾>Ê*²òÈFñWHQ„è8µ—œÅºÂÑ•jGTË—÷”k¬ÎŠ¥Zmµ0pæöïMŒB'epEc¢°Ö­ßl´ÞèõƒÍÖÁ””¨PŠ`µË’0Z‰`Èß
+«“I(þò%0l¬R¡Z
+,’]?Ù(a£v™s£½0Ñ ±(¡µ†Çguy"tD¯O7Ú	ç}¶N‚e«ŸÍ$“çkN<%¥؁†Áà<Ø2⤝IÚT¡ätd‹ÎŒÚ"…—ϐ
+xéî^ÃlÃ9Ë’ÒHj+$Ù{pB`ØÏ(Ò˜(„&5¶ÁcËõèTJ“*OÈŒ>¾.Ê}3\¹4"ßÑgC¾]]™Ëêewið ,<`Z´x^R“¸¯¬ë,öÁ³:ë¸8È8e~y«‰€ ‰I%
+Qw®‹Ø‹U{¹ß¦ÑhôýžFÿJ‘á›~…ü¸¿øïVmü“æ1³Hë
+þXó/dïï×IûÝ`žô3ßK¼ÃiÖÇïêJw;žò¤É['Ý<0n=‰ßA°0Ö[ÅbÑiõay8(O—›¨…2сäñ¥ÔSd`Îþ$·;¢HQÂœ÷ëÃ:x¶Q¬Qõà“Àn”F¡X0ÄÎ@¥!J¾ðM
+Û‡ö±	càÌÎw	D,ä
+üM%ú´ýtè=éCBˆ‡ˆ>™þYµ-6ŸN.*&wóüë 7L⺍ª¶/„ƒ¼zIɃòãœã¬ô­5NšV‘gcnR˜gœMlÍ¥Á¹šË#æwÔ"$ÅS×/Ä݃.Å	Ûx^s}›b§ljpMò2,+Ó‡iÉÙ1¢çYŸL{¶bm"cù)Ò	Â$·Àyù§À.IïÌwáÄCzB9FzÍÈŒ\rOm#wÏQy\—ùª2v­ÍÁéÞй^Ðèkn¹»0ô"¨Èælè“ M§ µ›(úÀÐc‚Ú8OËfÑA†9ãÖi‹2¡úúŒ…
+Ä­pBL,H°u;ÜÜ%à%òFmk-¢oÄ·ÀKyÝEŽïùý¢X*}
+šd•
+Ó$+ZÔ¯¤Éf¦)Ÿ4›Ïz#èê"¦T·‡ß¾ò‹Eg°Â{»„ÑeÝÂ/“¤\I˜"õ´_´¶±Òg4ÚˆíÅ@dIίä.‘g1‰œÝ…éæoÙÞ/hôh©m{—È{·KWë9gÔÆú‹únq[ö¸U
+tÂGÿ²`×:`£Œ"«u˜£Ñ9i›^@€ƒ0æ?/kƒÃCTÀi@Љ8Q†„œI+*ÈΠR¾d³&„è]ômæ‘	¸ÁÈ`‘Y×k×è¿„g$4Gå
+4'2î„‚¸7xM•°àrkF¿wŠlˆO.&°…µ» /å2RA³u5 ³Ô’è"¡VzÛõ¤<D>åØžØ{’
+ÕÇ9?Á–r—üÔ@Ý,ÙàY­ñ97€ÜQ&@ðñ\ÁSCM_ºŽRbÅ0j0Vs$¹œK
+?µndDt¡oTbα†1ÌLr*Ç öSýÞÎƶŸ£ÀšCAcpßD=ns’4^+À¹\šËiúò¦Ãu“̶z•¢ϸ7”†æå¼3¨iÞ­{°µ?A
+%j ËmÐÀ˶¹¡i2žvt946²£fFÊ…ñôt2XÂT at 5êÆ>@Žà‚RŽKŸ¿SF“\»ŸÜÛfKäR{*7àÒøɆg3ªÉŒÛ¸z[˜ö¡—-ànoýµ´j…{A±æ˜W×ËB	®&|ˆ†@±+¤‡CÙ{õÝt±×™'_}15çaE8õLqw‹á¶®®
+‡EvÖ
+e7ÛðÄZµá÷Gà<‘1™íÐX³³±ƒqÏž˜\QڝØÕkÐðŽÎéØ°—l£pÊ2)Ÿ
+}…ô8
+/T¿Îe‰6Êt-f+¤¹6–—Ëœòbtp}ª›ìª‰=ìý2­Én¿œ?"CçÉYˆé-®ÐôÑIÏ8eO=šœT`±£:®ªuQ\d§XÂ*I….SPuÑ[ûå|XÝÍÊÉ‘uÉŽz‡GcÆô~U‰U‹‡%žbYN¡o¼ËUæ\µóPµº£Åbƒ„0cß?#X쌹eù?"
+Û%[t	[onÌ‹B¥Úiv´m^m:dŽËŒrÇÅéÌ{ÞÁ&:T€+†‰s\:Mܵïm|Ðbвámì}Ê7QHS3_Ãvß|Îä1a4ì‘á‘ŠÃâUse
+xò-€ËI¹.i¼îÅââ{<œ^ï¾&}>U[bk4c&ø]”÷ÃdŠ²èØ*aǵ1¿òšÍiÌ6žÀÞ"Ì.¨—°‚ÔµZ@¤^ädÝxdlj·å!x†¤2-‹ÿi;¹·Ñ”îÇÃÚœeR¼Ð"%$-K7ÞÌiÃeK‘W Š“ÿÓTÞ+ˆêu¨ï%ÑÔuPÑ ÞÞ"ƒëûUwñ=T:(¾¡þFïã,à;|H®tËî:†Â‹Wï> T½I…*(n‡·W²v&›?XÐͽÃ	ÏUQöò€€#ÆÆËÇ9—1}äR:e®²›J³£Ìa¹‰¡×HËÒ èîµÞ»Åg©°%œðø3u_ý¹»¯ù$Ý—¸ú¸îk~—îKÒú¿û¶îk>w÷µŸ¤ûW×}íïÒ}IZÕ}¿Ý8!^rYœÑwg²¼¯Sœz¼×ËzufäßÖ
+“’g-½Á¥Gv“•î4ŽöƒW‚5¯wßùrÂû{o)=oâ')¯ÍXón‡÷æõãÛ:/v
+¢¿	SF&®c©sÝüÛ¼Ô¹.J4ÜÌs3M©wx®»çz<Š¡ëýæîK{7÷µVêÏÓ}õgî¾þÓs_b飺¯[÷­wªs÷%‰}T÷½ß7»vss(ÈÞ[¼`bǧCíñ “Z€¸Æ?=L4×€X›¾ˆÞ2sÄc“¤…‰a­67 endobj
 60 0 obj
 3536
@@ -360,234 +349,205 @@
 64 0 obj
 <</Length 65 0 R/Filter /FlateDecode>>
 stream
-xœí\I·¾Aò>½gh:͝tƒ¬ØpbEv¤ñÉŒ±4Z ÑHžÑê_Ÿ*v“,’Õo=Ù`è >®Å¯v’?ƒ8ñßüÿƒç7þzÏ=¾ºKÄÑ×ùëٍŸoˆùq®}ôù	4Pæ(ÁJ«NÝs}¡ý`ý‘Ý á‡ç7¾_ýe}lïCPÿ=ù4UCø4Á9h|ò*ß^ƒöÂ(³:_ƒÓÒÈÕÓüu¶>ƒ”z´«‹µ4ƒ	«Wëc%Åà”ƒO5hmX=YèÆŒzuš‡5Ç0¸ÕËõ±”ƒñ"¤¥W«ËXSJ£VÖzÐj´rõbjîýùùZBgìê
-ºv>ÐßI§?ÃPƒÕhV¯óœÈïØÁ0jeçÉ» cÙ¨‡1&¥ÞD`•ñg	DxŒóÃ(äê~nó
-ÎvĪD×Q‰Õ×¥ô>L. „¥$a—œiçò¯cü
-B˜•Î…²ÞÄ&ã <Ù¿¡L~&‚‘Jµ’ƒô~Á…Õ›5âEZ?ŒÎ&|̍Fè´Ln•ô Å B©TÖôj4.>½ÖÈ›K_•Ò³RJš©\ƒ±²ˆcŸ†›–9Žë<-LÆÃBõy-ãè)Â+è&dZ^䍆ݗÚvŸ´)¿?„ß
-ü!W
-ò^”*5ÿDûL?’ynš‡tÍO2HYØŸáÜô ¤ ½@`A˜zÃ4ˆ—+lc†P‘ƒ>¤õ‹LCųUaïÒûyùù´ôy‰=ùÁ²ÞsYÈlqN:‚Ÿå P
-²F¨›€­¨ãzßLBdL`Ñ•URBj5À€„QÞM­©¦	ü)È<Îsï¤y&QIJtz°ÀÇBNÓ\œ’
-4^€6+µùFIØ_CEÁ’ÅH¥v‡ØI„Րl@5•ÃS"@}W&ÚÒ	'Zv¸ÈâRVF,K{Ñ´Àþ>K¿r’t›×#Pû΍“O¿_ݝäÐèT¯JéÛNÔa)‘dÏàÓ£´@2¢³€h—«¿ÃÊ@‡x ÁÝR¡ë×9Pl]¿­¸}Vê~YJOËç¶_¾³÷åsèzÀf—kZ&ØŠ§Xè%ÕWìrîÆFº¥]j´´ÄÔèY)üa•[}B‡J…ïX
-<Ï]½,…ç“(ñÀ²Åª"óÓEÏ}ÛK%W?¬K…¿Uzî8õ”ùý^YÖëRÚ«…Ì]¶‡‡5QÌX37ãG£{ßl
-M°-KaÑáƐ“ª’oÖ2QU‰D—`¢0Î ÇÀ&0Rhí Œ¯Ã‡)fô.æ-Ô^T’V¸j ³;f‚f>ÑÌ¡q	©y¿pñÓèFWi(B]„[00’!ÒçÊ3ŒŒ\œZ&h~ÉÉR2Ò1Î$Hh¶7Hq"¬¨n˜ÅÃ-Xà©(̵%KºàÇÝ`±Røxld{à‚²þjð¾À «dç’d-ˆžto™/e–	÷É-í‚Ü.n…}Ö¶\ŽŒÿeÁŠ‹æ‘lÌÇþÔÞ죆Šƒ‰,(³S¢}ÈLÑ(FK·2:뙪Ð-¾Htp¥iL/(’¢Ñ\h.{}X%¥Ð]¬æYƒi\‰ÞÃq2ûqÐ,”À(±‹þ£&ØLä¨ë&)©‰Œ&ül
-¬{›^P¼ÿ3¡J%­æ<4k£¡cG“ŸÝÄŽ
-™xÀO™ÁA± ï¢+øs·çØé>~2Ú†£²l¨s0£Ñlf€ui0‰²§yI•jÐéZº½î
-h‹©
-»¥wþ4*lu9×u\R:äó¼$wH.ëªÍÓfX÷›#)´Ç¥îYI$’Ü9yY*TafÌIz€„½–.ÙŸ—I¤ÇËF`!ß°§²iæ¢rÁÁsˆÉŠ,·K2‹€¿4'ˆÎJg1]•j¢ÈÀ#ÿ`×½å/$W®Ï¬Ô2,9xL‰¹|Ûaã¾áf=fÓðý¾MGq·€ Òä6”N0!D…Û‹ÊI‹4“ÇÈÇ`wpò•
- ùÄFbu<HøðÉtWIÈÆeTjpÖVy at b5•h<Ô4!2£b <Ï)ªÎ	Yb!8;6šÊi)AÓ÷k/
- ú½híš&ëÆúú¢€-)<ú‹Ñ@	à‡œùbCý/¬JBKó<j»¤[ìñ¢S‰—G+—k9¢Gp·ÃðÃ~Áí^.é|†[@å@Ù™z—Œ5§ª@G¼ØdõŽ~†¡{Äò÷.n€z«ÐUh$b[â‰PozÓ&™ã-6ÂÀ¯3sç#ø`Tæ—Â~›Ë•=ñhý¡&aIÚàÜÁÁô‹jÉÌî½<’È’Ú£-›Xr»o2ÑõzɉéLPƒÕ.¤Ïïs.ZIJ*!ø8z<ü*KµZÃc$¹ºXÙîQÍìüH­µU›þ­)q>]š<,íÀ®Q-E Fövq¨½œSìÇ82ØP$ÝÙ…„F~Š„5‹JÈŽÖË!s€“Cl¡ßlØ·‰”Öf
-el4r0”0TÀpìºI.4òúöGh›g¼hÛvB‚0ØH(,·æûÞÏF®ÔË9–hDkÃzµ,Кó
-hÒÊæ|“Šw`ƒ,S¡ô Ë9ÒÓιXö3ÈARr
-ò¬Ô%§(‰—Û÷àâ•}ÎËåÝž«®ŒGº@uÉ•Á°”´
-gd)Ve`÷Û#4¼”-‰6OŸý(šÄ+ýD¸A‹1y´ª
-/’³[ÛÏôpG—PÛz»»U¿ÌÝ)/ƒçÆY	"÷©‚L¿ªÜãVT\hhðñ^¶¥½[¤sZP.¼Ì?“îÛƒ•õéQÖ"š¯š»†âíóå
-¾ÈÀä[5Tb}¨¹À0ê#¨½0GýË6t$ï´âÄ—Å¢ÖÕÔ&ÅåÐ"Z(ác~–œ¬œ»rð¶N¦¤š
-4—þ/rø€?jX?p!½Ä;
-\D냏gÏYw¢…zgº:±5¿dbí‚q°ÅêbýcÔŸK§÷8à>L!‡À9U^$ú̺=ÕªA§Å³…‡z®¦æ›´þ@£’¤²RÞÑdÏœ©Œ&¦®½Šî˜9®ØUÎâξbE½œ!F«
-Sš†3DbždòµÞ© §F’ŽáL|ÎáW¸%EÌ2Ú£òIâ¬$Rûšš,é>™ã­|u„ö¿Í…|÷M¾™R]„gn¦TOH¤FÄ¢zËßÇJ…õë
-ôÞIêkk'ø²Ï-Ir­x–ÝÁ!ÂœŒIîIµdIWNUŠ1á©8ºŠäpÉgÖÕ!…plQL*7)oë˜0=K±dÒGÃA˜ú÷¤›X»£ð,~IÐê/ñDcT,õ¯AÅêèKˆšŒ‚tBÔ–hI1DºJï~àc<ŸQ½ÛÊ“x“Å`ü£º+õ±DÌ[¶îÓRúŠø6ëx]dSe“;Wr‰1­4‰þ”Ž”‘LÒU%#òõÍÅ÷²~磊‚íÅK¶Â]–®9Ñ}Å^¾7¹”\Ô«>w ‘üØÔyRJ‰†zYJ¿+Ÿ}Ö°QGç™:ßѾ8êøêR.8ÝViz綧FxJ2ô›c-cé¿YØ\°¥]n6o®1ú1—‘ì.)]NôþzOððs ý~AÍ®.›l¢¦7¢*2$T,Qaó=»pÒó²-Ý´¥Y®#ƒ—ߤ^~¹m/nqWžßçu~S
-p·ë[c³½ò|Á5:kIÚºHýíÏ‘äO‘{"·ï7bÑÁ‹Bí»¥.!yŠ€ñc©{¯”Þg›ý8{W(ò‰ŒoËïßå/Ÿ—Â;ÓÎâá˜æWÀHÿ_åF_ÐASáÍ
-©ñmIg|ñšTΝ™á­_}š>çâïc5©øü-ïUÓ)Ðoƒ€`!¨éG<$4-+Ѓ±_œÜøüû¸‚Ùendstream
+xœí\Y·~‚ä/,ü4cx;Í›tY±ã$ŠìHë';0Ö«Õí®d­Ë¿>Uì&Y$«çXl0A-ÏâW7ɏÆAøgþ÷ìò֟ﻣÇ×·Æ£¿ÃßÇ·~¼%b…£ùŸ³Ë£ÏN ’2GaVZ}tòèÖÔZ	íëÜè	?\Þúvõ§õ±¼Aý÷äŸÐPT
+áÓç ñÉC¨|g}<Ú£Ìêb=NK#WOó×ùúXRêÑ®®ÖÒ&¬^­•ƒS>Õ µubõd- 3êÕi>ÖÃàV/ÖÇRÆ‹:”^­^ÆšRµz´ÖƒV£•«çSsïèÏ—k	mœ±«kèRØAø@'þC
+rT£Y½Îs"¿c蕝'ï‚Že£Æ@š”z1t€U^ÅŸ%á1Î#£«¹ÍW8#Ø«]G%Vÿ*¥`r!+ÒÑsæ´€©7Lƒx¹Æ6f9HáCÚQ¿È4¤Q<[ö.½_”ŸOKŸ/±'?8CÖû|.y-.HGð³J¡BÖu°Uu\ï›IˆŒiB+2‹Ü;ižI±,,ð㱐Ó4—+ªW¥ôm'ê°”H²gðéQZ ÑY@´ËÕ_ae C<à^©Ðõë(¶®ßVÜ>+u¿(¥§åóŒí—ïì]ùº°Ù˵-lE†S,ô„ê+v9÷b#ÝÒ.5ZZbjô¬~·Ê­>¢C¥ÂŸX
+\æ®^”‹I”x`ÙbU‘ùé¢ç>Ší¥’«ïÖ¥Â_*=wœzÊü~¿À€,ëu)íˆÕBæÛÃÊ(f¬™›ñ£Ñ½o¶†Œ&X€^ =¦šºç¥î鶩ߧ#+¼Â~›È–Fn"¸ÜŠ¶™¼Y3UC	K´Y¥Ä¾ˆgU>Š\Ðü.¸ß¡uh)ÚéÎÐÒ7ƒi¶´H³} ¥­ß¼Àú[ù|šQUõ•vµ²Sá’!˜ðQ£.µzHeP%¸F[Qen†*ÒlT‘fû ÊH`ùQü­@ëfºÐÞZ¤Ù>Ð"Íö–= ÀÚäìæ~U4d§ˆSòeù|ÚVh?Ï3ªˆŸñ`³|ÃâãŒó1yÿIƒêØêáMÆßÁÄÏŸ²@ÂÔÍfHx¶Y2ª±]½åmdUèI¦K…ãƒ/×jb”z
+KaÑáƐ“ª’oÖ2QU‰D—`¢0Î ÇÀ&0Rhí Œ¯Ã‡)fôSÌì¤SƒQš
+铈FÚ-”[WÇ)ç€g$•Ö!iöI.,EÑâBœyÿ(™t0€§óøE‚dȬ#`J‡ÕIÉf<É¡SQ…NÓjK˜sŽ}Z˜d•BõèŒîùý1l„H¡s‰¾nk¾ZK7	Lÿ.¡"GLÇ1¥ÚqKrkN	ª@û”®á]çØƅ¸Å2¨@£³g¥wkpƒuSfqoæ¬ÏB$;æwDØ/r$Šž¡¨0†$³!±w€èªž1¡ÜÓdN˜=ñqk	kÏ3ñ Y¸TGEÂHkÙ³Ö”™²\@d£~ßá‚Ì ”¢{À³ŽbX:ñ^ÑÊ’³£žÏ`¬{´°Mž$Üޮʛ<Ï.+á–S„K9,²#jÏ*I+\5ÐÙŠ3A3ŸÀèæи„Ô¼_¸øit£«4¡.Â-ÉéóeŽFF.Î	-
+“4¿àd)ég$4Û¤8VT7Ìâa+}0KŠõÁƒûYQ‘¨È䍣’~Âl\R␙[úmºw|ú ö£x*
+smÉ’®¸ÅñG7XF¬>™Å¸ ¬?¼/0HÇ*Ù¹¤Y¢']#Á[æK™eÂ}2 at eev“‹UÒ–œ¸˜A?-¨.ò8lì‘œ¯W`Ú[`ávliY¼Áý"×\8KÀîN–&Ôkª*o#ïÆï~¡5k›£»6‚ÅdmtèQ
+Jò•èX ÉE.ÄZ—…§ÚªC~ÑÍiú`·†ú›dCƒ4œmäÓ¤U³Ðv° åŽ{S:Dðö‡g'ŒƒIÞúb6Ÿßh•ß	py²Ð^}†SRR	E„^6”—DZ涗‡Øbï[Ú2b¤ýd!š_ÇÒ®MCµçò¨¨œúš„6Ñ	¹|Wå$M¥\â¢W+ŠÐSV<w†%â¶ìs:'E½È,Ê
+ºOªSciì•#¨Êï%Sšµ•Ñè7`Ìz[›âÊ…AjÓkN¡ªpDŒ¥QŸ™¶7xÍ{D¤Íå4};¾ÁD”cMpíG#v‘¨QÚª?¿Uo2®¸±¬¸ßÚI&ÌKµO ¬ÎX¶_ at L':¿~ÈIè LóljmG•¬QßœAUց¡‚*·¤Ù5s<r²LMH†©âx©ý,Ç°<½ºãkôP×lg“Ü·î‚þEÇ`\nŽó++Ug˜s’ a¯¥€‡‹Göçeéñ¢XÈ7ì©lš¹¨\pðb²"Ëí’Ì"à/Í	¢³ÒYLW¥š(2ðÈ?Øuoù‹É•ë3+µKSb.ßvظo¸YÙ4|¿oÓQÜ- (‡4¹¥LÈQáö¢rÒ"Mãäã1ò1Øœ|¥HD>±…‘X>|2ÝU²q•œµUXM%5
+BˆÌ¨—9EÕ9 !K,g'ÐFS9-%húníå @D¿­]ÓdÝA__@!HæþG‹@飪”]ª»	“Œ†-¨=	¾¸±
+(Õ	Ÿ³ƒ¸Ã˜ÜŽ·•¥=†¼\ŠÆ8‚Ý/i6%9ª(ð)5Ó˜®õ›c°\Ø"Þzµ–aêÊxV!%‚G1(|ã3_l¨ÿÃ…UIhižGm—tK€=^t*ñòˆaår-Gôîvx~Ø/¸=ÐË%Ïp¨ (;Sïcƒ±æT舛¬ÞÑÏ0tXþÞÅÍ+Ž]7É…F^ÿÌžãhmóŒ—mÛNHf	…åÖ|ß»ÙÈ•z9ǍhmX¯–Zs^MZÙœoRñìbeƒc*”d9GzÚ9Ë~9HJNAž—ºä%ñrû\¼²Ïy¹¼Ûs½Ñ•ñh@¨.¹2–’¶!ãì,Ūì¾q{„†—²%Ñæéó¢ÄB“x¥Ÿw"h1&VµáErvkû™îèj[ow·ê—‚¹;ååcð|Á8+Aäâ>UéW•{ÜÁŠŠ
+m6Þ˶´÷b‹tNÊ…ùgÒ}{°²>=ÊZDóUs×0@¼}¾œ¡Á˜|b«†J¬5F}µ÷æ¨Ù†Žä–@œã²XÔºšÚ¤¸:CäA%|ÌÏ’s•sCÞÖÉ”TóªáƒæÒÿUðG
+ë.¤—xG‹h½÷ñì9ëN´PïLW'¶æ—L¬]0¶X]¬Œ‚Zbàséô܇)äX#§Ê‹DŸY·§Z5è´x¶ðPÏÕÔ|“‚ÖïiT’TVŠÃ;šì™3•ÑÄÔµWÑ3Ç»ÊYÜÙ—@¬h —3ÒhµaJÓp†ã@Ì“Ì@¾Ñ;ôÔHÒ1œÉ‚Ï9ü·¤ˆyCF{T>Iœ•Dj_S“%Ýg!s¼¯ŽÀþ×¹ã¾É7Sª‹ðÌÍ”ê	‰ÔˆXToùûX©°~]Þ;I}íqí_ö™£%I®ϲ;8D˜1É=©–,éÊ©J1&<5GW‘.ù̺:D£Ž­#ŠIå&åm¦¢g)–Lúh8SÿžtkwžÅ/	úAâ%žhŒŠ… þ
+¨X}iQ“QNˆÚ-©#†HXWéÝ÷|ŒçSªw[yo²ŒTw¥>”ˆyËÖ}ZJ_±ßa¯«,bªlRbçJ.1"¦•&‘ßґR#’Iº®dD¾¾¹øÞCvÀï~PÑ}ÝR°½ ø’­p¥ëCNt_³—ïM.%õªÏH$?4už”R¢¡^”ÒoÊgŸ5lÔÑE¦Î7´/Ž:¾º”N·UšÞ¹íi†Ñ endobj
 65 0 obj
-4702
+4704
 endobj
 69 0 obj
 <</Length 70 0 R/Filter /FlateDecode>>
 stream
-xœí\Yo]·~ô/ܼI…Åp_…“ØiZ7‹£4(’"-/‚eÉ–¼$íŸï×!®•ØN~È	—áÌÇ™oæðêÙ†3±áø/ÿ÷Þ“î¸Í˝غ›¿Õ§Ç;ÏvDþž{o>9€ÒoVZ½9x°#ra4³~ã¸c^<Ùùa×ïík<wn—ÇGŒÞ½¶·og^…]7í [«l­?îµækó¿þº³/a6ÏÅf_ÈÍÁ,|³u}Ùf¸ßZO[ëóÖz»µ·Ö‹ißû­õtlçðh%³FìÞk}OÆ%œãa9Y->Þh}I‡£öøí¸ÍØ÷¼µ.ôI‡›{Žqô 2l”B®Èuß;
-Û=nuÐó颧uÐ ‰áÌr½û'- ì°,¶uþ¸;@± äîèfö…HŽ’<i0:œâŒ´>œbò¼µ²ÖzØZ	vŽZëeg	ϘîÜÛ_Œ=±q>Óý
-ˆ^eÔÚù™Àèt†½k
-[ÿÏG‘ÑëQ½‹Sé¤ìO%9ø^*¹<•8¨ª4f÷[?®S%gAªû}ß¾+ö.£¦þ–Lõ¾ï¾Û 9çD¬µ.Ì´•SŒeIºm up5~ÜÞ9øã(—H0ç/ϧ{xºm¿ZëٴÓöxgD;åYk|1;mSJAcêiʧÅ—‰d~_yC5_´–ó<sÞÐÕΩˆ³ó6±MŽò¬d–·å_Mg æ&(»Õ:œM·w£š… ð—j¯Zã½Yˆ~1óqÓMQ=îÖQ»+£Žé¨Ëééµîˆ´4Ίî7å
-Œê«¶~ÝZ¿n­$À|Ñ óéÂ)ããÁ¢/>~UMòekü‰ª¢2Bˆ¿©ÚùŽ:gâéË ƒ¡1ú‰î¥4Þ¤kÖÇ[u¦¯™â ¿O—ÿ¬Z?9ËÔn‘l†y5Â{ôE§F$NÿшåñK3H >˜ë¬êƒŒ¿?c	ƒÇ/jêUóÑaº<\gMI<«¥”f\€üÒ1)Ó/{û’I®¸Ç.˜ö†£«àÌiiâ¡LJÍ-º“† 0ˆ(©™·\Z_ÔñÏ÷ÓÚè@æ¤oA
-Ådty´w4”’́–Ä5¥W»?7éÒòA~‡m¤é%ÌtEÖÁÅñJZKJ	ЗJC¤36ï-v|ئ|´'
-D	o«tNç9Q
- §íJå‰ÈqÇT0¤'™þñ*_€ìE"î²j\аd‘_+Ï´-€V·’,Óæ¦òfñˆ3Óp%ˆÕN«®Öi®WÁ^úºÍ>ŒWÁ'À|Û`N9¡§=r’LO!$'­`säÕìû°¹ÎóiâŽr]d8ë;,C8YøÃî°aìþ_ÐÌÝi˜%üÿ¤ÓL¬’-ÈbÈE¨Cv“àÜgÐ‹»€Ù	gBaòh½p È48³+
-ÈX°«°ˆ	i—ɶh:àýfY´E{:H¨,d*Ÿ@2-ér£&÷ÓHÆ Ù‚%pèˆKYyf-0Nº@YÕ0u×—ÍW^1o¤ÙÊ0ãaTzo…į2øRÂÃR€‡}CcLÈ
-Œ—žnñ9¤ä– /lH²±ÓÔèc¥Ê‚b.dçy7ПõAk%ÛÜ)2:äž‚°—™ïæCtaX¸ð—––ºÔ©!Œ2¹²å‡h
-Šó‹Jòñ³–a^rî#ªÌ^ZRB1®•­33lÂꬮBj1	*„7R^‚ÜI*.y~-Åj…"¾…Vé_Ô×mHÛ[«XÑZÇ®D‡òè€ãŒgÑ؇“òQrTmÑúµšQÛY[jë…\-lÏ:ñ“èÙ‚}ü®hz :="èYW~Ýï
-ò›Á‰~z
-£ø£QCXÇ½@›¨MQKs§­ì{:)åÏŠÂ×êÖ¼V¢ÄoÄiâTV-®ÙTJLÓ^_`ù4âD¸„%"(J6€EB F»+EkédöÇ8'ŽêÝ™à¤VJÿäX‘ghŽq5Ò?,)„Lµ@œßWæç°ÔýìCº€±inápLkD³r`®RÐ9;g^$iƒš‹Mmª¶ÜǶ %-ˆ¶ynü¸e\
-–¬p-VÝÐ,Æ»P}Z1ìÝüVšô„¼ÌôñNãžÏÝA¬¤̲9*Á’ÖJâ7gÖn'Å/€™‚à·m}•d…t N¾4€/­`ö}p®®É@;™$Mg3§ƒ<×BÄ	ô5B
-¯‘¡c'ƒÑñhÔ‰º³ÜÝ?îV u8*Ãd›Ûè”$»…´-Òçm\SµS^BÙaY0;{ãô@>e̸°6u‹¤I³+æ¾ÆZ|û¡<+!Ù"ál×.¿Ì»0EhEçŽãv*‡ìlw8 'd\nqÇ¿I´ê„ç‚Ù““F!Æü¶÷­džœ'¸!Â~ÿî-õ¢Þz¢¦s[H×ì2
-yݶFì3Óê4çùB‘s³°“À»ðjCÄ[L•*-.øeDÉù‚Wª·-?KL<£MfŸ:³éë=rù`
-ͱþîÀQÛÕºÇÒŒ¥oüï•bǍhÙÕÊèœÒèx¥‰ÀhîUÇb0Î߃$b}ýƒ¬?³m'íãÑIýL7?í­Šy˜1Ú¹‚9²×Èþ¤‚t[¹E½gHù¾ «,_ÙÆ0…ÃóGF¼HåZD]©MH5s1¿‡Ñ!C"ma÷ƒY©pZÚžýVÊà5$¯ÉÉeÝË.“;¾ñq¿]ª%?®&?'!?UzÚú.~L~2^>®pÏfÒÌîy,(´rÁ5ZrU1¡ý|Ÿ¬ñ`ñ8ü0éRí`ßýÅæçÚÔ·¦ÐC°^õÊ!s•ëÁ—+GpýÂk*G« +{=šbà¢m"ÿˆlø2ǣƿb³øùvì°ÐÞ8ï[>Ýg&Ú+6¡ƒÖä¯2œÕÆ-Ê¡Õ+¯Ö„x¼’¹ÙWvYÌôñOC'qó`çø÷_ Èendstream
+xœí[Yo]·~ú#nÞt‹æzH:èƒë-nÝxSZIaȺ¶$Ø–lÉKŒþùÎðœ!¯ä MІ˜žCr†³~CÞ¼[I¡Vÿä¿ßì\âWG;ruþ;Úy·£Ò„UþëðÍêÏû0I‡UqÒ“]í¿Ü™W«•rVLaå¥>¼Ùùq7¬÷¬ˆAz¿+ÓÐGgw¯­÷œ’"˜¸ë‡,Q5QZùÛJþ×þ_vö4ì¤Zí)½Úß+ñçY‡wëN;™Ò¢¿
+Ùß®‹¶Gβµ[4[½a>õîÝç¢WC#²¤ÜûrA›ž‹Aæ❹Ϊ>Øú#”Ðeü¢¦V5ן(×ôá6kJ+ ʬ.ð,c¬
+ä×^8h™>¯÷´ÐÒH‰]	œÄT!…·Ú¥ TBk+'L%6Ñ`1Ú
+«¹P?Ôõï×FXëld{ò¯ …:º¼:x,Æhá£BK"OÌîÏ$ÝÌ>*å oÑH8Ƽ½†^'‘môi½Ñ“HWÆ(З™—hï¦|¶4ñˆ¶<^kU"LU:o󞨐Sƒvµ	LäWÈǛɶµFå+½H$}VXÙñ³	ÂjÐhÕÈI36´7—G4K@?“°4ŠYí´êú¨ns£
+6ûK{o³Ç&˜f‡yJnÎ9ƒ‹¤ÝI/‡‘Ä+4VÂYm–x£ =x
+¦‘©R›#ƒ˜+ZÈÕžÊMMf­mZ0oc¦ªxmÍ”ù(=í@ۍªiÛQ“¾WEkš®ý¹¥SθÜ$ºäl0ËCVð‹¦Ú„ôB+•Ï§sbœ‚_i]~ë³\¼
+ã‰9Í|>¼b+KØeÖã„7ž%’ŒÏl´3[Ï`©ôaxa…U+	›pJu¾Û`ƒçÄ{È*(%ð³ñQ`6Ø_;·§ÇXªcŒ³kS®H9ðŽžs	 ?,ëlÂÏkü¡^-À(:©ð²N§Šú¬»âµ—ðÞ8Ý10ÞëئÎ=Cê$œÁwù†
+þ¤tʵ&œ‚²¶sÈŒ}?_ãGpþtKààÚÎwÅÎ\H	J,î¥+œ%ãÀáƒËÑuÐ^~kE„Þs’‘§…ü΢‚áEM¶½³ð
+þŠu–²—®`ÇO8,Kº¯:¿Ö•ÏM]2^àšÚ+k1=©1/ÄdjÀ÷”oŠO?
+fD ÜêÁ@‚H±Ì<Ìsÿ0$¡aó }ÿP­Çê+276u4
+ЃO5}‹ñgytõfŽf6(‰Þ+Çî/…¸€«Á3ƒŽ&¿”d3WÂ!µÂÈOMè%¯œ PQ£µÐ¥KÙ³žŒy5öY endobj
 70 0 obj
-4060
+3109
 endobj
 76 0 obj
 <</Length 77 0 R/Filter /FlateDecode>>
 stream
-xœ­[Yo7Þ灁ýó8³È´yy	r8ˆ7»›K@‚}°%G"Kò!ÿ~«xU±›=#{ƒ-«mœ|ĵôd>=OlV‰:h§&ƒïö°†ÓZínòÕ„Ä-äjßù^KPj²¯2ˆ,€]R*4
-@ÑxrÎe^;[^šÄÕ4W:S×
-®°N‰’Âöì_›³ü¶;ËZZm™AaªIwIƒÏш¡!àª=°G‘û—÷¤äLŸéâo›°^‘˜i1XN£$³bœf`¸„ßáw:Á‚Ù[… Ž½&ù¾)F?vàÎÒ£GsB¯zœ’ÒÓæäÈåp^­éã	ôYñúÚ®QQµ	ÑRð :ŒÕ3FÉÓ
-w2É	EP.k«Y¹«²:‰°ïTÔゆôv±"0z}Ý”næaÊƽ‡™óÖ	b²L
-'k=é;<ÿÎmÀðZ±*Á0šbÆã|æ"8°4‡¶ÚÍÖÅ÷wíözÏe4àZ©{*¼^ò™`î!	œÒ­!l(\Ží؁’:H;ÞÌ\OÁÌðÈK56hGlë3 FÞuª—¤Ò¹Éʍ†qS¸ƒ3Ä%ƒQÇ+öÛÛ½å> X-k%s4‰ñc.â%Œ=TÚö§ÃÝÌí`RìÚ÷Ä胄¼#ø[u"1>yz?žÌ⎎ñÕO¿JÚzªßáÁ&m'|´?8ðd`ÐÝøØÅLÒÁN¤xv¶œ¬ç<ÁèYGÀ4za‡’0fa“ˆ™Ë(cvd¯Ç*Iøª‰¯ú•`©Ž³èj€J³ËQf xÙ&1ÇŠÇ4&Ñk::y7HŽš¤khEYvÁ<Ù:àѵU…E!ˆ–%öYÓy±¤»à‰‚oy›wëF én6­6„”áÕ•Ò³ä©fR.„zÞš™×`RÎĉXz}B5È%|ÞÉ9;Ãf u2Ƽ™¤ÀÔ™g-KÐbGr^:‚i©eîQž¸Ê‡í-S-M˜3 l
-¬“ÖèÓxsab,K&Cw¥B0¾<z™båºÒ%l$À8¢¢íÁöŠ	L‡Òè'ðCå“CÁÀ *Sƒ)¤#SJ&Šqõ‘2œÎÖ(j¯y`õŸÁªz-ez±K¹Qµ-(UŸ*^’Q?.òÿ·†k¨^"\βëŒpB½5é¸øuY±
-’%ZKeõu‘âOÝ(¯[¤7ÓÖ#ŠµbAJwø°¤×Ëå¸ÞXDl%„Ø-›„ÿëZ´…Çü«"]*€Iê‚ÄÌl=Ò‰f§á™X”z>4ÕD?Y.sÁ‚«jŠ/zª‡ªR×Ìüäâ]*ê-ý
-5Ä­Ê­Vávºnw”¡Ë¾¦ˆÀbêöi©ÎeâîTtHý]}aak«}/9ÿ!Z–cŸÎŒ>®É¬èȁžNøîm~—^ƤrÎcÊ–»˜`VìwßcæXØàj’X¥Ê†M”±‘9s6L¹Ã¶¦VYB–=涝çE^ù“»^Æ5ÊZŽÕK1³å»Nbû¸¿rÐÁŸtÉ
-A\-ù]‘Õf7Íœ:†=ˆ³öÔ­#(Òà‹ì3°blôkAô"[9„´$I-ëV=\}×qV›¯¼êå°|±aº:Ä»ùm­iÆéB¶Ë•¦äXJ`Ã*5—¼-Õã¤ÖËæîfÞ¤™9Â|yä
-›¬1õڐ-/qU¦³7WËN—ÕŒ,çSo€X[Í<d=b©jñòóÞDè¾W±6 QØ´˜¨þ{[gŒáKßú"B¢ÅrÏJ™µ\ÌÃ'!¦ËýqØáC£ïiôÃ0Ôº¡Pkñ+ƒµ¨Ëx$"òLJ ã”CáãZG+nTüÓ÷ý,ÃrÎC%gæâíÂç…<•´`õ˜aÁ%Ç]¶«Ü¯ý¬ eVÌ_ø/«#€fr–Ó>l–fº=žú.Râql˜÷vÔ„„õ¹ˆ…Žr¦Ã]£^ê1^èné{gÊ’&¢qíòrÙò_2pÊpà³dU­±™:å,8§‘úÍL#„~ÎÛ•ì3Ñ|üÁinI>ÍrzÒ¦:uïÙ‘Ëэó壌áZ:]Kˆ…Õ0)+ Nt½‘b?"
-Æ4ãïiô˜‘JÜÛHYD5ÔŒ>ÒŸÅ­ÀëÒŠƒ®‰õ¹
-ÓÂͲyãLŸãC9×þ¾ŒµèhCk”ÿyaÆó±šE3üQ׫ñ[¶ÂýyŒ€‹Òo_`w|Š]ZL‚Ë3FÖó6½ÄÅ®Õ4úœ¿ÕØ®L^)˜h-@ Ö&‹õ¾€'Bê:yt¶ùiór+1_¥ÒÏþ€	ùçaÙ-ÌÅ(þªð«Ç›‡ÿ½}óêîÙæá¯[¹yøþï«¿†?¿Ùþmóèñö§õ_Æ­EöÛÐý‹Nf«P¥]þ‰¡Ùd‚E*䜛R&wDZû+
-ùÑ›„P3åÚLF(lÝSìDê¾°“ñÖøÜ(dJ¥Ô1`$úw#R›¶‘ÀƒFM#v<½On¶†±tŸ
-§‹Ô•-gÓž_ì±A„räØØ(&
- +xœµ[ÙnÇÍ3a ¿pßroà;ê}É‹År¬,Þ@ÀFDR¢
+‹”D‹¶ô÷9ÕËtõLIyAàhз—êêSU§ª›ovb’;Aÿ+ÿž_<úÆï.:»â¿Ë“7'2uØ•ίvOÑIê4“6NíN_œäÑr'µžÂÎ?)³;½:ùnG)e˜¼Ù?9(>î> ŸVFîŸô$œsû냖“ˆQîߢ›5ÊØýO‡£ŽjrÎŸô?_Ž4tfß½˜´Öû«ƒ˜œ&Æ2¥‰.&£B0¾|z‰IÛL—XHxc\“b^1î_`HZi¿•:*ïö7´¢›¢2ûï›?Ðp©d’ˆ	W?Ù&³Àio³DóϘ]LÖi<T„o©•×ÍmNÁ[ÝÉ\·ù¿ÓÑÉØ]œ¢SÎÐÉ(ô×1ìNÿsrú×ïö_Žsíor2Á
+³;Ž
+ª·Rcr¬£”nz8SÔp´S1j’ÔXŒÓY¢Ü“ý~}Pv²18œ¦ž b/¡xú9Ji±!@˜èé8iye鸎ơ]QOã44Qæ!+TlPeítÖmNZðXW<J•×\"a©­ô,­¤ rIhÉ;ÒŽŒH'û™Œ	ÒjËƳ¾d~6N>ÚN³F›ó—…Bõ’&²Ø³î)Íd…:©¾!geüä­g?ë±PÞy“ãyk-r’"›È›2t+à´ä¬%3ÖR’„QáØìã}L at IÄ\+Ç.·Kb¶!lîö3CùlÖ.¬ÏÁNƒz*D\ký¦gDC“ÎÑ+Û"À‘j•ýáÑòšÙkÚ±ÔkË¥Ñçí3+^_zÆ~Çyq|p–löÉ÷zÒ
+tÖŸoŠR†õ|Eä'NDì>ZªQf§®lP¹Îf§ÚÙûé¶~
+&ô§H2	(âš…±YË
+ðU–ÈÂÄßѨ¤P¦‡öàˆjM+PWÚ¤‰.jPu«ž€tAo–­wÀ%YMtœ¶Þ.ÁHþ¹Çe¯+o$‡XqK~LAXŽ+¦µ¶fÛõ„«%ucø߈Ñ~^
+§LÔ8÷Ìù‚
+<_ÐÖ®žôSxœ)‚1™ýíó³üéáÁ¿œ[‡Ù|YŒól½5&ù!E¹œ;nP„ù ÈX
+ÚI;}ë#í]ÿ֜ɴ¤{¨§AX", u%îðnïgV4f?å$‰&7™Îág–¨{š(k›!Á^öJ3§ÍˆÆ?¥P5Áz_àgŸiÆŸâ­¯ÊÎðL¡~HŸ\íL7‹˜z J¿CꍄØ& Šˆˆ½Ó“ËÛ7æ¸Ú‡ØJïŽs÷ÏR1Â;Ã9Êe“q¡Ù˜½,ÑÌIæ‰ù‘„ª~il—úÁºT\c‘<Mîa/^~P¨úìqúQX=›è]K2Ï+¬FŽMña+‰^U+‡”¶!i.ý…͈‡£÷œ[Bæ¼êqXzÆý›o—§µew“¡à¹ÒœK	â¹0Œ¶ŒWŽ+[oæ¨p»ˆ>” -ÜÕË£e'üªEÛÜUzÇCIÉ«²œ½»â±2%vÛeY®§Þ]6|.SÖ;<íSµÿ[ï"tg~Òda$”…*üyžgÌ£E6SOä[-]÷lT‘Kã(}R©p;ܯRv(jÝ´ôéUk}×ZßS­W-Õºh­Ïï̺Œ'!"¯4e—æ>20
+iI
+ˆÏq0sVx9s?>Ç(ä}Ev3¼pÉy—•Ä(’ÁËôyf]üÇRY1¿Cõ¿ÌN"˜ÉY.{Æc²Ü¶—ÉÅ–—³é6#ç†ya;Ù˜=÷µäˆBGÙ83çS©jiVf+Ø3÷`ÌÉ/Á°¼äž°†ñRFŸ¯ØjÆRÕç”˯ˆK#Ë[xEd}ÎۍÂs“ùáøòR(æ}*¶(çI›®¨û NZŽn\*·*éZ"
+VÃf蟬@Šèzÿ”\JöOÁ˜ÙçPë»Öz—JìŸ,š8ûÛ‘é¬N?'D#~!èM“,¢#L+´¨æï`ú]û‡j×R 
+¡n웕§ÏÛæÑߎ4Æ#Å­/›ááŠ&ÂÕÊoŸÐët‡uI‘&¸œ1SfíFZdm•Öåú­¦çPòÆ…‰Ö¨Ø¾0ùP®÷	¾9ŠùÀ2~
+´ÂcþA?çIaûê­ÿÜ~ç@F+ܵí³ßjÉ#Šy±pÆwV£~ìe6â]tŸü:nÄ¬wsß4¹T
+Óí>(|‹Þ}D±A«aIbIû·œžŽ¼¦}=4Kf‹?4ŸvþPSƒ98æÓÀ襃
+f“¤¼Vÿf)‘õöNRÕ¯Åøóa"¸n’î·ú‹€C 2)6¯Ñ
+CPC>è1OÒ©¥3K˜Þ™96Â(d>LYü^øý’X¢Šê˜vã9SSƒûOOՐ@nKõúη¬dûց†y»z½°|bÑŠ¹«œ1/ÔGç{îâ˜å.­ŽiÂÜÎ)`½~ÓãR:O)æ{ºÎÁhK0âM¬’YYû€
+ô¨Gtô¯/™–û‚-ÂÚ_Ž.Øc[ˆ_?ðÄÆÔ—6ÈÁ§â•ÒR/bEÑHCá³z]Á^u—WUaœT¿ö—Ù3ÕKˆôÎ2_Mö©`~t&‰ŸõEÚ”¼œ
+Ü+zTmÏÿ¤ÃùˆÊû²<ùì
+·®gAY=Oœ³œRÀ* QͺxÅþû…;éM³ÔEq®Üv÷r7»¡o!Ýoa7åjÔwåF¦zh“í«0'Nç(Ñ,•{#è=¯\™6º°†õèÎZx.ƒ\‡=z'ƒDÀÄ„3C¸èðNoh/_лá}d×ðœµåŒ\kÿì³…Ê'íuYw¥6º¦]~lä›:ZÄßîÆcÅNÉ0®óñœÜñð«8ñlàí)Ò²ÞѿƸ¬Ç¶¨¿–®SÏö7ÌÂÚ~KHê5WqýMh)EÆ—T*9ùø*”é«ÕL_Ï+Rƒ}4·ñý&_I.wfbl+Ÿ^’vÊ7t-‘ ÔÃíÔïÙ¸ŒòýtÆNÓc0¬ëù,@Óâm_Ún¢yHvÑ6‚0ÁEÓSa­Öèlê+:U6sAr¥”bÁ;à˜J…Áä+Õ¬@—]	ZõDéïjVˆ×ÖðO6éÙ<k|Ù>Kk~d7¨ôŒ©ƒ	qÞ¹ïÒXÁí²3¢ânÈäuÚúÚ²nçŽÔ‰gÜN&ox=©¸Hã#]µ%VòL¶¶Y¶P“ˆh¿‡ÉiËÉEºò»É®žZÛxvVãCO°§`Ú(“¸­ù	ö†,Ï…Qð:ºÄôñà3[.(çˆ,»×)`|}òü¯ˆ&endstream
 endobj
 77 0 obj
-4168
+3702
 endobj
 81 0 obj
 <</Length 82 0 R/Filter /FlateDecode>>
 stream
-xœÅZKs·Îy~Åܼ{ ˆFã™[d+2ãı,:9¤r‰l1®NäWªòëý5fð˜å¬äÍîP¥*qØzúkôÓoG­hÔòoþùúa¸þ2Œw?™:ÒøY}ú×ðv ù=¯ŸÝb¹1©ä·ã훁æõ†£òqôl™ñöaøÛî÷{£Øowßîµ
-Ö¦@»»ý•S1¹ÝO{R6:mwßg¢1Žwßì¯ØxÅ‘w”©1†Ýo÷WŒAûtÏʐ6…§qf÷uåÓžÀ†š¸ûÙ©@f÷•¶ìËß
-Xv/ÿye”ÑÚwÜ_·•E¶Äëœ~„pÖ†dghƥ݊H¿ýÃðüvx	Ý
-oGö6)“•'ûGb-ÅâüÒ1ŽúXóÿÚÊŸ÷†à´.îþ]}²™¸¨ÌÈ9ˆž(*µé6Ý·7N9ïCó”¥:C1©Wg¡Tå1Ǥ¯Qš:ˮ˨nt ÎOöNi§=õ‘­‹#×|ŽW:„´{Uu<íæE”™7ÃÄaç’ŠB
-¡¢·OìÖ(}ÙtuHt9PÇÍþ
-ƒ÷:·vƽf`L-ì«]K¯›ÍµíMKͨ$¨Vá§u(Ò$3³s6-ôk)‚̝‚+¥éÓ³Æ5JUhÝu[Âq…eT{&©	‰g Ék·ûGÖ\‚’>ª˜‹;R,ÌãñH³–ptUî‡Jp1HŒºÏF®M¥½,ª”²Êʇ5Š¥ ´JÙU)gÙ¡Q’µâè”ÔïF­Ð‘§w\Y8›ä•Q#Nɽ'º¢<ù«š¸z‡úã>"þD¶»[¡Ú¨™Žáð(žòWä¸ÀÑ‹üyÒDF
-‚+Âû£9‚fŒ¥Ûã°š•saãã&qi’Þzß-8&}®»ž@z)µzé[’y^ý½;Ž–y֏붇Äñ(´€T«Ÿ-ÝmA£œu[-gÞø˜o qÚ¶0¤|[Ћ|Ù.Û™§ÀaµÜ
-ÇŽiȇÑݺ- ¥%Z˜*Dãµàéâû¶øPsXéÙB\:¬F
-lï°uUuÏGN	”Î_+á,wõ.߀ZÆõ<o•ÊX¬\ûür3o•¬M‰7¯¯"åÒqcd0Ô%±GÖµ`_ìª¢÷•÷X³Wn-FØYè±µcY
-R+×ùªÅ ;†Á¢1xtÒäój+eϽ¬qš._®‚žK€2^µÀt=šyuÃ¥nZÐyÀYñ·r®õ]Ý
-øjwÙPÀ{mTôYb“ð"QŠu)Ý›)uË·Wú˜"ם!ä¯{ó®J9벁¡Y'Ü’\k|Þ[^Ïýü±ÜÅœOÑ2f¿Ü¬÷”Ã^âC‡Ì_õÛg8$k—ûí­Á1Šé·×ã×zäììs½¹ì0¥@KÙ·½š[´ }Èär]Žg
-Aù©!C¥‡–’
-ÂœæÒ¢á‰	9$øÖ£¿EÄAp(=ÚbåEb\ÅŠ
-›(L³ªºˆóÙú¥f6U
-¨f§/Š“Ð>ÅÔ3mU-]QLô¹—mÕL£œUÎ84Ë2o;«˜	Á‰ƒÝ´˜‰:§†*ï¹.ˆÚ’žBpKS­R¿\¥rZS¡sS±9Ü-¥¾±îêðmÇ[ðÕ(?WP­^[à›§¨:*¥¬*³W+”&CÙÕãÛŒwÆWnçÏQíãWožŠj"TBYS&©V(õ}eSn#Æ‚lÎx%+ÕØã*³HíýR_7O0­Pêûê®Úv¼±´7rã%v™cËLñùÃå	U
-ñ
-Å0x&©PÊ®F9uÚ4˜ÕiS;¥EO2T6EÜIßÆ£1“Á+«H[Ÿv¯;
-¥ ¡ó0xx¤Ko¿ƒ_3ÑŒr©ŸÌ¬ÍGæO›h&ÃóçO4/§mš&&ü<
-sÊ<óúl4쇃;íÊýÿ®Oµ†q%¼9•Þ¸M£›:Â^5ðrøšOuQendstream
+xœÅZKs·ÎyÅÜ<{ ˆ¯Ü"[±™8‰eÑÉ!•‹iKv•èD~Vù×çkÌà1»³´—«¡Ê%“j˜þúùõÞZÑ å¿ùçÝýîúó0¼þa§‡ñçõîíŽò‚aþqw?<»Å"rCRÉÏÃí«Ý´›c£òqðÖ(2ÃíýîßãŸ÷FYžÇo÷Zæh|½¿r*&"7þ´'ÅÑi¿ÏBcœ¿Þ_Y㕍v¤,1ŒÜ_1†ì“½U†´)ggƯê9í7C
+š8~‡­SÌø~Uš­/ÿnpd÷ðŸ÷WF­}wú][YtKvý¤¡sH<C3.ÿ+*ýçö/»ç·»;¯R°Ñ
+¿ÀvßîÈÇ ‚\„ŽÄÃ}“$Â#Òðfgˆñˆ´&	.(ŠÔ]UòÍîå™>ÄÊXyTñ“ÿT
+þ¦šäÈ8¬«ä×ê¿‹™X+ãÂø13qôvülå•Ö1Äjc‰”
+ª¤F(©Dk’
+ºîºÀ0®Jfa…ÏáEë9ùe`Œ;‰†_ÛÊŸ÷†ô.Žÿ­1ÝBDŒdÄòbŠJGmº…ÍÚßíSÎûÐ"­0YhzI5—µ1*Çk’fÀ²ë&shÀöNi§=õµ Ë¼ë
+7g¸!/«U§Ýv‘—óf„QµuEˆ:TIEÌšŒhµ"©ˆë®l`m8´ÁÍþ
+©€Ç9·æÊÞð¾Á¡Œ0j±Õêå]­¶½™¦ÅŽÔ>cUx °´E›dæã§jT¦ˆšh;£VI3¡—×$Õ„u×FeJ*†ez&5 ÉÎÐ’×nü2Û*Á,T”%Ï(–bäñëJ1bÖ-îç¿:ÔW"¨ýrÇxšŠÈ§Ò^–TIYÅ.zEaM”6")»ªäq¦±UL±6ÞÎ$]ÕmÒ
+ô-¶çs®XÅÁšä•#Ì„<»Ù]ßümøñûŸ¾Þ]ÿk Ýõ'ò¿gŸ}ˆ7
+Ø=¿^œF9:©òµãô	óéá“¢åñV¤µ¥S8<¸ÈSàð”$.pô*ÿ½i*£“ Õx½kNà@Ðbéö8X[å\Xàø°iÜCš´gﻧ´—.ð^bHR¾;í[çx^³»sGk'ëîúÛC²ñ$´’n{hym—Ð:@
+åí>Zë:º6g<„ÜA»@«×Kg¾¬5rê¹ÎžŠDgQºüö€QñwaF¡ª7JmBùPo<Ö%À YKžTæ@‘棩f‰Ñh‘²JH^ÍMÀ"U|&‹%1·…3«Z%	Ñ2á´s…>à\)—“sYs‰fB¢í¯#ÓÉr™¦ri¶å2È·|Y¹¬®¬­ºJ4ÜC“[¬×QüÊ©²ÂYÒVYh‹¸"‘›¹r9§J3ZàPQEƉc4.òÛÝAœ/Ýge÷må6ƒy@†Â^ç6MKdlß2º8îáý³z¸ÛV‹ñ)œ1²ÔžÍq
+>·Äù~òl^òpkÀaœPºNã¥ôuU¨éö8@°]
+‡ GÚ;$+º¨ï‡‡D†2GÛGàÌÑÌ­wJdúã+ü,ÙIeÆc—xjæЀ¥Ñ³ÇŽ. ’+$Ç­:ÄÐrÄŸ¸Êæ¶t’Ÿ›¹Üé©mt8Þ«Ë3›íâovØë3=[y	JÝLßV•	~Eb+Aùi@'‘^kP°´F&“›-Åœ”yd*	Š‚
+0Lò^°[uv1A2°D©‰r at 6FWBþzÌ-'Õ'P€hë$ã{²a†˜˜:²ÑVUjq$1Qwl£IA70ˆ&
+ƒg\D6Bp‘ùûþ–d#ê\Ù«¾—¦=…âL—¨Š¿;&qÅ×™âo7@¹ÐÁÝ–ßS"–7ß­U‰ñ¨ezbùåúŽVÁv—¡ÚªrõiE"]Ѧî2T“¼ÚðlIjã@ˆ;|EÒã+·“šMRŸ8ßiZ‘Ô'Ö]¾íÎ|µnÏü§Q­¾ùòP§C•”UåÊÑŠ¤éPvõø6;;ã+¯òæ;íSR¯\j:4IYU®­Hêë®ßvg¾ÜãJš[^¬ÜÎiOo’ú¬ùNÏŠ¤>«îêmw¶ #™%仍\+	¹²ÌoÐ9\Þ™BnÒÇc£•ÉèMÝÕ$5ë`V/PòÔü<Éuª©®ÞK“6“’\@bEš}ïP!1›)‡%ÚȇÇÄ8ñö+ð{®¼‚õWë•×UÏ»òŠ:m¿äÊ+ÉuâAÈ©2S«ÃþäŽˆ¾GJžù*z rM¨¶ÝIæÌï'qšn8<æ¤SøŒ
+î<|ç_¿¶Z#xž™Ê@Ý®O›zçºzäÅîÿÆd<endstream
 endobj
 82 0 obj
-2238
+2207
 endobj
 86 0 obj
 <</Length 87 0 R/Filter /FlateDecode>>
 stream
-xœíYÉr7Íy¾bnݍ-·HVleµl&9¤rHd[qE²ã½*_Ÿnp°9L̈Ô)å*“zzðzæu¯•éµü?/oºãǾ¿zÛ%´7ý×åÛÝëÎŒèqt²ä	ÆöQEŽúåóÎŒãA…Ð[o…~yÓý<|¹-ÒÖÉŠ{ƒèy2oˆñŒ“óîøüÛþÝ›÷ϺãŸzÓ?”ÿNòÇùýþ³î켿`[&¨µDÊíbÉ©è1Øþ#ûàƒÎ¸T´½”Çþ¦"HN¹Ø_w`Å9ÄDÖ%0Rfä÷îÉüí*@yvPVÿEñͺ-~Dº8Ÿ|½W~ß$­Àúá{ÙACÁáðhqä”ÖÁ‡²…" eý(±<1¼háSÆÌ-ËãPŸ6Þ/Î åqÕL%v0ÓÂÍ …Õ1¦d”±ž3‹43=WÜ@:J7€ãœŠìúÈöê‡Üa[än:eÙéUÀy
-r'JÊhrq¸ä|	ÜvIº\ÏÙÀ‘h#±ÅåS6ð)o71@ûº¤¼ÝÄÿßnŽo7§o$IN‚Áo$w*»[Þ“zv&2òùé¶þksŒœåäi¸ÒŒµÜ-°hQ¸èþ;¢`vendstream
+xœíYKs7Îy~Åܘ=XVwë™[lpž6É!•CbÀ¡
+C€+z-ÿŒ/¯»ã‡¾¿zÓéþÿ{Õ½ê -èÇ?—×ýÉší£Šé×O»ÍnèQEØ[o•	ýúºûuøz…ŠŒwfx¶ÒÊ=W«#«B°ÃÛðZ«Íð:	-
+OVG„NQ “4?|¹:2ƨàÂpE
+AcVŠ‡ÇEQýÄz@±FÃVIVyÀá
+TڐËß#ŸÓœþnu„
+µvö˺RŒ£Èºù“.g•6èÿ*»þfÆX‡—æk1T«í/WØ"ï‡÷«#ÍBMÀˆò×Ï‹™UÍïÕÅEÏoëoº³uwÑ9=Û¿ïÀ¯¼í-º <õ×UBÆ)ûç‚a at qN‘O,)»ŠäÏîсÙÃ:’œ”ÅMú|U"]AîDÅèJùx§|/‘6Z¡õÏâ0ÁÑð`uä”ÖÁ‡â$+µA9h<P$°Ñ€
+ÜŒ à-{>ÁD~ÛçÒ4¸4ÀÚ¹0¶ÎàÈ#+5œB5¯j¾¬iU·?›i?Òn‘”ÿ@Rií³5k+,.5¸
+SãÒ")tÒÒÃŒ 8°ìù—ˆ*øic:‘!ÁF`Ñi;ü‘<Ù)w
+Æ\arrüq¦	AäÚgýÙÔë*ÑÈ`ãuà9Àäzªó²j”ÔU¨#H§Þ•H•#éØYO‘Ü ckLÛDéPÛû;I¢ˆ4ÉÀÓÍKv8K^€â‚W=mÎ=âAßñ˜1^Ô³ÿ¼Ð““óîøüûþï×oŸtÇ¿ôÐß—ÿœ<8å?çwû/º³óþâPì	½c•7ÃP‹bû{Žê>Xý- ð†c&(êè==\»*¸ÎJ.6o]˜Æ\<lQpi\ˆ^ý\ÀIvZ¹Qƒ¨
+ÚÏ[Ó¶Òáw
+1—F-D#EƒvZˆÎr@SˆuU)»]‰u^šSˆErƒBÇ>b­N˜íç/Döj
+µ´W½`
+[`õS5#s
+ׂ܄ÂWýþïõ‘Â^\чÛÀÅTH˜àª£&YkѵÙ\xɾJ$礇A‘ËÁO`Tv5ÛENw»ée»Áè…-3UÇqâ
+ &DZª„@“ŠÄ¦ï“D˜B”5nS%OkUK2õ¯gVL ­gŒ¬Á$n–0–4šUE6⨼ ¯åf,ö`F±H«0$®¼”5ÄÜ8¡ß•h-ižÈò¨%nÀ•
+±¯ªvj'šmA•n»/ÿXs*#ÍLÍ…åòÏ1¹›ü«ˆkb£ m”¡0ïö-¢-Ó	áVLçþ’Fq5}éIìQf#yÏ׃–“7l‹Ô¯I³•<ñ¡&IdnGY…ûK¯È•È·N§‚MšdUhV\@|_åë´ÙÍ3÷åã.±G}Çqã8!Ä“M‘mˆE]•iÄŒÄK !Ur†oÙÑÊ­bA>qH²%<F`F%™XìTœ Øg¹ÛP‡Å-÷:Ý=[Ë7MÏ™¹y”œÞ >j4‹w+m›ÛƒF±4:¾CðÍ+LÐÝ·ÏEÑ” rW³fS‚ãs&G›WѺ(¿ÎH€ÑÛ¼ŠVÉÓåTKq£<Q€iH–´èò;e1¡êãã挤XÕTt‹©t…M¤§ò«	ºñ±šeQ~{œ‘TŠšÝRª:Ïc„BËGI‹.?Š ,ÊïŠ3’r`USÑ-¦ZУc-ýo‹+¿Ó•Ã‹ 5>îÍHÊQUMŵ˜jÁÌ>77ŽÒOF‰õÌ'… ˜è­÷F¾ïšô7î©’jûfÉó9»?Ž¯”×ÂAÐyäÒ(ÐÆÅá’»"2m’¦¸Ý™•µÑ°ÆõcVð1¿´QÀö§‡òKýÿKçJF«Š¹¯l1ÓffÁsFðu54^{ÈŠÐÓj2BGn®ÉÄ`oªi>Œ<¶ÂwøoÎij@n±@1“p(±¡›‘‹î_M«9
+endstream
 endobj
 87 0 obj
-1745
+1707
 endobj
 91 0 obj
 <</Length 92 0 R/Filter /FlateDecode>>
 stream
-xœÕ\I³·Ι¿‚7“‡h¬¹E¶"+vÙ~vª’Ê!‘m9I.¯©Ê¯Ïט,³Pä#g”XU&_À ÷=øa/…ÚKþ×¾|³{ô¹ß¿úi— {µÿ$û×êÿýèýã{LPvEtÚ™ýý·;ՏWÑ
-·÷R
-ö÷ov=üþ¨gÔáŸG)¼1ѫëã!*e¿•0ÁJsø1µ¶tøæxGÚ	
-t 
-Á~{¼3¤`Ih%µé×ÔV¾Îë”oXF	,¨Ãá-V4cãá'|Ґ~×X²zø¯Ç;-´”®ZýeÉ{SFu5ôû‚ÑÛüü·s;©&ý<Œñ±ÆãûŒ/oY“pQ×-»/³ÿ^þüÈ×yÉŠðeöwyàpHkoz¼=j+¬ÛºÇXÿvÿ‡Ý“ûÝg`ö«Ý{r&
-øγöŠÈcã{½2°X=~¶{ôìûŸüå›Ý£?ïÕîÑÇü¿Ç/>Ädzö¿Ù=y¶ÿk©a!'¦^‹øóüµœÀ”`÷ÿ†?Ý)‚ˆvï¬r ÁþM‰¤Ý¿Þie´0qb(ϐ<+C¾Û}quqAh“Ó¸S˜ßeás°D#3·øëùwf°öYøK…2ÁÑáÅñÎ	)ƒ™‰LMJƒÉy
-$Ã;'”šƒdbäY乌( ¿ˆº¡ÉçV–7תô¢Æ³ÿ§Œüõ¨ôÆJ»:»£mg4óé¤dWÖjXhßé„s¾¨^KÎH L¬É™!ñˆBžæ …œÃ¬Û3ê19?:BC­tM®,࣌|²´Òûxø"Ó¸›M}ì'CÄŠµQ„Š 0`o¤"ØÒ9HÆ~˜tr°e‘ãÙñƒçZ;Çãš2E
-ä«]qa/‹ÌeÛý	‰“Ò»˜Za¦¯Q`ª\ ™žŽØ(ÎA2A󬛐Ø(°Ë·Ví1;U ¬²«trðVDú ã<¨£
-ƒsøº`ÁTTVøb‹Þˆ†mÅçk ¢à„…H1šÎñ¨’Gi	=a—3…È„Óì†Yr•$:ù-Гû‚Ð"ð…¿:"JB×bh)Ž§'öáyvϝ„H-í›,ñ~Wß7„’l»ïZLjóö9cœ«G,íßq ±Áþ±¼¤VŠ·9A÷³òûSÌ…@†%ÅÐL°
-ðÒÀ'kðz’ÍX" ÷GVUV•Ø¯Ò Îi\0y”ù9ZBØ,ÿ{¶hî´)M^r$RQæ/œ¤¨`=¾:j/j¸:šý2OÏ4¨œÂ«6È@(ìm öÛ‡YŠ ! †„eÛn‚LâÙý2ÄJf Vq,ûz÷mãa`,d--VÉÃ\Ÿ
-h仈sð(èû–@Š­-öXhV–-LµHÚj$Š7ëµW©©öÂÐLµ·C¼Ì—öª›øÕ±J(;+~›©ïÈn!¸ß‚Ïø^Ý7˜O¢•%Ì°R›ˆ0—5ݵ÷ËT
-¡å˜‡ Tt3Ê{¾÷
-2'mad¸¾ÈinWO±DS*5QŒŠ^&ÜÁ~èZ•ÚZ´Rà1Ø0Ԑ“֐*•A‰æ1pœÍaLöjHõ©´Úxä-ÂXzo#žwºléŸç¤°óÃoSéñ¡8²‰ð@ë–l¡±&©
-Åum¡aŠÆå-ÿiç×Eú2E%9
-™@°MQ‹GTU)£†È‹-ÂB#4Ö,#¦N)ôÚxin’ñ-^Ò¶*	+QÁ¼‡Q¹Q¤I5Èk#äNauv äCÊ0wBxVñüÍpËBT	bS—ÆX¦×¸`j8¯0.­6y“‚)r¶@ Ÿ¶ï—~O3¹J1P‚Ë1&”	ñ¸0H6™@‘ºRFQt„jBdOøa¹ÊJ„t¹ç.¦d<·”ÈY-«Ö‰«ÆX’Sõv¿ëÆXã:“NYåêx:‹¬2,òe#ñÕcˆÔL&‚†Äùµ‹l.l€Z-!—¬æ6ü2J ›¬:þ[÷¨Öq‘¹Aã¤È¦½÷2«]U…-¹æDdÏÁ7ÆÔj±6¾ZêÔjѲí<‰WpLj
-Y}Ç)ÍŽ×/¤öžªdqƒëªôÒhÆÜTz™!y”±Á³c›d-̳n¢—äR!µ&WU¬ll.†Ápp˜Ïä¸8u¶nÇt>°6ò°"©Ð:om›_.Þ‹ÊY¼‰+âͶ‘tKÇ}çµtƒ²(:ÉΡÈv\%Ûʧnr’†»J¸ìL:ò\Q¸
-¥á…-99 Zâ—ððÆm‚BMÇrZáqnCÈ’ŠI~£ký­³h#Àj¶þ3€Ñî©1×Þ=Á¹øv÷ãúGÒô™”ùõ,6AË¶ÞÍÈÔÈöÍ¡v²É(ªÚ-̐/•¿µvP{îç­[@µgÉบ28íù\¿kFB戇îÎ’®Þ¦êà¼P”Ö¼IñÛ…ä>5áK5óÊV­žŠ!øÙFÚ¾»µ""'ëÎ7}´Úpg
-U}´eTß6;pžncÕH[ ×å4 e)ùõ`7&å¹åoÅ]Z,!\2ZóŒ–CJZÚí坴ScÁ'Õï>#Ó©^¸:¶±{%ç$¶›‰ùø­
-E[Ð@{#Tô
-
-Ö®…k™|ÀÚ¨‘jÊ¿öê+Vš.5µd]œÑ
-þÑøªéRsìë¦K­‡U¸l‰Ïzë¦Ë2ò&8ÃG„1½C²I·ÙKu«d™€²{w¢®nÊ³-‘[Ò£ÛdÇ0¾Î·;žê
-g»#½9ñ†¤"íyõ½»î
-±zï³÷9Lrþs^)ÆàûK ¡T4bè2{•ïîQr‘­î-äÒë½×Ïæe\„ŽÝU,ý9϶Úyø¦ÄÈ(âá%lrΔK-ªÖœ—¬xÿ58çò;
-º½ÌíŽ;ê¼¢ÿ«ËïxË:þ\~W_ôÕ]~7¾°Îðí|GMìŽ7.¹ünþ"=iDXäâk=´~Àå	.*È/¦¹úu0Ó¢ùg»ÿ­	p'endstream
+xœÕ\I“ܶιoî>àaÍ-²[‰£h;UIåÈ–œ*\ò–ªüú|$pk5{†Tb—­Ñ+ms:+©úrÆ_­ý€òI²Dùu‰)µ‹
+sß΍Hû¸B¥€ÔXî@y€«nÆx/¸Aæb,Œ׫\°¶
+K4uaàRU¤¢¤0/îxåR¤ZNžRR¡"Òƒ5\~†Ô&ŒV
+ÉkiSz’£JtŽAwÝ*U­Z{àͽ8G/{óg¹ +‰xÿ»©†øP‚ÕDA`YKþÎX“Lƒâ¶þÎ0÷â€ä
+½ûù+:ȸ¨òß@ñ}LE÷æ$#Ÿˆ\'U$¯Rüu…ÈšÌN[÷º¶¹v8/u‹ÂJDÃslÚ6çþ[sîM®¸áš’ÂÀÀQJ;p·2ð²*›óâ Yªí»\ñnIƒCg"2X7oÞõ°³Â¼­ì܍·Iç·k0¡*SC2ÆJ¥FÞ»ïPªK:”Qk&`sBPGkH»&d>õ¼-*Û¶ü-©Ú’åé,ok:4·È訌ìlæöÔªxeNÖ¥79s‚Kb;¯Ì)¯ÊÆ3…Pôð€µ=eÈ…ºœ@ ˆ{JnPÌPçùx¿iÖõ [vl‘§êwkº4pø!]WÙWU?•Ð?FTb(¯D½ÆÛö¿%ÈË^Þ(£…gõÄ—_ÿG• Heä5–yU÷0
+—Æ¥“xU¨V­îa¢¤
+„çhûqyÔ²¤ôõ2“$¤c"2;­TëyU)«$Â(g HvÌíÏɐ+l?¤÷}8#ry7aÜ¥½=.3ÙpNÜ4=’\;ñÝ6=7~t*7§Óq7,Êe'…5HˆÔB&âoHüÖ]¯€ú(ì@ÜATþžråiƒ2Éò!¹êÉÕXò{ȉŒ°Ñ
+ˆ/‰ÆX˜ËF‡åö0BÎͼu{
+kbk¬ÝCBÖaÕXB0
+ÍÓÆÌ´•ñBô–¦!‹è¯¸dB?Yo»¹²†ûYä”äÉ:†xÂó°†+z—Òƒ>b’W^XΟ§«ÖOûpH˜]]¡ÜÛè0R¢ŒûË1T•AáÖ8Á±¶#ÆԐ֤»yµ«Tµju&œ¾‹VÅ›ÅF
+c”ä"þ6ZÒKÍšàsš^ק9ƒíŠ®J0!Ý Ä#âìVW%^YÕt3툕¤”xrEšcôxd{ƒ
+$&Œ¶}ë鸳; 㬒&Ü;-Õ®j}–Úo¢¤—ÐcšTØš^-ušTŠí2÷PLš©Øã”E…ÆÛ¦ç)Æ”z«
+9•šÔÖ1•fH^e,ª Nʦlsy×=¬ZaÕñ«|h.¦«Àoyò‹.n
+]lqû¤«1µà·&>#56§Ê¬í+Ù+»8:ìB·O½›Ñ©‘§›#íì,NTu˜yã<×uÒJ¢=´Ö³‘Ú³NpŽìRK+ÈX«ZL²Þ½Û4DÚamýàSw!
+h>Þn™
+Å4D`d,Œ›>ØÔ]/þ¿ÚsmŽ»5õéÅ=”†ú«¢Þš7«ºýügkÙ®!‘=}^žùœw„±ñ~Œ“b\•M•ÿ-jù¬ÿö}ñc+¥÷P(žñPÖpŸ½¿a>
+Ðlü®‹ÑuKàɈ?ó«Û%Ê™Ð~,—!yUß™X8Þº_’W´K (ÀQ9Ío4îÓ-Ió ,7GjÓWŸR·Ž Byl%I,Á[²£Ûc¸Zç‡O­„«Ð‘•œùÀ	ºpÞw×~àTã>{±À¤¿äëŽ6mèc{I$”ŠF´ubç‹â´‰luwL^Ô_3H%xِþúfƒ3ÙðrÊ×U¢¥î­Èéïn).þIÝ…/3€¶£7tä<ü™L)ˆÞ»zb¬ƒÔät7©TÎnQýÊ }tÞГóàg&rúÓÝHZ€«Èé/E).nQ“Ê =«lèÈyø3™œ6¤´~¿0…Žþ’òÌéÑ]^2H)::þL¦Cñu[ü'ò`~º†¤ƒ¸ØG¹è­à3Æ€HQؐ®éöȹHˆ\}¶ºâplïéީܱ§ÓΛÀ« _@•¯áÉP!¦Šhì75OB"I—Íí78à’+È(èá•Z7<eæý_]AÆ(ëø?pY}a”â›é. 8)vb¤ìر­{Kרþ '¦>‹Vf«“³_påYK4Fx;‡Šúò³ÖßæÇ-nŸ*X_g8¹sv4Ó&ú‹Ãw?dendstream
 endobj
 92 0 obj
-3425
+3403
 endobj
-96 0 obj
-<</Length 97 0 R/Filter /FlateDecode>>
-stream
-xœµWKo7¾/ô/Ì-3 at FE=O‚$‡hÑ`ŠœõÆÛ‰í¾þ}É‘F¢vÇz|0­)’ßLJ¿ZÁ ù§ü>Ü쾆«‡Ýr:ÀðS•>î¾ì ü¡ËíáåžÐ
-I%o¼öïwPÊÇ!è }¸Ùý>~7ÍNŘþ±ÿ‘¡S$Ñ¥HyI—›LðãõÊF§íxœfPÆXíÇÛiFƒô‚?MZkœïêãÕ©˜-!rŠãø÷ÄùE4Òøý4›dU¤Óæåu5yQ]»]ßÎP›(¡6˜È²_¡&,­J!¹%àU|lâ‡EŒÖÚñÐNUÜ¢‚ò!U:½ Ç#Eíf‚Žœ«Ðb‰aôsýž¥”V¶éŠ,K3c“Pvd6’33˜üö¡Ñö¢Ñ²å/“œÀ¶<ôT3¡YÌCÑ÷Û-R2«¨-çÄfò8™@í
-‚èô-›‚QyÈc°Û6n"_yQëu1>5r	XU=ývEÌôfZvÉš´k1Krÿ
-öÉÑ‹‘VëÔ/l‰þ‹ò8¾šœÒNûî°‹“B#¨µJ+‹>,ºZâPÀÅ1Ìd[­L€
-†«	滯÷»_éç?Æ·ùšendstream
-endobj
-97 0 obj
-1160
-endobj
 4 0 obj
 <</Type/Page/MediaBox [0 0 595 842]
 /Rotate 0/Parent 3 0 R
@@ -728,16 +688,6 @@
 /Contents 91 0 R
 >>
 endobj
-95 0 obj
-<</Type/Page/MediaBox [0 0 595 842]
-/Rotate 0/Parent 3 0 R
-/Resources<</ProcSet[/PDF /Text]
-/ExtGState 98 0 R
-/Font 99 0 R
->>
-/Contents 96 0 R
->>
-endobj
 3 0 obj
 << /Type /Pages /Kids [
 4 0 R
@@ -754,8 +704,7 @@
 80 0 R
 85 0 R
 90 0 R
-95 0 R
-] /Count 15
+] /Count 14
 >>
 endobj
 1 0 obj
@@ -916,134 +865,161 @@
 15 0 R/R72
 72 0 R>>
 endobj
-98 0 obj
-<</R7
-7 0 R>>
-endobj
-99 0 obj
-<</R15
-15 0 R/R35
-35 0 R/R28
-28 0 R>>
-endobj
-100 0 obj
-<</Subtype/Type1C/Filter/FlateDecode/Length 101 0 R>>stream
-xœ­YXTgÖ¾ãÈÜ«±2Þ-yì&3¿Ô ªïpóÃ:V°é…êìxˆ•"={t~k»Ñc‡“†	¤+´{uM`†#êz
-c¦7…WUëµyZì-ͺÓuûæÝ
-Ç Úv˜]òãH&b™.NwˆˆNܾ#ææo³ÍgNeÔT
-T{hB!VëÂ*µ–ÄDˉJ…ÏÄF¼}”–Gžig¬ÊØOˆä£šGÔÃ
-¶jÝ‘ÊèÏ G^†¼ñ·¶xÃ+‘4é/‘µÀ%hR1æHúU^‹9Ñ¿žcp-?³VŒvtLfS
-4ÚR–ë$Å`Ðk*TZ
-Ä0åt(8ïâÉA]4ÀAu£À“áÐ^#ãKéÌt­&CÁí|l››¤ÕdSÙå2þ ]íÏÉi}5›Õþà›u¾BpÏÁ9TÖ9‡&¥¹4ƒŠ2wŒ3‹Ž?çCwŠ;ÆuÌfK![®TBR*·ÉÁ»iã¡1`‡±=ž‚]±š†'¡Ñôï‘1y(E²F–Šß2‹€ùoÜ…£#hî3Hto"~× Ó%€ª˜Ðe8àõf4ÖÄÛµ…WY¿¸€JnÙHo ùè>[wø`Ýa`.Ÿ™‚­pï…Ó<¼­¡²#hÁÀ¬ëžßæô%ø?~X$ýwŸí¶-*Z&}|þ%z.e+¶É:}_iË.í]5ÔÀaKÎ,*4‹~­AF4¯‹-Bg³À`tU´A…ÒDnðýΰxñU?E{M´’>®Mt?ûþ ÌßÄý¿‹˜‹­{ëL2=
-dñPbC¢"B™÷á=RÅ7.Þú⫶©ëMdéaf4õvŽI„ºŸxWŒñÃY$1㈑|óÑGûôŐVÌ%)c!œ‰,‰®©+6T6{7¬_8mýPÓ³¯ã«¯Û¢m×ÕÂh‡=„îÛiu~“Ô:áMhw5:Û•Wtè¹E£,š-A½uãé÷#¿ÁoÉð‹ß´‰WÒ¨ÿ‚Ø„ÝpÉ3#è„gªP)‹*,Y¾'AS`èfg ­mʯo;mF
-»ºüÐæ*qǐ.?ŽÇGÎÃs	‚ì^öÃ}úq~À4Y*—ØËGs“PšÄÒÑX	5ëJ°Œ©’„ («ÎÓ¯Ïg|„/EJók;ðâü‹;6Òýhî5'=ìÞ—Ù:Ðè8•&:	˜ãSYUA}}`ë<Ÿ%®	œô*êFcÙ¯ºoüãtò*ì^Öœ¼] ÂºöHô4ïJãéÏ(Íe§ÂÓŠm}q•,§ ¢v0waDd¨&`G¸,5)2Ę‘9lKH«ª˜G.\mŽo¯5íjÊ,ôô¹2]IL\aRI^yvEiR½gô6…»çÖএfü¢El3yUm—%îˆõ_Fځ…^æhǸ-½-¸ñŽYlç÷5Ò[áAWô§ÇBa£iîÐßå½åôdÿ1œ=Êz	Ê^4ªÖ–`Ž€’ OC4ÜÄO+·n¨ˆüÅ“o6Ò{È­gMÊ›ñ0ŸÙèë1{ºÏ‰¯c8U¡&#˜DH‹•a[:Òò3µÚòrN§]Yù>·ý#Q`úÀ_>?´3©@æ_ï™ã–ÃH¯®Í_Rxr`cuëÔ-sR ŽÓ¦ä°0…Y.ûúeº’9•29E©òªu‡„d}¼–¬õ-	©‰’Õ‡Õ*>O`^ç.#$BÝß,æ·¢Lö·Fw:lsŒ÷a4èÉoüPgéËW“c|=˜Š2‘R5¡#ÄÔMÒ «9Ï¿«¶‘Æ¡Hô‚E4T@IŸ§«0÷Qw%~gQÄ{x¤ìi"û¸òÚ¸Æ|‡%·ñÿåw„ë½ÏKáBY´ô¢%%Ѝ~»}ˆáZËÀ£Õ«ÕçcÅN`®•Þ¬Í‚|â*RÒRøƆÃfH=œð(ñ+ÛØs›Ö•“ó‹ûí'¶%Å€ÂÍü;fkҧݨ<åý³laԏ|`r!§X†æÑ-™Ÿä­Y§˜>d૧ïëå޲崴wÇÒ”exsc—mÙÔpúç“ð÷[ׂ’éߺ¢€z§c#‰+úOÓ±i³S	éÖ\þªúÔ.¡µ¤}#8‹bF3¢/ Ubä ô–·Íøm´"\¢™4d”’‰ú×Ѹ¦Kµ—Îq'Â×ÑA^ÞKàA)™³Dìi‹°¢Þ/¬¯¼XHló#´ÿÅC\|š« zizUízí1]%1¼–j/Uf¶È¤?dð»ÙúpcH`ThX¨)Ì\[e¬9Âç7±ÖúxuØ9ôÙ¹õ¤ö—Ñ3Þ–ÅÌ+‹=ÁI»‹ÇÎ\Cï›ð—,N«-o†‚º™FäÐ,jªB9÷Pñã;f²HÓåX‹}qeD]òÔF%È!’!Iôƒ„aœG ¤Uÿ¯çÐJäAƒ¢]2¾’&ZRT–‘OT©œ´/(ö/Âö%÷üÊy¾'FQBQõù×¹j¡`³H¹<aVWÁªéëú—SÉgqaB1®“R´Àõ®b„ѳT–bƒ)7òÍ¢r>AÌOEwØ܊ҽ絯'°U'DÍšüHˆµR)çØâî¨^QH$^gWÝeD>‚4kÕ‘¿.NÎB†¢0
-ÇÈ6+A—^…‘›‘÷ÒÖ’äÑu(¬Môâ¼íA%¬F—žzȸt:/çìá6Q8C°*BȨ¼R— œ¡\“'‡DˆNHJMÃCq[>’þ]ùo ¶¨vÂÍõ+ùNŸûøêжµk§Œ!WÕjOéŒPuš:á*oˆ¯£Â-‚ÁE#©IcŠ%¿)@ž8çÚŽDõʍ0Þ×´€¼"X³QAl)w3”¨ó3ùAÙ1ö8Ýv,2¤û—W×[à¡„õZáúCP *@ÖøgÛÌ}ª-[K/´£óÛì˜LU!”‚.3³ˆ±˜æ_E„ÎOgÑ䐓sôð
-­™SûÀð#È¡÷h²"!â““	åÎã#¶èÒÿ³Ķƒº¡¥Ø˜•’›IvAždÎ'F¬kÙÛ»»–½´lÏÚ÷«ZX™E¼VЊ$vçîÝ+«ÍM­ÅíB¶ÂÔA]ÙZ¯Kb7ªs!ž91]±r¶íìR„µT–纮×,UÇÃvpÖ†
-H¼ZM»ãÌÚ:;‚ÚyÍ–Õ«Ôہü£ZgÖV}hSW
-`ŠÒ§B1˜êÎ|^ç™#oÙ”#/Œ'IIÙ*ì·wjëLdoÑì´D«‹¬RîàôO«à®¾×øßÚÿ÷Æ‚ŽóJ¸ëïòz‡|åÿì-[nà‡w­(_œGå·l¤Ñ\¾7‹.þƒ?ª¢µÚœ¢švFº#²¸mÓƒ^-£F=Á’ٮαñ2=.a‘;MpªÍ/i9þqN%쇦°J¯jwýpoµc°Ëö@/'aoYÑœ`$í¡Œ¤³»ø4e!NÙ/â_†┝؛×"¬(ƒÔ"I°ÜBœ¿hþ¤i)T©„8£;ÝmñT>Q“¡Î"2¶ó$Twgqˆ]uîÂ'À>¦…¶XÖé€íy¹F¯Éý¿¸ú
-d¤x#çÎ[}Š>¹'³3
-ÑL>Ó½×™eù£å¯/eŒ—ÑÜ"´Â$FîüötÄ~WßØа°ÒÐ&CQ^±‘:­VŒ”ióW¬”%%TLZ¦23ÿÖ—¨'gñÏXoüe­Aôä¤ÝÆi,I.®÷GÖh5 q€æíFóP_Ô¿Pb=“­Ô+’'-ÆÒUÜFÜ-	‹IÝgçãÞc«Ó¸ïeyÀdeè³eÿðtO߆ô,\“£Þ됕#êkÿ)J¥BêòXÙ÷#Oà)€½-n¿Lv²$a)IÂâV«Õ$,ùp›³L¡Ðh@ÙjÁõëˆ>Ñêñ*;%Y9yBì+(äxR”ÊĨ9²'qÙjúe“x!ºóBŒÖeÿÙµñª—1çmÄü²g6³PH“Ÿ’+OP&'«8ü׿ÍKO$Ž[m'ÏMÉ/ÊÈËÓ7F™:lM¢–[(ç–˜wE—Yø*ý+ß/¶~7³Ä
-a^˜ûø€Eé³á}˜›1©uÎÞ÷.G„cð¥qß·õ2¯Áuûàˬ'¬ªŠýN~Â)8çsŽ•£7®äVAœ-™·æÀ
-¢§‹åËwŒ]äy7‘Žfó>R‰Ð/Ĩ½c-פj"ÔiªIÓ@2#í”˳¡”Û'¹Ù¼x¼(x›ëÜÒS¾²Æt³	v3M¡†àˆ€„m-E"ÔçÁƒg7W\{Û(@ø*™^Ü0¢>3Yh|±¬ê1‘SŒ’ŽdýøRcuÁØmÌI«x¦V.^æW‘P!˜ýnÀ™ž,n#£Ÿ{®Š•-5>d\èXPBn'ýŸ=Øþw™@FāfÞÍ`Ú¯.¸d#ý¡ÍdQùT	iÞÜva:9BÌOíšN^nï>¥¥Ì#ø-uYñ)*aÔǧ;ý¬PÕ›X%A*¾‡UWâQ·ï‰À!›[Ö‡žl1£˜{6ÒŸ	඲荙O1µÅ5ÞׇChƒ¢!(Ô÷âƒÂ,Ufš†ÈFº,:esôð€­ÙÎÆT½š`ŠI†Ôx>HBK-ÊÖé³2¸ü’æc7àTm͉-ñÖyÂ&Fú±ÔŽnžÞa[I#[s48™ÉJ«*+ãªü|Ó¶Ú_M¼5óì;$hñJm,8÷j2Áé$åBºøa·ì!½<.»o#íD¶è[I£,Ô¯épe›ÂÏÄíð-»‚N+ŠcÛá+Ò>¯Õ?½_r-š-åöåÔ•š#Š£âƒR<—sÿš˜®>d
-  A&L6yÝæXWÎÝ%Ò
-æ2¸ÿ7£P÷3­m'+8Üï6¶BàÙØf8Bûj76×Ú]Ø Á¯Ô¥  cleføžòjñö…¼l¸|ŸÖ|í÷v'¯ìpÆ6taÌçÌËùÿmœyª6+Sa‹ÒNz›Ò¨	Òý9̦¬ñØËE6º63÷ ˜“ý[˜C>ŠÊ¥fû“<½Ûrª²1=¤†óT§D at 4DÄ—¥ÿf0#¥Aþ*pö“Ž‘$ê?~ÿ7ÚGa%½¥V©(r9,§(ï í­kó݁…%ë‡ü׃y|£í/¥»TñÕ\²:,üaGVœ)U%,bäÚ‰%–Ë}yà‹ÜH©åR”ñɱ9;J‚¤,~s¦ID"ö>ÿ讘_',zi3©#¹÷Qûþßý±Éw×ÚUÛ¼”é\póÚÌP`Æbf¦þͽÿäSG\/,ñ­èÇ7Û>=X\¼*ZX7)´á5)ªD2õ&1˜¦ûï7Ç„kJQp¾»ÐæžÞàzvŸnèÕÔ۫×C¯Þõ¿¸È?»
+95 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 96 0 R>>stream
+xœ­YXT׶>ÃÀœ£±2ž+ú}Ùÿþ?ÈðýÀ/XÿÍ:G:MÚ0¨ï 3¬%[úú€×OؤÚ.·½b§³ûl°ýàìÁŸþfHŸ!‹‡œÚ{hÜПÿ–ϽÎEʆË*†Mv}ø»ÃύØ2"û
+ÝHÇ_D«¨~V`Fžž3‹ÐÐûèË*1å³ù›‰x ^Ìl‰³:»AÆï¦÷@Ñ×\ƒYâ«šàsÁOÏUÒ×ur_Yg%í«–¿ËEñe’~)dÙ-f~¹ATßá æGt¬bÓÕÙ	+PÚ¯‡0.ˆnÒ_†½°iÚÔŒ9Žv„ÄlyƒM|‹¬ð
++-é÷‹Eÿ³v7•Ýá£Í¢ò;b~ºÏVŸ?ª-ò”(uˆ&
+âÀY­%{0kJâ!viÔéÉoa-#“2OvÕÍPΙépÍru<„§6XGnxʡȍíÙ¦'%(’¢7„.Y	é±e挔0Õ±%Q1ÑIÁ.m¾Gηž:UÉ‘]ÓS`æ­Ú¢MÖÈâüªKÈû’´Y ',6Ò.rXFNب=ª«j’=BH–Éá ­¢¸ròÂù|§uNüWn"‡ÐìfÐzî‚9¨)±4À°€³[èjFzõG—[Ñ—sÒ¶Êúý":NÉ«Pãæ*ÑžÛhÓ#1Âü묇JILxYLmµ¡t÷ÇóZÞÅ'a
+Àƒ¾4¸õÉËÛªµR¡æB&®Höfã´ýÈͼÕv<÷¼Æ·‘¬oqʉ]4¡³5’ÝF§Ÿ,xj#åQoÁ"
+Ý ËnçÐ+Ùr¥’S¹->M›Œ;ìˆíñ4ì†=Ñ<½‡f~‹dˆÉƒì$9(vid©øa³±˜÷ðæ=è(:†6í9‡D÷'ã·2]"¨Š€)½QÖ
+¼ÑŒÆ›x»¶ˆ*ë—PÉméh!zÀÖ=\w˜«ç¦a+ÜwñLOoCk˜,ÑZ00,3Úœ>#+¡ôÖÇ·ï¡7á\\†ÿ6s’°aüÕƒLî./}*nì˜ÇþAy´ 9ˆC£Ñ´ASð<ô_ÃØî2»·[ŸJ>„KÑGí_“kO
+-Ç:ún	[·ö­.U*[7ÆVÅY(!Eä~À9/ý³ìñ§¢iïÉVÒ'µIçß‚™cñëxà“·s¹uI¦GA,NC`\htdRb`˜30Þ»O²øÚåÛŸ~Þ6}£ ©Sºk˜M¿“c!Ë‹î‰Ñ~$‹$fÜ1’¯Þÿ€¾ÒŠ¹de\D0Q%15uņÊfŸ†‹glÎazNÐM|ýåf[´íºZØí°Ð}í Îo‚Z'<	í­Fç»âŠŽ<£t‰Es%¨¢¾xúíè¯ðßdøÅoÊÄK	iÔJlÂ^¸dÍHú]aM*eQEw”ïKÐ4¾ÕHi›öëÓΚQÞ.?´µJÜ1¬ËEà‰Qð|‚ »ž:cx@?Éœ!«Be{yÐXn
+J“tW4V‚&@͆,cª$¡(Úªóì«ý_!áS‚E‘Òüʼ¸ø⮍ô šƒEI
+»ÿY¶4:N¥‰I†p&Ô¸ÓTVUP_Tç¶Àw™["'½Ž,h,ûU÷N^…=*кÓw*TX׋¹†\k<f#ý	E ùìtxZQ£­/®’åTÔî挊
+Ó¥&G…z3:‡m	mU•óøÒ¥ëÍ	Ͳ¦=M™e‚¾ƒ^#W¦Ë!™‰/L.É+Ï®(M®÷ŠqUx¸sî
+îúh`&.Yò®«É»j‡,ig\+Ñ°/=ACíqÎÜd<|ø\.údà‘5Àlró+ŒÕªehRë¨$‘Øœz¨¸ÎØÐrÂä¾6_€žö¬+¼µ±Ë¶li8ûÓÃ)x”û­kA»èߺ¢Àz§£‰+zÏÀS±;)³Ó	éÖ]ý¼úÌ¡´¤}%8‹QjF³¢.¡ÁUbä Ô–7Ìø
+´*B¢™<lŒ’‰þ×Ѹÿãä¦+µW.p§"6ÐÁÞ>Ëàa)é³DìÙnaE}_X_{±˜ØæÇh1ÿ‹‡	¸ø(WAôÒô2ÛõÚºJbx»³½\™Ù"“~ŸÁïeë#Œ¡AÑaáa¦psm•±¾§…#Îor­õÉêðèãIg¼-‹™W{€Óv—Oœ»Þ1áY.YœVŠüÌ£í]áHÓh’Ó8¿uÁu­SI8Ä3§
+Ÿu|Á0Y¾òhòåxFú¸&mwZ­1<ØOfÑ–…3CæeÞÈ­=¡º iÒ䥂ê%#»™­Õågs Õ뎛ý/øÞ'Œìõù·Èâéò[3
+²î¦üC3ÚÓÝë»/æ;øgl“.ÿ:Wi–ø©Hûá
+óÛÖã$|%ÑzÍ_U\TŒŽáâ?¿æ7ŽU›u7»m¤±ü›ì|Õçêˆh<ê׊·„ž¾mé‚™Êöcú²ç?7 at 5U†ÇÒsa2ò@í‡u\·gÁ¯øÈ.Hx>:öã
+ŠŸ‘+!#7#¯ÇÖ’àÑu(¼Môâ¢íC%¬F—žzȸr6/çüÑ6QØCˆ*	BI«¼Z—(ì¡\“'‡$ˆILNMÃÃq?[>ŠþCùo ¶¨vÃ>Í>õKùN_øàúð¶õg¯Œ%WÕjÏèŒPuš:á*ˆïãBLHoÓMž³0(K`ñˆ±ïŒwƽ«Ð:Žø<éKãáˆÁdD?xŒ$¥œÞ+5„Fû'º:\q¼ÿìêåkù2mIĆ_C·Áy²¾«Ú[ãLzïiàM6ÖDI~²nØvç»L×ý‚î³eGÌ…B¬£I¾£!\t±Â–š4¦8òIêô¤É8×v4ªWh„ö¾¦ä!šÍêH†ît7C‰:/)S‘œkÓmÇ#Cz0yy}7<”°Që+\
+TÈÿd›™¨Oà¡ËÊ,ú5Ù>ÃÍrá+»BÐwC¦[å;DĈ	`w¬`ÿEâëª Štÿͯê¾0Á1Å›Q ±æÁû&ë¶ëÛ¡™—®VÙHäèîgl†g{;0ÆsE_ÈNF¬§×F(äʃ™r¦I
+nñmöjÙR²
+˜ÙKœ—â«kËÕé
+Ûµ²šÆÃùõÀ>å5UæCʶ|³j±jUð|ÿˆMàʼý$âüÅCûÚ˹44‹E_èï²Õ£ñÈm·Ñì,N+Ñl>ӽݙÕý¥]÷·=2ÆËŒhþZe#þ.{6ò ›_\XxxiX“¡(/‹ØHV«F‰ÊÀ´…«VË’“A
+*&-S™™û3Ô›ëöÏXoüy½AôÝi1ºƒÓX]|)ˆ¬ÑZ@+¥R¡uyœìÛѧð4ÀÞ€çùàEx+(èî=ØG~îuén =E•ß,TA¸Ž~üñ{³èȏÈõ¡˜wBØIzpšë®i©Ë‰ûað2É‹çh2âΞ€§vH2åsÜ[9LšºþèKZ«ãªýRÕ Qqh>
+ÌÃýoÏ~gËœ
+«exoS"íxZxmÂs/ÙöxšOÒ\ůg«ãk|cw)œF­!‰fÔP”QŸýÉùe=MÏH—Ïš‡{;Vºìo,«©æÐÆ×ÿ“Û„¤Õ^!¥fdêýý‡UÖmÈrÆ3ôΣyÏm¤˜Bûя쭚ӗIjnM;9î­yŽóL±ufƒ©îˆ3ìä̇/6ÓúAô”dõÚpWYð6U„&U©NƒTMšv1ÒN¹<J¹’[ÍKÇà¡KB\Ýæ—žñ“5¦›M°—i
+3„D&ºN~¼‰P¿‡ŸÝZuã
+£+ÿŠÄ
+Á|t‡DÎ|ütqiýD°ÔkMB\\œlùÂèIðãBǁ¢ rË8éíÃöÈÒ"6óîkÔ~}Ñé÷µh6‹Ê§KHñvàvÝÉ1b~ÚàxWwÒ3Y¼÷”–>6â·Ôe%¤¨„VŸíô·BU¯c•©ø^V]G߁C6·­|·ÍŒbïÛH"€Û΢×f?ÅÔ6·?_m¢
+Š†4b Pÿ˳T™i"鲘”­1ËÀ¶g;Sõj‚)f¤&Èðar´Ô¢l>+ƒË/i>ñƒªí9q%>:/ØÂH&–Ú1Ò=ÒË'|;)dëŽÇŸÑ'=yCiUee|U@¢_ÚvûKc‰·fž}ƒ¤-^
+²M7N'ü‡šLpúI¹.~DÅí‡ûF ¯G+ØH;‘-ú‚­¤QÐt´²Máoâvz‚KPåNSÉîÜ–³®ïσðÌâp™ôgl@Ì¢ÇHüõ?È}Ò©ß`ñRŸÍÛb8ô¾Æ®‚ೊâ¸vøœ”ÏõO”‚Õf®Ì6ÃVb·Äû;n'}ð¯Ã7+sªÑ÷›„Y5ZõH蟏 ÛüHöPv’‡Wü™ÝæÅ4¶NIÐDµS“„&#½{#+Éww÷}¸»iW”óP+B!	¨N*¯¨(Ù}fC›ÃDüÚf,â°äŸÞüÑÐuZˆš‘ÿèzÑ—EÄ|ÿ‚ͤÀÈ`¥÷u¡²œ‰`Ò‰ëKrÏdgÝ Mƒ<%ò„9X0	À2x“€ËåÐ!8˜Ç¥áý9'2*ŠîøéÊMG’—#QPõ¨#6Òëh&¿Ý¾[¹J™sµ]¹zaÓÂu^Ûý8ÓNö“æÃÇà"óhê©É£Þv˜§sisæò“›#ªâéýµ!öëGþlُÈêëÛ?5Éz·q±Æ„¼•û˜Qîlm|{ðûAµ±íÁ„Åó7Ͷ_øáíÓõ¾lïFIÓ£;üH%+!¯¥Äè
+Hã¤7¶¯wÒí	ãäÔ•š#‹£‚S¼–ðø’˜®~¤
+$ A&L<uÃÖ87ÎÃ%Êæ3xàWcå¹Ö¶Óð.›+¶3³üÇN{9x{B{
+.ßï÷:ƒoüÑìä¥îÂØ£†.Œù¾„ÙQ9ÿÿ3/ÕVe*lSÚIïP5Aڐ¿†Ù´už;㸨FwÃ`&à^s²sÈ÷/Q¹ÜÌâ endstream
 endobj
-101 0 obj
-7650
+96 0 obj
+7536
 endobj
-102 0 obj
-<</Subtype/Type1C/Filter/FlateDecode/Length 103 0 R>>stream
-xœW	TWÖ®¢é®·”BŒÕ¸ïŠ‰	.1FÜ%*—nِ}—­ûÒ Í¾
-("´•n\"ÍhÔ,ÆD'‰ë¨‰3Ñh¢£·Èc&ÿ+ÐŒ'™sþÿü§çÐÕ·ß»Ëw¿û]–±µaX–åÜ–Ìñžüºüï(i+½f#
-V-Ûè;Ñyvp°ó
-ùÎ+ü#üãüýº/wÙº=Ò?ÜyI˜Ÿx(Ã0cf‡nœæ·Õ“{x@ÄæÈÀíï-ˆ
-ŠÖ.Š	ñ]=ÁeòëoLyó-שӦ3ÌPf3—Æx2îÌrƃ™ÇŒd¼˜ùÌ{Ìf%³YżɌeV3‹of	3‡Ϭa–2nÌTƁéËôcú3¯03€È82NÌ«Ì f,ÍcË$3?°‹Ø›¾6i6Oë'll#•ï(o««ŒªÜ.;ÍçOöÐö(¶{Å®±ç¬žWíçÚgÿ¨×š^&‡ͽ™Þ•}Ä>;ûöí›Ó÷©§ÃoŠå:¬èb•V³ÒúŽiBú.ÝÎ]fz,Éé|昺°ìðì,Ø|¬FµÇp ¾†Zo嶃?„ç‚Á×ŽѤ:O\”4ª&Ã8Mð즆ã9r[Š'-J’¨rèP‚U²3³¨@×#«öâáG߉Û’ÍïŠz´Q‘™;”îœüÔäK
-Wkø
-öÒ§ûn䐹Ú~áSÄ,‘ÔÿÙ€s²3š¥ÍìA´Çyh§6c¡$RãõúäL1=fëüIÀ“!€ãœÉÁ8ÐxF—©×ëuzuvvR„óÚýq»MK]'\þJâáNx‘×~œ„£pr#òF‘¦Qý±œÆf¬µ²8{ãßð5Å¡Ž9‚æiçƒ!É›Ãi×îÞÿqêEÒ«PÃë÷^‡cü=׫dŠHV’ϬÅÜcÓÌ5î~n¤‡šŒ!7<>ö¨$ÌúŁÓ	§vøÍæõ†ôª™m¤• ½BªÇ0MzH&×)ÃÈ-CóÖÊ°ê-s±A¯ËRÓâ ŠßØ»§¦¹¼µ%À2×…(ü	/Ž˜­¹L~íŠð
-¯®A…õŽFr;X>ÞbÅŠã,GGœfQt¬ÂZA«Š"c6Í$sä ÐrFu¿Èw–Ú‚û´ªwSµãDO¬@N-™úÇvý“Û¿d]¾~ïJ&íg¯cÄÓüë
-€…ãÛNC9-¹xê›/ÛB›“‹Ô
-uy•†ìLJ>I|TYÌž=eU¦ºØ&­Æ7*6Jô­ó+ô¦aŠï½ã\äk	TÇÅÄn†-oߏuëÀcŠú4ñ¾þ2iõæÍË)–N¼pÊ)”Øãííç}ìÁ/0þ…ÔKš%T1!Ci	bVvJzfvXŦ|Ú!d,C±ÏöÆLu}¦9#§-ÿŽDy/®x&fTës‏‚ìH5á¸H/7 ¢ZÜSudóG°œNaßt:¾Í½Kí»?0eÑ¢âeÅpœÿô.˜P‘ïns’
- xäÖª_P¬ÜÐÿ…eG¾?7D.ÛOª—ûé/ÿ/–ýµtñgÅYÕì/ô®^Èhn%ÃÑK«Òö=:›ßr4rC®G~u¹õôe±]»š[¼>¯¥4ÊNM‘A-µýŒÃåžQ`D‡BhÙÒèçèïßØrÈÜØ"’¹de¥3/áì"H{áBΖHã¸n2ã_
-ŸJK§2onÖú¥3ßÍÚ}JÄûñølS¹QŸ‡>«»׬bÎtÎþ­ÙÒ8rkÜ9Éâ·è¨èð£ó_£TÑ$UiQ"[p‡­ó§Q]5<†ýð	ü®R·È8éÎUŽ~]àZHlhßÑxk‰|Ú:3†ÑÓpoÇ@m­ª-ÎÊ:øÂVÐÁ
-z-÷æœ#C¼ˆ]¦«¶)¶~_ƒé`Uú®¸bÑ\XG9Œÿ¢Åšz#G^'ol 
-ä£/~ó¡¥µZ½	4?‹m*SÔ˜Ò Q½8* –'ìia‚klÐû¾æ£? ÓøÓNYÈl=÷‘t¦(¤@iº€i¸¾´¸°à®\ïeYë!fB¸œÝ¨ÓïIåõ\§ùJ‰7ŸÊùw¦ù-ö¥0/IØ
-ÝŠŽ[”`ïù$¶#×ΊãoÍ+_ã`õ’(þÿ¨iÙk'ÏP³}æeÛÿÕ€{YÉ=y‚Ų¬òûø~¶p•U•UÕm«N¥–‡îÓ›T¸žð=ì¹6&ÈW½ÓG8püä.ý®þÖʈMê`Ÿµ©A06O¬¡•±ÕÛ1i¦ŽžVö×Fé7Á¸ËSnÂ5´*+hUæ@D-܁D=è²ÒÔäíÎdž¬üѪ
-ÒM¤ËC0Œí2ºÉµ†îdˆýúVU¨n…QŒï‚ÚMÓþÅçÇåÊmG[̘_s$­#ºujóã»ÞVÁÎ<cï õĹ÷ØlWà§8W¸GÚ'=—Éfé¡™m¥Â/Q–Îeø•p0ƒ¤T écÇIÆLÉÁ„‡"}Ù&ADi´)|w|`2|	
-N–=üÊXCךs	e®T}L‡¥@RCB¢£·¦F-ÎmÏ3¯õ]·™«Ü|5jB¢SÓ(Æ:ÅIS_¤éð!±ß›øŠ¥™ýmp	Q`Þ¤ã	†ù¬‡!„‰Z»ßGm-,o„}|Khƒ¯64T;éÑJºüLûî‡G†ÿH&Õ‹wê?9ßñWÜÎ5±æ9}Í¡ø=
-ªŽÖ¦î_k--_@>ðwÁ#$$kEݶÀm:]²>ZŸ¥ËȆtÈâãò¡Z|‘UªžåU¿‘YÑ'¬c¥ÙªÝú¼ðX$$‹äAç2¥? *ÂÊÄóÒÎ~xõ4­céb"…	äß#½„}q‚ùgT–ÐS™£&â‰R…°G=U£utWú¼¥±êäJ™;¡$Y¯ƒÌTq]üû)^á>Åk+Ó
-Ù†là“!5NMZ©rK©.2äˆ%eÍ­·h²aÂÛn0ŒôÞ´¸ìã@u{éášæmõ›B¶Ä®ò+öĉîbt˜z›Þè³#H£~áóGh··™=†`ÎÁðIî¹½ÕXÚ}Jy¿9».Ü?+>¶òõ‘M{Ì•­g7~2”ô%3g’²ù@Ê1úÑyìeÒ3z¼µQD–œAøGY‰f¸
-…<ön?yæ!Ì5f{žîdm;91^òêl–î…E`+97 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 98 0 R>>stream
+xœW	TWÖ®¢é®—¤b¬ÆwŒ&¨‰cÅE‰Šâҍ "›ìû*[÷¥Aš”U¡ºQIhF£f1&:I4Ñ£&þ&:z‹<f2¯ f<Éœóÿç?u8‡®¾ýîöÝï~e¬­–e9W÷^Ó_“ÿ/
+g¥W­¤
+ ›_µŽèöP‚­l­¿:äã!hŒÞqú FÁ²n+¼]CwÅ…øïˆttrà8}ölÇùÁ~áÛ´!ŽîÚÈ~ÁÚHú!ÈÑ3t[€_dÜTÇùAAŽkä_D8®ñ‹ðöóísî¼+*Ò/ÜÑ=Ô×/<„a§ù!ÛB}wùm_î±#2 ꝥс1AÚå±Á>ë§8OmÆÌ×ßp™5{ÃŒbV1f³šqc3ãOf	ó³”YË,cÖ1¯3™õÌ
+Æ‹qg0“™
+ÌJÆ•™ÅØ1ƒ™!ÌKÌËŒÀe†1öŒó
+3œ™@ËÂX3)Ì÷ìr¶ÑÊÁJoõTñŽâˆuë«Ê8åÕU”êçÀmä:øu¼ÔoJ¿f›ù6×ú‡÷¿nf›eûÓ+ø8ê€á<4B|u:ÞÂE„–äÁß…Cí±Fu‘8+§hT͆pšágØO
+'s䶔  OÚ”$Ie×­‹dcbQ,nAV!ÄsÂ>ï+W÷oˆz´R‘¹»•î‚|Õä37
+WgøҧϷpÈ\ïºt¤&bžHþlÀÙI9™­Ò°Vö(Úâb´QH;°ŸPš
+i	z}J–˜»kÉ4àÉHÀÉ'Îåâ0f<§ËÒëõ:½:''9ÂymKüþš£e§¾!\ÁZⶈð„#¯þ0
+Çãô&䍢ݯV¯¥2ÔÏ+&¶‰ú)E[…Ô€¡ŸöL'.3G“¡dؽ)8]n?Ä!"1Õ
+Øï›Sð^U«ºöø‰}ø+"ðfU¦){þ¡yÚso¤¦[©¢¡_JbúfæÉ“Çrؾ%˜Œ8û‰I©ñÇû˜â÷ï7ímë\Ðû­+ŠË„Ž°³PA[.žùò³ÎÖ”buce}þ^CNå„d>º<öÀòªšú¸f­Æ':.Zô©÷-ò¢iŠïüeQP±9@·üAS·½&!"Ó=Öð-Á8çæû×î¬n/½ë—ÃÊ;[!+WcL9
+UP˜[QRÆcÿa&\>y.ß¾
+n›7ƒÛLõYâ-|ñYòú;VS,ÙûŸ=zé"TP(±]ÇCìÑO1áS…4@š'T11Sé‰bvNjFVNhåö:Ád"¡£pPTS–º!Ë”™Çӏ‡ƒ–ÿ‹3D{­¨|*fVësく†œH5á¸XȨ0 ²Z<PubÇû°ÎààRtè3ÅìSû´¬-^^²ª:øîB
+*
+…ÄÜäB(¾òêÔÏ™OèÿB~ã6.–Ûö£êÅyúëÿ‹ü~eͽ¼ÄYp^5û3õ5À¬@íc,dzjUz'o'§~ç
+Òčü&òó«íg¯Š]ÚõÜÒà UðIe7vVªj©ó'#ÏŒ#ºBÛÎ&_Ÿ +¼…&‡ü\Z\Rt,\˜.¶CxB¤ì©´>gwvf¶N§&ËÈ8¥¤áþ.¹W
+pù7p½ÂU–V”ÕîÃÄÙÞ¸›†¬çÓb IÔpõ†©a'”ƒY+¥2/(Ë­}Šî[”`ïùž&Öã6-Ln-®X“`½{´7ÿ”šìÓÔFÍý¯lû¿p/*¹'O°D–U¾+ÑM 0
+„ɽP»Éaú?ù‚ø<yìèˆ*q¤µG×mABïÛ*Ø“o¬âí¤þ¸ð[Š]
+ü
+÷H״ߤGŠIzhbÛ©ðK’¥s9~.ÜÌ$©$
+HÆÄI at R0Ss1ñ¡H_v
+QS¾?¡0>ƒK…§Ë~n¬¥·‰å.T}́•@R“‚ƒcbv¥E+Ýq¤Ëñ&]O0Ú{Œ$LôÒ¼oµ¥¨¢	ñm!>ڐí´Gkq ÎþúûGï†ÿ@¦5ˆw>¼+qry®|éÊu¦Â÷&ŽQ`¬Ä÷
+_ߝA>>¦ c}·ËúOïìRJ»”cn­V‘ÍFÎbƒlÑÆÚ¥Ú¶_K‘­-²u¶rmíæßE1Ø
 endstream
 endobj
-103 0 obj
-4070
+98 0 obj
+3974
 endobj
-104 0 obj
-<</Subtype/Type1C/Filter/FlateDecode/Length 105 0 R>>stream
-xœµV{PSW¿×@îUQ[ÝÛjËÞÛŽ£VTt«XmpD°¢´¨¼%ò’B*Ï@ò% ¯<xðQ*(VQQ¶µ¶Çmݾ·îZ۵ݞÐãL÷ÄGÛÝÙþ³3;™drgÎ9ßw~ïwiÊe
-EÓ´Ø?8Ô{¹óß|dz´Ã}Šã÷"À±“‡'£\ÁMn.Gܧ·ÏFéO¢³Ð’'(MoܲË_&ÏV$%$*=ø/ôð^½z•‡oªD‘´'Vê«L”¤Æ*ÉCŠÇvÙž$‰2{‰‡oJŠG¨sGºG¨$]¢ÈÄ?(í/K•«”…G°,^¢Rõ”¯T&Q$¤+“TûRb³R/Yæ½|ý*Šúµ•z•ÚHm§6Q;¨0*z
-¢‚)?j'BÍ fQOR³©9”'5—zšÜŽb( gÒJúý)kDž¢+.Oº$¸Œ»¦»öˆ}†9Ϻ±^ìöÇ©)Ó^šVý½1ŽšùÓ”[.ØQŒÝ±ÁJ;žžâJj+Ô m©&Kîÿm®:N–¶EÇJ™K‚8mZÖÎÄê6òTcí š7Åç°·ñ-a¾¿z~l¬.<„Ç~cåNP€®“ù}ÛDå79–[éÎ	Ô9!rD£dqïa»-öijñï¾y‰Ñ´;_£Ù<NÆQÜ^ˆjÉtáôÀ¥®Žã'Ž@/ËnïŠ„ ؉œ!Û™%g•>/RÉ-ÈÿA¡Â1‘cÊåš`ù6ì6žÅ+žÇOà¹ÿX„Dhú-FoáLÈû3sü-Á±6vî2ØèKW‘ÿÕÞ!Ò1Ú̝Léƒ`¿xûí…=ûº…Þ¾“`„rçW›_¢É‡<V]} Ád66™Õ‰¯ÇïËUó©Í‰µ"ïM¯„Ù[] ÈÍ–B<l;¢0i"߈L€×ٍ·CÑ,4ýîÙZ‹.níâÃÛv‹Emɯ.°€
-+«ëØ»ùÜ
-ø¶Ùýí‚ÅÞYmö3˜¯Ì†¸ýr!KššŸl;FÜ~CL†Þž6¡©®
-Þör…?¾º.b©ó–>T¾Õ±ÒL@Ù"ô¡c
-gc~a–ª ˆOiM©Ø,ž‘°yG$ö$
-ݲÃEƒçòjK[3͹µ*±1ŠÝ+6ïîùFÅ—˜A¯ÓkËK Ø<Ðd؝ÉMµQ¯·5òÆJ0Ô7ôDC#°ßŸ¹9œÜ]P%$tÉ+6L­ð«ƒQ¶Ë6ø¢+–¤x}a%”[F³ðv"ÞgìÈÇJßGîM"´Ö1ŸCžv쉂TbWÂËJÙ̏qƒEוg/{¿ ÚÁøKcãà«Fžœ2ë¾S<lšs‡FôeòsÜçÚ2šeiªyjKVK—¹­‰Ç<á¤Ì•ªb¢”Ö_”rŠ¸ªFàðŸ—{‡óÐÛÅgû{]pøq•À¬ŒÚ°~µæäYý…ÁžN
-N@ér/b :“[Òú¼E@é†Ãv{sC‘0H¨vµ3…•Cr8‹¸\t¶.îFé}Dú"t™9Й@e—‡M¦«£'ô6=i,S›©á 4‰Ö¨;X-£¹ÓɉBrH&ëCœëß‹Ö&GS±×\ƒ¶¼˜ø¥ôå…ùoD‡EçÅ8S¨‡¤Ðq2p
-pÚ‰NzYI=ÔAC¥©º¶Þv¨¿¥«#±=¡=¡QE,†Â¹sWÁ´ƒ¤—F»^ƒlCz7áD´ô‡Ë§D'cÿ#~| vkN¼úFXSÐÿ-Šþ—Ð"zÂa6´žøÕß*B¯—pc½ñÒ,UšÜ¢ê¬¯©4VðeezâÖ-BÉŒ`q°¸½ùÒ•¶´yœ?wYÄ,»AÞØ€/†Ÿ€2[[}wG–EV ])oygxp؏ÏlXºr—oèGá×tíœO“F§u§[Î_z¸	Ñã¨nÑÄÀï;"¹&^É'‰wOWÉ€}n™y	xâK¯ïFß<Ú"T½v:³ØOkï"
-c_4{á+99 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 100 0 R>>stream
+xœµVyPgïv`ºUÔD·LÜnؤ\5^˜Äc5*`‰"`DIðB@Æ„™a˜aցaf£3 ×\\3€J8<P<ð>X5&ˍæ>L“5Ù|Ã~Ve{<²Ù­Í?[µÕÕ]ÝUïûÞû~ï÷{¿&‰€I’ÂÈØø°9þ·É¾Iߤ¾ß+„ ìŸ4ú£ñ(÷Y´|šù! Éå«6DJeùòqº"dJäԐ°æ…„g‹ä[S$!±)ŠtQvŠ‚ÿÈ
+Y+Ýš!RäÏ	ÏÊ
+‰÷¯È
+‰åŠä*QÚ£Ô‘Òl™R!’‡ÄJÓDr	AÏ…K¤"¹8W‘¡Üž•¢Îž>söœ¥sçĈÕÄ›Ärb-±‚XG$ÑÄ[DKDë‰8b1Žx–˜@„ÏÁÄóüéŠ+Ú ®?ê^a¬î䃅S\(áÔ'.dv‘®¡ÈkÝý|Åh%s$«ªþâÊÕ›­º®í\wÏ°Ànÿm,*5–ÖTí¬·Ù-n»Æ“þvÚöB
+›Ý˜^ÃC¶"jqüþmUÅÜÎÂ|	¤Ášýr›aóŸ7‹ámzùÝx4¾òƒæ’s«ÛÙÄ–õð:ÄA	ä;ŠªŠà‚kCU-}¿ˆy¾o´CoC+çð¶U¹€þ&+ò!u‡ŒSK²‹T@·bļÑÆfîîjáܵ•ð.ÐwP ¼öæ’M³ü§,žO9}síäÞÃ(ÿ°+n(N^Ú{ñ=öŒr)II‹‚¯X~—qýä¡{Є{$"/	P„ï!Ó¢j”æ(U²ì&uS»½ÅÍbÇ1êr¥žgJó¿˜r”WU5œ…}t^jéæ|Ôcmó(¾ØóTÛèŒ/‚yÊ´(jnÒ²¥GN²è#
+‡ú98es8<‚X·e6åôî<΃Òû¼ÞÆú.àIB!®*ÐKEé*ú9äó'	8ç/]؁r{xêÐ^dg ¼Äå°ëÒ€Ívíü¡rW9_Xž1²!Aaæ'ZƒiO1Ðyyù&¿„ÇúTæ~QÂCׯÏ×Æ_GÁóË„ù;uùô™…‰S2±NU¡
+¯1¨øàfs?/šƒ`†ƒþ`d´—~Šðp`Ïcx—G3¿‘¬ÿQ²c¿JödD9ÑGóíóNòÐu”:8äøžCN†g=[ºÓ;’j·+ÐÛ¥ÌEUwšD­Ì‘9”muÕ+»kW9¯ÚêœÕ[6s¥e&#”Ò‹ÁR9tQO¥üôž+—\’§g7«[Ý.û˜{*çðN²wÙx{\‡ÞgàŽáCñPêH÷XË$ÛæKcŠb0­"¢sY÷’k¹'àS8vÂ{¶óó·p–ÆÉø³¢íjDjÏÃ?roÍús
+WŽ·û[zVáx½&A¬€%Ú85£N‡'þ×Ñ?î¢@/ÙeÞøbÐ"F),Û¡[WTPRÏëšÆ±ÂÖÆ—[šÐtrúܧ5û&ïátÔ”×Á.WK]‡GíÁTÆ:®ô
+ýñ‰e³æn_Åá$¬
+Ìõ‘þ™2lñËm´Óâ’nD¢ÚADò¢{ß·™q›Êl†pãPl¥è—fÏàû™/güp¾ïÎ&®ò­cy]@ZsHÃÑ<Gá)8oÂkÐ$¼%v\4;nqûl(p?ÔÑ6=°za!OÛB]Xò”‚Hþ<+0ƒæ (´…¢Éhšˆ–†`ÓýÌY†wÚ¸è>Ô`Ò($[’rR_ó9â‡ËÙÏo¼sD¹¾«U	ÔOðSµú^v~u»·‰ì½Jox3ýžAV4®g ³S›í`wŠ UY§nin¨óžÿë	Æ–a
+Šý‘_ƒžCg~þÇ9™‹¥E‡¯21}ºØUÜRÔïÒ·:ïqÊ»-£Ž­ßë!™³Ij‘|£xÇÖ§MT¹|ï^ßëmßAé0É4b=…Ç€±¦ÔA+…YxS [¸Ë^y±¦Úfý€6Ò…¡xº,m2žø͉ZØÚ{ endstream
 endobj
-105 0 obj
-2508
+100 0 obj
+2570
 endobj
-106 0 obj
-<</Subtype/Type1C/Filter/FlateDecode/Length 107 0 R>>stream
+101 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 102 0 R>>stream
 xœ­VyTSW@ÞS,m_ÅѾdf\kE™C«¥X­ZDÔº ¨´œ¾çáÕ/š#öŽñ>ìýÀ§Eì#V‹¿f♿±¾lÓ”˜)ÃSESg?¢—Ü¡üyÚB¥9…=r¯çÔè+Š¡ôå
@@ -1069,11 +1045,11 @@
 {5‰YÏ Šé£ÍÈ,BU(†ëÃæ8Æ/Ïî^cÇM6¤¨ãøjÆ9ÕåËOõÖ*¦M±œ6ÍU3í1Šú/S\!
 endstream
 endobj
-107 0 obj
+102 0 obj
 2471
 endobj
-108 0 obj
-<</Subtype/Type1C/Filter/FlateDecode/Length 109 0 R>>stream
+103 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 104 0 R>>stream
 xœ…VXTÕ>Ã0ç‰P™F at mÌÄG*^³‡¾®ˆš/@	„‰!ä退‰(3³ÎŒ‚ *¢"£òP b©yíVZ™~Y}š½LËËÍ»mú¼û@jfÝûíoæÌœ³Î^{­õÿÿZ
 ÆÕ…Q(ÜÔ9AáãäŸþÒ …4ØEzR	$t°«ÐµXîJpwmì1ÓÍýq^_׏Q*3B–MMJÎL‹5š|‡Oá;nâÄ	¾¯$R㢣}çD™Œ†„(ý³ÒwaRtœÁ”9Æ÷••+}Èo¬ò]`XeHM7Äô:Ÿš”œf2¤úÎIŠ1¤&23ø•Ä褘¹É†ÔUÆ3Mqi‹fů^•‘æçþÃaæ1Ó˜W™éÌXf>3ƒYÈ,bf1Ï1ÙÅL0ÊŒgF2!L83‡	b–0s™ç&Ä<ICf8&›¹©˜§Øë2Ò¥C9GyÄu ë)ÕDÕ×ì&ön$·‰»Êá÷‰èSìæçÖþØòÇ~qv¿ü¸æ®bÝbÆã®ÒÌ€ˆÃD)¸RÑܵ[)%vjrv­ƒ,H‚‚܍™DèþÑ;ïMsîdàÓõìᨭÂÛ°ßÌ‹œ%Ê{‰ èÚñq:Ø3d˜êjf¿­Ð_A#5É‘ï¥x
 ²¤NE2X».Ù_ÉnoŸŒuz"KW$²^êÇEžÛ#œ± N[öXyq8T\mûGƒ#}²–TÏxÔ ”ûyñAÿQ¡ÂS´êKÈpdJ®Jϝ-‚9ËyÜUÜÌä5I}›ð	ÂþJì–Fi2×XÒaÿZcÆîºzGËUÂÎ'3_!á‰Ï÷ÏàüÛ^ä‹Ê×ÂúL«%;_›²,#x¢ô?ò6à µ9dJ÷Bo2]ŠPý @£!’ÊñK`¤W¹f?2˜üüWOq㯊Â5÷QXXAR¨7u‡>t—÷ÀNÀ€óyÞ¿‰JÜܥЀÍV6þ`l}ddl|-¢m½öx7c_%Xà³ì6{%‚LÒ´#ïéckcc«öþ,ß)~‚êNy$ÁÙèõ”,¿ìð”c'þÛYFùàQH£82-Ïj¥L´øVÝ}‹ûòƒßÖ:ò³«µYyÉYÍÇÔ¦8÷×Ö4íq!ýÈÐÒGë?E‘tÊ$ê¡ 7(®È®—\=6iv}4”œ­]A[Ia1F8X²¼ˆݐ}Lëæ:¡Ò½OS‘»;²{ÜÜ=æ¿[ôý
 endstream
 endobj
-109 0 obj
+104 0 obj
 2974
 endobj
-110 0 obj
-<</Subtype/Type1C/Filter/FlateDecode/Length 111 0 R>>stream
+105 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 106 0 R>>stream
 xœcd`ab`dddwö
 Ž44 endstream
 endobj
-111 0 obj
+106 0 obj
 237
 endobj
-112 0 obj
-<</Subtype/Type1C/Filter/FlateDecode/Length 113 0 R>>stream
+107 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 108 0 R>>stream
 xœYXT׶>ÃÀ™cWðPï9¤Xb‹=Š&cA±¢ H:ÌÐÛÌ:Òa†:EŒ]±bÔ$c}1ÑÅhcbî:¹›÷½·‡Afrã-|Û³ÏÞ{­õ¯õÿk#¢,-(‘H$Yìæî>}šá×qÂh‘0ÆBø›8Ç
 ûþpµBƒÅh°eó‡kaЈӆSb‘ÈyÅæÅ¡»c¥þ¾~¿í0}Þ¼wœ‚}¤þ;¼Bܼ"ü|‚½"È Èam蟈ةNAAko„;¬ñ	÷‘Fùì4î½84xwd„ÔÁ-t§4„¢¨e+œbCv¸-
 ݹqåâÝ>-	Ûµj©Ôwµs¸ßš#ü×.‹pw‰
@@ -1156,11 +1132,11 @@
 <@7x°~ðŠú+´?
 endstream
 endobj
-113 0 obj
+108 0 obj
 6149
 endobj
-114 0 obj
-<</Subtype/Type1C/Filter/FlateDecode/Length 115 0 R>>stream
+109 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 110 0 R>>stream
 xœ­WTSWº>áHÎQµÞ3ƒÞp¨C­Õj¡/Tª¥ˆÚŠ‚µ<äž	ïWx¿“ðˆÂÂ#bˆ¨UEKm©vlít°h{.­ãmµ3ãc‡»Õ»TÚÕÛéÜ»Ö]‡µVöÞÿ¿¿ÿûþÿ;"jŽ%‰ìý¶l÷¾,³ýFd{ÂÎöï4àÈ©ÛS;ìÁ‡9Ö'êCºEhÛ䵐¢E¢Moú¥¤*Òââ3]Üý<\žññyÎe½\šž™ì²%23^*Ì$ÿÈ\‚R¢¤™Š.ëe2—íÂŽ—íÒiz¶4Fˆì—"OÍÊ”¦»lI‰‘¦'SåªHŽN‰I•n‹}}cz\F|f‚ÖŽì¤Yd®<Ê멾µ›ÚF½B½Nm¤Þ 6Q+©W©g¨eTåOí ^£vR”L­¡B¨@jµ…Ú@½Im¥ü(GʉZ@¹Prj)¹<ÅP
 "G‘\tÑn»Ýgôô>ÏIœsÕ~ƒx±ø4óSÆ\fìæ®›{xÞŽùôüõóßs¨v|ÉqØñ¾“£ÓJ'ë‚ÀïDQž”Ówv+ߧð“íS‹ÈðgÚ¶
 }Áõ¾7Ô`©a-L¼J
@@ -1191,34 +1167,34 @@
 b©g,ó&çóóæ<×é0פup˜lup¤¨ÿqfù7
 endstream
 endobj
-115 0 obj
+110 0 obj
 3328
 endobj
-116 0 obj
-<</Subtype/Type1C/Filter/FlateDecode/Length 117 0 R>>stream
+111 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 112 0 R>>stream
 xœ5P[HSa ƒ…+68«x³Á&No­¨æîC\¾ÉÄé¶NÇ;x»‹7nõj­f[­“·sÅV#o· ~!^OR„Z ™-,J‡•6RAøN÷Ó·©Ø bˍò‰ö98Ãœh¡…rJ„•ÿ²¾¢ï,	ÄPçORA%Škò¶zoa]ãÍæ<Xi\"¼›÷-EC¡Ð³qøžFÉX6‹waEVNféóæ®'=£†®²ñ™§o!½6y<ïäå‚SEJìÅf¯×烦âùß^×èkD!ek/ÃÄÊ/äA$‰ÆТbñ•.K
 /ØTw§®(…öGAØG;56óuC’èQ*ÊX]YÕÄ	!öS0…ŸéùÌiÌà¸ìšò°Çìë¬í±µ³c/¾Á{:rÏ›îkVº}¶¶&èõ5ú`}£v³ÿ_EÉ‚Xê'D°@Š3(W!à8ñ€vw[«§‰Å?6ÊdF=;Ö£f-F¹ÿÖòŒÀåV¿,”Þ+ç©\q¯oâ~*ÑÕ»~¢"k§º(!~!—ªýLÜPÃ,t3Û endstream
 endobj
-117 0 obj
+112 0 obj
 656
 endobj
-118 0 obj
-<</Subtype/Type1C/Filter/FlateDecode/Length 119 0 R>>stream
+113 0 obj
+<</Subtype/Type1C/Filter/FlateDecode/Length 114 0 R>>stream
 xœ5_Hq IÑßé¹ÑITÂútŠ±È{:Pò18QJ[o;É3D:|0ªþ׶ˆ–×c<6³Žš—qÁ‡òUVy›Ë{®ÞÛÜrz )Ê×báЛÈüôÜ;ø“D‰ióbª¨Ôi?oíêêæ{n…/Rß>ôF ¹ò2'[kÌ»fQ‹-b“·	rÝ#häqGi!D¬N
 a‹«ˆý£Aô]}UD‹JÃÕóe™þi³:âóÂ 9RÛgcÙ›¥GE‰H½[‰DEIµ6>þ¾%4Ó".âYE§¬½7žúBCî ÍG…'æüc|1ãÒš=—klêJ†åJÚ[ÛI®™kô܃Ýÿ/àQ*/\Úz4Å…AtRÅ‹¸`"‚°ÓÕpz¼”ømãŠÌ‚"zÂ
 ²)»E>é›õñpÎr“ÉÛ‰lxÿ©ú+‘#TmHÄn"ɈŸ	ˆQu—\4û	>aa'• Õ;BwŠ…GŠD endstream
 endobj
-119 0 obj
+114 0 obj
 655
 endobj
 15 0 obj
-<</BaseFont/ICLHMS+CMR10/FontDescriptor 14 0 R/Type/Font
-/FirstChar 11/LastChar 122/Widths[ 583 556 0 833 833
+<</BaseFont/MOMLGJ+CMR10/FontDescriptor 14 0 R/Type/Font
+/FirstChar 11/LastChar 122/Widths[ 583 556 0 833 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 500 0 0 0 0 278 389 389 0 0 278 333 278 500
 500 500 500 500 500 500 500 500 500 500 278 0 0 0 0 472
@@ -1226,30 +1202,30 @@
 681 778 736 556 722 750 750 1028 0 750 611 0 500 0 0 0
 0 500 556 444 556 444 306 500 556 278 306 528 278 833 556 500
 556 528 392 394 389 556 528 722 528 528 444]
-/Encoding 120 0 R/Subtype/Type1>>
+/Encoding 115 0 R/Subtype/Type1>>
 endobj
-120 0 obj
+115 0 obj
 <</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[
 11/ff/fi
-14/ffi/ffl
+14/ffi
 34/quotedblright
 39/quoteright
 92/quotedblleft]>>
 endobj
 13 0 obj
-<</BaseFont/UZYZOC+CMBX12/FontDescriptor 12 0 R/Type/Font
+<</BaseFont/KSKQOQ+CMBX12/FontDescriptor 12 0 R/Type/Font
 /FirstChar 45/LastChar 120/Widths[ 375 0 0
 563 563 563 563 563 563 563 563 563 563 313 0 0 0 0 0
-0 850 800 0 0 738 0 0 0 419 0 881 0 0 0 0
+0 850 0 0 0 738 0 0 0 419 0 881 0 0 0 0
 0 0 0 0 782 0 0 1162 0 0 0 0 0 0 0 0
 0 547 625 500 625 513 344 563 625 313 0 594 313 938 625 563
 625 0 459 444 438 625 594 813 594]
 /Encoding/WinAnsiEncoding/Subtype/Type1>>
 endobj
 11 0 obj
-<</BaseFont/ITYNZM+CMR12/FontDescriptor 10 0 R/Type/Font
+<</BaseFont/AKZNKH+CMR12/FontDescriptor 10 0 R/Type/Font
 /FirstChar 44/LastChar 120/Widths[ 272 0 272 0
-490 490 490 0 0 0 0 490 0 0 0 0 0 0 0 0
+490 0 490 0 0 0 490 490 0 0 0 0 0 0 0 0
 762 734 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 490 0 0 0 435 0 490 0 272 0 517 272 816 544 490
@@ -1264,9 +1240,9 @@
 628 0 0 511 668 693 0 0 0 0 0 0 0 0 0 0
 0 459 511 0 511 406 0 0 0 250 0 0 250 772 0 459
 511 0 354 359 354 511 485]
-/Encoding 121 0 R/Subtype/Type1>>
+/Encoding 116 0 R/Subtype/Type1>>
 endobj
-121 0 obj
+116 0 obj
 <</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[
 39/quoteright]>>
 endobj
@@ -1280,18 +1256,18 @@
 0 0 863 0 800 0 0 1189 0 0 0 0 0 0 0 0
 0 559 0 511 639 527 0 0 639 319 0 607 319 958 639 575
 639 0 474 454 447 639 0 831 607]
-/Encoding 122 0 R/Subtype/Type1>>
+/Encoding 117 0 R/Subtype/Type1>>
 endobj
-122 0 obj
+117 0 obj
 <</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[
 12/fi]>>
 endobj
 35 0 obj
 <</BaseFont/WNYVFJ+CMSY10/FontDescriptor 34 0 R/Type/Font
 /FirstChar 15/LastChar 15/Widths[ 500]
-/Encoding 123 0 R/Subtype/Type1>>
+/Encoding 118 0 R/Subtype/Type1>>
 endobj
-123 0 obj
+118 0 obj
 <</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[
 15/bullet]>>
 endobj
@@ -1315,9 +1291,9 @@
 723 0 0 0 767 0 0 0 0 0 0 0 0 0 0 0
 0 531 590 472 590 472 325 531 590 295 0 561 295 885 590 531
 590 0 414 419 413 590 561 767 561 561]
-/Encoding 124 0 R/Subtype/Type1>>
+/Encoding 119 0 R/Subtype/Type1>>
 endobj
-124 0 obj
+119 0 obj
 <</Type/Encoding/BaseEncoding/WinAnsiEncoding/Differences[
 12/fi]>>
 endobj
@@ -1332,34 +1308,34 @@
 /Encoding/WinAnsiEncoding/Subtype/Type1>>
 endobj
 14 0 obj
-<</Type/FontDescriptor/FontName/ICLHMS+CMR10/FontBBox[-40 -250 1009 750]/Flags 4
+<</Type/FontDescriptor/FontName/MOMLGJ+CMR10/FontBBox[-40 -250 1009 750]/Flags 4
 /Ascent 750
 /CapHeight 750
 /Descent -250
 /ItalicAngle 0
 /StemV 151
 /MissingWidth 333
-/CharSet(/colon/L/slash/A/y/ffl/n/ff/c/B/z/zero/o/d/Y/N/one/C/p/e/Z/quoteright/O/D/quotedblleft/two/q/f/parenleft/P/E/three/r/g/parenright/question/Q/F/four/s/h/R/five/G/quotedblright/t/i/S/H/fi/six/u/seven/j/comma/T/I/v/k/hyphen/U/J/eight/w/l/a/period/V/K/nine/x/m/b/ffi/W)/FontFile3 100 0 R>>
+/CharSet(/colon/L/slash/A/y/n/ff/c/B/z/zero/o/d/Y/N/one/C/p/e/Z/quoteright/O/D/quotedblleft/two/q/f/parenleft/P/E/three/r/g/parenright/question/Q/F/four/s/h/R/five/G/quotedblright/t/i/S/H/fi/six/u/seven/j/comma/T/I/v/k/hyphen/U/J/eight/w/l/a/period/V/K/nine/x/m/b/ffi/W)/FontFile3 95 0 R>>
 endobj
 12 0 obj
-<</Type/FontDescriptor/FontName/UZYZOC+CMBX12/FontBBox[0 -201 1139 700]/Flags 4
+<</Type/FontDescriptor/FontName/KSKQOQ+CMBX12/FontBBox[0 -201 1139 700]/Flags 4
 /Ascent 700
 /CapHeight 700
 /Descent -201
 /ItalicAngle 0
 /StemV 170
 /MissingWidth 375
-/CharSet(/colon/A/n/c/B/zero/o/one/d/p/two/e/three/f/E/r/g/four/s/h/five/t/i/six/u/seven/T/I/v/k/hyphen/eight/w/l/a/nine/K/x/m/b/W)/FontFile3 102 0 R>>
+/CharSet(/colon/A/n/c/zero/o/one/d/p/two/e/three/f/E/r/g/four/s/h/five/t/i/six/u/seven/T/I/v/k/hyphen/eight/w/l/a/nine/K/x/m/b/W)/FontFile3 97 0 R>>
 endobj
 10 0 obj
-<</Type/FontDescriptor/FontName/ITYNZM+CMR12/FontBBox[0 -205 793 714]/Flags 4
+<</Type/FontDescriptor/FontName/AKZNKH+CMR12/FontBBox[0 -205 793 714]/Flags 4
 /Ascent 714
 /CapHeight 714
 /Descent -205
 /ItalicAngle 0
 /StemV 118
 /MissingWidth 326
-/CharSet(/A/n/zero/o/one/e/two/r/g/s/at/t/i/u/seven/comma/k/l/a/period/x/m)/FontFile3 104 0 R>>
+/CharSet(/A/n/zero/o/e/two/r/g/s/at/t/i/six/u/seven/comma/k/l/a/period/x/m)/FontFile3 99 0 R>>
 endobj
 8 0 obj
 <</Type/FontDescriptor/FontName/GRQREI+CMR17/FontBBox[0 -195 744 707]/Flags 4
@@ -1369,7 +1345,7 @@
 /ItalicAngle 0
 /StemV 111
 /MissingWidth 301
-/CharSet(/A/o/d/p/e/quoteright/P/r/s/G/t/i/S/u/T/v/hyphen/U/J/l/a/m/b)/FontFile3 106 0 R>>
+/CharSet(/A/o/d/p/e/quoteright/P/r/s/G/t/i/S/u/T/v/hyphen/U/J/l/a/m/b)/FontFile3 101 0 R>>
 endobj
 71 0 obj
 <</Type/FontDescriptor/FontName/FVSMAJ+CMBX10/FontBBox[0 -194 1164 705]/Flags 4
@@ -1379,7 +1355,7 @@
 /ItalicAngle 0
 /StemV 174
 /MissingWidth 383
-/CharSet(/A/n/c/o/d/N/p/e/r/s/h/R/G/t/i/fi/u/T/exclam/I/k/w/l/a/x/colon/m/W)/FontFile3 108 0 R>>
+/CharSet(/A/n/c/o/d/N/p/e/r/s/h/R/G/t/i/fi/u/T/exclam/I/k/w/l/a/x/colon/m/W)/FontFile3 103 0 R>>
 endobj
 34 0 obj
 <</Type/FontDescriptor/FontName/WNYVFJ+CMSY10/FontBBox[0 0 443 444]/Flags 4
@@ -1388,7 +1364,7 @@
 /Descent 0
 /ItalicAngle 0
 /StemV 66
-/CharSet(/bullet)/FontFile3 110 0 R>>
+/CharSet(/bullet)/FontFile3 105 0 R>>
 endobj
 27 0 obj
 <</Type/FontDescriptor/FontName/BNGLQK+CMTT10/FontBBox[-4 -229 537 694]/Flags 5
@@ -1400,7 +1376,7 @@
 /AvgWidth 525
 /MaxWidth 525
 /MissingWidth 525
-/CharSet(/colon/L/A/underscore/y/n/c/semicolon/M/zero/B/braceleft/o/d/Y/N/one/C/p/e/O/two/D/equal/braceright/q/f/parenleft/P/E/three/r/g/parenright/Q/F/four/s/five/h/asterisk/R/G/t/i/S/H/six/u/j/comma/T/exclam/seven/I/v/k/hyphen/U/quotedbl/eight/w/l/a/period/V/nine/x/m/b/slash/W)/FontFile3 112 0 R>>
+/CharSet(/colon/L/A/underscore/y/n/c/semicolon/M/zero/B/braceleft/o/d/Y/N/one/C/p/e/O/two/D/equal/braceright/q/f/parenleft/P/E/three/r/g/parenright/Q/F/four/s/five/h/asterisk/R/G/t/i/S/H/six/u/j/comma/T/exclam/seven/I/v/k/hyphen/U/quotedbl/eight/w/l/a/period/V/nine/x/m/b/slash/W)/FontFile3 107 0 R>>
 endobj
 20 0 obj
 <</Type/FontDescriptor/FontName/IRVDMF+CMR8/FontBBox[0 -205 857 704]/Flags 4
@@ -1410,7 +1386,7 @@
 /ItalicAngle 0
 /StemV 128
 /MissingWidth 354
-/CharSet(/y/n/c/o/d/p/e/O/f/P/E/r/g/question/s/h/t/i/H/fi/u/comma/T/v/k/hyphen/w/l/a/period/x/m/b)/FontFile3 114 0 R>>
+/CharSet(/y/n/c/o/d/p/e/O/f/P/E/r/g/question/s/h/t/i/H/fi/u/comma/T/v/k/hyphen/w/l/a/period/x/m/b)/FontFile3 109 0 R>>
 endobj
 18 0 obj
 <</Type/FontDescriptor/FontName/WTBOIB+CMR6/FontBBox[0 -21 564 675]/Flags 4
@@ -1420,7 +1396,7 @@
 /ItalicAngle 0
 /StemV 84
 /MissingWidth 416
-/CharSet(/one/two/three/four)/FontFile3 116 0 R>>
+/CharSet(/one/two/three/four)/FontFile3 111 0 R>>
 endobj
 16 0 obj
 <</Type/FontDescriptor/FontName/WTBOIB+CMR7/FontBBox[0 -20 529 674]/Flags 4
@@ -1430,143 +1406,138 @@
 /ItalicAngle 0
 /StemV 79
 /MissingWidth 384
-/CharSet(/one/two/three/four)/FontFile3 118 0 R>>
+/CharSet(/one/two/three/four)/FontFile3 113 0 R>>
 endobj
 2 0 obj
 <</Producer(ESP Ghostscript 815.04)
-/CreationDate(D:20070811165352)
-/ModDate(D:20070811165352)>>endobj
+/CreationDate(D:20070826231432)
+/ModDate(D:20070826231432)>>endobj
 xref
-0 125
+0 120
 0000000000 65535 f 
-0000061343 00000 n 
-0000101592 00000 n 
-0000061185 00000 n 
-0000058685 00000 n 
+0000058425 00000 n 
+0000098418 00000 n 
+0000058274 00000 n 
+0000055936 00000 n 
 0000000015 00000 n 
-0000004972 00000 n 
-0000061391 00000 n 
-0000099596 00000 n 
-0000096006 00000 n 
-0000099321 00000 n 
-0000095657 00000 n 
-0000098988 00000 n 
-0000095270 00000 n 
-0000098511 00000 n 
-0000094606 00000 n 
-0000101367 00000 n 
-0000098346 00000 n 
-0000101142 00000 n 
-0000098181 00000 n 
-0000100845 00000 n 
-0000097668 00000 n 
-0000061432 00000 n 
-0000061462 00000 n 
-0000058853 00000 n 
-0000004992 00000 n 
-0000009777 00000 n 
-0000100336 00000 n 
-0000097186 00000 n 
-0000061558 00000 n 
-0000061588 00000 n 
-0000059015 00000 n 
-0000009798 00000 n 
-0000015038 00000 n 
-0000100143 00000 n 
-0000096950 00000 n 
-0000061642 00000 n 
-0000061672 00000 n 
-0000059185 00000 n 
-0000015059 00000 n 
-0000019954 00000 n 
-0000061770 00000 n 
-0000061800 00000 n 
-0000059355 00000 n 
-0000019975 00000 n 
-0000024247 00000 n 
-0000061843 00000 n 
-0000061873 00000 n 
-0000059525 00000 n 
-0000024268 00000 n 
-0000027920 00000 n 
-0000061938 00000 n 
-0000061968 00000 n 
-0000059687 00000 n 
-0000027941 00000 n 
-0000032886 00000 n 
-0000062033 00000 n 
-0000062063 00000 n 
-0000059857 00000 n 
-0000032907 00000 n 
-0000036515 00000 n 
-0000062106 00000 n 
-0000062136 00000 n 
-0000060019 00000 n 
-0000036536 00000 n 
-0000041310 00000 n 
-0000062201 00000 n 
-0000062231 00000 n 
-0000060181 00000 n 
-0000041331 00000 n 
-0000045463 00000 n 
-0000099865 00000 n 
-0000096446 00000 n 
-0000062285 00000 n 
-0000062315 00000 n 
-0000060343 00000 n 
-0000045484 00000 n 
-0000049724 00000 n 
-0000062380 00000 n 
-0000062410 00000 n 
-0000060513 00000 n 
-0000049745 00000 n 
-0000052055 00000 n 
-0000062508 00000 n 
-0000062538 00000 n 
-0000060683 00000 n 
-0000052076 00000 n 
-0000053893 00000 n 
-0000062581 00000 n 
-0000062611 00000 n 
-0000060853 00000 n 
-0000053914 00000 n 
-0000057411 00000 n 
-0000062654 00000 n 
-0000062684 00000 n 
-0000061023 00000 n 
+0000004971 00000 n 
+0000058473 00000 n 
+0000096422 00000 n 
+0000092841 00000 n 
+0000096148 00000 n 
+0000092492 00000 n 
+0000095818 00000 n 
+0000092107 00000 n 
+0000095346 00000 n 
+0000091449 00000 n 
+0000098193 00000 n 
+0000095181 00000 n 
+0000097968 00000 n 
+0000095016 00000 n 
+0000097671 00000 n 
+0000094503 00000 n 
+0000058514 00000 n 
+0000058544 00000 n 
+0000056104 00000 n 
+0000004991 00000 n 
+0000009776 00000 n 
+0000097162 00000 n 
+0000094021 00000 n 
+0000058640 00000 n 
+0000058670 00000 n 
+0000056266 00000 n 
+0000009797 00000 n 
+0000015037 00000 n 
+0000096969 00000 n 
+0000093785 00000 n 
+0000058724 00000 n 
+0000058754 00000 n 
+0000056436 00000 n 
+0000015058 00000 n 
+0000019959 00000 n 
+0000058852 00000 n 
+0000058882 00000 n 
+0000056606 00000 n 
+0000019980 00000 n 
+0000024253 00000 n 
+0000058925 00000 n 
+0000058955 00000 n 
+0000056776 00000 n 
+0000024274 00000 n 
+0000027927 00000 n 
+0000059020 00000 n 
+0000059050 00000 n 
+0000056938 00000 n 
+0000027948 00000 n 
+0000032896 00000 n 
+0000059115 00000 n 
+0000059145 00000 n 
+0000057108 00000 n 
+0000032917 00000 n 
+0000036525 00000 n 
+0000059188 00000 n 
+0000059218 00000 n 
+0000057270 00000 n 
+0000036546 00000 n 
+0000041322 00000 n 
+0000059283 00000 n 
+0000059313 00000 n 
 0000057432 00000 n 
-0000058664 00000 n 
-0000062727 00000 n 
-0000062757 00000 n 
-0000062811 00000 n 
-0000070549 00000 n 
-0000070571 00000 n 
-0000074729 00000 n 
-0000074751 00000 n 
-0000077347 00000 n 
-0000077369 00000 n 
-0000079928 00000 n 
-0000079950 00000 n 
-0000083012 00000 n 
-0000083034 00000 n 
-0000083359 00000 n 
-0000083380 00000 n 
-0000089617 00000 n 
-0000089639 00000 n 
-0000093055 00000 n 
-0000093077 00000 n 
-0000093821 00000 n 
-0000093842 00000 n 
-0000094585 00000 n 
-0000095124 00000 n 
-0000096353 00000 n 
-0000096865 00000 n 
-0000097097 00000 n 
-0000098096 00000 n 
+0000041343 00000 n 
+0000044524 00000 n 
+0000096691 00000 n 
+0000093281 00000 n 
+0000059367 00000 n 
+0000059397 00000 n 
+0000057594 00000 n 
+0000044545 00000 n 
+0000048319 00000 n 
+0000059462 00000 n 
+0000059492 00000 n 
+0000057764 00000 n 
+0000048340 00000 n 
+0000050619 00000 n 
+0000059590 00000 n 
+0000059620 00000 n 
+0000057934 00000 n 
+0000050640 00000 n 
+0000052419 00000 n 
+0000059663 00000 n 
+0000059693 00000 n 
+0000058104 00000 n 
+0000052440 00000 n 
+0000055915 00000 n 
+0000059736 00000 n 
+0000059766 00000 n 
+0000059809 00000 n 
+0000067431 00000 n 
+0000067452 00000 n 
+0000071512 00000 n 
+0000071533 00000 n 
+0000074190 00000 n 
+0000074212 00000 n 
+0000076771 00000 n 
+0000076793 00000 n 
+0000079855 00000 n 
+0000079877 00000 n 
+0000080202 00000 n 
+0000080223 00000 n 
+0000086460 00000 n 
+0000086482 00000 n 
+0000089898 00000 n 
+0000089920 00000 n 
+0000090664 00000 n 
+0000090685 00000 n 
+0000091428 00000 n 
+0000091965 00000 n 
+0000093188 00000 n 
+0000093700 00000 n 
+0000093932 00000 n 
+0000094931 00000 n 
 trailer
-<< /Size 125 /Root 1 0 R /Info 2 0 R
-/ID [(£ÛÎ_>¢ù¯\(MBο^þç)(£ÛÎ_>¢ù¯\(MBο^þç)]
+<< /Size 120 /Root 1 0 R /Info 2 0 R
+/ID [(Ôò––yÔ\reI;¥!‚æ»)(Ôò––yÔ\reI;¥!‚æ»)]
 >>
 startxref
-101703
+98529
 %%EOF

Modified: puppetor/trunk/doc/howto.tex
===================================================================
--- puppetor/trunk/doc/howto.tex	2007-08-26 21:03:54 UTC (rev 11279)
+++ puppetor/trunk/doc/howto.tex	2007-08-26 21:18:53 UTC (rev 11280)
@@ -171,7 +171,7 @@
 
 \begin{verbatim}
 ClientApplication client = network.createClient("client",
-    "www.google.de", 80, 7002);
+    "www.google.com", 80, 7002);
 \end{verbatim}
 
 Before starting the request we want to register for events coming from this
@@ -539,38 +539,15 @@
 Handling event: APPLICATION_REQUESTS_PERFORMED
 \end{verbatim}
 
-\section{Example 5: Beta test of distributed storage for hidden service
+\section{Tests of distributed storage for hidden service
 descriptors}
 
-\textbf{WARNING: This example does not work with an unmodified Tor!}
+The purpose of the tests in package
+\texttt{de.uniba.wiai.lspi.puppetor.diststorage} is the validation
+of the distributed storage for hidden service descriptors as described
+in proposal 114.
+\textbf{WARNING: These examples do not work with an unmodified Tor!}
 
-The purpose of this example is the automatic validation of the distributed
-storage for hidden service descriptors as described in proposal 114.
-
-When running, the example starts a network of local Tor processes, consisting
-of 2 directory nodes and 9 periodically changing onion routers, some of them
-(not the initial nodes, but those nodes replacing them) with attached hidden
-services. Each hour, one node is stopped and a new node is started, so that the
-population size stays the same.
-
-The automatic validation performs four measurements:
-
-\begin{enumerate}
-\item Are the online statuses of hidden service directories propagated to all
-running nodes successfully, and how long does propagation take?
-\item The same measurement with offline statuses.
-\item Are hidden service descriptors stored on the correct, responsible hidden
-service directories, and how long does propagation take?
-\item Are hidden service requests successful within a given timeout?
-\end{enumerate}
-
-The results of these measurements are written as comma-separated values to the
-four files \texttt{online-propagation}, \texttt{offline-propagation},
-\texttt{descriptor-propagation}, and \texttt{hidden-service-requests} in the
-working directory of the test run. Successful measurements are written as the
-number of seconds that the measurement took, failures are encoded as
-\texttt{-1}, and aborted measurements are dropped.
-
 \section{Architecture}
 
 Though the examples show how to use the simulator, they do not provide insights

Added: puppetor/trunk/lib/bcpg-jdk16-137.jar
===================================================================
(Binary files differ)


Property changes on: puppetor/trunk/lib/bcpg-jdk16-137.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: puppetor/trunk/lib/bcprov-jdk16-137.jar
===================================================================
(Binary files differ)


Property changes on: puppetor/trunk/lib/bcprov-jdk16-137.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java	2007-08-26 21:03:54 UTC (rev 11279)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/RouterNode.java	2007-08-26 21:18:53 UTC (rev 11280)
@@ -54,14 +54,15 @@
 	public abstract String determineFingerprint() throws TorProcessException;
 
 	/**
-	 * Determines the base32-encoded fingerprint of this node.
+	 * Returns the base32-encoded fingerprint of this node.
 	 * 
 	 * @return The base32-encoded fingerprint of this node.
-	 * @throws TorProcessException
-	 *             Thrown if the fingerprint cannot be determined.
+	 * @throws IllegalStateException
+	 *             Thrown if node is neither in state
+	 *             <code>NodeState.RUNNING</code> or
+	 *             <code>NodeState.SHUT_DOWN</code>.
 	 */
-	public abstract String determineFingerprintBase32()
-			throws TorProcessException;
+	public abstract String getFingerprintBase32();
 
 	/**
 	 * Returns the dir port of this node.

Added: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/AdvertisingAndAccessingV2HiddenServiceOverPrivateTorNetwork.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/AdvertisingAndAccessingV2HiddenServiceOverPrivateTorNetwork.java	                        (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/AdvertisingAndAccessingV2HiddenServiceOverPrivateTorNetwork.java	2007-08-26 21:18:53 UTC (rev 11280)
@@ -0,0 +1,182 @@
+package de.uniba.wiai.lspi.puppetor.diststorage;
+
+import java.util.Random;
+
+import de.uniba.wiai.lspi.puppetor.ClientApplication;
+import de.uniba.wiai.lspi.puppetor.DirectoryNode;
+import de.uniba.wiai.lspi.puppetor.Event;
+import de.uniba.wiai.lspi.puppetor.EventListener;
+import de.uniba.wiai.lspi.puppetor.EventManager;
+import de.uniba.wiai.lspi.puppetor.EventType;
+import de.uniba.wiai.lspi.puppetor.Network;
+import de.uniba.wiai.lspi.puppetor.NetworkFactory;
+import de.uniba.wiai.lspi.puppetor.RouterNode;
+import de.uniba.wiai.lspi.puppetor.ServerApplication;
+import de.uniba.wiai.lspi.puppetor.TorProcessException;
+
+/**
+ * Example for advertising and accessing a hidden service over a private Tor
+ * network.
+ * 
+ * @author kloesing
+ */
+public class AdvertisingAndAccessingV2HiddenServiceOverPrivateTorNetwork {
+
+	/**
+	 * Sets up and runs the test.
+	 * 
+	 * @param args
+	 *            Command-line arguments (ignored).
+	 * @throws TorProcessException
+	 *             Thrown if there is a problem with the JVM-external Tor
+	 *             processes that we cannot handle.
+	 */
+	public static void main(String[] args) throws TorProcessException {
+
+		// create a network to initialize a test case
+		Network network = NetworkFactory.createNetwork("example4");
+
+		// create two directory nodes with parameters (router name, control
+		// port, SOCKS port, OR port, dir port)
+		DirectoryNode dir1 = network.createDirectory("dir1", 7001, 7002, 7003,
+				7004);
+		DirectoryNode dir2 = network.createDirectory("dir2", 7011, 7012, 7013,
+				7014);
+
+		// create three router nodes with parameters (router name, control port,
+		// SOCKS port, OR port, dir mirror port)
+		RouterNode router1 = network.createRouter("router1", 7021, 7022, 7023,
+				7024);
+		RouterNode router2 = network.createRouter("router2", 7031, 7032, 7033,
+				7034);
+		RouterNode router3 = network.createRouter("router3", 7041, 7042, 7043,
+				7044);
+		RouterNode router4 = network.createRouter("router4", 7051, 7052, 7053,
+				7054);
+
+		// configure all nodes hidden service directories
+		dir1.addConfiguration("HidServDirectoryV2 1");
+		dir2.addConfiguration("HidServDirectoryV2 1");
+		dir1.addConfiguration("MinUptimeHidServDirectoryV2 0 minutes");
+		dir2.addConfiguration("MinUptimeHidServDirectoryV2 0 minutes");
+		router1.addConfiguration("HidServDirectoryV2 1");
+		router2.addConfiguration("HidServDirectoryV2 1");
+		router3.addConfiguration("HidServDirectoryV2 1");
+		router4.addConfiguration("HidServDirectoryV2 1");
+
+		// add hidden service
+		router1.addHiddenService("hidServ", 7025, 80);
+
+		// re-configure routers 1 and 3 for V2 compatibility
+		router1.addConfiguration("PublishHidServDescriptors 0");
+		router1.addConfiguration("PublishV2HidServDescriptors 1");
+		router1.addConfiguration("FetchHidServDescriptors 0");
+		router1.addConfiguration("FetchV2HidServDescriptors 1");
+		router2.addConfiguration("FetchHidServDescriptors 0");
+		router2.addConfiguration("FetchV2HidServDescriptors 1");
+		router3.addConfiguration("FetchHidServDescriptors 0");
+		router3.addConfiguration("FetchV2HidServDescriptors 1");
+		router4.addConfiguration("FetchHidServDescriptors 0");
+		router4.addConfiguration("FetchV2HidServDescriptors 1");
+
+		// configure nodes of this network to be part of a private network
+		network.configureAsPrivateNetwork();
+
+		// write configuration of proxy node
+		network.writeConfigurations();
+
+		// start proxy node and wait until it has opened a circuit with a
+		// timeout of 15 seconds
+		if (!network.startNodes(15000)) {
+
+			// failed to start the proxy
+			System.out.println("Failed to start nodes!");
+			return;
+		}
+		System.out.println("Successfully started nodes!");
+
+		// hup until proxy has built circuits (10 retries, 10 seconds timeout
+		// each)
+		if (!network.hupUntilUp(20, 6000)) {
+
+			// failed to build circuits
+			System.out.println("Failed to build circuits!");
+			return;
+		}
+		System.out.println("Successfully built circuits!");
+
+		// obtain reference to event manager to be able to respond to events
+		EventManager manager = network.getEventManager();
+
+		manager.registerEventTypePattern(
+				"Hidden service routing table has changed",
+				EventType.NODE_ROUTING_TABLE_CHANGED);
+		manager.registerEventTypePattern("Sending publish request for "
+				+ "v2 descriptor for "
+				+ "service '.*' with descriptor ID '.*' with validity of .* "
+				+ "seconds to hidden service directory '.*' on port .*",
+				EventType.BOB_SENDING_PUBLISH_DESC);
+		manager.registerEventTypePattern("Successfully stored service "
+				+ "descriptor with desc ID " + "'.*' and len .*",
+				EventType.HSDIR_DESC_STORED);
+		manager.registerEventTypePattern("Sending fetch request for v2 "
+				+ "descriptor for "
+				+ "service '.*' with descriptor ID '.*' to hidden "
+				+ "service directory '.*' on port .*",
+				EventType.ALICE_SENDING_FETCH_DESC);
+		manager
+				.registerEventTypePattern(
+						"Successfully stored service descriptor with "
+								+ "desc ID '.*'", EventType.HSDIR_DESC_STORED);
+
+		manager.addEventListener(new EventListener() {
+			public void handleEvent(Event event) {
+				System.out.println(event);
+			}
+		});
+
+		// wait for 30 minutes that the proxy has published its first RSD
+		if (!manager.waitForAnyOccurence(router1,
+				EventType.BOB_SENDING_PUBLISH_DESC, 30L * 60L * 1000L)) {
+			// failed to publish an RSD
+			System.out.println("Failed to publish an RSD!");
+			return;
+		}
+		System.out.println("All RSDs published!");
+
+		// determine onion address for hidden service
+		String onionAddress = router1.getOnionAddress("hidServ", 2);
+
+		// create server application
+		ServerApplication server = network.createServer("server", 7025);
+
+		// start server
+		server.listen();
+		System.out.println("Started server with onion address '" + onionAddress
+				+ "'");
+		
+		Random rnd = new Random();
+
+		for (int i = 0; i < 10; i++) {
+
+			int socksPort = 7022 + rnd.nextInt(4) * 10;
+			System.out.println("Socks Port = " + socksPort);
+			
+			// create client application
+			ClientApplication client = network.createClient("client",
+					onionAddress, 80, socksPort);
+
+			// perform at most five request with a timeout of 45 seconds each
+			client.performRequest(5, 45000, true);
+
+			try {
+				Thread.sleep(60000);
+			} catch (InterruptedException e) {
+			}
+		}
+		
+		// shut down nodes
+		network.shutdownNodes();
+
+	}
+}

Copied: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/DistributedStorage.java (from rev 11212, puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/DistributedStorage.java)
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/DistributedStorage.java	                        (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/DistributedStorage.java	2007-08-26 21:18:53 UTC (rev 11280)
@@ -0,0 +1,1458 @@
+/*
+ *  
+ * WARNING! This long-running test case sometimes fails for yet unknown
+ * reasons, possibly because of the test case implementation! Don't rely
+ * on it!
+ *
+ */
+
+package de.uniba.wiai.lspi.puppetor.diststorage;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import de.uniba.wiai.lspi.puppetor.ClientApplication;
+import de.uniba.wiai.lspi.puppetor.DirectoryNode;
+import de.uniba.wiai.lspi.puppetor.Event;
+import de.uniba.wiai.lspi.puppetor.EventListener;
+import de.uniba.wiai.lspi.puppetor.EventManager;
+import de.uniba.wiai.lspi.puppetor.EventSource;
+import de.uniba.wiai.lspi.puppetor.EventType;
+import de.uniba.wiai.lspi.puppetor.Network;
+import de.uniba.wiai.lspi.puppetor.NetworkFactory;
+import de.uniba.wiai.lspi.puppetor.ProxyNode;
+import de.uniba.wiai.lspi.puppetor.RouterNode;
+import de.uniba.wiai.lspi.puppetor.TorProcessException;
+
+/* TODO Document this class properly */
+
+/**
+ * <p>
+ * Automatic validation of the distributed storage for hidden service
+ * descriptors as described in proposal 114. <b>WARNING: This example does not
+ * work with an unmodified Tor!</b>
+ * </p>
+ * 
+ * <p>
+ * When running, the example starts a network of local Tor processes, consisting
+ * of 2 directory nodes and 9 periodically changing onion routers, some of them
+ * (not the initial nodes, but those nodes replacing them) with attached hidden
+ * services.
+ * </p>
+ * 
+ * <p>
+ * The automatic validation performs four measurements:
+ * </p>
+ * 
+ * <ol>
+ * <li>Are the online statuses of hidden service directories propagated to all
+ * running nodes successfully, and how long does propagation take?</li>
+ * <li>The same measurement with offline statuses.</li>
+ * <li>Are hidden service descriptors stored on the correct, responsible hidden
+ * service directories, and how long does propagation take?</li>
+ * <li>Are hidden service requests successful within a given timeout?</li>
+ * </ol>
+ * 
+ * <p>
+ * The results of these measurements are written as comma-separated values to
+ * the four files <b>online-propagation</b>, <b>offline-propagation</b>,
+ * <b>descriptor-propagation</b>, and <b>hidden-service-requests</b> in the
+ * working directory of the test run. Successful measurements are written as the
+ * number of seconds that the measurement took, failures are encoded as <b>-1</b>,
+ * and aborted measurements are dropped.
+ * </p>
+ * 
+ * @author kloesing
+ */
+public class DistributedStorage {
+
+	/**
+	 * Observes a hidden service directory from starting it to shutting it down.
+	 * Waits for 24 hours after starting the node, so that it will be accepted
+	 * as hidden service directory by the directory authorities. Afterwards,
+	 * initiates an online propagation measurement for every node that is in the
+	 * network or that enters the network while the observed hidden service
+	 * directory is online. After going offline, initiates an offline
+	 * propagation measurement for every node that has previously accepted this
+	 * hidden service directory.
+	 */
+	private static class HiddenServiceDirectoryObserver extends Thread
+			implements EventListener {
+
+		/**
+		 * Is the hidden service directory online for at least 24 hours, so that
+		 * it will be listed by the directory authorities?
+		 */
+		private boolean twentyFourHoursUp;
+
+		/**
+		 * The Tor process behind the observed hidden service directory.
+		 */
+		private RouterNode hsdNode;
+
+		/**
+		 * Set of nodes that have reported to accept this hidden service
+		 * directory.
+		 */
+		private Set<EventSource> nodesThatKnowMe = new HashSet<EventSource>();
+
+		/**
+		 * Creates a new observer instance, but does not start it yet.
+		 * 
+		 * @param hsdNode
+		 *            The Tor process behind the observed hidden service
+		 *            directory.
+		 * @param nodeID
+		 *            The node ID of the observed hidden service directory.
+		 */
+		private HiddenServiceDirectoryObserver(RouterNode hsdNode) {
+
+			// remember the args
+			this.hsdNode = hsdNode;
+
+			// listen for events coming from my HSDir
+			manager.addEventListener(hsdNode, this);
+
+			// listen for starting/stopping nodes
+			manager.addEventListener(this);
+		}
+
+		@Override
+		public synchronized void run() {
+
+			// not yet accepted
+			this.twentyFourHoursUp = false;
+
+			// wait for 24 hours until hsdir is accepted by DAs
+			long startingTime = System.currentTimeMillis();
+			// for testing; change to 24 * 60 * 60 * 1000
+			long endOfWaiting = startingTime + 30 * 60 * 1000;
+			long now;
+			while ((now = System.currentTimeMillis()) < endOfWaiting) {
+				try {
+					wait(endOfWaiting - now);
+				} catch (InterruptedException e) {
+				}
+			}
+
+			// accepted
+			this.twentyFourHoursUp = true;
+
+			// add to set of running hidden service directories
+			globalRoutingTable.addHiddenServiceDirectory(this.hsdNode);
+
+			// measure how long the current nodes need to get aware of this
+			// hidden service directory
+			for (RouterNode router : runningRouters) {
+				new OnlinePropagationMeasurement(router, this.hsdNode).start();
+			}
+		}
+
+		public synchronized void handleEvent(Event event) {
+
+			if (!this.twentyFourHoursUp) {
+				// when the represented node is not running for at least 24
+				// hours, others would not consider it as hidden service
+				// directory and we cannot perform any useful measurements
+				return;
+			}
+
+			if (event.getType() == EventType.NODE_STARTED) {
+				// when another node is started, initiate measurement of the
+				// propagation time that this hiddden service directory is
+				// online
+				new OnlinePropagationMeasurement(event.getSource(),
+						this.hsdNode).start();
+
+			} else if (event.getSource() == this.hsdNode
+					&& event.getType() == EventType.NODE_STOPPED) {
+				// when the represented node is stopped, initiate measurement of
+				// the propagation time that this hidden service directory is
+				// offline (any online propagation measurements that are still
+				// running will realize by themselves that they cannot succeed
+				// and will abort)
+				for (EventSource node : nodesThatKnowMe) {
+					if (node != this.hsdNode) {
+						new OfflinePropagationMeasurement(node, this.hsdNode)
+								.start();
+					}
+				}
+
+				// remove from set of running hidden service directories
+				globalRoutingTable.removeHiddenServiceDirectory(this.hsdNode);
+
+				// stop listening for events
+				manager.removeEventListener(this);
+
+				// just in case that there is another event in the queue, don't
+				// handle it any more
+				this.twentyFourHoursUp = false;
+
+			} else if (event.getType() == EventType.NODE_ROUTING_TABLE_CHANGED
+					&& event.getMessage().contains(
+							this.hsdNode.getFingerprintBase32())) {
+				// when some node reports to have changed its routing table and
+				// now includes the node ID of the represented node, remember
+				// that node for later offline propagation measurement
+				nodesThatKnowMe.add(event.getSource());
+
+			} else if (event.getType() == EventType.NODE_STOPPED
+					&& event.getSource() != this.hsdNode) {
+				// when some other node is stopped, remove it from the list of
+				// nodes that know that the represented hidden service directory
+				// is online
+				nodesThatKnowMe.remove(event.getSource());
+			}
+		}
+	}
+
+	/**
+	 * The states in which a measurement can be.
+	 */
+	private static enum MeasurementState {
+
+		/**
+		 * The measurement was started and is currently running.
+		 */
+		STARTED,
+
+		/**
+		 * The measurement has succeeded with a positive result.
+		 */
+		SUCCEEDED,
+
+		/**
+		 * The measurement has failed within the given maximum time.
+		 */
+		FAILED,
+
+		/**
+		 * The measurement was aborted, because it has become impossible to
+		 * succeed.
+		 */
+		ABORTED
+	}
+
+	/**
+	 * Verifies that the online status of a given hidden service directory is
+	 * propagated to a given running node, and measures how long that
+	 * propagation takes. If the propagation does not succeed within one hour,
+	 * it is considered as failed.
+	 */
+	private static class OnlinePropagationMeasurement extends Thread implements
+			EventListener {
+
+		/**
+		 * The state of this measurement.
+		 */
+		private MeasurementState measurementState;
+
+		/**
+		 * The hidden service directory of which the online status should be
+		 * propagated.
+		 */
+		private RouterNode hsdNode;
+
+		/**
+		 * The node to which the online status should be propagated.
+		 */
+		private EventSource node;
+
+		/**
+		 * Creates a new measurement, but does not start it yet.
+		 * 
+		 * @param node
+		 *            The node to which the online status should be propagated.
+		 * @param hsdNode
+		 *            The hidden service directory of which the online status
+		 *            should be propagated.
+		 */
+		private OnlinePropagationMeasurement(EventSource node,
+				RouterNode hsdNode) {
+
+			// remember the args
+			this.hsdNode = hsdNode;
+			this.node = node;
+
+			// listen for events coming from the node and the hidden service
+			// directory
+			manager.addEventListener(node, this);
+			manager.addEventListener(hsdNode, this);
+
+		}
+
+		@Override
+		public synchronized void run() {
+
+			// start the measurement in state STARTED
+			this.measurementState = MeasurementState.STARTED;
+
+			// wait for a maximum of one hour for the measurement to succeed
+			long startingTime = System.currentTimeMillis();
+			long endOfWaiting = startingTime + 60 * 60 * 1000;
+			long now;
+			while (this.measurementState == MeasurementState.STARTED
+					&& (now = System.currentTimeMillis()) < endOfWaiting) {
+				try {
+					wait(endOfWaiting - now);
+				} catch (InterruptedException e) {
+				}
+			}
+
+			// if the node did not learn about the hidden service directory
+			// within one hour, fail the measurement
+			if (this.measurementState == MeasurementState.STARTED) {
+				measurementState = MeasurementState.FAILED;
+			}
+
+			// unregister event listener
+			manager.removeEventListener(this);
+
+			// print out measurement result
+			long duration = System.currentTimeMillis() - startingTime;
+			System.out.println(new Date() + ": Online propagation for HSDir "
+					+ this.hsdNode.getName() + " to node "
+					+ this.node.getName() + " took " + (duration / 1000)
+					+ " seconds and ended in state "
+					+ measurementState.toString());
+			if (this.measurementState == MeasurementState.SUCCEEDED) {
+				resultWriter.writeOnlinePropagation(duration / 1000);
+			} else if (this.measurementState == MeasurementState.FAILED) {
+				resultWriter.writeOnlinePropagation(-1);
+			}
+		}
+
+		public synchronized void handleEvent(Event event) {
+
+			// only accept events when this measurement is running
+			if (measurementState != MeasurementState.STARTED) {
+				return;
+			}
+
+			if (event.getSource() == this.node
+					&& event.getType() == EventType.NODE_ROUTING_TABLE_CHANGED
+					&& event.getMessage().contains(
+							this.hsdNode.getFingerprintBase32())) {
+				// when the node has added the node ID of the hidden service
+				// directory, succeed the measurement
+				this.measurementState = MeasurementState.SUCCEEDED;
+				notify();
+
+			} else if (event.getType() == EventType.NODE_STOPPED) {
+				// when either the node or the hidden service directory were
+				// stopped within the one hour period, the measurement cannot be
+				// succeeded anymore and is therefore aborted
+				this.measurementState = MeasurementState.ABORTED;
+				notify();
+			}
+		}
+	}
+
+	/**
+	 * Verifies that the offline status of a given hidden service directory is
+	 * propagated to a given running node, and measures how long that
+	 * propagation takes. If the propagation does not succeed within one hour,
+	 * it is considered as failed.
+	 */
+	private static class OfflinePropagationMeasurement extends Thread implements
+			EventListener {
+
+		/**
+		 * The state of this measurement.
+		 */
+		private MeasurementState measurementState;
+
+		/**
+		 * The hidden service directory of which the offline status should be
+		 * propagated.
+		 */
+		private RouterNode hsdNode;
+
+		/**
+		 * The node to which the offline status should be propagated.
+		 */
+		private EventSource node;
+
+		/**
+		 * Creates a new measurement, but does not start it yet.
+		 * 
+		 * @param node
+		 *            The node to which the offline status should be propagated.
+		 * @param hsdNode
+		 *            The hidden service directory of which the offline status
+		 *            should be propagated.
+		 */
+		private OfflinePropagationMeasurement(EventSource node,
+				RouterNode hsdNode) {
+
+			// remember the args
+			this.node = node;
+			this.hsdNode = hsdNode;
+
+			// register for events from the node that should observe the offline
+			// status
+			manager.addEventListener(node, this);
+		}
+
+		@Override
+		public synchronized void run() {
+
+			// start the measurement in state STARTED
+			this.measurementState = MeasurementState.STARTED;
+
+			// wait for a maximum of 90 minutes for the measurement to succeed
+			long startingTime = System.currentTimeMillis();
+			long endOfWaiting = startingTime + 90 * 60 * 1000;
+			long now;
+			while (this.measurementState == MeasurementState.STARTED
+					&& (now = System.currentTimeMillis()) < endOfWaiting) {
+				try {
+					wait(endOfWaiting - now);
+				} catch (InterruptedException e) {
+				}
+			}
+
+			// if the node did not learn about the offline status of the hidden
+			// service directory, fail the measurement
+			if (this.measurementState == MeasurementState.STARTED) {
+				measurementState = MeasurementState.FAILED;
+			}
+
+			// unregister event listener
+			manager.removeEventListener(this);
+
+			// print out measurement result
+			long duration = System.currentTimeMillis() - startingTime;
+			System.out.println(new Date() + ": Offline propagation for HSDir "
+					+ this.hsdNode.getName() + " to node "
+					+ this.node.getName() + " took " + (duration / 1000)
+					+ " seconds and ended in state "
+					+ measurementState.toString());
+			if (this.measurementState == MeasurementState.SUCCEEDED) {
+				resultWriter.writeOfflinePropagation(duration / 1000);
+			} else if (this.measurementState == MeasurementState.FAILED) {
+				resultWriter.writeOfflinePropagation(-1);
+			}
+		}
+
+		public synchronized void handleEvent(Event event) {
+
+			// only accept events when this measurement is running
+			if (measurementState != MeasurementState.STARTED) {
+				return;
+			}
+
+			if (event.getType() == EventType.NODE_ROUTING_TABLE_CHANGED
+					&& !event.getMessage().contains(
+							this.hsdNode.getFingerprintBase32())) {
+				// when the node has removed the node ID of the hidden service
+				// directory, succeed the measurement
+				this.measurementState = MeasurementState.SUCCEEDED;
+				notify();
+
+			} else if (event.getType() == EventType.NODE_STOPPED) {
+				// when the node was stopped within the waiting period, the
+				// measurement cannot be
+				// succeeded anymore and is therefore aborted
+				this.measurementState = MeasurementState.ABORTED;
+				notify();
+			}
+		}
+	}
+
+	/**
+	 * The routing table containing the global state of all hidden service
+	 * directories in the network.
+	 */
+	private static HidServRoutingTable globalRoutingTable = new HidServRoutingTable();
+
+	/**
+	 * Observes all publications of descriptors by hidden service providers.
+	 * Whenever there is a novel descriptor, the observer launches measurements
+	 * of the ropagation of the new descriptor to the responsible hidden service
+	 * directories.
+	 */
+	private static class DescriptorObserverStarter implements EventListener {
+
+		/**
+		 * Set of all descriptor IDs that have been observed so far.
+		 */
+		private Set<String> knownDescIDs = new HashSet<String>();
+
+		/**
+		 * Creates a new observer that starts listening for events.
+		 */
+		private DescriptorObserverStarter() {
+			manager.addEventListener(this);
+		}
+
+		public void handleEvent(Event event) {
+			// listen for new desc-ids
+			if (event.getType() == EventType.BOB_SENDING_PUBLISH_DESC) {
+				// a descriptor was published by any hidden service provider;
+				// check if this descriptor ID is novel
+
+				// parse desc id from event message
+				String message = event.getMessage();
+				String prefixDescID = "with descriptor ID '";
+				String descID = message.substring(message.indexOf(prefixDescID)
+						+ prefixDescID.length());
+				descID = descID.substring(0, 32);
+
+				if (!knownDescIDs.contains(descID)) {
+					String prefixSecondsValid = "with validity of ";
+					String secondsValidPlusRest = message.substring(message
+							.indexOf(prefixSecondsValid)
+							+ prefixSecondsValid.length());
+					String[] splitted = secondsValidPlusRest.split(" ");
+					long secondsValid = Long.parseLong(splitted[0]);
+
+					if (secondsValid > 30 * 60) {
+						new DescriptorObserver(descID, secondsValid).start();
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Observes a descriptor from its first publication to 30 minutes before its
+	 * validity ends. Initiates a descriptor propagation measurement for every
+	 * hidden service directory that either is or becomes responsible for the
+	 * descriptor ID. (This does not include checks that a descriptor remains
+	 * stored on the responsible hidden service directories.)
+	 */
+	private static class DescriptorObserver extends Thread {
+
+		/**
+		 * The descriptor ID of the observed descriptor.
+		 */
+		private String descID;
+
+		/**
+		 * Time in millis when the validity of the observed descriptor amounts
+		 * 30 minutes.
+		 */
+		private long endOfWaiting;
+
+		/**
+		 * The set of hidden service directories that we think is responsible
+		 * for storing the observed descriptor.
+		 */
+		private Set<EventSource> hsDirsDeemedResponsible;
+
+		/**
+		 * Creates a new observer instance, but does not start it yet.
+		 * 
+		 * @param descID
+		 *            The descriptor ID of the observed descriptor.
+		 * @param validityInSeconds
+		 *            The validity of the descriptor in seconds.
+		 */
+		private DescriptorObserver(String descID, long validityInSeconds) {
+
+			// remember the args
+			this.descID = descID;
+
+			// determine when the validity of the observed descriptor amounts 30
+			// minutes
+			this.endOfWaiting = System.currentTimeMillis() + validityInSeconds
+					* 1000 - 30 * 60 * 1000;
+		}
+
+		@Override
+		public void run() {
+
+			if (System.currentTimeMillis() < this.endOfWaiting) {
+				// when the descriptor is not valid for at least 30 minutes, we
+				// don't need to perform any measurements at all, because it is
+				// quite unlikely that they would succeed
+				return;
+			}
+
+			// start measurements for the currently responsible hidden service
+			// directories
+			hsDirsDeemedResponsible = globalRoutingTable
+					.getResponsibleHSDirs(this.descID);
+			for (EventSource responsibleDir : hsDirsDeemedResponsible) {
+				new DescriptorPropagationMeasurement(responsibleDir,
+						this.descID).start();
+			}
+
+			// wait until the validity of the descriptor is 30 minutes or less
+			long now;
+			while ((now = System.currentTimeMillis()) < this.endOfWaiting) {
+
+				// wait for changes in the global routing table
+				globalRoutingTable.waitForRoutingTableChange(this.endOfWaiting
+						- now);
+
+				// check if the descriptor validity is still sufficient to
+				// initiate new measurements
+				if (now < this.endOfWaiting) {
+
+					// check if the change affects us
+					Set<EventSource> newResponsibleHSDirs = globalRoutingTable
+							.getResponsibleHSDirs(this.descID);
+					Set<EventSource> newcomers = new HashSet<EventSource>(
+							newResponsibleHSDirs);
+					newcomers.removeAll(this.hsDirsDeemedResponsible);
+					if (newcomers.size() > 0) {
+
+						// initiate a new measurement for every new responsible
+						// hidden service directory
+						for (EventSource responsibleDir : newcomers) {
+							new DescriptorPropagationMeasurement(
+									responsibleDir, this.descID).start();
+						}
+						this.hsDirsDeemedResponsible = newResponsibleHSDirs;
+					}
+				}
+			}
+		}
+	}
+
+	/**
+	 * Verifies that a descriptor is propagated to a given hidden service
+	 * directory, and measures how long that propagation takes. If the
+	 * propagation does not succeed within 90 minutes, it is considered as
+	 * failed, unless a change in the routing table makes the hidden service
+	 * directory irresponsible for the given descriptor.
+	 */
+	private static class DescriptorPropagationMeasurement extends Thread
+			implements EventListener {
+
+		/**
+		 * The state of this measurement.
+		 */
+		private MeasurementState measurementState;
+
+		/**
+		 * The descriptor ID of the observed descriptor.
+		 */
+		private String descid;
+
+		/**
+		 * The hidden service directory that is deemed responsible to store the
+		 * given descriptor.
+		 */
+		private EventSource responsibleHSDir;
+
+		/**
+		 * Creates a new measurement instance, but does not start it yet.
+		 * 
+		 * @param responsibleHSDir
+		 *            The hidden service directory that is deemed responsible to
+		 *            store the given descriptor.
+		 * @param descid
+		 *            The descriptor ID of the observed descriptor.
+		 */
+		private DescriptorPropagationMeasurement(EventSource responsibleHSDir,
+				String descid) {
+
+			// remember the args
+			this.responsibleHSDir = responsibleHSDir;
+			this.descid = descid;
+
+			// register for events from the hidden service directory
+			manager.addEventListener(responsibleHSDir, this);
+		}
+
+		@Override
+		public synchronized void run() {
+
+			// start the measurement in state STARTED
+			this.measurementState = MeasurementState.STARTED;
+
+			// wait for a maximum of 90 minutes for the measurement to succeed
+			long startingTime = System.currentTimeMillis();
+			long endOfWaiting = startingTime + 90 * 60 * 1000;
+			long now;
+			while (this.measurementState == MeasurementState.STARTED
+					&& (now = System.currentTimeMillis()) < endOfWaiting) {
+
+				// wait for a change in the routing table, that might make the
+				// hidden service directory irresponsible for the given
+				// descriptor, or be interrupted by an incoming event
+				globalRoutingTable
+						.waitForRoutingTableChange(endOfWaiting - now);
+
+				if (this.measurementState == MeasurementState.STARTED
+						&& !globalRoutingTable
+								.getResponsibleHSDirs(this.descid).contains(
+										this.responsibleHSDir)) {
+					// routing table has changed, so that the hidden service
+					// directory is not responsible for the given descriptor any
+					// more
+					this.measurementState = MeasurementState.ABORTED;
+				}
+			}
+
+			// if the node did not learn about the hidden service directory
+			// within the given time, fail the measurement
+			if (this.measurementState == MeasurementState.STARTED) {
+				measurementState = MeasurementState.FAILED;
+			}
+
+			// unregister event listener
+			manager.removeEventListener(this);
+
+			// print out measurement result
+			long duration = System.currentTimeMillis() - startingTime;
+			System.out.println(new Date()
+					+ ": Descriptor propagation for desc ID " + this.descid
+					+ " took " + (duration / 1000)
+					+ " seconds to responsible HS directory "
+					+ this.responsibleHSDir.getName() + " and ended in state "
+					+ measurementState.toString());
+			if (this.measurementState == MeasurementState.SUCCEEDED) {
+				resultWriter.writeDescriptorPropagation(duration / 1000);
+			} else if (this.measurementState == MeasurementState.FAILED) {
+				resultWriter.writeDescriptorPropagation(-1);
+			}
+		}
+
+		public synchronized void handleEvent(Event event) {
+
+			if (event.getType() == EventType.HSDIR_DESC_STORED
+					&& event.getMessage().contains(this.descid)) {
+				// when the hidden service directory stores the given descriptor
+				// for the first time, the measurement succeeds
+				this.measurementState = MeasurementState.SUCCEEDED;
+				interrupt();
+			}
+		}
+	}
+
+	/**
+	 * Observes a hidden service for the first 20 minutes after starting it
+	 * before adding it to the list of available hidden services. When the node
+	 * is stopped (within or after the 20 minutes), the hidden service will be
+	 * removed from the list of available hidden services.
+	 */
+	private static class HiddenServiceObserver extends Thread implements
+			EventListener {
+
+		/**
+		 * The onion address by which this hidden service can be accessed.
+		 */
+		private String onionAddress;
+
+		/**
+		 * The node that provides the hidden service.
+		 */
+		private EventSource providingNode;
+
+		/**
+		 * Creates a new observer instance, but does not start it yet.
+		 * 
+		 * @param providingNode
+		 *            The node that provides the hidden service.
+		 * @param onionAddress
+		 *            The onion address by which this hidden service can be
+		 *            accessed.
+		 */
+		private HiddenServiceObserver(EventSource providingNode,
+				String onionAddress) {
+
+			// remember the args
+			this.onionAddress = onionAddress;
+			this.providingNode = providingNode;
+
+			// listen for events coming from the providing node
+			manager.addEventListener(providingNode, this);
+		}
+
+		/**
+		 * Is the observed hidden service still available, or was the providing
+		 * node stopped?
+		 */
+		private boolean stopped = false;
+
+		@Override
+		public void run() {
+
+			// wait for 20 minutes until the hidden service can be considered
+			// available
+			long startingTime = System.currentTimeMillis();
+			long endOfWaiting = startingTime + 20 * 60 * 1000;
+			long now;
+			while (!this.stopped
+					&& (now = System.currentTimeMillis()) < endOfWaiting) {
+				try {
+					Thread.sleep(endOfWaiting - now);
+				} catch (InterruptedException e) {
+				}
+			}
+
+			// add it to the list of available hidden services
+			availableHiddenServices.put(this.onionAddress, this.providingNode);
+		}
+
+		public void handleEvent(Event event) {
+			if (event.getType() == EventType.NODE_STOPPED) {
+				// when the providing node is stopped, the hidden service will
+				// not be available any more
+				this.stopped = true;
+				availableHiddenServices.remove(this.onionAddress);
+			}
+		}
+	}
+
+	/**
+	 * A list of all hidden services that are available for testing.
+	 */
+	private static Map<String, EventSource> availableHiddenServices = new HashMap<String, EventSource>();
+
+	/**
+	 * Periodically (every 5 to 10 minutes) picks a hidden service that is
+	 * available and running for at least 20 minutes and performs a request to
+	 * it using an arbitrary node as proxy.
+	 */
+	private static class HiddenServiceRequestStarter extends Thread {
+
+		@Override
+		public void run() {
+			// first wait until HSDirs are up and descriptors distributed --
+			// stable state
+			// Thread.sleep(24 * 60 * 60 * 1000 + 90 * 60 * 1000);
+			try {
+				Thread.sleep(30 * 60 * 1000 + 30 * 60 * 1000);
+			} catch (InterruptedException e) {
+			}
+
+			Random rnd = new Random();
+			while (true) {
+				if (availableHiddenServices.size() > 0) {
+
+					// pick an available hidden service at random
+					String onionAddressToTry = new ArrayList<String>(
+							availableHiddenServices.keySet()).get(rnd
+							.nextInt(availableHiddenServices.size()));
+					EventSource providingNode = availableHiddenServices
+							.get(onionAddressToTry);
+
+					// pick an arbitrary running node as proxy
+					RouterNode useAsProxy = runningRouters.get(rnd
+							.nextInt(runningRouters.size()));
+
+					// start measurement
+					new HiddenServiceRequestMeasurement(onionAddressToTry,
+							providingNode, useAsProxy).start();
+				}
+
+				// wait for a random time between 5 to 10 minutes
+				try {
+					Thread.sleep(5 * 60 * 1000 + rnd.nextInt(5 * 60 * 1000));
+				} catch (InterruptedException e) {
+				}
+			}
+		}
+	}
+
+	/**
+	 * Verifies that a hidden service can be accessed, and measures how long
+	 * performing a request takes. If the request does not succeed within one
+	 * minute, it is considered as failed, unless either the node providing the
+	 * hidden service, or the node that is used as proxy fails.
+	 */
+	private static class HiddenServiceRequestMeasurement extends Thread
+			implements EventListener {
+
+		/**
+		 * The onion address to which the request shall be performed.
+		 */
+		private String onionAddress;
+
+		/**
+		 * The node that provides the hidden service.
+		 */
+		private EventSource providingNode;
+
+		/**
+		 * The node that is used as proxy for the request.
+		 */
+		private EventSource useAsProxy;
+
+		/**
+		 * The client application that performs the requests.
+		 */
+		private ClientApplication clientApp;
+
+		/**
+		 * The state of this measurement.
+		 */
+		private MeasurementState measurementState;
+
+		/**
+		 * The time when the request was sent from the client.
+		 */
+		private long requestSentFromClient;
+
+		/**
+		 * The time when a reply was received at the client.
+		 */
+		private long replyReceivedAtClient;
+
+		/**
+		 * Creates a new measurement instance, but does not start it yet.
+		 * 
+		 * @param onionAddress
+		 *            The onion address to which the request shall be performed.
+		 * @param providingNode
+		 *            The node that provides the hidden service.
+		 * @param useAsProxy
+		 *            The node that is used as proxy for the request.
+		 */
+		private HiddenServiceRequestMeasurement(String onionAddress,
+				EventSource providingNode, ProxyNode useAsProxy) {
+
+			// remember the args
+			this.onionAddress = onionAddress;
+			this.providingNode = providingNode;
+			this.useAsProxy = useAsProxy;
+
+			// register for events from the two involved nodes
+			manager.addEventListener(providingNode, this);
+			manager.addEventListener(useAsProxy, this);
+
+			// determine socks port of proxy
+			int socksPort = useAsProxy.getSocksPort();
+
+			// create client application and register for events originating
+			// from it
+			this.clientApp = network.createClient("client", onionAddress, 80,
+					socksPort);
+			manager.addEventListener(this.clientApp, this);
+		}
+
+		@Override
+		public synchronized void run() {
+
+			// start the measurement in state STARTED
+			this.measurementState = MeasurementState.STARTED;
+
+			// perform the request
+			this.clientApp.performRequest(1, 60 * 1000, true);
+
+			// wait for a minute for the request to be performed
+			long startingTime = System.currentTimeMillis();
+			long endOfWaiting = startingTime + 60 * 1000;
+			long now;
+			while (this.measurementState == MeasurementState.STARTED
+					&& (now = System.currentTimeMillis()) < endOfWaiting) {
+				try {
+					System.out.println(new Date() + ": Waiting...");
+					wait(endOfWaiting - now);
+				} catch (InterruptedException e) {
+				}
+			}
+			System.out.println(new Date() + ": Finished waiting!");
+
+			// if the client application did not receive a reply within the
+			// given time, fail the measurement
+			if (this.measurementState == MeasurementState.STARTED) {
+				measurementState = MeasurementState.FAILED;
+			}
+
+			// unregister event listener
+			manager.removeEventListener(this);
+
+			// print out measurement result
+			System.out
+					.println(System.currentTimeMillis()
+							+ ": Hidden service request for onion address "
+							+ this.onionAddress
+							+ " running on node "
+							+ this.providingNode.getName()
+							+ " using node "
+							+ this.useAsProxy.getName()
+							+ " as proxy took "
+							+ (replyReceivedAtClient > 0
+									&& requestSentFromClient > 0 ? ((replyReceivedAtClient - requestSentFromClient) / 1000)
+									: -1) + " seconds and ended in state "
+							+ measurementState.toString());
+
+			if (this.measurementState == MeasurementState.SUCCEEDED) {
+				resultWriter
+						.writeHiddenServiceRequest((replyReceivedAtClient - requestSentFromClient) / 1000);
+			} else if (this.measurementState == MeasurementState.FAILED) {
+				resultWriter.writeHiddenServiceRequest(-1);
+			}
+		}
+
+		public void handleEvent(Event event) {
+			// only accept events when this measurement is running
+			if (measurementState != MeasurementState.STARTED) {
+				return;
+			}
+
+			if ((event.getSource() == this.useAsProxy || event.getSource() == this.providingNode)
+					&& event.getType() == EventType.NODE_STOPPED) {
+				// when either the node providing the hidden service, or the
+				// node that is used as proxy fails, abort measurement
+				System.out.println("node has stopped: " + event);
+				this.measurementState = MeasurementState.ABORTED;
+				notify();
+
+			} else if (event.getSource() == this.clientApp
+					&& event.getType() == EventType.CLIENT_SENDING_REQUEST) {
+				// when the client application reports sending the request, note
+				// the time
+				this.requestSentFromClient = event.getOccurrenceTime();
+
+			} else if (event.getSource() == this.clientApp
+					&& event.getType() == EventType.CLIENT_REPLY_RECEIVED) {
+				// when the client application reports receiving a reply,
+				// succeed the measurement
+				this.replyReceivedAtClient = event.getOccurrenceTime();
+				this.measurementState = MeasurementState.SUCCEEDED;
+				notify();
+
+			} else if (event.getSource() == this.clientApp
+					&& event.getType() == EventType.CLIENT_GAVE_UP_REQUEST) {
+				// when the client application reports giving up the request,
+				// fail the measurement
+				System.out.println("client gave up request" + event);
+				this.measurementState = MeasurementState.FAILED;
+				notify();
+			}
+		}
+	}
+
+	/**
+	 * Writes the results of the measurements to files.
+	 */
+	private static class ResultWriter {
+
+		/**
+		 * Performs the actual writing to file.
+		 * 
+		 * @param fileName
+		 *            File name to write the measurement result to.
+		 * @param timeInSeconds
+		 *            Value to be written.
+		 */
+		private synchronized void writeToFile(String fileName,
+				long timeInSeconds) {
+			try {
+				File file = new File(network.getWorkingDirectory()
+						.getAbsolutePath()
+						+ File.separator + fileName);
+				if (!file.exists()) {
+					FileWriter fw = new FileWriter(file);
+					fw.append("" + timeInSeconds);
+					fw.close();
+				} else {
+					FileWriter fw = new FileWriter(file, true);
+					fw.append("," + timeInSeconds);
+					fw.close();
+				}
+			} catch (IOException e) {
+				System.err.println(new Date()
+						+ ": Could not write measurement result to file.");
+			}
+		}
+
+		/**
+		 * Writes the result of an online propagation measurement to file.
+		 * 
+		 * @param timeInSeconds
+		 *            Measurement result.
+		 * @throws IOException
+		 *             Thrown if the file could not be written for some reason.
+		 */
+		private synchronized void writeOnlinePropagation(long timeInSeconds) {
+			this.writeToFile("online-propagation", timeInSeconds);
+		}
+
+		/**
+		 * Writes the result of an offline propagation measurement to file.
+		 * 
+		 * @param timeInSeconds
+		 *            Measurement result.
+		 * @throws IOException
+		 *             Thrown if the file could not be written for some reason.
+		 */
+		private synchronized void writeOfflinePropagation(long timeInSeconds) {
+			this.writeToFile("offline-propagation", timeInSeconds);
+		}
+
+		/**
+		 * Writes the result of a descriptor propagation measurement to file.
+		 * 
+		 * @param timeInSeconds
+		 *            Measurement result.
+		 * @throws IOException
+		 *             Thrown if the file could not be written for some reason.
+		 */
+		private synchronized void writeDescriptorPropagation(long timeInSeconds) {
+			this.writeToFile("descriptor-propagation", timeInSeconds);
+		}
+
+		/**
+		 * Writes the result of a hidden service request measurement to file.
+		 * 
+		 * @param timeInSeconds
+		 *            Measurement result.
+		 * @throws IOException
+		 *             Thrown if the file could not be written for some reason.
+		 */
+		private synchronized void writeHiddenServiceRequest(long timeInSeconds) {
+			this.writeToFile("hidden-service-requests", timeInSeconds);
+		}
+	}
+
+	/**
+	 * Writes the results of the measurements to files.
+	 */
+	private static ResultWriter resultWriter = new ResultWriter();
+
+	/**
+	 * The network configuration.
+	 */
+	private static Network network;
+
+	/**
+	 * The event manager of this application.
+	 */
+	private static EventManager manager;
+
+	/**
+	 * List of all directory nodes.
+	 */
+	private static List<DirectoryNode> runningDirs;
+
+	/**
+	 * List of all router nodes.
+	 */
+	private static List<RouterNode> runningRouters;
+
+	/**
+	 * Sets up and runs the test.
+	 * 
+	 * @param args
+	 *            Optionally, a base port number can be passed so that the
+	 *            started Tor processes use ports starting from that number (up
+	 *            to the next few hundreds).
+	 * @throws TorProcessException
+	 *             Thrown if there is a problem with the JVM-external Tor
+	 *             processes that we cannot handle.
+	 */
+	public static void main(String[] args) {
+		try {
+
+			System.out.println("WARNING! This long-running test case "
+					+ "sometimes fails for yet unknown reasons, "
+					+ "possibly because of the test case "
+					+ "implementation! Don't rely on it!");
+
+			int portStart = 7000;
+
+			if (args.length == 1) {
+				try {
+					portStart = Integer.parseInt(args[0]);
+				} catch (NumberFormatException e) {
+					System.out.println("Usage: java "
+							+ DistributedStorage.class.getCanonicalName()
+							+ " [basePort]");
+					System.exit(1);
+				}
+			}
+
+			// create a network to initialize a test case
+			network = NetworkFactory.createNetwork("distributed-storage");
+
+			System.out.println(new Date() + ": Starting test run "
+					+ network.getWorkingDirectory().getName());
+
+			// obtain reference to event manager to be able to respond to events
+			manager = network.getEventManager();
+
+			// add event type patterns for events that only occur in a modified
+			// Tor
+			manager.registerEventTypePattern(
+					"Hidden service routing table has changed",
+					EventType.NODE_ROUTING_TABLE_CHANGED);
+			manager
+					.registerEventTypePattern(
+							"Sending publish request for "
+									+ "v2 descriptor for "
+									+ "service '.*' with descriptor ID '.*' with validity of .* "
+									+ "seconds to hidden service directory '.*' on port .*",
+							EventType.BOB_SENDING_PUBLISH_DESC);
+			manager.registerEventTypePattern("Successfully stored service "
+					+ "descriptor with desc ID " + "'.*' and len .*",
+					EventType.HSDIR_DESC_STORED);
+			manager.registerEventTypePattern("Sending fetch request for v2 "
+					+ "descriptor for "
+					+ "service '.*' with descriptor ID '.*' to hidden "
+					+ "service directory '.*' on port .*",
+					EventType.ALICE_SENDING_FETCH_DESC);
+			manager.registerEventTypePattern(
+					"Successfully stored service descriptor with "
+							+ "desc ID '.*'", EventType.HSDIR_DESC_STORED);
+
+			// create two directory nodes with parameters (router name, control
+			// port, SOCKS port, OR port, dir port)
+			runningDirs = new ArrayList<DirectoryNode>();
+			DirectoryNode dir1 = network.createDirectory("dir1", portStart + 1,
+					portStart + 2, portStart + 3, portStart + 4);
+			DirectoryNode dir2 = network.createDirectory("dir2",
+					portStart + 11, portStart + 12, portStart + 13,
+					portStart + 14);
+			dir1.addConfiguration("MinUptimeHidServDirectoryV2 0 minutes");
+			dir2.addConfiguration("MinUptimeHidServDirectoryV2 0 minutes");
+			runningDirs.add(dir1);
+			runningDirs.add(dir2);
+
+			runningRouters = new ArrayList<RouterNode>();
+
+			// create 9 router nodes with parameters (router name, control port,
+			// SOCKS port, OR port, dir mirror port)
+			int routerCounter = 1;
+			for (; routerCounter < 10; routerCounter++) {
+				RouterNode router = network.createRouter("router0"
+						+ routerCounter, portStart + routerCounter * 10 + 11,
+						portStart + routerCounter * 10 + 12, portStart
+								+ routerCounter * 10 + 13, portStart
+								+ routerCounter * 10 + 14);
+				router.addConfiguration("HidServDirectoryV2 1");
+				router.addConfiguration("FetchHidServDescriptors 0");
+				router.addConfiguration("FetchV2HidServDescriptors 1");
+				runningRouters.add(router);
+			}
+
+			// configure nodes of this network to be part of a private network
+			network.configureAsPrivateNetwork();
+
+			// write configuration of proxy node
+			network.writeConfigurations();
+			System.out.println(new Date()
+					+ ": Successfully written configurations!");
+
+			// start proxy node and wait until it has opened a circuit with a
+			// timeout of 10 seconds
+			if (!network.startNodes(10000)) {
+
+				// failed to start the proxy
+				System.out.println(new Date() + ": Failed to start nodes!");
+				System.exit(1);
+			}
+			System.out.println(new Date() + ": Successfully started nodes!");
+
+			// start observers for all initial routers which might become hidden
+			// service directories after some time (if not stopped before)
+			for (RouterNode router : runningRouters) {
+				new HiddenServiceDirectoryObserver(router).start();
+			}
+
+			// start measurement of descriptor propagation
+			new DescriptorObserverStarter();
+
+			// start thread that will periodically try to access a hidden
+			// service
+			new HiddenServiceRequestStarter().start();
+
+			// hup until proxy has built circuits (6 retries, 10 seconds timeout
+			// each)
+			if (!network.hupUntilUp(6, 10000)) {
+
+				// failed to build circuits
+				System.out.println(new Date() + ": Failed to build circuits!");
+				System.exit(1);
+			}
+			System.out.println(new Date() + ": Successfully built circuits!");
+
+			int HOURS_TO_WAIT = 30;
+
+			// let it run for HOURS_TO_WAIT minutes...
+			System.out.println(new Date() + ": Waiting for " + HOURS_TO_WAIT
+					+ " hours, changing node population every hour...");
+
+			long hiddenServiceStableTime = System.currentTimeMillis() + 30 * 60 * 1000;
+
+			Random rnd = new Random();
+			long waitingTime = 0;
+
+			for (int i = 0; i < HOURS_TO_WAIT - 1; i++) {
+				// wait for 15 to 30 minutes
+				waitingTime = 15 * 60 * 1000 + rnd.nextInt(15 * 60 * 1000);
+				System.out.print("Waiting for " + waitingTime / 1000
+						+ " seconds");
+				long startOfWaiting = System.currentTimeMillis();
+				while (System.currentTimeMillis() < startOfWaiting
+						+ waitingTime) {
+					System.out.print(".");
+					try {
+						Thread.sleep(5000);
+					} catch (InterruptedException e) {
+						// do nothing
+					}
+				}
+				System.out.println();
+
+				// shut down one node
+				int candidate = rnd.nextInt(runningRouters.size());
+				RouterNode removedRouter = runningRouters.remove(candidate);
+				System.out.print(new Date() + ": Shutting down router "
+						+ removedRouter.getNodeName() + "... ");
+				removedRouter.shutdown();
+				System.out.println("succeeded");
+
+				// wait for the rest of the half hour
+				waitingTime = 30 * 60 * 1000 - waitingTime;
+				System.out.print("Waiting for " + waitingTime / 1000
+						+ " seconds");
+				startOfWaiting = System.currentTimeMillis();
+				while (System.currentTimeMillis() < startOfWaiting
+						+ waitingTime) {
+					System.out.print(".");
+					try {
+						Thread.sleep(5000);
+					} catch (InterruptedException e) {
+						// do nothing
+					}
+				}
+				System.out.println();
+
+				// wait for 15 to 30 minutes
+				waitingTime = 15 * 60 * 1000 + rnd.nextInt(15 * 60 * 1000);
+				System.out.print("Waiting for " + waitingTime / 1000
+						+ " seconds");
+				startOfWaiting = System.currentTimeMillis();
+				while (System.currentTimeMillis() < startOfWaiting
+						+ waitingTime) {
+					System.out.print(".");
+					try {
+						Thread.sleep(5000);
+					} catch (InterruptedException e) {
+						// do nothing
+					}
+				}
+				System.out.println();
+
+				// start another node
+				boolean startSuccessful = false;
+				do {
+					RouterNode newRouter = network.createRouter("router"
+							+ routerCounter, portStart + routerCounter * 10
+							+ 11, portStart + routerCounter * 10 + 12,
+							portStart + routerCounter * 10 + 13, portStart
+									+ routerCounter * 10 + 14);
+
+					newRouter.addConfiguration("HidServDirectoryV2 1");
+					newRouter.addConfiguration("FetchHidServDescriptors 0");
+					newRouter.addConfiguration("FetchV2HidServDescriptors 1");
+
+					// if the system is running for at least 24 hours, it can be
+					// considered stable, so that hidden services can be started
+					long now = System.currentTimeMillis();
+					if (now >= hiddenServiceStableTime) {
+
+						// add hidden service to the configuration of the new
+						// router
+						newRouter.addHiddenService("hidServ" + routerCounter,
+								portStart + routerCounter * 10 + 15, 80);
+
+						// let the new router only publish v2 descriptors
+						newRouter
+								.addConfiguration("PublishHidServDescriptors 0");
+						newRouter
+								.addConfiguration("PublishV2HidServDescriptors 1");
+					}
+
+					// re-configure nodes of this network to be part of a
+					// private network
+					network.configureAsPrivateNetwork();
+
+					newRouter.writeConfiguration();
+					System.out
+							.print(new Date()
+									+ ": Starting router "
+									+ newRouter.getNodeName()
+									+ (now >= hiddenServiceStableTime ? " with hidden service"
+											: "") + "... ");
+					if (newRouter.startNode(15000)) {
+						System.out.println("succeeded");
+
+						runningRouters.add(newRouter);
+
+						startSuccessful = true;
+
+						// if a hidden service was started, start an observer
+						// for it
+						if (now >= hiddenServiceStableTime) {
+							new HiddenServiceObserver(newRouter, newRouter
+									.getOnionAddress("hidServ" + routerCounter,
+											2)).start();
+						}
+
+						// start observer for the new hidden service directory
+						new HiddenServiceDirectoryObserver(newRouter).start();
+
+					} else {
+						System.out.println("failed");
+
+						// trying to start another router node...
+						// TODO limit this restarting of nodes to a certain
+						// number to get aware of permanent errors
+					}
+
+					routerCounter++;
+				} while (!startSuccessful);
+
+				// wait for the rest of the half hour
+				waitingTime = 30 * 60 * 1000 - waitingTime;
+				System.out.print("Waiting for " + waitingTime / 1000
+						+ " seconds");
+				startOfWaiting = System.currentTimeMillis();
+				while (System.currentTimeMillis() < startOfWaiting
+						+ waitingTime) {
+					System.out.print(".");
+					try {
+						Thread.sleep(5000);
+					} catch (InterruptedException e) {
+						// do nothing
+					}
+				}
+				System.out.println();
+
+				System.out.println(new Date() + ": Waiting for another "
+						+ (HOURS_TO_WAIT - i - 1) + " hour"
+						+ (i == HOURS_TO_WAIT - 2 ? "" : "s") + " ...");
+			}
+
+			// waiting for the last hour
+			try {
+				Thread.sleep(1L * 60L * 60L * 1000L);
+			} catch (InterruptedException e) {
+				// do nothing
+			}
+
+			// shut down nodes
+			network.shutdownNodes();
+
+			System.out.println(new Date() + ": Exiting...");
+			System.exit(1);
+
+		} catch (TorProcessException e) {
+			System.out.println(e);
+			e.printStackTrace();
+			System.exit(1);
+		} catch (Throwable t) {
+			System.out.println(t);
+			t.printStackTrace();
+			System.exit(1);
+		}
+	}
+}

Added: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/HidServDirectoryTest.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/HidServDirectoryTest.java	                        (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/HidServDirectoryTest.java	2007-08-26 21:18:53 UTC (rev 11280)
@@ -0,0 +1,431 @@
+package de.uniba.wiai.lspi.puppetor.diststorage;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+import java.net.Socket;
+import java.security.Security;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import de.uniba.wiai.lspi.puppetor.DirectoryNode;
+import de.uniba.wiai.lspi.puppetor.EventSource;
+import de.uniba.wiai.lspi.puppetor.Network;
+import de.uniba.wiai.lspi.puppetor.NetworkFactory;
+import de.uniba.wiai.lspi.puppetor.RouterNode;
+import de.uniba.wiai.lspi.puppetor.TorProcessException;
+
+/* TODO Document this class properly */
+
+/**
+ * <p>
+ * Test application of the distributed storage for hidden service descriptors as
+ * described in proposal 114. <b>WARNING: This example does not work with an
+ * unmodified Tor!</b>
+ * </p>
+ * 
+ * <p>
+ * When running, the example starts a network of local Tor processes, consisting
+ * of 2 directory nodes and 4 onion routers, and lets it stabilize for one
+ * minutes. Afterwards, it performs the following test operations:
+ * </p>
+ * 
+ * <ol>
+ * <li>Post a number of freshly generated v2 rendezvous service descriptors via
+ * HTTP POST to the responsible (and one irresponsible) hidden service directory
+ * and observe if the operation succeeds.</li>
+ * <li>Fetch the previously posted descriptors (and one freshly generated one)
+ * via HTTP GET from the responsible (and one irresponsible) hidden service
+ * directory and validate the reply.</li>
+ * <li>Request the replicas of descriptors in all intervals between two hidden
+ * service directories from all such and display the replies.</li>
+ * </ol>
+ * 
+ * <p>
+ * Note: This test application requires crypto from BouncyCastle; you need to
+ * include the jar "bcprov-jdk16-137.jar" into your classpath and download and
+ * install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction
+ * Policy Files 6 from the Sun homepage. (Installation directory under Ubuntu
+ * Linux is /usr/lib/jvm/java-6-sun-1.6.0.00/jre/lib/security/)
+ * 
+ * @author kloesing
+ */
+public class HidServDirectoryTest {
+
+	/**
+	 * Helper method: Sends a publish request containing the given <b>descString</b>
+	 * via HTTP POST to the given <b>dirPort</b>.
+	 * 
+	 * @param descString
+	 *            The ASCII-encoded descriptor to be published.
+	 * @param dirPort
+	 *            The dir port to send the request to.
+	 * @return The HTTP reply.
+	 */
+	private static boolean sendDescriptor(String descString, int dirPort) {
+
+		try {
+
+			// create new socket using Tor as proxy
+			Socket s = new Socket("localhost", dirPort);
+
+			// open output stream to write request
+			PrintStream out = new PrintStream(s.getOutputStream());
+
+			out
+					.print("POST /tor/rendezvous2/publish HTTP/1.0\r\nContent-Length: ");
+			out.print(descString.length());
+			out.print("\r\nHost: 127.0.0.1:");
+			out.print(dirPort);
+			out.print("\r\n\r\n");
+			out.print(descString);
+			out.print("\r\n");
+
+			// open input stream to read reply
+			BufferedReader in = new BufferedReader(new InputStreamReader(s
+					.getInputStream()));
+
+			// read reply
+			String inputLine = null;
+			StringBuilder result = new StringBuilder();
+			while ((inputLine = in.readLine()) != null) {
+				// System.out.println(inputLine);
+				result.append(inputLine + "\n");
+			}
+
+			// clean up socket
+			in.close();
+			out.close();
+			s.close();
+
+			if (result.toString().startsWith("HTTP/1.0 200 ")) {
+				return true;
+			}
+			return false;
+
+		} catch (IOException e) {
+			System.out.println("Sending failed!");
+			return false;
+		}
+	}
+
+	/**
+	 * Helper method: Sends a fetch request for the given <b>descId</b> via
+	 * HTTP GET to the given <b>dirPort</b>.
+	 * 
+	 * @param descId
+	 *            The descriptor ID to be fetched.
+	 * @param dirPort
+	 *            The dir port to send the request to.
+	 * @return The HTTP reply.
+	 */
+	private static String fetchDescriptor(String descId, int dirPort) {
+
+		try {
+
+			// create new socket using Tor as proxy
+			Socket s = new Socket("localhost", dirPort);
+
+			// open output stream to write request
+			PrintStream out = new PrintStream(s.getOutputStream());
+
+			out.print("GET /tor/rendezvous2/");
+			out.print(descId);
+			out.print(" HTTP/1.0\r\n\r\n");
+
+			// open input stream to read reply
+			BufferedReader in = new BufferedReader(new InputStreamReader(s
+					.getInputStream()));
+
+			// read reply
+			String inputLine = null;
+			StringBuilder result = new StringBuilder();
+			while ((inputLine = in.readLine()) != null) {
+				// System.out.println(inputLine);
+				result.append(inputLine + "\n");
+			}
+
+			// clean up socket
+			in.close();
+			out.close();
+			s.close();
+
+			return result.toString();
+
+		} catch (IOException e) {
+			System.out.println("Sending failed!");
+			return null;
+		}
+	}
+
+	/**
+	 * Sets up and runs the test.
+	 * 
+	 * @param args
+	 *            Command-line arguments (ignored).
+	 * @throws TorProcessException
+	 *             Thrown if there is a problem with the JVM-external Tor
+	 *             processes that we cannot handle.
+	 */
+	public static void main(String[] args) throws TorProcessException {
+
+		int numberOfDescs = 10;
+
+		if (args.length == 1) {
+			try {
+				numberOfDescs = Integer.parseInt(args[0]);
+			} catch (NumberFormatException e) {
+				System.out.println("Usage: java "
+						+ HidServDirectoryTest.class.getCanonicalName()
+						+ " [numberOfDescs]");
+				System.exit(1);
+			}
+		}
+
+		if (numberOfDescs < 0 || numberOfDescs > 1000) {
+			System.out.println("Bad value for numberOfDescs: " + numberOfDescs
+					+ "! Setting to 10.");
+			numberOfDescs = 10;
+		}
+
+		Security.addProvider(new BouncyCastleProvider());
+
+		// create a private tor network with hs dirs, let it stabilize
+		// create a network to initialize a test case
+		Network network = NetworkFactory.createNetwork("example4");
+
+		// create two directory nodes with parameters (router name, control
+		// port, SOCKS port, OR port, dir port)
+		DirectoryNode dir1 = network.createDirectory("dir1", 7001, 7002, 7003,
+				7004);
+		DirectoryNode dir2 = network.createDirectory("dir2", 7011, 7012, 7013,
+				7014);
+
+		// create three router nodes with parameters (router name, control port,
+		// SOCKS port, OR port, dir mirror port)
+		RouterNode router1 = network.createRouter("router1", 7021, 7022, 7023,
+				7024);
+		RouterNode router2 = network.createRouter("router2", 7031, 7032, 7033,
+				7034);
+		RouterNode router3 = network.createRouter("router3", 7041, 7042, 7043,
+				7044);
+		RouterNode router4 = network.createRouter("router4", 7051, 7052, 7053,
+				7054);
+
+		Set<RouterNode> allRouters = new HashSet<RouterNode>();
+		allRouters.add(dir1);
+		allRouters.add(dir2);
+		allRouters.add(router1);
+		allRouters.add(router2);
+		allRouters.add(router3);
+		allRouters.add(router4);
+
+		// configure all nodes hidden service directories
+		dir1.addConfiguration("HidServDirectoryV2 1");
+		dir2.addConfiguration("HidServDirectoryV2 1");
+		dir1.addConfiguration("MinUptimeHidServDirectoryV2 0 minutes");
+		dir2.addConfiguration("MinUptimeHidServDirectoryV2 0 minutes");
+		router1.addConfiguration("HidServDirectoryV2 1");
+		router2.addConfiguration("HidServDirectoryV2 1");
+		router3.addConfiguration("HidServDirectoryV2 1");
+		router4.addConfiguration("HidServDirectoryV2 1");
+
+		// configure nodes of this network to be part of a private network
+		network.configureAsPrivateNetwork();
+
+		// write configuration of proxy node
+		network.writeConfigurations();
+
+		// start proxy node and wait until it has opened a circuit with a
+		// timeout of 15 seconds
+		if (!network.startNodes(15000)) {
+
+			// failed to start the proxy
+			System.out.println("Failed to start nodes!");
+			return;
+		}
+		System.out.println("Successfully started nodes!");
+
+		// hup until proxy has built circuits (10 retries, 10 seconds timeout
+		// each)
+		if (!network.hupUntilUp(20, 6000)) {
+
+			// failed to build circuits
+			System.out.println("Failed to build circuits!");
+			return;
+		}
+		System.out.println("Successfully built circuits!");
+
+		// wait for 30 minutes for stabilization
+		try {
+			Thread.sleep(30 * 60 * 1000);
+		} catch (InterruptedException e1) {
+			e1.printStackTrace();
+		}
+
+		// add all routers to the global routing table
+		HidServRoutingTable routingTable = new HidServRoutingTable();
+		for (RouterNode router : allRouters) {
+			routingTable.addHiddenServiceDirectory(router);
+		}
+		System.out.println(routingTable);
+
+		Random rnd = new Random();
+
+		List<RendezvousServiceDescriptor> allDescs = new ArrayList<RendezvousServiceDescriptor>();
+
+		// post descs (correct and false ones) to all responsible dirs
+
+		for (int i = 0; i < numberOfDescs; i++) {
+
+			RendezvousServiceDescriptor desc = RendezvousServiceDescriptor
+					.prepare();
+
+			// try to parse and verify it
+			RendezvousServiceDescriptor parsed = RendezvousServiceDescriptor
+					.parseAndVerify(desc.getDescriptorString());
+			System.out.println("Can generated descriptor with ID "
+					+ parsed.getDescriptorID() + " be parsed and verified? "
+					+ (parsed != null));
+
+			allDescs.add(desc);
+
+			// post to all responsible and ONE irresponsible node
+			Set<EventSource> responsibleNodes = routingTable
+					.getResponsibleHSDirs(desc.getDescriptorID());
+
+			for (EventSource node : responsibleNodes) {
+
+				System.out.print("Posting descriptor to node " + node.getName()
+						+ "... ");
+				boolean result = sendDescriptor(desc.getDescriptorString(),
+						((RouterNode) node).getDirPort());
+				System.out.println(result ? "successful" : "failed");
+
+				try {
+					Thread.sleep(100);
+				} catch (InterruptedException e) {
+				}
+			}
+
+			// post to one false node
+			List<EventSource> notResponsible = new ArrayList<EventSource>(
+					allRouters);
+			notResponsible.removeAll(responsibleNodes);
+			EventSource node = notResponsible.get(rnd.nextInt(notResponsible
+					.size()));
+			System.out.print("Posting descriptor to IRRESPONSIBLE node "
+					+ node.getName() + "... ");
+			boolean result = sendDescriptor(desc.getDescriptorString(),
+					((RouterNode) node).getDirPort());
+			System.out.println(result ? "successful" : "failed");
+
+			try {
+				Thread.sleep(100);
+			} catch (InterruptedException e) {
+			}
+
+		}
+
+		// fetch descs (existing and non-existing ones) from each resp dir
+		RendezvousServiceDescriptor freshDesc = RendezvousServiceDescriptor
+				.prepare();
+		allDescs.add(freshDesc);
+		for (RendezvousServiceDescriptor desc : allDescs) {
+
+			Set<EventSource> responsibleNodes = routingTable
+					.getResponsibleHSDirs(desc.getDescriptorID());
+
+			for (EventSource node : responsibleNodes) {
+
+				System.out.print("Fetching descriptor from node "
+						+ node.getName() + "... ");
+				String result = fetchDescriptor(desc.getDescriptorID(),
+						((RouterNode) node).getDirPort());
+
+				RendezvousServiceDescriptor received = RendezvousServiceDescriptor
+						.parseAndVerify(result);
+				System.out
+						.println((received != null) ? "successful" : "failed");
+
+				try {
+					Thread.sleep(100);
+				} catch (InterruptedException e) {
+				}
+			}
+
+			// fetch from one false node
+			List<EventSource> notResponsible = new ArrayList<EventSource>(
+					allRouters);
+			notResponsible.removeAll(responsibleNodes);
+			EventSource node = notResponsible.get(rnd.nextInt(notResponsible
+					.size()));
+			System.out.print("Fetching descriptor from IRRESPONSIBLE node "
+					+ node.getName() + "... ");
+			String result = fetchDescriptor(desc.getDescriptorID(),
+					((RouterNode) node).getDirPort());
+
+			RendezvousServiceDescriptor received = RendezvousServiceDescriptor
+					.parseAndVerify(result);
+			System.out.println((received != null) ? "successful" : "failed");
+
+			try {
+				Thread.sleep(100);
+			} catch (InterruptedException e) {
+			}
+
+		}
+		allDescs.remove(freshDesc);
+
+		// request all replicas from all nodes
+		List<RouterNode> allNodes = routingTable.getAllHSDirs();
+		for (int i = 0; i < allNodes.size(); i++) {
+			RouterNode from = allNodes.get(i);
+			RouterNode to = allNodes.get(i < allNodes.size() - 1 ? i + 1 : 0);
+
+			for (RouterNode router : allRouters) {
+				String request = from.getFingerprintBase32() + "-"
+						+ to.getFingerprintBase32();
+				System.out.print("Fetching replicas for interval " + request
+						+ " from node " + router.getName() + "... ");
+				String replicas = fetchDescriptor(request, router.getDirPort());
+				int numReplicas = 0;
+				int numParsed = 0;
+				StringBuilder sb = new StringBuilder();
+				while (replicas.contains("rendezvous-service-descriptor ")) {
+					replicas = replicas.substring(replicas
+							.indexOf("rendezvous-service-descriptor "));
+					String desc2;
+					if (replicas.indexOf("rendezvous-service-descriptor ", 16) > 0) {
+						desc2 = replicas.substring(0, replicas.indexOf(
+								"rendezvous-service-descriptor ", 16));
+						replicas = replicas.substring(desc2.length());
+						numReplicas++;
+					} else {
+						desc2 = replicas;
+						replicas = "";
+						numReplicas++;
+					}
+					RendezvousServiceDescriptor received = RendezvousServiceDescriptor
+							.parseAndVerify(desc2);
+					if (received != null) {
+						sb.append(received.getDescriptorID() + " ");
+						numParsed++;
+					}
+				}
+				System.out.println(numReplicas + " replicas, " + numParsed
+						+ " successfully parsed: " + sb.toString());
+			}
+		}
+
+		// shut down nodes
+		network.shutdownNodes();
+
+	}
+}

Added: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/HidServRoutingTable.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/HidServRoutingTable.java	                        (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/HidServRoutingTable.java	2007-08-26 21:18:53 UTC (rev 11280)
@@ -0,0 +1,195 @@
+package de.uniba.wiai.lspi.puppetor.diststorage;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import de.uniba.wiai.lspi.puppetor.EventSource;
+import de.uniba.wiai.lspi.puppetor.RouterNode;
+
+/* TODO Document this class properly */
+
+/**
+ * Manages a routing table of hidden service directories that can be used to
+ * maintain a global view of a Tor network under test and to synchronize on
+ * changes on it.
+ */
+public class HidServRoutingTable {
+
+	/** Compares two base32-encoded IDs to each other. */
+	private static Comparator<String> comparator = new Comparator<String>() {
+
+		private int[] base32Lookup = { 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D,
+				0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+				0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+				0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
+				0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF,
+				0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+				0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
+				0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF,
+				0xFF, 0xFF, 0xFF, 0xFF };
+
+		private byte[] base32toHex(String base32) {
+
+			int i, index, lookup, offset, digit;
+
+			byte[] bytes = new byte[base32.length() * 5 / 8];
+
+			for (i = 0, index = 0, offset = 0; i < base32.length(); i++) {
+				lookup = base32.charAt(i) - '0';
+
+				/* Skip chars outside the lookup table */
+				if (lookup < 0 || lookup >= base32Lookup.length)
+					continue;
+
+				digit = base32Lookup[lookup];
+
+				/* If this digit is not in the table, ignore it */
+				if (digit == 0xFF)
+					continue;
+
+				if (index <= 3) {
+					index = (index + 5) % 8;
+					if (index == 0) {
+						bytes[offset] |= digit;
+						offset++;
+						if (offset >= bytes.length)
+							break;
+					} else
+						bytes[offset] |= digit << (8 - index);
+				} else {
+					index = (index + 5) % 8;
+					bytes[offset] |= (digit >>> index);
+					offset++;
+
+					if (offset >= bytes.length)
+						break;
+					bytes[offset] |= digit << (8 - index);
+				}
+			}
+			return bytes;
+		}
+
+		public int compare(String arg0, String arg1) {
+			byte[] bytes0 = base32toHex(arg0);
+			byte[] bytes1 = base32toHex(arg1);
+			for (int i = 0; i < bytes0.length && i < bytes1.length; i++) {
+				if ((bytes0[i] + 256) % 256 < (bytes1[i] + 256) % 256) {
+					return -1;
+				} else if ((bytes0[i] + 256) % 256 > (bytes1[i] + 256) % 256) {
+					return 1;
+				}
+			}
+			return 0;
+		}
+	};
+
+	/**
+	 * Sorted map of hidden service directory IDs and the corresponding router
+	 * node.
+	 */
+	private SortedMap<String, RouterNode> hsDirs = new TreeMap<String, RouterNode>(
+			comparator);
+
+	/**
+	 * Adds a hidden service directory to the routing table. The node needs to
+	 * be started before being added!
+	 * 
+	 * @param hsdNode
+	 *            The node to be added as hidden service directory.
+	 */
+	public synchronized void addHiddenServiceDirectory(RouterNode hsdNode) {
+		this.hsDirs.put(hsdNode.getFingerprintBase32(), hsdNode);
+		notifyAll();
+	}
+
+	public synchronized String toString() {
+		StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()
+				+ ": hsdirs={ ");
+		for (String nodeID : this.hsDirs.keySet()) {
+			sb.append(this.hsDirs.get(nodeID).getName() + "("
+					+ nodeID.substring(0, 4) + "),");
+		}
+		String result = sb.toString();
+		result = result.substring(0, result.length() - 1) + " }";
+		return result;
+	}
+
+	/**
+	 * Removes a hidden service directory from the routing table.
+	 * 
+	 * @param hsdNode
+	 *            The hidden service directory to be removed.
+	 */
+	public synchronized void removeHiddenServiceDirectory(RouterNode hsdNode) {
+		this.hsDirs.remove(hsdNode.getFingerprintBase32());
+		notifyAll();
+	}
+
+	/**
+	 * Returns the set of responsible hidden service directories for the given
+	 * descriptor ID.
+	 * 
+	 * @param descID
+	 *            The descriptor ID for which the responsible hidden service
+	 *            directories shall be determined.
+	 * @return The set of responsible hidden service directories.
+	 */
+	public synchronized Set<EventSource> getResponsibleHSDirs(String descID) {
+
+		Set<EventSource> result = new HashSet<EventSource>();
+		if (this.hsDirs.size() < 3) {
+			return result;
+		}
+
+		for (EventSource s : this.hsDirs.tailMap(descID).values()) {
+			if (result.size() < 3) {
+				result.add(s);
+			} else {
+				break;
+			}
+		}
+
+		for (EventSource s : this.hsDirs.values()) {
+			if (result.size() < 3) {
+				result.add(s);
+			} else {
+				break;
+			}
+		}
+
+		return result;
+	}
+
+	/**
+	 * Returns a list of all hidden service directories in the routing table,
+	 * ordered by their node IDs.
+	 * 
+	 * @return List of all hidden service directories.
+	 */
+	public synchronized List<RouterNode> getAllHSDirs() {
+		List<RouterNode> result = new ArrayList<RouterNode>();
+		for (RouterNode router : this.hsDirs.values()) {
+			result.add(router);
+		}
+		return result;
+	}
+
+	/**
+	 * Waits for the given number of millis until either a node is added or
+	 * removed.
+	 * 
+	 * @param timeToWait
+	 *            The number of millis to wait.
+	 */
+	public synchronized void waitForRoutingTableChange(long timeToWait) {
+		try {
+			wait(timeToWait);
+		} catch (InterruptedException e) {
+		}
+	}
+}

Added: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/RendezvousServiceDescriptor.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/RendezvousServiceDescriptor.java	                        (rev 0)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/diststorage/RendezvousServiceDescriptor.java	2007-08-26 21:18:53 UTC (rev 11280)
@@ -0,0 +1,904 @@
+package de.uniba.wiai.lspi.puppetor.diststorage;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.SecureRandom;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Random;
+
+import org.bouncycastle.asn1.ASN1OutputStream;
+import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;
+import org.bouncycastle.asn1.x509.RSAPublicKeyStructure;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.digests.SHA1Digest;
+import org.bouncycastle.crypto.encodings.PKCS1Encoding;
+import org.bouncycastle.crypto.engines.RSAEngine;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.jce.provider.JCERSAPublicKey;
+import org.bouncycastle.openssl.PEMReader;
+import org.bouncycastle.util.encoders.Base64;
+
+/* TODO Document this class properly */
+
+/**
+ * Data structure of a v2 rendezvous service descriptor that further contains
+ * methods to encode, parse, and verify ASCII-encoded representations.
+ * 
+ * The cryptographic routines have been adopted from the Onion Coffee project.
+ * 
+ * @author kloesing
+ */
+public class RendezvousServiceDescriptor {
+
+	/** Descriptor ID consisting of 32 base32 chars. */
+	private String descriptorID;
+
+	/** Version number. */
+	private int version;
+
+	/** Permanent key. */
+	private String publicKeyString;
+
+	/** Secret ID part. */
+	private String secretIdPart;
+
+	/** Publication time. */
+	private String publicationTime;
+
+	/** Protocol versions. */
+	private int protocolVersions;
+
+	/** Introduction points. */
+	private String introPointsString;
+
+	/** Signature. */
+	private String signatureString;
+
+	/** ASCII-encoded representation; */
+	private String descriptorString;
+
+	@Override
+	public String toString() {
+		return "descriptorID=\"" + descriptorID + "\", " + "version=" + version
+				+ ", " + "publicKeyString=\"" + publicKeyString + "\", "
+				+ "secretIdPart=\"" + secretIdPart + "\", "
+				+ "publicationTime=\"" + publicationTime + "\", "
+				+ "protocolVersions=" + protocolVersions + ", "
+				+ "introPointsString=\"" + introPointsString + "\", "
+				+ "signatureString=\"" + signatureString + "\"";
+	}
+
+	/**
+	 * performed on server side, as encrypted ipos and secret-id-part we take
+	 * random values to make things less complicated; the hsdirs don't care.
+	 */
+	public static RendezvousServiceDescriptor prepare() {
+		try {
+			RendezvousServiceDescriptor rsd = new RendezvousServiceDescriptor();
+
+			KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA",
+					"BC");
+			generator.initialize(1024, new SecureRandom());
+			KeyPair pair = generator.generateKeyPair();
+			RSAPublicKey pubKey = (RSAPublicKey) pair.getPublic();
+			RSAPrivateKey privKey = (RSAPrivateKey) pair.getPrivate();
+			RSAPublicKeyStructure key = new RSAPublicKeyStructure(pubKey
+					.getModulus(), pubKey.getPublicExponent());
+			rsd.publicKeyString = getPEMStringFromRSAPublicKey(key);
+			RSAPrivateKeyStructure privateKey = new RSAPrivateKeyStructure(
+					privKey.getModulus(), pubKey.getPublicExponent(), privKey
+							.getPrivateExponent(), null, null, null, null, null);
+
+			Random rnd = new Random();
+			byte[] secretIdPartBytes = new byte[20];
+			rnd.nextBytes(secretIdPartBytes);
+			rsd.secretIdPart = binaryToBase32(secretIdPartBytes);
+
+			rsd.publicationTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
+					.format(new Date());
+
+			rsd.version = 2;
+
+			rsd.protocolVersions = 5;
+
+			rsd.introPointsString = aesSample;
+
+			byte[] hash = getHash(getPKCS1EncodingFromRSAPublicKey(key));
+			byte[] digestInput = new byte[10 + secretIdPartBytes.length];
+			int i, j;
+			for (i = 0, j = 0; j < 10; i++, j++)
+				digestInput[i] = hash[j];
+			for (j = 0; j < secretIdPartBytes.length; i++, j++)
+				digestInput[i] = secretIdPartBytes[j];
+			byte[] descIdBin = getHash(digestInput);
+			rsd.descriptorID = toBase32(descIdBin);
+
+			StringBuilder sb = new StringBuilder();
+			sb.append("rendezvous-service-descriptor ");
+			sb.append(rsd.descriptorID);
+			sb.append("\nversion ");
+			sb.append(rsd.version);
+			sb.append("\npermanent-key\n");
+			sb.append(rsd.publicKeyString);
+			sb.append("secret-id-part ");
+			sb.append(rsd.secretIdPart);
+			sb.append("\npublication-time ");
+			sb.append(rsd.publicationTime);
+			sb.append("\nprotocol-versions ");
+			sb.append(rsd.protocolVersions);
+			sb.append("\nintroduction-points\n");
+			sb.append(rsd.introPointsString);
+			sb.append("signature\n");
+			String descWithoutSignature = sb.toString();
+
+			byte[] signature = signData(descWithoutSignature.getBytes(),
+					new RSAKeyParameters(true, privKey.getModulus(), privKey
+							.getPrivateExponent()));
+
+			String signatureString = toBase64(signature);
+
+			sb.append("-----BEGIN SIGNATURE-----\n");
+			while (signatureString.length() > 0) {
+				if (signatureString.length() > 64) {
+					sb.append(signatureString.substring(0, 64));
+					sb.append("\n");
+					signatureString = signatureString.substring(64);
+				} else {
+					sb.append(signatureString);
+					sb.append("\n");
+					signatureString = "";
+				}
+			}
+
+			sb.append("-----END SIGNATURE-----\n\n");
+			rsd.descriptorString = sb.toString();
+
+			return rsd;
+
+		} catch (Exception e) {
+			return null;
+		}
+
+	}
+
+	/** performed on client side */
+	public static RendezvousServiceDescriptor parseAndVerify(String str) {
+		RendezvousServiceDescriptor rsd = new RendezvousServiceDescriptor();
+		{
+			String rsdTag = "rendezvous-service-descriptor ";
+			if (!str.contains(rsdTag)) {
+				// System.out
+				// .println("String does not contain \"" + rsdTag + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(rsdTag));
+			rsd.descriptorString = str;
+			str = str.substring(rsdTag.length());
+			if (str.length() < 32) {
+				return null;
+			}
+			rsd.descriptorID = str.substring(0, 32);
+			str = str.substring(32);
+		}
+		{
+			String versionTag = "version ";
+			if (!str.contains(versionTag)) {
+				// System.out.println("String does not contain \"" + versionTag
+				// + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(versionTag) + versionTag.length());
+			if (!str.contains("\n")) {
+				return null;
+			}
+			rsd.version = Integer.parseInt(str.substring(0, str.indexOf("\n")));
+			str = str.substring(str.indexOf("\n") + 1);
+		}
+		{
+			String permanentKeyTag = "permanent-key\n";
+			if (!str.contains(permanentKeyTag)) {
+				// System.out.println("String does not contain \""
+				// + permanentKeyTag + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(permanentKeyTag)
+					+ permanentKeyTag.length());
+			String publicKeyBegin = "-----BEGIN RSA PUBLIC KEY-----";
+			if (!str.contains(publicKeyBegin)) {
+				// System.out.println("String does not contain \""
+				// + publicKeyBegin + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(publicKeyBegin));
+			String publicKeyEnd = "-----END RSA PUBLIC KEY-----";
+			if (!str.contains(publicKeyEnd)) {
+				// System.out.println("String does not contain \"" +
+				// publicKeyEnd
+				// + "\"");
+				return null;
+			}
+			rsd.publicKeyString = str.substring(0, str.indexOf(publicKeyEnd)
+					+ publicKeyEnd.length());
+			str = str.substring(str.indexOf(publicKeyEnd)
+					+ publicKeyEnd.length());
+		}
+		{
+			String secretIdPartTag = "secret-id-part ";
+			if (!str.contains(secretIdPartTag)) {
+				// System.out.println("String does not contain \""
+				// + secretIdPartTag + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(secretIdPartTag)
+					+ secretIdPartTag.length());
+			if (str.length() < 32) {
+				return null;
+			}
+			rsd.secretIdPart = str.substring(0, 32);
+			str = str.substring(32);
+		}
+		{
+			String publicationTimeTag = "publication-time ";
+			if (!str.contains(publicationTimeTag)) {
+				// System.out.println("String does not contain \""
+				// + publicationTimeTag + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(publicationTimeTag)
+					+ publicationTimeTag.length());
+			if (!str.contains("\n")) {
+				// System.out.println("String does not contain \"\\n\"");
+				return null;
+			}
+			rsd.publicationTime = str.substring(0, str.indexOf("\n"));
+			str = str.substring(str.indexOf("\n") + 1);
+		}
+		{
+			String protocolVersionsTag = "protocol-versions ";
+			if (!str.contains(protocolVersionsTag)) {
+				// System.out.println("String does not contain \""
+				// + protocolVersionsTag + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(protocolVersionsTag)
+					+ protocolVersionsTag.length());
+			if (!str.contains("\n")) {
+				return null;
+			}
+			rsd.protocolVersions = Integer.parseInt(str.substring(0, str
+					.indexOf("\n")));
+			str = str.substring(str.indexOf("\n") + 1);
+		}
+		{
+			String introPointsTag = "introduction-points\n";
+			if (!str.contains(introPointsTag)) {
+				// System.out.println("String does not contain \""
+				// + introPointsTag + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(introPointsTag)
+					+ introPointsTag.length());
+			String introPointsBegin = "-----BEGIN AES ENCRYPTED MESSAGE-----";
+			if (!str.contains(introPointsBegin)) {
+				// System.out.println("String does not contain \""
+				// + introPointsBegin + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(introPointsBegin));
+			String introPointsEnd = "-----END AES ENCRYPTED MESSAGE-----";
+			if (!str.contains(introPointsEnd)) {
+				// System.out.println("String does not contain \""
+				// + introPointsEnd + "\"");
+				return null;
+			}
+			rsd.introPointsString = str.substring(0, str
+					.indexOf(introPointsEnd)
+					+ introPointsEnd.length());
+			str = str.substring(str.indexOf(introPointsEnd)
+					+ introPointsEnd.length());
+		}
+		{
+			String signatureTag = "signature\n";
+			if (!str.contains(signatureTag)) {
+				// System.out.println("String does not contain \"" +
+				// signatureTag
+				// + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(signatureTag)
+					+ signatureTag.length());
+			String signatureBegin = "-----BEGIN SIGNATURE-----\n";
+			if (!str.contains(signatureBegin)) {
+				// System.out.println("String does not contain \""
+				// + signatureBegin + "\"");
+				return null;
+			}
+			str = str.substring(str.indexOf(signatureBegin)
+					+ signatureBegin.length());
+			String signatureEnd = "\n-----END SIGNATURE-----\n";
+			if (!str.contains(signatureEnd)) {
+				// System.out.println("String does not contain \"" +
+				// signatureEnd
+				// + "\"");
+				return null;
+			}
+			rsd.signatureString = str.substring(0, str.indexOf(signatureEnd));
+			str = str.substring(str.indexOf(signatureEnd)
+					+ signatureEnd.length());
+		}
+
+		// signature okay?
+		JCERSAPublicKey rsaKey = getRSAPublicKeyFromPEMString(rsd.publicKeyString);
+		RSAPublicKeyStructure pubKey = getRSAPublicKeyStructureFromJCERSAPublicKey(rsaKey);
+		String descWithoutSignature = rsd.descriptorString;
+		descWithoutSignature = descWithoutSignature.substring(0,
+				descWithoutSignature.indexOf("-----BEGIN SIGNATURE-----"));
+		// System.out.println("Desc without signature: '" + descWithoutSignature
+		// + "'");
+		// byte[] hash = Encryption.getHash(descWithoutSignature.getBytes());
+		byte[] sig = parseBase64(rsd.signatureString);
+		// System.out.println("Checking signature for hash: ");
+		// for (byte b : hash)
+		// System.out.print(b + " ");
+		boolean signatureOkay = verifySignature(sig, pubKey,
+				descWithoutSignature.getBytes());
+		if (!signatureOkay) {
+			// System.out.println("Signature not okay!");
+			return null;
+		}
+
+		// descriptor id okay?
+		byte[] hash = getHash(getPKCS1EncodingFromRSAPublicKey(pubKey));
+		byte[] secretIdPart = base32toBinary(rsd.secretIdPart);
+		byte[] digestInput = new byte[10 + secretIdPart.length];
+		int i, j;
+		for (i = 0, j = 0; j < 10; i++, j++)
+			digestInput[i] = hash[j];
+		for (j = 0; j < secretIdPart.length; i++, j++)
+			digestInput[i] = secretIdPart[j];
+		byte[] descIdBin = getHash(digestInput);
+		String descIdString = toBase32(descIdBin);
+		// System.out.println("parsed desc id=" + desc.descriptorID
+		// + ", calculated desc id=" + descIdString);
+		if (!descIdString.equals(rsd.getDescriptorID())) {
+			// System.out.println("Desc ID not okay!");
+			return null;
+		}
+
+		return rsd;
+	}
+
+	private static String binaryToBase32(byte[] bytes) {
+		int i = 0, index = 0, digit = 0;
+		int currByte, nextByte;
+		StringBuffer base32 = new StringBuffer((bytes.length + 7) * 8 / 5);
+		String base32Chars = "abcdefghijklmnopqrstuvwxyz234567";
+		while (i < bytes.length) {
+			currByte = (bytes[i] >= 0) ? bytes[i] : (bytes[i] + 256);
+			if (index > 3) {
+				if ((i + 1) < bytes.length) {
+					nextByte = (bytes[i + 1] >= 0) ? bytes[i + 1]
+							: (bytes[i + 1] + 256);
+				} else {
+					nextByte = 0;
+				}
+				digit = currByte & (0xFF >> index);
+				index = (index + 5) % 8;
+				digit <<= index;
+				digit |= nextByte >> (8 - index);
+				i++;
+			} else {
+				digit = (currByte >> (8 - (index + 5))) & 0x1F;
+				index = (index + 5) % 8;
+				if (index == 0) {
+					i++;
+				}
+			}
+			base32.append(base32Chars.charAt(digit));
+		}
+		return base32.toString();
+	}
+
+	private static byte[] base32toBinary(String base32) {
+
+		int i, index, lookup, offset, digit;
+
+		byte[] bytes = new byte[base32.length() * 5 / 8];
+
+		for (i = 0, index = 0, offset = 0; i < base32.length(); i++) {
+			lookup = base32.charAt(i) - '0';
+
+			/* Skip chars outside the lookup table */
+			if (lookup < 0 || lookup >= base32Lookup.length)
+				continue;
+
+			digit = base32Lookup[lookup];
+
+			/* If this digit is not in the table, ignore it */
+			if (digit == 0xFF)
+				continue;
+
+			if (index <= 3) {
+				index = (index + 5) % 8;
+				if (index == 0) {
+					bytes[offset] |= digit;
+					offset++;
+					if (offset >= bytes.length)
+						break;
+				} else
+					bytes[offset] |= digit << (8 - index);
+			} else {
+				index = (index + 5) % 8;
+				bytes[offset] |= (digit >>> index);
+				offset++;
+
+				if (offset >= bytes.length)
+					break;
+				bytes[offset] |= digit << (8 - index);
+			}
+		}
+		return bytes;
+	}
+
+	static int[] base32Lookup = { 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
+			0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+			0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+			0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
+			0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
+			0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+			0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+	private static String aesSample = "-----BEGIN AES ENCRYPTED MESSAGE-----\n"
+			+ "99caooDjcURlHhbPVFGnpjH/Wq7D3PrSgvI1hGsO0mITGVOEmI4SNeLSLcLu9+As\n"
+			+ "kYfwWczVmLIfJD3cf9ed2fhJKZmuMVuRov33vK3QzhZa7Jo0L+9l3j/88vR91hbl\n"
+			+ "GkFIVlTT5sYhXKdOn1VqmWcKHuWmGqnD/HTtA5Yu8a+SNp5wvUrCpOlDB5MKrxMI\n"
+			+ "7NiJEpimSySgLDPV2DBjG+oLz0Nh5kNoTGfOnWC8HVruy2dFw0DmYOyFsjJYuucO\n"
+			+ "7PcJYL9pSAGxH42bCYvlMTWy40RFXK2CtTBjIni4+uz6L75dW4tAChjLrSQH7E4x\n"
+			+ "gV4U/9LBFnEt57g3kEmDKnc68XPO4+Jy340+kuSZJLcUL0k5sv9gpGLSPC5D4OfN\n"
+			+ "voIx0tG9ov46QtOtY03SP75ekeM4zvhBj1wQDk3YKvYKTGrXO3naDon8WZbFe3ri\n"
+			+ "Hb4MEkfei4mY0ox4YBWGgMr5URW6XZrbAwlyT1+kcTAb4z8JDAa96MLW46zjAOAp\n"
+			+ "PKvwd7aeqpnrfUYpNL1nVCRg844ORdzRySMCGmmZ3b++hmGtz2oF0Bd/DiksuRz8\n"
+			+ "XgoZX2pSiG1tlSJ1R/Vi9JbXdA4akl3SrPILmTIgt6OI6nj996eXEBtZu+1+sdre\n"
+			+ "COGtkdaqp2rqirMceL1TkJdYxCRy6H9Sb5KeoVw7cCjcjOJM4PXBPnpBIUF5ZUQc\n"
+			+ "MLFimQEaEcIDOgA6nbN+8VSZCUiMX5R9VCD1tRTcrKMGfoCkpMWzGf12HbgMz/Wn\n"
+			+ "1rqi9zTZqkv/gq7bXmL6YoCI9ZMdFU45uFEfwX7BoQ2GYANqUVjE14ehyTEFJmja\n"
+			+ "T92IdlXaH45mTZeG3ilkfd1JHB5EAB3+HzM3rhWyOshaKhP4sGRZxusZ8xJIspCz\n"
+			+ "7x7Vb/XjmOSm+hmM9F3jJxpsUW48jDWqwyrZz7h+1kboUpYChmMyGvtPozRyOmOG\n"
+			+ "zdl3+8arz/hx0i2s/u3IyVSagvBALeCydrZdhZF1VTf9FosE6Q9fwXKAlM4PUf9r\n"
+			+ "mgsu1ckXfNZPbENlVYFQ6MOvKeiI1PbgjlWMZD/POGrNeVoNVTPsQ5A32CpVZvM9\n"
+			+ "C0PAwTg9hqH2kQbDwvCkpOdH7CXsxC/+MU75El1jDnzT0cij/nXtWiZ6j16QxmZW\n"
+			+ "POS602E0uKAdtq8SE2oBZGNXwg/3bCf7f+zIm9nD0gR6owY9mJ5sVg4ArDRoj4n4\n"
+			+ "60R7BOtBpF2m4ioW/pn0KyqajIuKChn9SbDPB243/eV0BFO3hCvnCIEleANY/u3z\n"
+			+ "D/1WRerbfFLA40rB3Q7dEDukmBUcgV5g6+7SQbV+AbkHLDBtql9K+K2jhd3KcxAX\n"
+			+ "O28vxMnIB3RAPF55c7cCPYZYq8N4tIVAQLPwkRCQgfDwnBnrHF5n6WTtGEDjn3F0\n"
+			+ "GaJZhHsnyWXnVUE+zpBC8mHfLp6301dPREc5YvozE1V1vVDdrooEFKGc2Lh6HSbf\n"
+			+ "IwSNoxiEsNh/mqSZ0LulDnJXWjudwTZjJVfaOe1u6n80xYMkgkGsEM5MWNrMaMob\n"
+			+ "mKLuolptyffHER59pJMSOos9wf+JRlx7P2GerdU1sD/CKx2zzzNzyr4dW/GTBL3V\n"
+			+ "o/Riz/rEbKBUxp3yaBfcJ14tGLkW4M7Yx9Js9t5nX1tOefkVCNUBwBBnFyA4hkzF\n"
+			+ "21pXxEN6fCRFKIDv9jwmwrRrM/Ydaj1XG7nhimlWEi2kzpuOhWGQ3Kkl+h/4PDDg\n"
+			+ "eVnAbO2hmwiLZ2b/mmyezenPhkvgH/V3WchQHZGZGwiLL3XKxC8I7dRRF1XdXJsG\n"
+			+ "WqLK49x75wolLcLx73nKY64O2v6J+09dyXIAKmsPL59jdKBSia6t/lbJ07CM1DCA\n"
+			+ "BBRSCF7GmIENJ8oYDYYsXEKBMUlYJO8QEj80udFTFsenhxmiCOBBHOJ8AMKCQGKn\n"
+			+ "qtQr/NCkVtGuPvgVOPAslJ4tDTcYO1RJgIEwBPmAwIZ9P5bB6E05lq+6VYz7aOk0\n"
+			+ "A8ziP+xWs0IxoG8uinPPimnR1T/6HkU23iK07OTfHYLNw9sKpROuFjKdb5fi0xZh\n"
+			+ "92vxAv439riwvBR6D3tKuCJX+L3nEUQ4DY0ZCmrefpU5tj9IZz7e3OeNPNBX4bdw\n"
+			+ "ZZB4XRL1fHc8al84jHTYlqcnm/+mpTlzOICYDIpwQMaQA4yVpEa4Jj8cLES0Yma8\n"
+			+ "rI+aY6rEGINBhiUGFyZXLVaGaR3b4vlcZzBeTEmKZfpHhxB+MmUhPE4IpDSsxlng\n"
+			+ "OpLf11SyLU0A1DR7U4fUDAbfTKgMaoPHZhdFn2v/Fnl1yD9XsH4qF9ku/7HdoTIV\n"
+			+ "rsgAER+Ln/8L1if4Ydkh71B81Yb17/Mzavwi+Y0YxQE+zHexWNatDnCROgBpV6Qd\n"
+			+ "KMdOrS/kE/OcElPRCgbmOsZBP87Hb2zDFXt6tMXBz9iRWe59XuFJGyf1lW4d7ZoH\n"
+			+ "+1vLJ1z8ctVyoznBKLXlQXOx8F8Q8MxOCfHx+elu5QXq5aSAt/v2fNqaLqm5lTqh\n"
+			+ "-----END AES ENCRYPTED MESSAGE-----\n";
+
+	/**
+	 * parses a base64-String. <br>
+	 * <b>Q</b>: Why doesn't provide Java us with such a functionality? <br>
+	 * <b>A</b>: Because it sucks. <br>
+	 * <b>A</b>: RTFM e.g.
+	 * 
+	 * @see sun.misc.BASE64Decoder <br>
+	 * 
+	 * @param s
+	 *            a string that contains a base64 encoded array
+	 * @return the decoded array
+	 */
+	public static byte[] parseBase64(String s) {
+		byte[] b = new byte[s.length() + 5]; // size is a upper approximation
+		// of expected length needed
+		int fill = 0;
+		char[] c = s.toCharArray();
+
+		// main loop
+		int temp = 0; // stores the reconstructed bitfield
+		int temp_fill = 0;
+		String base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+		for (int i = 0; i < c.length; ++i) { // loop over the complete string
+			int v = base64.indexOf(c[i]);
+			if (v >= 0) { // base64 char found
+				temp = temp << 6;
+				temp = temp | v;
+				++temp_fill;
+				if (temp_fill >= 4) { // filled up 24bit
+					System.arraycopy(intToNByteArray(temp, 3), 0, b, fill, 3);
+					fill += 3;
+					temp_fill = 0;
+					temp = 0;
+				}
+				;
+			} else {
+				// the string to be parsed does obviously contain other
+				// characters, too.
+			}
+			;
+		}
+		;
+		if (temp_fill > 0) { // end of string, 24 bit buffer still filled?
+			if (temp_fill == 1)
+				temp = temp << 18;
+			if (temp_fill == 2)
+				temp = temp << 12;
+			if (temp_fill == 3)
+				temp = temp << 6;
+			System.arraycopy(intToNByteArray(temp, 3), 0, b, fill, 3);
+
+			if (temp_fill == 1)
+				fill += 2;
+			if (temp_fill == 2)
+				fill += 2;
+			if (temp_fill == 3)
+				fill += 2;
+		}
+		;
+
+		// copy from temp array to return-array
+		byte[] ret = new byte[fill];
+		for (int i = 0; i < fill; ++i)
+			ret[i] = b[i];
+		return ret;
+	}
+
+	/**
+	 * do a base32-enconding from a binary field
+	 */
+	public static String toBase32(byte[] data) {
+		String base32 = "abcdefghijklmnopqrstuvwxyz234567";
+
+		StringBuffer sb = new StringBuffer();
+		int b32 = 0;
+		int b32_filled = 0;
+		for (int pos = 0; pos < data.length; ++pos)
+			for (int bitmask = 128; bitmask > 0; bitmask /= 2) {
+				b32 = (b32 << 1);
+				if (((int) data[pos] & bitmask) != 0)
+					b32 = b32 | 1;
+				++b32_filled;
+				if (b32_filled == 5) {
+					sb.append(base32.charAt(b32)); // transform to
+					// base32-encoding
+					b32 = 0;
+					b32_filled = 0;
+				}
+			}
+		// check if bits were left unencoded
+		if (b32_filled != 0)
+			System.out
+					.println("Common.toBase32: received array with unsupported number of bits "
+							+ toHexString(data));
+		// return result
+		return sb.toString();
+	}
+
+	static String[] hexChars = { "00", "01", "02", "03", "04", "05", "06",
+			"07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11",
+			"12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c",
+			"1d", "1e", "1f", "20", "21", "22", "23", "24", "25", "26", "27",
+			"28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32",
+			"33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d",
+			"3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47", "48",
+			"49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53",
+			"54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e",
+			"5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
+			"6a", "6b", "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74",
+			"75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
+			"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a",
+			"8b", "8c", "8d", "8e", "8f", "90", "91", "92", "93", "94", "95",
+			"96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0",
+			"a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab",
+			"ac", "ad", "ae", "af", "b0", "b1", "b2", "b3", "b4", "b5", "b6",
+			"b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1",
+			"c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc",
+			"cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+			"d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2",
+			"e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed",
+			"ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8",
+			"f9", "fa", "fb", "fc", "fd", "fe", "ff" };
+
+	/**
+	 * Converts a byte array to hex string
+	 */
+	public static String toHexString(byte[] block, int column_width) {
+		StringBuffer buf = new StringBuffer(4 * (block.length + 2));
+		for (int i = 0; i < block.length; i++) {
+			if (i > 0) {
+				buf.append(":");
+				if (i % (column_width / 3) == 0)
+					buf.append("\n");
+			}
+			;
+			buf.append(hexChars[block[i] & 0xff]);
+		}
+		return buf.toString();
+	}
+
+	public static String toHexString(byte[] block) {
+		return toHexString(block, block.length * 3 + 1);
+	}
+
+	/**
+	 * Convert int to the array of bytes
+	 * 
+	 * @param myInt
+	 *            integer to convert
+	 * @param n
+	 *            size of the byte array
+	 * @return byte array of size n
+	 * 
+	 */
+	public static byte[] intToNByteArray(int myInt, int n) {
+
+		byte[] myBytes = new byte[n];
+
+		for (int i = 0; i < n; ++i) {
+			myBytes[i] = (byte) ((myInt >> ((n - i - 1) * 8)) & 0xff);
+		}
+		return myBytes;
+	}
+
+	/** creates an base64-string out of a byte[] */
+	public static String toBase64(byte[] data) {
+		return new String(org.bouncycastle.util.encoders.Base64.encode(data));
+	}
+
+	/**
+	 * compares two arrays.
+	 * 
+	 * @return true, if the two arrays are equal
+	 */
+	public static boolean arraysEqual(byte[] one, byte[] two) {
+		if ((one == null) && (two == null))
+			return true;
+		if ((one != null) && (two == null)) {
+			// System.err.println("first array contains data, second doesn't");
+			return false;
+		}
+		if ((one == null) && (two != null)) {
+			// System.err.println("seconds array contains data, first doesn't");
+			return false;
+		}
+		if (one.length != two.length) {
+			// System.err.println("Different size: "+one.length+" !=
+			// "+two.length);
+			return false;
+		}
+		for (int i = 0; i < one.length; ++i)
+			if (one[i] != two[i]) {
+				// System.err.println("byte "+i+" of "+one.length+" differs:
+				// "+one[i]+" != "+two[i]);
+				return false;
+			}
+		;
+		return true;
+	}
+
+	/**
+	 * returns the hash of the input
+	 * 
+	 * 
+	 */
+	public static byte[] getHash(byte[] input) {
+
+		SHA1Digest sha1 = new SHA1Digest();
+		sha1.reset();
+		sha1.update(input, 0, input.length);
+
+		byte[] hash = new byte[sha1.getDigestSize()];
+		sha1.doFinal(hash, 0);
+		return hash;
+
+	}
+
+	/**
+	 * checks signature of PKCS1-padded SHA1 hash of the input
+	 * 
+	 * @param signature
+	 *            signature to check
+	 * @param signingKey
+	 *            public key from signing
+	 * @param input
+	 *            byte array, signature is made over
+	 * 
+	 * @return true, if the signature is correct
+	 * 
+	 */
+	public static boolean verifySignature(byte[] signature,
+			RSAPublicKeyStructure signingKey, byte[] input) {
+
+		byte[] hash = getHash(input);
+
+		try {
+			RSAKeyParameters myRSAKeyParameters = new RSAKeyParameters(false,
+					signingKey.getModulus(), signingKey.getPublicExponent());
+
+			PKCS1Encoding pkcs_alg = new PKCS1Encoding(new RSAEngine());
+			pkcs_alg.init(false, myRSAKeyParameters);
+
+			byte[] decrypted_signature = pkcs_alg.processBlock(signature, 0,
+					signature.length);
+
+			return arraysEqual(hash, decrypted_signature);
+
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+
+		return false;
+
+	}
+
+	/**
+	 * sign some data using a private kjey and PKCS#1 v1.5 padding
+	 * 
+	 * @param data
+	 *            the data to be signed
+	 * @param signingKey
+	 *            the key to sign the data
+	 * @return a signature
+	 */
+	public static byte[] signData(byte[] data, RSAKeyParameters signingKey) {
+		try {
+			byte[] hash = getHash(data);
+			PKCS1Encoding pkcs1 = new PKCS1Encoding(new RSAEngine());
+			pkcs1.init(true, signingKey);
+			return pkcs1.processBlock(hash, 0, hash.length);
+		} catch (InvalidCipherTextException e) {
+			System.out.println("Common.signData(): " + e.getMessage());
+			e.printStackTrace();
+			return null;
+		}
+	}
+
+	/** used to encode a signature in PEM */
+	public static String binarySignatureToPEM(byte[] signature) {
+		String sigB64 = toBase64(signature);
+		StringBuffer sig = new StringBuffer();
+
+		sig.append("-----BEGIN SIGNATURE-----\n");
+		while (sigB64.length() > 64) {
+			sig.append(sigB64.substring(0, 64) + "\n");
+			sigB64 = sigB64.substring(64);
+		}
+		sig.append(sigB64 + "\n");
+		sig.append("-----END SIGNATURE-----\n");
+		return sig.toString();
+	}
+
+	/**
+	 * copy from one format to another
+	 */
+	public static RSAPublicKeyStructure getRSAPublicKeyStructureFromJCERSAPublicKey(
+			JCERSAPublicKey jpub) {
+		return new RSAPublicKeyStructure(jpub.getModulus(), jpub
+				.getPublicExponent());
+	}
+
+	/**
+	 * converts a JCERSAPublicKey into PKCS1-encoding
+	 * 
+	 * @param rsaPublicKey
+	 * @see JCERSAPublicKey
+	 * @return PKCS1-encoded RSA PUBLIC KEY
+	 */
+	public static byte[] getPKCS1EncodingFromRSAPublicKey(
+			RSAPublicKeyStructure pubKeyStruct) {
+		try {
+			ByteArrayOutputStream bOut = new ByteArrayOutputStream();
+			ASN1OutputStream aOut = new ASN1OutputStream(bOut);
+			aOut.writeObject(pubKeyStruct.toASN1Object());
+			return bOut.toByteArray();
+		} catch (Exception e) {
+			return null;
+		}
+	}
+
+	/**
+	 * converts a JCERSAPublicKey into PEM/PKCS1-encoding
+	 * 
+	 * @param rsaPublicKey
+	 * @see RSAPublicKeyStructure
+	 * @return PEM-encoded RSA PUBLIC KEY
+	 */
+	public static String getPEMStringFromRSAPublicKey(
+			RSAPublicKeyStructure rsaPublicKey) {
+
+		// mrk: this was awful to program. Remeber: There are two entirely
+		// different
+		// standard formats for rsa public keys. Bouncy castle does only support
+		// the
+		// one we can't use for TOR directories.
+
+		StringBuffer tmpDirSigningKey = new StringBuffer();
+
+		try {
+
+			tmpDirSigningKey.append("-----BEGIN RSA PUBLIC KEY-----\n");
+
+			byte[] base64Encoding = Base64
+					.encode(getPKCS1EncodingFromRSAPublicKey(rsaPublicKey));
+			for (int i = 0; i < base64Encoding.length; i++) {
+				tmpDirSigningKey.append((char) base64Encoding[i]);
+				if (((i + 1) % 64) == 0)
+					tmpDirSigningKey.append("\n");
+			}
+			tmpDirSigningKey.append("\n");
+
+			tmpDirSigningKey.append("-----END RSA PUBLIC KEY-----\n");
+		} catch (Exception e) {
+			return null;
+		}
+
+		return tmpDirSigningKey.toString();
+	}
+
+	/**
+	 * makes RSA public key from base64 encoded string
+	 * 
+	 * @param s
+	 *            string that contais the key
+	 * @return
+	 * @see JCERSAPublicKey
+	 */
+	public static JCERSAPublicKey getRSAPublicKeyFromPEMString(String s) {
+
+		PEMReader reader = new PEMReader(new StringReader(s));
+		JCERSAPublicKey theKey;
+
+		try {
+			Object o = reader.readObject();
+			if (!(o instanceof JCERSAPublicKey))
+				throw new IOException(
+						"no public key found for signing key in string '" + s
+								+ "'");
+			theKey = (JCERSAPublicKey) o;
+		} catch (IOException e) {
+			System.out.println("Caught exception:" + e.getMessage());
+			theKey = null;
+		}
+
+		return theKey;
+	}
+
+	/**
+	 * Returns the ASCII-encoded descriptor string.
+	 * 
+	 * @return The ASCII-encoded descriptor string.
+	 */
+	public String getDescriptorString() {
+		return this.descriptorString;
+	}
+
+	/**
+	 * Returns the descriptor ID consisting of 32 base32 chars.
+	 * 
+	 * @return The descriptor ID.
+	 */
+	public String getDescriptorID() {
+		return this.descriptorID;
+	}
+}

Deleted: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/DistributedStorage.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/DistributedStorage.java	2007-08-26 21:03:54 UTC (rev 11279)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/examples/DistributedStorage.java	2007-08-26 21:18:53 UTC (rev 11280)
@@ -1,1522 +0,0 @@
-package de.uniba.wiai.lspi.puppetor.examples;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import de.uniba.wiai.lspi.puppetor.ClientApplication;
-import de.uniba.wiai.lspi.puppetor.DirectoryNode;
-import de.uniba.wiai.lspi.puppetor.Event;
-import de.uniba.wiai.lspi.puppetor.EventListener;
-import de.uniba.wiai.lspi.puppetor.EventManager;
-import de.uniba.wiai.lspi.puppetor.EventSource;
-import de.uniba.wiai.lspi.puppetor.EventType;
-import de.uniba.wiai.lspi.puppetor.Network;
-import de.uniba.wiai.lspi.puppetor.NetworkFactory;
-import de.uniba.wiai.lspi.puppetor.ProxyNode;
-import de.uniba.wiai.lspi.puppetor.RouterNode;
-import de.uniba.wiai.lspi.puppetor.TorProcessException;
-
-/**
- * <p>
- * Automatic validation of the distributed storage for hidden service
- * descriptors as described in proposal 114. <b>WARNING: This example does not
- * work with an unmodified Tor!</b>
- * </p>
- * 
- * <p>
- * When running, the example starts a network of local Tor processes, consisting
- * of 2 directory nodes and 9 periodically changing onion routers, some of them
- * (not the initial nodes, but those nodes replacing them) with attached hidden
- * services.
- * </p>
- * 
- * <p>
- * The automatic validation performs four measurements:
- * </p>
- * 
- * <ol>
- * <li>Are the online statuses of hidden service directories propagated to all
- * running nodes successfully, and how long does propagation take?</li>
- * <li>The same measurement with offline statuses.</li>
- * <li>Are hidden service descriptors stored on the correct, responsible hidden
- * service directories, and how long does propagation take?</li>
- * <li>Are hidden service requests successful within a given timeout?</li>
- * </ol>
- * 
- * @author kloesing
- */
-public class DistributedStorage {
-
-	/**
-	 * Observes a hidden service directory from starting it to shutting it down.
-	 * Waits for 24 hours after starting the node, so that it will be accepted
-	 * as hidden service directory by the directory authorities. Afterwards,
-	 * initiates an online propagation measurement for every node that is in the
-	 * network or that enters the network while the observed hidden service
-	 * directory is online. After going offline, initiates an offline
-	 * propagation measurement for every node that has previously accepted this
-	 * hidden service directory.
-	 */
-	private static class HiddenServiceDirectoryObserver extends Thread
-			implements EventListener {
-
-		/**
-		 * Is the hidden service directory online for at least 24 hours, so that
-		 * it will be listed by the directory authorities?
-		 */
-		private boolean twentyFourHoursUp;
-
-		/**
-		 * The Tor process behind the observed hidden service directory.
-		 */
-		private EventSource hsdNode;
-
-		/**
-		 * The node ID of the observed hidden service directory.
-		 */
-		private String nodeID;
-
-		/**
-		 * Set of nodes that have reported to accept this hidden service
-		 * directory.
-		 */
-		private Set<EventSource> nodesThatKnowMe = new HashSet<EventSource>();
-
-		/**
-		 * Creates a new observer instance, but does not start it yet.
-		 * 
-		 * @param hsdNode
-		 *            The Tor process behind the observed hidden service
-		 *            directory.
-		 * @param nodeID
-		 *            The node ID of the observed hidden service directory.
-		 */
-		private HiddenServiceDirectoryObserver(EventSource hsdNode,
-				String nodeID) {
-
-			// remember the args
-			this.nodeID = nodeID;
-			this.hsdNode = hsdNode;
-
-			// listen for events coming from my HSDir
-			manager.addEventListener(hsdNode, this);
-
-			// listen for starting/stopping nodes
-			manager.addEventListener(this);
-		}
-
-		@Override
-		public synchronized void run() {
-
-			// not yet accepted
-			this.twentyFourHoursUp = false;
-
-			// wait for 24 hours until hsdir is accepted by DAs
-			long startingTime = System.currentTimeMillis();
-			// for testing; change to 24 * 60 * 60 * 1000
-			long endOfWaiting = startingTime + 30 * 60 * 1000;
-			long now;
-			while ((now = System.currentTimeMillis()) < endOfWaiting) {
-				try {
-					wait(endOfWaiting - now);
-				} catch (InterruptedException e) {
-				}
-			}
-
-			// accepted
-			this.twentyFourHoursUp = true;
-
-			// add to set of running hidden service directories
-			globalRoutingTable.addHiddenServiceDirectory(this.nodeID,
-					this.hsdNode);
-
-			// measure how long the current nodes need to get aware of this
-			// hidden service directory
-			for (RouterNode router : runningRouters) {
-				new OnlinePropagationMeasurement(router, this.hsdNode,
-						this.nodeID).start();
-			}
-		}
-
-		public synchronized void handleEvent(Event event) {
-
-			if (!this.twentyFourHoursUp) {
-				// when the represented node is not running for at least 24
-				// hours, others would not consider it as hidden service
-				// directory and we cannot perform any useful measurements
-				return;
-			}
-
-			if (event.getType() == EventType.NODE_STARTED) {
-				// when another node is started, initiate measurement of the
-				// propagation time that this hiddden service directory is
-				// online
-				new OnlinePropagationMeasurement(event.getSource(),
-						this.hsdNode, this.nodeID).start();
-
-			} else if (event.getSource() == this.hsdNode
-					&& event.getType() == EventType.NODE_STOPPED) {
-				// when the represented node is stopped, initiate measurement of
-				// the propagation time that this hidden service directory is
-				// offline (any online propagation measurements that are still
-				// running will realize by themselves that they cannot succeed
-				// and will abort)
-				for (EventSource node : nodesThatKnowMe) {
-					if (node != this.hsdNode) {
-						new OfflinePropagationMeasurement(node, this.hsdNode,
-								this.nodeID).start();
-					}
-				}
-
-				// remove from set of running hidden service directories
-				globalRoutingTable.removeHiddenServiceDirectory(this.nodeID);
-
-				// stop listening for events
-				manager.removeEventListener(this);
-
-				// just in case that there is another event in the queue, don't
-				// handle it any more
-				this.twentyFourHoursUp = false;
-
-			} else if (event.getType() == EventType.NODE_ROUTING_TABLE_CHANGED
-					&& event.getMessage().contains(this.nodeID)) {
-				// when some node reports to have changed its routing table and
-				// now includes the node ID of the represented node, remember
-				// that node for later offline propagation measurement
-				nodesThatKnowMe.add(event.getSource());
-
-			} else if (event.getType() == EventType.NODE_STOPPED
-					&& event.getSource() != this.hsdNode) {
-				// when some other node is stopped, remove it from the list of
-				// nodes that know that the represented hidden service directory
-				// is online
-				nodesThatKnowMe.remove(event.getSource());
-			}
-		}
-	}
-
-	/**
-	 * The states in which a measurement can be.
-	 */
-	private static enum MeasurementState {
-
-		/**
-		 * The measurement was started and is currently running.
-		 */
-		STARTED,
-
-		/**
-		 * The measurement has succeeded with a positive result.
-		 */
-		SUCCEEDED,
-
-		/**
-		 * The measurement has failed within the given maximum time.
-		 */
-		FAILED,
-
-		/**
-		 * The measurement was aborted, because it has become impossible to
-		 * succeed.
-		 */
-		ABORTED
-	}
-
-	/**
-	 * Verifies that the online status of a given hidden service directory is
-	 * propagated to a given running node, and measures how long that
-	 * propagation takes. If the propagation does not succeed within one hour,
-	 * it is considered as failed.
-	 */
-	private static class OnlinePropagationMeasurement extends Thread implements
-			EventListener {
-
-		/**
-		 * The state of this measurement.
-		 */
-		private MeasurementState measurementState;
-
-		/**
-		 * The node ID of the hidden service directory.
-		 */
-		private String hsdNodeID;
-
-		/**
-		 * The hidden service directory of which the online status should be
-		 * propagated.
-		 */
-		private EventSource hsdNode;
-
-		/**
-		 * The node to which the online status should be propagated.
-		 */
-		private EventSource node;
-
-		/**
-		 * Creates a new measurement, but does not start it yet.
-		 * 
-		 * @param node
-		 *            The node to which the online status should be propagated.
-		 * @param hsdNode
-		 *            The hidden service directory of which the online status
-		 *            should be propagated.
-		 * @param hsdNodeID
-		 *            The node ID of the hidden service directory.
-		 */
-		private OnlinePropagationMeasurement(EventSource node,
-				EventSource hsdNode, String hsdNodeID) {
-
-			// remember the args
-			this.hsdNodeID = hsdNodeID;
-			this.hsdNode = hsdNode;
-			this.node = node;
-
-			// listen for events coming from the node and the hidden service
-			// directory
-			manager.addEventListener(node, this);
-			manager.addEventListener(hsdNode, this);
-
-		}
-
-		@Override
-		public synchronized void run() {
-
-			// start the measurement in state STARTED
-			this.measurementState = MeasurementState.STARTED;
-
-			// wait for a maximum of one hour for the measurement to succeed
-			long startingTime = System.currentTimeMillis();
-			long endOfWaiting = startingTime + 60 * 60 * 1000;
-			long now;
-			while (this.measurementState == MeasurementState.STARTED
-					&& (now = System.currentTimeMillis()) < endOfWaiting) {
-				try {
-					wait(endOfWaiting - now);
-				} catch (InterruptedException e) {
-				}
-			}
-
-			// if the node did not learn about the hidden service directory
-			// within one hour, fail the measurement
-			if (this.measurementState == MeasurementState.STARTED) {
-				measurementState = MeasurementState.FAILED;
-			}
-
-			// unregister event listener
-			manager.removeEventListener(this);
-
-			// print out measurement result
-			long duration = System.currentTimeMillis() - startingTime;
-			System.out.println(new Date() + ": Online propagation for HSDir "
-					+ this.hsdNode.getName() + " to node "
-					+ this.node.getName() + " took " + (duration / 1000)
-					+ " seconds and ended in state "
-					+ measurementState.toString());
-			if (this.measurementState == MeasurementState.SUCCEEDED) {
-				resultWriter.writeOnlinePropagation(duration / 1000);
-			} else if (this.measurementState == MeasurementState.FAILED) {
-				resultWriter.writeOnlinePropagation(-1);
-			}
-		}
-
-		public synchronized void handleEvent(Event event) {
-
-			// only accept events when this measurement is running
-			if (measurementState != MeasurementState.STARTED) {
-				return;
-			}
-
-			if (event.getSource() == this.node
-					&& event.getType() == EventType.NODE_ROUTING_TABLE_CHANGED
-					&& event.getMessage().contains(this.hsdNodeID)) {
-				// when the node has added the node ID of the hidden service
-				// directory, succeed the measurement
-				this.measurementState = MeasurementState.SUCCEEDED;
-				notify();
-
-			} else if (event.getType() == EventType.NODE_STOPPED) {
-				// when either the node or the hidden service directory were
-				// stopped within the one hour period, the measurement cannot be
-				// succeeded anymore and is therefore aborted
-				this.measurementState = MeasurementState.ABORTED;
-				notify();
-			}
-		}
-	}
-
-	/**
-	 * Verifies that the offline status of a given hidden service directory is
-	 * propagated to a given running node, and measures how long that
-	 * propagation takes. If the propagation does not succeed within one hour,
-	 * it is considered as failed.
-	 */
-	private static class OfflinePropagationMeasurement extends Thread implements
-			EventListener {
-
-		/**
-		 * The state of this measurement.
-		 */
-		private MeasurementState measurementState;
-
-		/**
-		 * The node ID of the hidden service directory.
-		 */
-		private String hsdNodeID;
-
-		/**
-		 * The hidden service directory of which the offline status should be
-		 * propagated.
-		 */
-		private EventSource hsdNode;
-
-		/**
-		 * The node to which the offline status should be propagated.
-		 */
-		private EventSource node;
-
-		/**
-		 * Creates a new measurement, but does not start it yet.
-		 * 
-		 * @param node
-		 *            The node to which the offline status should be propagated.
-		 * @param hsdNode
-		 *            The hidden service directory of which the offline status
-		 *            should be propagated.
-		 * @param hsdNodeID
-		 *            The node ID of the hidden service directory.
-		 */
-		private OfflinePropagationMeasurement(EventSource node,
-				EventSource hsdNode, String hsdNodeID) {
-
-			// remember the args
-			this.hsdNodeID = hsdNodeID;
-			this.node = node;
-			this.hsdNode = hsdNode;
-
-			// register for events from the node that should observe the offline
-			// status
-			manager.addEventListener(node, this);
-		}
-
-		@Override
-		public synchronized void run() {
-
-			// start the measurement in state STARTED
-			this.measurementState = MeasurementState.STARTED;
-
-			// wait for a maximum of 90 minutes for the measurement to succeed
-			long startingTime = System.currentTimeMillis();
-			long endOfWaiting = startingTime + 90 * 60 * 1000;
-			long now;
-			while (this.measurementState == MeasurementState.STARTED
-					&& (now = System.currentTimeMillis()) < endOfWaiting) {
-				try {
-					wait(endOfWaiting - now);
-				} catch (InterruptedException e) {
-				}
-			}
-
-			// if the node did not learn about the offline status of the hidden
-			// service directory, fail the measurement
-			if (this.measurementState == MeasurementState.STARTED) {
-				measurementState = MeasurementState.FAILED;
-			}
-
-			// unregister event listener
-			manager.removeEventListener(this);
-
-			// print out measurement result
-			long duration = System.currentTimeMillis() - startingTime;
-			System.out.println(new Date() + ": Offline propagation for HSDir "
-					+ this.hsdNode.getName() + " to node "
-					+ this.node.getName() + " took " + (duration / 1000)
-					+ " seconds and ended in state "
-					+ measurementState.toString());
-			if (this.measurementState == MeasurementState.SUCCEEDED) {
-				resultWriter.writeOfflinePropagation(duration / 1000);
-			} else if (this.measurementState == MeasurementState.FAILED) {
-				resultWriter.writeOfflinePropagation(-1);
-			}
-		}
-
-		public synchronized void handleEvent(Event event) {
-
-			// only accept events when this measurement is running
-			if (measurementState != MeasurementState.STARTED) {
-				return;
-			}
-
-			if (event.getType() == EventType.NODE_ROUTING_TABLE_CHANGED
-					&& !event.getMessage().contains(this.hsdNodeID)) {
-				// when the node has removed the node ID of the hidden service
-				// directory, succeed the measurement
-				this.measurementState = MeasurementState.SUCCEEDED;
-				notify();
-
-			} else if (event.getType() == EventType.NODE_STOPPED) {
-				// when the node was stopped within the waiting period, the
-				// measurement cannot be
-				// succeeded anymore and is therefore aborted
-				this.measurementState = MeasurementState.ABORTED;
-				notify();
-			}
-		}
-	}
-
-	/**
-	 * Manages the global routing table of all hidden service directories. This
-	 * global view differs from the local views of the nodes, because of the
-	 * propagation latency which may take some tens of minutes.
-	 */
-	private static class GlobalRoutingTable {
-
-		private static Comparator<String> comparator = new Comparator<String>() {
-
-			int[] base32Lookup = { 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
-					0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-					0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
-					0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
-					0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF,
-					0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-					0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11,
-					0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF,
-					0xFF, 0xFF, 0xFF };
-
-			private String base32toHex(String base32) {
-
-				int i, index, lookup, offset, digit;
-
-				byte[] bytes = new byte[base32.length() * 5 / 8];
-
-				for (i = 0, index = 0, offset = 0; i < base32.length(); i++) {
-					lookup = base32.charAt(i) - '0';
-
-					/* Skip chars outside the lookup table */
-					if (lookup < 0 || lookup >= base32Lookup.length)
-						continue;
-
-					digit = base32Lookup[lookup];
-
-					/* If this digit is not in the table, ignore it */
-					if (digit == 0xFF)
-						continue;
-
-					if (index <= 3) {
-						index = (index + 5) % 8;
-						if (index == 0) {
-							bytes[offset] |= digit;
-							offset++;
-							if (offset >= bytes.length)
-								break;
-						} else
-							bytes[offset] |= digit << (8 - index);
-					} else {
-						index = (index + 5) % 8;
-						bytes[offset] |= (digit >>> index);
-						offset++;
-
-						if (offset >= bytes.length)
-							break;
-						bytes[offset] |= digit << (8 - index);
-					}
-				}
-				StringBuilder result = new StringBuilder();
-				for (byte b : bytes) {
-					result.append(Integer
-							.toHexString(new Integer(b).intValue()));
-				}
-				return result.toString();
-			}
-
-			public int compare(String arg0, String arg1) {
-				return base32toHex(arg0).compareTo(base32toHex(arg1));
-			}
-		};
-
-		private SortedMap<String, EventSource> hsDirs = new TreeMap<String, EventSource>(
-				comparator);
-
-		private synchronized void addHiddenServiceDirectory(String nodeID,
-				EventSource hsdNode) {
-			this.hsDirs.put(nodeID, hsdNode);
-			notifyAll();
-		}
-
-		private synchronized void removeHiddenServiceDirectory(String nodeID) {
-			this.hsDirs.remove(nodeID);
-			notifyAll();
-		}
-
-		/**
-		 * Returns the set of responsible hidden service directories for the
-		 * given descriptor ID.
-		 * 
-		 * @param descID
-		 *            The descriptor ID for which the responsible hidden service
-		 *            directories shall be determined.
-		 * @return The set of responsible hidden service directories.
-		 */
-		private synchronized Set<EventSource> getResponsibleHSDirs(String descID) {
-
-			Set<EventSource> result = new HashSet<EventSource>();
-			if (this.hsDirs.size() < 3) {
-				return result;
-			}
-
-			for (EventSource s : this.hsDirs.tailMap(descID).values()) {
-				if (result.size() < 3) {
-					result.add(s);
-				} else {
-					break;
-				}
-			}
-
-			for (EventSource s : this.hsDirs.values()) {
-				if (result.size() < 3) {
-					result.add(s);
-				} else {
-					break;
-				}
-			}
-
-			return result;
-		}
-
-		/**
-		 * Waits for the given number of millis until either a node is added or
-		 * removed.
-		 * 
-		 * @param timeToWait
-		 *            The number of millis to wait.
-		 */
-		public synchronized void waitForRoutingTableChange(long timeToWait) {
-			try {
-				wait(timeToWait);
-			} catch (InterruptedException e) {
-			}
-		}
-	}
-
-	/**
-	 * The routing table containing the global state of all hidden service
-	 * directories in the network.
-	 */
-	private static GlobalRoutingTable globalRoutingTable = new GlobalRoutingTable();
-
-	/**
-	 * Observes all publications of descriptors by hidden service providers.
-	 * Whenever there is a novel descriptor, the observer launches measurements
-	 * of the ropagation of the new descriptor to the responsible hidden service
-	 * directories.
-	 */
-	private static class DescriptorObserverStarter implements EventListener {
-
-		/**
-		 * Set of all descriptor IDs that have been observed so far.
-		 */
-		private Set<String> knownDescIDs = new HashSet<String>();
-
-		/**
-		 * Creates a new observer that starts listening for events.
-		 */
-		private DescriptorObserverStarter() {
-			manager.addEventListener(this);
-		}
-
-		public void handleEvent(Event event) {
-			// listen for new desc-ids
-			if (event.getType() == EventType.BOB_SENDING_PUBLISH_DESC) {
-				// a descriptor was published by any hidden service provider;
-				// check if this descriptor ID is novel
-
-				// parse desc id from event message
-				String message = event.getMessage();
-				String prefixDescID = "with descriptor ID '";
-				String descID = message.substring(message.indexOf(prefixDescID)
-						+ prefixDescID.length());
-				descID = descID.substring(0, 32);
-
-				if (!knownDescIDs.contains(descID)) {
-					String prefixSecondsValid = "with validity of ";
-					String secondsValidPlusRest = message.substring(message
-							.indexOf(prefixSecondsValid)
-							+ prefixSecondsValid.length());
-					String[] splitted = secondsValidPlusRest.split(" ");
-					long secondsValid = Long.parseLong(splitted[0]);
-
-					if (secondsValid > 30 * 60) {
-						new DescriptorObserver(descID, secondsValid).start();
-					}
-				}
-			}
-		}
-	}
-
-	/**
-	 * Observes a descriptor from its first publication to 30 minutes before its
-	 * validity ends. Initiates a descriptor propagation measurement for every
-	 * hidden service directory that either is or becomes responsible for the
-	 * descriptor ID. (This does not include checks that a descriptor remains
-	 * stored on the responsible hidden service directories.)
-	 */
-	private static class DescriptorObserver extends Thread {
-
-		/**
-		 * The descriptor ID of the observed descriptor.
-		 */
-		private String descID;
-
-		/**
-		 * Time in millis when the validity of the observed descriptor amounts
-		 * 30 minutes.
-		 */
-		private long endOfWaiting;
-
-		/**
-		 * The set of hidden service directories that we think is responsible
-		 * for storing the observed descriptor.
-		 */
-		private Set<EventSource> hsDirsDeemedResponsible;
-
-		/**
-		 * Creates a new observer instance, but does not start it yet.
-		 * 
-		 * @param descID
-		 *            The descriptor ID of the observed descriptor.
-		 * @param validityInSeconds
-		 *            The validity of the descriptor in seconds.
-		 */
-		private DescriptorObserver(String descID, long validityInSeconds) {
-
-			// remember the args
-			this.descID = descID;
-
-			// determine when the validity of the observed descriptor amounts 30
-			// minutes
-			this.endOfWaiting = System.currentTimeMillis() + validityInSeconds
-					* 1000 - 30 * 60 * 1000;
-		}
-
-		@Override
-		public void run() {
-
-			if (System.currentTimeMillis() < this.endOfWaiting) {
-				// when the descriptor is not valid for at least 30 minutes, we
-				// don't need to perform any measurements at all, because it is
-				// quite unlikely that they would succeed
-				return;
-			}
-
-			// start measurements for the currently responsible hidden service
-			// directories
-			hsDirsDeemedResponsible = globalRoutingTable
-					.getResponsibleHSDirs(this.descID);
-			for (EventSource responsibleDir : hsDirsDeemedResponsible) {
-				new DescriptorPropagationMeasurement(responsibleDir,
-						this.descID).start();
-			}
-
-			// wait until the validity of the descriptor is 30 minutes or less
-			long now;
-			while ((now = System.currentTimeMillis()) < this.endOfWaiting) {
-
-				// wait for changes in the global routing table
-				globalRoutingTable.waitForRoutingTableChange(this.endOfWaiting
-						- now);
-
-				// check if the descriptor validity is still sufficient to
-				// initiate new measurements
-				if (now < this.endOfWaiting) {
-
-					// check if the change affects us
-					Set<EventSource> newResponsibleHSDirs = globalRoutingTable
-							.getResponsibleHSDirs(this.descID);
-					Set<EventSource> newcomers = new HashSet<EventSource>(
-							newResponsibleHSDirs);
-					newcomers.removeAll(this.hsDirsDeemedResponsible);
-					if (newcomers.size() > 0) {
-
-						// initiate a new measurement for every new responsible
-						// hidden service directory
-						for (EventSource responsibleDir : newcomers) {
-							new DescriptorPropagationMeasurement(
-									responsibleDir, this.descID).start();
-						}
-						this.hsDirsDeemedResponsible = newResponsibleHSDirs;
-					}
-				}
-			}
-		}
-	}
-
-	/**
-	 * Verifies that a descriptor is propagated to a given hidden service
-	 * directory, and measures how long that propagation takes. If the
-	 * propagation does not succeed within 90 minutes, it is considered as
-	 * failed, unless a change in the routing table makes the hidden service
-	 * directory irresponsible for the given descriptor.
-	 */
-	private static class DescriptorPropagationMeasurement extends Thread
-			implements EventListener {
-
-		/**
-		 * The state of this measurement.
-		 */
-		private MeasurementState measurementState;
-
-		/**
-		 * The descriptor ID of the observed descriptor.
-		 */
-		private String descid;
-
-		/**
-		 * The hidden service directory that is deemed responsible to store the
-		 * given descriptor.
-		 */
-		private EventSource responsibleHSDir;
-
-		/**
-		 * Creates a new measurement instance, but does not start it yet.
-		 * 
-		 * @param responsibleHSDir
-		 *            The hidden service directory that is deemed responsible to
-		 *            store the given descriptor.
-		 * @param descid
-		 *            The descriptor ID of the observed descriptor.
-		 */
-		private DescriptorPropagationMeasurement(EventSource responsibleHSDir,
-				String descid) {
-
-			// remember the args
-			this.responsibleHSDir = responsibleHSDir;
-			this.descid = descid;
-
-			// register for events from the hidden service directory
-			manager.addEventListener(responsibleHSDir, this);
-		}
-
-		@Override
-		public synchronized void run() {
-
-			// start the measurement in state STARTED
-			this.measurementState = MeasurementState.STARTED;
-
-			// wait for a maximum of 90 minutes for the measurement to succeed
-			long startingTime = System.currentTimeMillis();
-			long endOfWaiting = startingTime + 90 * 60 * 1000;
-			long now;
-			while (this.measurementState == MeasurementState.STARTED
-					&& (now = System.currentTimeMillis()) < endOfWaiting) {
-
-				// wait for a change in the routing table, that might make the
-				// hidden service directory irresponsible for the given
-				// descriptor, or be interrupted by an incoming event
-				globalRoutingTable
-						.waitForRoutingTableChange(endOfWaiting - now);
-
-				if (this.measurementState == MeasurementState.STARTED
-						&& !globalRoutingTable
-								.getResponsibleHSDirs(this.descid).contains(
-										this.responsibleHSDir)) {
-					// routing table has changed, so that the hidden service
-					// directory is not responsible for the given descriptor any
-					// more
-					this.measurementState = MeasurementState.ABORTED;
-				}
-			}
-
-			// if the node did not learn about the hidden service directory
-			// within the given time, fail the measurement
-			if (this.measurementState == MeasurementState.STARTED) {
-				measurementState = MeasurementState.FAILED;
-			}
-
-			// unregister event listener
-			manager.removeEventListener(this);
-
-			// print out measurement result
-			long duration = System.currentTimeMillis() - startingTime;
-			System.out.println(new Date()
-					+ ": Descriptor propagation for desc ID " + this.descid
-					+ " took " + (duration / 1000)
-					+ " seconds to responsible HS directory "
-					+ this.responsibleHSDir.getName() + " and ended in state "
-					+ measurementState.toString());
-			if (this.measurementState == MeasurementState.SUCCEEDED) {
-				resultWriter.writeDescriptorPropagation(duration / 1000);
-			} else if (this.measurementState == MeasurementState.FAILED) {
-				resultWriter.writeDescriptorPropagation(-1);
-			}
-		}
-
-		public synchronized void handleEvent(Event event) {
-
-			if (event.getType() == EventType.HSDIR_DESC_STORED
-					&& event.getMessage().contains(this.descid)) {
-				// when the hidden service directory stores the given descriptor
-				// for the first time, the measurement succeeds
-				this.measurementState = MeasurementState.SUCCEEDED;
-				interrupt();
-			}
-		}
-	}
-
-	/**
-	 * Observes a hidden service for the first 20 minutes after starting it
-	 * before adding it to the list of available hidden services. When the node
-	 * is stopped (within or after the 20 minutes), the hidden service will be
-	 * removed from the list of available hidden services.
-	 */
-	private static class HiddenServiceObserver extends Thread implements
-			EventListener {
-
-		/**
-		 * The onion address by which this hidden service can be accessed.
-		 */
-		private String onionAddress;
-
-		/**
-		 * The node that provides the hidden service.
-		 */
-		private EventSource providingNode;
-
-		/**
-		 * Creates a new observer instance, but does not start it yet.
-		 * 
-		 * @param providingNode
-		 *            The node that provides the hidden service.
-		 * @param onionAddress
-		 *            The onion address by which this hidden service can be
-		 *            accessed.
-		 */
-		private HiddenServiceObserver(EventSource providingNode,
-				String onionAddress) {
-
-			// remember the args
-			this.onionAddress = onionAddress;
-			this.providingNode = providingNode;
-
-			// listen for events coming from the providing node
-			manager.addEventListener(providingNode, this);
-		}
-
-		/**
-		 * Is the observed hidden service still available, or was the providing
-		 * node stopped?
-		 */
-		private boolean stopped = false;
-
-		@Override
-		public void run() {
-
-			// wait for 20 minutes until the hidden service can be considered
-			// available
-			long startingTime = System.currentTimeMillis();
-			long endOfWaiting = startingTime + 20 * 60 * 1000;
-			long now;
-			while (!this.stopped
-					&& (now = System.currentTimeMillis()) < endOfWaiting) {
-				try {
-					Thread.sleep(endOfWaiting - now);
-				} catch (InterruptedException e) {
-				}
-			}
-
-			// add it to the list of available hidden services
-			availableHiddenServices.put(this.onionAddress, this.providingNode);
-		}
-
-		public void handleEvent(Event event) {
-			if (event.getType() == EventType.NODE_STOPPED) {
-				// when the providing node is stopped, the hidden service will
-				// not be available any more
-				this.stopped = true;
-				availableHiddenServices.remove(this.onionAddress);
-			}
-		}
-	}
-
-	/**
-	 * A list of all hidden services that are available for testing.
-	 */
-	private static Map<String, EventSource> availableHiddenServices = new HashMap<String, EventSource>();
-
-	/**
-	 * Periodically (every 5 to 10 minutes) picks a hidden service that is
-	 * available and running for at least 20 minutes and performs a request to
-	 * it using an arbitrary node as proxy.
-	 */
-	private static class HiddenServiceRequestStarter extends Thread {
-
-		@Override
-		public void run() {
-			// first wait until HSDirs are up and descriptors distributed --
-			// stable state
-			// Thread.sleep(24 * 60 * 60 * 1000 + 90 * 60 * 1000);
-			try {
-				Thread.sleep(30 * 60 * 1000 + 30 * 60 * 1000);
-			} catch (InterruptedException e) {
-			}
-
-			Random rnd = new Random();
-			while (true) {
-				if (availableHiddenServices.size() > 0) {
-
-					// pick an available hidden service at random
-					String onionAddressToTry = new ArrayList<String>(
-							availableHiddenServices.keySet()).get(rnd
-							.nextInt(availableHiddenServices.size()));
-					EventSource providingNode = availableHiddenServices
-							.get(onionAddressToTry);
-
-					// pick an arbitrary running node as proxy
-					RouterNode useAsProxy = runningRouters.get(rnd
-							.nextInt(runningRouters.size()));
-
-					// start measurement
-					new HiddenServiceRequestMeasurement(onionAddressToTry,
-							providingNode, useAsProxy).start();
-				}
-
-				// wait for a random time between 5 to 10 minutes
-				try {
-					Thread.sleep(5 * 60 * 1000 + rnd.nextInt(5 * 60 * 1000));
-				} catch (InterruptedException e) {
-				}
-			}
-		}
-	}
-
-	/**
-	 * Verifies that a hidden service can be accessed, and measures how long
-	 * performing a request takes. If the request does not succeed within one
-	 * minute, it is considered as failed, unless either the node providing the
-	 * hidden service, or the node that is used as proxy fails.
-	 */
-	private static class HiddenServiceRequestMeasurement extends Thread
-			implements EventListener {
-
-		/**
-		 * The onion address to which the request shall be performed.
-		 */
-		private String onionAddress;
-
-		/**
-		 * The node that provides the hidden service.
-		 */
-		private EventSource providingNode;
-
-		/**
-		 * The node that is used as proxy for the request.
-		 */
-		private EventSource useAsProxy;
-
-		/**
-		 * The client application that performs the requests.
-		 */
-		private ClientApplication clientApp;
-
-		/**
-		 * The state of this measurement.
-		 */
-		private MeasurementState measurementState;
-
-		/**
-		 * The time when the request was sent from the client.
-		 */
-		private long requestSentFromClient;
-
-		/**
-		 * The time when a reply was received at the client.
-		 */
-		private long replyReceivedAtClient;
-
-		/**
-		 * Creates a new measurement instance, but does not start it yet.
-		 * 
-		 * @param onionAddress
-		 *            The onion address to which the request shall be performed.
-		 * @param providingNode
-		 *            The node that provides the hidden service.
-		 * @param useAsProxy
-		 *            The node that is used as proxy for the request.
-		 */
-		private HiddenServiceRequestMeasurement(String onionAddress,
-				EventSource providingNode, ProxyNode useAsProxy) {
-
-			// remember the args
-			this.onionAddress = onionAddress;
-			this.providingNode = providingNode;
-			this.useAsProxy = useAsProxy;
-
-			// register for events from the two involved nodes
-			manager.addEventListener(providingNode, this);
-			manager.addEventListener(useAsProxy, this);
-
-			// determine socks port of proxy
-			int socksPort = useAsProxy.getSocksPort();
-
-			// create client application and register for events originating
-			// from it
-			this.clientApp = network.createClient("client", onionAddress, 80,
-					socksPort);
-			manager.addEventListener(this.clientApp, this);
-		}
-
-		@Override
-		public synchronized void run() {
-
-			// start the measurement in state STARTED
-			this.measurementState = MeasurementState.STARTED;
-
-			// perform the request
-			this.clientApp.performRequest(1, 60 * 1000, true);
-
-			// wait for a minute for the request to be performed
-			long startingTime = System.currentTimeMillis();
-			long endOfWaiting = startingTime + 60 * 1000;
-			long now;
-			while (this.measurementState == MeasurementState.STARTED
-					&& (now = System.currentTimeMillis()) < endOfWaiting) {
-				try {
-					wait(endOfWaiting - now);
-				} catch (InterruptedException e) {
-				}
-			}
-
-			// if the client application did not receive a reply within the
-			// given time, fail the measurement
-			if (this.measurementState == MeasurementState.STARTED) {
-				measurementState = MeasurementState.FAILED;
-			}
-
-			// unregister event listener
-			manager.removeEventListener(this);
-
-			// print out measurement result
-			System.out
-					.println(System.currentTimeMillis()
-							+ ": Hidden service request for onion address "
-							+ this.onionAddress
-							+ " running on node "
-							+ this.providingNode.getName()
-							+ " using node "
-							+ this.useAsProxy.getName()
-							+ " as proxy took "
-							+ (replyReceivedAtClient > 0
-									&& requestSentFromClient > 0 ? ((replyReceivedAtClient - requestSentFromClient) / 1000)
-									: -1) + " seconds and ended in state "
-							+ measurementState.toString());
-
-			if (this.measurementState == MeasurementState.SUCCEEDED) {
-				resultWriter
-						.writeHiddenServiceRequest((replyReceivedAtClient - requestSentFromClient) / 1000);
-			} else if (this.measurementState == MeasurementState.FAILED) {
-				resultWriter.writeHiddenServiceRequest(-1);
-			}
-		}
-
-		public void handleEvent(Event event) {
-			// only accept events when this measurement is running
-			if (measurementState != MeasurementState.STARTED) {
-				return;
-			}
-
-			if ((event.getSource() == this.useAsProxy || event.getSource() == this.providingNode)
-					&& event.getType() == EventType.NODE_STOPPED) {
-				// when either the node providing the hidden service, or the
-				// node that is used as proxy fails, abort measurement
-				this.measurementState = MeasurementState.ABORTED;
-				notify();
-
-			} else if (event.getSource() == this.clientApp
-					&& event.getType() == EventType.CLIENT_SENDING_REQUEST) {
-				// when the client application reports sending the request, note
-				// the time
-				this.requestSentFromClient = event.getOccurrenceTime();
-
-			} else if (event.getSource() == this.clientApp
-					&& event.getType() == EventType.CLIENT_REPLY_RECEIVED) {
-				// when the client application reports receiving a reply,
-				// succeed the measurement
-				this.replyReceivedAtClient = event.getOccurrenceTime();
-				this.measurementState = MeasurementState.SUCCEEDED;
-				notify();
-
-			} else if (event.getSource() == this.clientApp
-					&& event.getType() == EventType.CLIENT_GAVE_UP_REQUEST) {
-				// when the client application reports giving up the request,
-				// fail the measurement
-				this.measurementState = MeasurementState.FAILED;
-				notify();
-			}
-		}
-	}
-
-	/**
-	 * Writes the results of the measurements to files.
-	 */
-	private static class ResultWriter {
-
-		/**
-		 * Performs the actual writing to file.
-		 * 
-		 * @param fileName
-		 *            File name to write the measurement result to.
-		 * @param timeInSeconds
-		 *            Value to be written.
-		 */
-		private synchronized void writeToFile(String fileName,
-				long timeInSeconds) {
-			try {
-				File file = new File(network.getWorkingDirectory()
-						.getAbsolutePath()
-						+ File.separator + fileName);
-				if (!file.exists()) {
-					FileWriter fw = new FileWriter(file);
-					fw.append("" + timeInSeconds);
-					fw.close();
-				} else {
-					FileWriter fw = new FileWriter(file, true);
-					fw.append("," + timeInSeconds);
-					fw.close();
-				}
-			} catch (IOException e) {
-				System.err.println(new Date()
-						+ ": Could not write measurement result to file.");
-			}
-		}
-
-		/**
-		 * Writes the result of an online propagation measurement to file.
-		 * 
-		 * @param timeInSeconds
-		 *            Measurement result.
-		 * @throws IOException
-		 *             Thrown if the file could not be written for some reason.
-		 */
-		private synchronized void writeOnlinePropagation(long timeInSeconds) {
-			this.writeToFile("online-propagation", timeInSeconds);
-		}
-
-		/**
-		 * Writes the result of an offline propagation measurement to file.
-		 * 
-		 * @param timeInSeconds
-		 *            Measurement result.
-		 * @throws IOException
-		 *             Thrown if the file could not be written for some reason.
-		 */
-		private synchronized void writeOfflinePropagation(long timeInSeconds) {
-			this.writeToFile("offline-propagation", timeInSeconds);
-		}
-
-		/**
-		 * Writes the result of a descriptor propagation measurement to file.
-		 * 
-		 * @param timeInSeconds
-		 *            Measurement result.
-		 * @throws IOException
-		 *             Thrown if the file could not be written for some reason.
-		 */
-		private synchronized void writeDescriptorPropagation(long timeInSeconds) {
-			this.writeToFile("descriptor-propagation", timeInSeconds);
-		}
-
-		/**
-		 * Writes the result of a hidden service request measurement to file.
-		 * 
-		 * @param timeInSeconds
-		 *            Measurement result.
-		 * @throws IOException
-		 *             Thrown if the file could not be written for some reason.
-		 */
-		private synchronized void writeHiddenServiceRequest(long timeInSeconds) {
-			this.writeToFile("hidden-service-requests", timeInSeconds);
-		}
-	}
-
-	/**
-	 * Writes the results of the measurements to files.
-	 */
-	private static ResultWriter resultWriter = new ResultWriter();
-
-	/**
-	 * The network configuration.
-	 */
-	private static Network network;
-
-	/**
-	 * The event manager of this application.
-	 */
-	private static EventManager manager;
-
-	/**
-	 * List of all directory nodes.
-	 */
-	private static List<DirectoryNode> runningDirs;
-
-	/**
-	 * List of all router nodes.
-	 */
-	private static List<RouterNode> runningRouters;
-
-	/**
-	 * Sets up and runs the test.
-	 * 
-	 * @param args
-	 *            Optionally, a base port number can be passed so that the
-	 *            started Tor processes use ports starting from that number (up
-	 *            to the next few hundreds).
-	 * @throws TorProcessException
-	 *             Thrown if there is a problem with the JVM-external Tor
-	 *             processes that we cannot handle.
-	 */
-	public static void main(String[] args) throws TorProcessException {
-
-		int portStart = 7000;
-
-		if (args.length == 1) {
-			try {
-				portStart = Integer.parseInt(args[0]);
-			} catch (NumberFormatException e) {
-				System.out.println("Usage: java "
-						+ DistributedStorage.class.getCanonicalName()
-						+ " [basePort]");
-				System.exit(1);
-			}
-		}
-
-		// create a network to initialize a test case
-		network = NetworkFactory.createNetwork("distributed-storage");
-
-		System.out.println(new Date() + ": Starting test run "
-				+ network.getWorkingDirectory().getName());
-
-		// obtain reference to event manager to be able to respond to events
-		manager = network.getEventManager();
-
-		// add event type patterns for events that only occur in a modified Tor
-		manager.registerEventTypePattern(
-				"Hidden service routing table has changed",
-				EventType.NODE_ROUTING_TABLE_CHANGED);
-		manager.registerEventTypePattern("Sending publish request for "
-				+ "v2 descriptor for "
-				+ "service '.*' with descriptor ID '.*' with validity of .* "
-				+ "seconds to hidden service directory '.*' on port .*",
-				EventType.BOB_SENDING_PUBLISH_DESC);
-		manager.registerEventTypePattern("Successfully stored service "
-				+ "descriptor with desc ID " + "'.*' and len .*",
-				EventType.HSDIR_DESC_STORED);
-		manager.registerEventTypePattern("Sending fetch request for v2 "
-				+ "descriptor for "
-				+ "service '.*' with descriptor ID '.*' to hidden "
-				+ "service directory '.*' on port .*",
-				EventType.ALICE_SENDING_FETCH_DESC);
-		manager
-				.registerEventTypePattern(
-						"Successfully stored service descriptor with "
-								+ "desc ID '.*'", EventType.HSDIR_DESC_STORED);
-
-		// create two directory nodes with parameters (router name, control
-		// port, SOCKS port, OR port, dir port)
-		runningDirs = new ArrayList<DirectoryNode>();
-		DirectoryNode dir1 = network.createDirectory("dir1", portStart + 1,
-				portStart + 2, portStart + 3, portStart + 4);
-		DirectoryNode dir2 = network.createDirectory("dir2", portStart + 11,
-				portStart + 12, portStart + 13, portStart + 14);
-		runningDirs.add(dir1);
-		runningDirs.add(dir2);
-
-		runningRouters = new ArrayList<RouterNode>();
-
-		// create 9 router nodes with parameters (router name, control port,
-		// SOCKS port, OR port, dir mirror port)
-		int routerCounter = 1;
-		for (; routerCounter < 10; routerCounter++) {
-			RouterNode router = network.createRouter("router0" + routerCounter,
-					portStart + routerCounter * 10 + 11, portStart
-							+ routerCounter * 10 + 12, portStart
-							+ routerCounter * 10 + 13, portStart
-							+ routerCounter * 10 + 14);
-			router.addConfiguration("HidServDirectoryV2 1");
-			router.addConfiguration("FetchHidServDescriptors 0");
-			router.addConfiguration("FetchV2HidServDescriptors 1");
-			runningRouters.add(router);
-		}
-
-		// configure nodes of this network to be part of a private network
-		network.configureAsPrivateNetwork();
-
-		// write configuration of proxy node
-		network.writeConfigurations();
-		System.out.println(new Date()
-				+ ": Successfully written configurations!");
-
-		// start proxy node and wait until it has opened a circuit with a
-		// timeout of 10 seconds
-		if (!network.startNodes(10000)) {
-
-			// failed to start the proxy
-			System.out.println(new Date() + ": Failed to start nodes!");
-			System.exit(1);
-		}
-		System.out.println(new Date() + ": Successfully started nodes!");
-
-		// start observers for all initial routers which might become hidden
-		// service directories after some time (if not stopped before)
-		for (RouterNode router : runningRouters) {
-			new HiddenServiceDirectoryObserver(router, router
-					.determineFingerprintBase32()).start();
-		}
-
-		// start measurement of descriptor propagation
-		new DescriptorObserverStarter();
-
-		// start thread that will periodically try to access a hidden service
-		new HiddenServiceRequestStarter().start();
-
-		// hup until proxy has built circuits (6 retries, 10 seconds timeout
-		// each)
-		if (!network.hupUntilUp(6, 10000)) {
-
-			// failed to build circuits
-			System.out.println(new Date() + ": Failed to build circuits!");
-			System.exit(1);
-		}
-		System.out.println(new Date() + ": Successfully built circuits!");
-
-		int HOURS_TO_WAIT = 30;
-
-		// let it run for HOURS_TO_WAIT minutes...
-		System.out.println(new Date() + ": Waiting for " + HOURS_TO_WAIT
-				+ " hours, changing node population every hour...");
-
-		// TODO change after testing...
-		long hiddenServiceStableTime = System.currentTimeMillis() + 30 * 60 * 1000;
-
-		Random rnd = new Random();
-		long waitingTime = 0;
-
-		for (int i = 0; i < HOURS_TO_WAIT - 1; i++) {
-			// wait for 15 to 30 minutes
-			waitingTime = 15 * 60 * 1000 + rnd.nextInt(15 * 60 * 1000);
-			try {
-				Thread.sleep(waitingTime);
-			} catch (InterruptedException e) {
-				// do nothing
-			}
-			
-			// shut down one node
-			int candidate = rnd.nextInt(runningRouters.size());
-			RouterNode removedRouter = runningRouters.remove(candidate);
-			System.out.println(new Date() + ": Shutting down router "
-					+ removedRouter.getNodeName() + "...");
-			removedRouter.shutdown();
-
-			// wait for the rest of the half hour
-			waitingTime = 30 * 60 * 1000 - waitingTime;
-			try {
-				Thread.sleep(waitingTime);
-			} catch (InterruptedException e) {
-				// do nothing
-			}
-			
-			// wait for 15 to 30 minutes
-			waitingTime = 15 * 60 * 1000 + rnd.nextInt(15 * 60 * 1000);
-			try {
-				Thread.sleep(waitingTime);
-			} catch (InterruptedException e) {
-				// do nothing
-			}
-
-			// start another node
-			RouterNode newRouter = network.createRouter("router"
-					+ routerCounter, portStart + routerCounter * 10 + 11,
-					portStart + routerCounter * 10 + 12, portStart
-							+ routerCounter * 10 + 13, portStart
-							+ routerCounter * 10 + 14);
-
-			newRouter.addConfiguration("HidServDirectoryV2 1");
-			newRouter.addConfiguration("FetchHidServDescriptors 0");
-			newRouter.addConfiguration("FetchV2HidServDescriptors 1");
-
-			// if the system is running for at least 24 hours, it can be
-			// considered stable, so that hidden services can be started
-			long now = System.currentTimeMillis();
-			if (now >= hiddenServiceStableTime) {
-
-				// add hidden service to the configuration of the new router
-				newRouter.addHiddenService("hidServ" + routerCounter, portStart
-						+ routerCounter * 10 + 15, 80);
-
-				// let the new router only publish v2 descriptors
-				newRouter.addConfiguration("PublishHidServDescriptors 0");
-				newRouter.addConfiguration("PublishV2HidServDescriptors 1");
-			}
-
-			// re-configure nodes of this network to be part of a private
-			// network
-			network.configureAsPrivateNetwork();
-
-			// manager.addEventListener(newRouter, new
-			runningRouters.add(newRouter);
-			newRouter.writeConfiguration();
-			System.out.println(new Date()
-					+ ": Starting router "
-					+ newRouter.getNodeName()
-					+ (now >= hiddenServiceStableTime ? " with hidden service"
-							: "") + "...");
-			newRouter.startNode(5000);
-
-			// if a hidden service was started, start an observer for it
-			if (now >= hiddenServiceStableTime) {
-				new HiddenServiceObserver(newRouter, newRouter.getOnionAddress(
-						"hidServ" + routerCounter, 2)).start();
-			}
-
-			// start observer for the new hidden service directory
-			new HiddenServiceDirectoryObserver(newRouter, newRouter
-					.determineFingerprintBase32()).start();
-
-			routerCounter++;
-
-			// wait for the rest of the half hour
-			waitingTime = 30 * 60 * 1000 - waitingTime;
-			try {
-				Thread.sleep(waitingTime);
-			} catch (InterruptedException e) {
-				// do nothing
-			}
-			
-			System.out.println(new Date() + ": Waiting for another "
-					+ (HOURS_TO_WAIT - i - 1) + " hour"
-					+ (i == HOURS_TO_WAIT - 2 ? "" : "s") + " ...");
-		}
-
-		// waiting for the last hour
-		try {
-			Thread.sleep(1L * 60L * 60L * 1000L);
-		} catch (InterruptedException e) {
-			// do nothing
-		}
-
-		// shut down nodes
-		network.shutdownNodes();
-
-		System.out.println(new Date() + ": Exiting...");
-		System.exit(1);
-	}
-}

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java	2007-08-26 21:03:54 UTC (rev 11279)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/NetworkImpl.java	2007-08-26 21:18:53 UTC (rev 11280)
@@ -307,7 +307,7 @@
 			}
 		}
 
-		// wait for all fingerprints have been determined
+		// wait for all fingerprints to be determined
 		for (FingerprintThread fingerprintThread : fingerprintThreads) {
 
 			// join fingerprint determination one after the other

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java	2007-08-26 21:03:54 UTC (rev 11279)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/ProxyNodeImpl.java	2007-08-26 21:18:53 UTC (rev 11280)
@@ -648,9 +648,6 @@
 
 		// be sure that Tor is ready, especially if computer is very busy and
 		// many nodes are created
-		// TODO don't wait, because we could miss log messages while waiting
-		// TODO should we better only parse the process output instead of
-		// parsing log messages from the controller?!
 		try {
 			Thread.sleep(1000);
 		} catch (InterruptedException e2) {

Modified: puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java
===================================================================
--- puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java	2007-08-26 21:03:54 UTC (rev 11279)
+++ puppetor/trunk/src/de/uniba/wiai/lspi/puppetor/impl/RouterNodeImpl.java	2007-08-26 21:18:53 UTC (rev 11280)
@@ -11,6 +11,7 @@
 import java.util.Set;
 import java.util.logging.Level;
 
+import de.uniba.wiai.lspi.puppetor.NodeState;
 import de.uniba.wiai.lspi.puppetor.RouterNode;
 import de.uniba.wiai.lspi.puppetor.TorProcessException;
 
@@ -29,12 +30,23 @@
 	protected int dirPort;
 
 	/**
+	 * Temporary config file that is used to determine the fingerprint of this
+	 * node.
+	 */
+	protected File tempConfigFile;
+
+	/**
 	 * The fingerprint of this node that is determined as hash value of its
 	 * onion key.
 	 */
 	protected String fingerprint;
 
 	/**
+	 * The base32-encoded ID of this node.
+	 */
+	protected String fingerprintBase32;
+
+	/**
 	 * The IP address of local nodes (typically <code>localhost</code> or
 	 * <code>127.0.0.1</code>).
 	 */
@@ -125,48 +137,35 @@
 		// bypass testing if we are reachable
 		this.configuration.add("AssumeReachable 1");
 
+		// create file reference for temporary config file
+		this.tempConfigFile = new File(this.workingDir.getAbsolutePath()
+				+ File.separator + "torrc.tmp");
+
 		// log exiting
 		this.logger.exiting(this.getClass().getName(), "RouterNodeImpl");
 	}
 
-	public synchronized String determineFingerprintBase32()
-			throws TorProcessException {
-		String fingerprint = determineFingerprint();
-		fingerprint = fingerprint.substring(fingerprint.indexOf(' ') + 1);
-		byte[] bytes = new byte[20];
-		int j = 0;
-		for (String part : fingerprint.split(" ")) {
-			bytes[j++] = (byte) Integer.parseInt(part.substring(0, 2), 16);
-			bytes[j++] = (byte) Integer.parseInt(part.substring(2), 16);
+	public synchronized String getFingerprintBase32() {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "getFingerprintBase32");
+
+		// check state
+		if (this.nodeState != NodeState.RUNNING
+				&& this.nodeState != NodeState.SHUT_DOWN) {
+			String reason = "Node is neither in state NodeState.RUNNING "
+					+ "nor in NodeState.SHUT_DOWN, but in state "
+					+ this.nodeState + "!";
+			IllegalStateException e = new IllegalStateException(reason);
+			this.logger.throwing(this.getClass().getName(),
+					"getFingerprintBase32", e);
+			throw e;
 		}
-		int i = 0, index = 0, digit = 0;
-		int currByte, nextByte;
-		StringBuffer base32 = new StringBuffer((bytes.length + 7) * 8 / 5);
-		String base32Chars = "abcdefghijklmnopqrstuvwxyz234567";
-		while (i < bytes.length) {
-			currByte = (bytes[i] >= 0) ? bytes[i] : (bytes[i] + 256);
-			if (index > 3) {
-				if ((i + 1) < bytes.length) {
-					nextByte = (bytes[i + 1] >= 0) ? bytes[i + 1]
-							: (bytes[i + 1] + 256);
-				} else {
-					nextByte = 0;
-				}
-				digit = currByte & (0xFF >> index);
-				index = (index + 5) % 8;
-				digit <<= index;
-				digit |= nextByte >> (8 - index);
-				i++;
-			} else {
-				digit = (currByte >> (8 - (index + 5))) & 0x1F;
-				index = (index + 5) % 8;
-				if (index == 0) {
-					i++;
-				}
-			}
-			base32.append(base32Chars.charAt(digit));
-		}
-		return base32.toString();
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(), "getFingerprintBase32",
+				this.fingerprintBase32);
+		return fingerprintBase32;
 	}
 
 	public synchronized String determineFingerprint()
@@ -197,7 +196,8 @@
 				+ " 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000";
 		copyOfConfig.add(fakeDirServerString);
 		try {
-			BufferedWriter bw = new BufferedWriter(new FileWriter(configFile));
+			BufferedWriter bw = new BufferedWriter(new FileWriter(
+					this.tempConfigFile));
 			for (String c : copyOfConfig) {
 				bw.write(c + "\n");
 			}
@@ -211,8 +211,9 @@
 		}
 
 		// start process with option --list-fingerprint
+		// TODO make this more configurable
 		ProcessBuilder processBuilder = new ProcessBuilder(torExecutable
-				.getPath(), "--list-fingerprint", "-f", "torrc");
+				.getPath(), "--list-fingerprint", "-f", "torrc.tmp");
 		processBuilder.directory(this.workingDir);
 		processBuilder.redirectErrorStream(true);
 		Process tmpProcess = null;
@@ -261,6 +262,38 @@
 		}
 
 		// read fingerprint from file
+		this.readFingerprintFromFile();
+
+		// log exiting and return fingerprint
+		this.logger.exiting(this.getClass().getName(), "determineFingerprint",
+				this.fingerprint);
+		return this.fingerprint;
+	}
+
+	/**
+	 * Reads the fingerprint from disk. This requires that the fingerprint file
+	 * has been written before by Tor. Otherwise, a TorProcessException is
+	 * thrown.
+	 * 
+	 * @throws TorProcessException
+	 *             Thrown if no fingerprint file has been written by Tor before.
+	 */
+	private void readFingerprintFromFile() throws TorProcessException {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(),
+				"readFingerprintFromFile");
+
+		// check if the fingerprint has been read before
+		if (this.fingerprint != null) {
+
+			// log exiting and return fingerprint
+			this.logger.exiting(this.getClass().getName(),
+					"readFingerprintFromFile");
+			return;
+		}
+
+		// read fingerprint from file
 		File fingerprintFile = new File(this.workingDir.getAbsolutePath()
 				+ File.separator + "fingerprint");
 		try {
@@ -276,10 +309,50 @@
 			throw ex;
 		}
 
-		// log exiting and return fingerprint
-		this.logger.exiting(this.getClass().getName(), "determineFingerprint",
-				this.fingerprint);
-		return this.fingerprint;
+		// parse fingerprint string to base32 encoded ID
+
+		// convert fingerprint string to base32 encoding
+		// TODO move to separate util class, document it
+		String fp = this.fingerprint;
+		fp = fp.substring(fp.indexOf(' ') + 1);
+		byte[] bytes = new byte[20];
+		int j = 0;
+		for (String part : fp.split(" ")) {
+			bytes[j++] = (byte) Integer.parseInt(part.substring(0, 2), 16);
+			bytes[j++] = (byte) Integer.parseInt(part.substring(2), 16);
+		}
+		int i = 0, index = 0, digit = 0;
+		int currByte, nextByte;
+		StringBuffer base32 = new StringBuffer((bytes.length + 7) * 8 / 5);
+		String base32Chars = "abcdefghijklmnopqrstuvwxyz234567";
+		while (i < bytes.length) {
+			currByte = (bytes[i] >= 0) ? bytes[i] : (bytes[i] + 256);
+			if (index > 3) {
+				if ((i + 1) < bytes.length) {
+					nextByte = (bytes[i + 1] >= 0) ? bytes[i + 1]
+							: (bytes[i + 1] + 256);
+				} else {
+					nextByte = 0;
+				}
+				digit = currByte & (0xFF >> index);
+				index = (index + 5) % 8;
+				digit <<= index;
+				digit |= nextByte >> (8 - index);
+				i++;
+			} else {
+				digit = (currByte >> (8 - (index + 5))) & 0x1F;
+				index = (index + 5) % 8;
+				if (index == 0) {
+					i++;
+				}
+			}
+			base32.append(base32Chars.charAt(digit));
+		}
+		this.fingerprintBase32 = base32.toString();
+
+		// log exiting
+		this.logger.exiting(this.getClass().getName(),
+				"readFingerprintFromFile");
 	}
 
 	@Override
@@ -300,4 +373,21 @@
 	public int getDirPort() {
 		return this.dirPort;
 	}
+
+	public boolean startNode(long maximumTimeToWaitInMillis)
+			throws TorProcessException {
+
+		// log entering
+		this.logger.entering(this.getClass().getName(), "startNode");
+
+		// before starting the node, determine its fingerprint
+		this.determineFingerprint();
+
+		// perform the same as a proxy node does
+		boolean result = super.startNode(maximumTimeToWaitInMillis);
+
+		// log exiting and return result
+		this.logger.exiting(this.getClass().getName(), "startNode", result);
+		return result;
+	}
 }



More information about the tor-commits mailing list