'
config /config 28
1559781494 'footer' value ''
config /config 29
1559781494 'details' value ''
config /config 44
1419221098 'logo-mimetype' value 'image/png'
config /config 54765
1419221098 'logo-image' value X'89504E470D0A1A0A0000000D49484452000000FD000000C80802000000ACE070B5000000017352474200AECE1CE9000000097048597300000EC400000EC401952B0E1B0000000774494D4507DC010D0227231D0490E00000001974455874436F6D6D656E74004372656174656420776974682047494D5057810E17000020004944415478DAECBD779865C7751F784EDDF872EC9CC3644C402602C10882012228895A8A16BDB46C69B5963E71B5DE4FDE95B4FE447B2579575A4BB66CD1946CC912CD9528896226402412200683C10C3039F5A4CEDDAFFBE5707385FDE3DDFBDEEB9E9EC1807100BCFABE015EBF57E1D4A95F9D3AE75775EBE2BFBEC240804000002104082100FD3F0144FB1F02FA1F052080102000D0FFC3CF2F400821001005F83580104208818080CD8A8222CDBA50088076737E5E81D0ACC1AF120580FF4F0810D814D92F2E00D0CF2F8410204020FA1582DFA4401080D06E1DFC9A9A352034A5F03B2010103649DBAC050588567F0504C2375B051114045F6DCD9C7EB75A72FAD5FA9FFD8A0375C106793AB5D76CCE171EDA8571936682E11102B02945B3A5B6D820404073F444B36FAD6A850014417F015AFAE914CF57A4F0E5DE50103ABB0CB0B15F2D4102DD7774190218742AA453EC0E3008682B4460ABBF00D0FCB5D54CA090A0C1666542A08CAD1F5034A56C824A00E844C414E40211912096EA462C1C42BF00563C70B8C066111F41D81CF7D6A0A20001884D40A1003F3BF8E86C0ADC847913308800C045531614420040B3C58EFA9B3AC6607EB5BF10C2CFDB1CFCA6CA452021A008DA6FCE575F441FAA08001D0D34B3A23FF97C4B80ED392D7C61FDDEFA0A046876A289A4E6E0080C7A073EC2B0853F14E8A35608BF125FECE62C0CF405027DD97D03E01B8EA6307EB18D05DBBD6CC1A8597FB3534DABD1EC14B6040BA0E9EB41B45B11E8C31A31D04ED01E069DF56B68690F4480501FBB20A0AD29F4B5EA773930524D85082138F8BAE202485B39FE6035B1C17D730BA4D9CF4021ED410F74D26E4900A2907DB38AD01202843F7053617C7F865000CEC53F7CF795D90B577FFB1F3F160BEB00A012F8DB1CBF62F226DAFCDE05D0E442B80C9AD99AD6B2692745C790008084A010080314A800018E00210421D0A7923A15AE1004110128B4542F025D2102781C984000A19026F01040500E1236A70C024260359AD241D0C1B614A23D5B41A0FFB9D99E085A12AD29EBDB0C7FBA8936BCFC59844D8D8B4E64631353C2FF801D4A08267D3058C1FC8116467DA4B5B1021D195004386DF73798052D2903CC43AB78E728435B287F0D0DAA141B460D3661177D638ECDF5B165DAA0DDD500A4A285B656BB013637B72B7CE80980BE909C9080035629EF95C9C99A2791961A108336772555CB631E158B36F3C56A0D49D0ED269A5B2D35970B39B092205A96DEEF9ED00926150480DFFECBAFAC976BA56239A388B8EADB408D80002081AAFC51430102B6C7E4071300805F5CA155DE5A8B8037A1248001E804B7870927D887FCA93253097EAC4F4E4978AECE6502170C9A73A05FC33E0D4F5499400108442003210410448F8947FAD4291D1D269ECA7B4B2E27025419F786C8D90663027960F78500D2C216B4178DB6D1DA6065838E40DB4277D8CE8EEF02E803B6CC7A7B3A34BDA3C0596AC3A22D407B81460C16A2168482B65B561103B726182A1F2B416501F43B978B563FDAF30EFC1480185B28BA06FABE9DF157BFD65A03D0B14840875DEFC410B47A18ACFF81E62050484B391C3A94D32C84828BA188F2DE1E3D4DF89FCD190C0415C263BEF00A114C00E54297F0AE8C76226FE53DEE721020640400E171000435F05F8245AF6DBA0041EE54788769082C03C0E5E5B5935717FB92F1F1BE1E4D554587123A2D978F184001222CC1B12A3F51E788B8234AFA153C5EE382907BE3E48AC118C2F63039DFE0554F443524001C605B54AADAE22B658F22BE2F2D4B48DE9D21276AB4E2C2DE843CAE61CEE127EBFC8194ACA1783A4F19C0AEA8F45F672D5BC05098EC90489EC3AE10998848BBA3D23FACD1C77AE58B751A55A51E055E2E796B9E400C8CAD6FB3024FD05FB9DB0E8F800E4005BE4E87EDEA807E4B111B2706B646570012085C4EF4031B810280B4E304246DDDB72750CB4A07234700B83FD19A5A838E89215AFE5007F45B8E5DB0CC6D807F73E5171B9DBC76A75A4155ABE7ED5F05F15D9A967F1374A003FA6D274674280710808B60852582733F13069D90091E2FDA027018589E48BF35A4CC0C467E22A3165D264BD27FBD54DDDF137A4F8FF627E72A2E17DB93DAB0E5FCCB039934E75F5F361BB2F48FFAF565C3FBCD3355AFE529B6C4F6FF44820211B0BD44F88B4FCBE982E9A1BE47EEBACDF1E8EDDBC76442024506DE91EF022062501C4042D8192177C6A58C86F7C7A4550FEE4B900309A281C87BF0F6A45470852560224C7402084000AF184C57F13D19794A470EF033FDCA9CC1E30A19D4C93B52F2A10ACBEAE4DD597950C115CB1F284FC04319E56D49B9E88807B2EAC7FAD4AB162F3AFCE982175648BF043316B799A833F870AF4A9BD17AB3AFC2778B102198EEE8F71AA1F94BE07DFA6B3D06459BDFB76BF0B1EC67087C95E60F8155F0DD5F7F29814057C1FCF35DA9A6490EB2F9FE862F4F80E066D14032DF3AF9C63528BCA9A03FC511FD616AAE4441FDCD0EF8DE55A081C0EF8566A1A02036575DECB08A1848D6CC11C8032D2474C0A3C39CFABAF2E777A0D52003020048880A822C617392945DFE7B33F55772D6AF9CAD7D62349C95F10B8BE6484406002E40089051FCEA898A03F82F26635F5E32CF9B2CA510848EFE82AF936613C4F75DDB94880F7DF4630500805858FFF58F7DE0A7DF7EA72411214407EC3B62B70E4B2204CC5BE2BC215489188C2F392224C1D1329B75E0408C3C5960A6808712C4F3433EDF6A7D35E71D33F887FB1500B0B84829C00508002EA0E2F19C2B562DFE4285ED49CA030A0A000DE1B9A2F752851A4C502E00414240802A1502A0464544916E0B93258B3108BA0D2DBF04B0CD2321B64C71007DDF8E621BFAED6011DAF34474C00BD0C7410B2FD0392502E863E01863C78A891DCEAFEF907640D387A0EFEBFB1C8BEFCD77982ABFDDC0296F0D73736DC220F040E84076B058A1EF05B4277FABDDA0C71BE481567CECBBCFBE8FDF8E22B0C39B1718CC2E68F9FA7EE0D78AB43ADB0500009783C50408A87AC2A65C80708490012ED4E84C8366657C72DD36A948A9C4625076B82A0115E2CF66EBE31169D9A0EB1E6F46782DE843DBE101193B3DB90D7E1AAE962A25454A27E3E7E7573EF1DEFB3B56B516E801DB61556B5D049381C1C0E662DDE2C530F9680F79A64077C6C8BE309E33C45D4929ABC0B91AF700165D7E202B61992754FCE98C1A26F05C812A04BE94E30FF728F5326D30C8BB1C004C2AFA54B23B8E1A40858104B068F39F1FD13C0E452A8E96585188BBA29209F83F8FEAFFDFAA57F6A0E27290E577A795459311E8A42E105EAFAF2F0247EEFABE7E8B56B9695F1FDA3C09B6B92DF841F8FAF043F6F53BF9EBC08B87EFC5D76FFFD0E9880308385FB12F005001FF71C16302B81067005C019F9D7705804AD0A4E2E9159320522E8E9EA9D84C7C7BDDA602A212BA5C48D8E1F8890EB19B32FFEE552E82F1F1596D0188C838EC8F8A81FC658ED27CAEF8D80307D62B75D7F3B68F0C342BF9EF2BECBCC109B649513F4403D15C7A08A20060427001120A269A841470011C400A3A4805C804B91094030090C0DF64DC1791099009302E0400130000324110E071DE1ABC26AC9B910F13424660022444CA05074004093A787D9F54059FD7172DD24708C42643DCC1EBFB7F4140A48B7651DCCCEBFB6140C0EB37B9AE16AF2F0010380F689F4E5E1F7C12A635BFDA34768003D141D4088142F000EED0E4FC44C0C3F81C780B72ED8210D0EACD5D8A0E5E5F049B2D0133DEE6F503D97C8474F6BC03A62290AC45BF6FE6F5FD3020E0F58382BCCD47F9BE7EE7F6482B4ED99AD7EFC09E401E84A90181E3EF28E1B5BCBEDC3135B1B57E35EB5765291D8B5C5C299C5B588E84D4E19EF41DDBC65A71ADE57A0832B4A2E4806E436C62D7F7092404095020C8C1E61769691940089009800082A890165C00B019EB0104B5110400D1ACAA39720A213E6C0286A439AD090206A64A4294034EADCDEBE32646BE6D05B6E2F5B14D19B6EC0604EBF4265E1F5F9BD747DFB86EE4F5616B72734B5E3F9001DBD672E39AD08E49B7E0F53B298E8DBC7EB07E6FE6F5DBE42676B80AD7F2FA9DDAD98AD7C7AD797D6CB3BC41D4D9226D03E214C44685B476EEFC4AB063D9111D9B1E106C6A6DE6F565019DBC5D10F02308018CF3ED63C3DBC7861559DA3F352A13B2522C0F6652006018864B05A2E2EBDB5F44103632A8A2152E047B142D3712DAE44227E7EDCFFB8E1D2E688BD7B9C5B5690D6EF1FAA28393F69BE9ACF0FBE3F5C5CDF2FA2D72F346BC7E5B07017D7C73BC3EBC4E5E5FFCA8797DFF434010DC90D7870E5E1F368EF235BCFE0685B435099B3CD18047686D4B37C56AFBA04DB7C26F33A004FCD0AEE5C773C1EFD939F999AF7DFB3B272F5C5C5C03008FB142A51E0BE92D14630B32AD085F040C4F073DE20747CD30A3E5CB06216010DC77EC3160DBBAF8C50377392004005A548CCF2F056C78200076A81F5BD1556BABD4676ADA344873400206035A3588166502A283C3F1BF479F86F76341EC08735B444CE0EFFB7447AB6033D8C4F65AD70E73C1A7623AB8A30E0EA7F9639B7182563CEAFFEA2BA123CCC5C0D7F7CD4F40E26D0C58D107C316616EE05A61306A4D315B212F7470472DC15A0C8F68ABD5FFB5D55FBC66943747D22D95F9FBE12D7804EDFA06C227C4B09DA173389BBF12248840FC5A7CBEA0590B41444AE9375F3E5D6C98BBC686960A1526C4AB9716BE7AE8C4506F462284044840687A1780004890F8717EF307DFE677540B4173FED46BFA3E4D56DA1F4B40D2920A81F8C50111895F614B605F009F60F0FF84D67F90F8AAF31D0C241830212D2613A1E34BD21EFD26FC5A0D05DC394267EB045A6C1C2208B2593608A8339FAA692B2A70A39AB9484BAA169D17888CA4830E6DB184013304C45FF73754D254626B48FD130A2D62C3575473AC3ADB6D1A5D1270354D8B12540B2D3B03084D8FB52D0F00B40A062341DA076F8275BE43B88E82FEDC0F9A6815F467BB2F404B21D85EA95AAB5630E6D05257ABDDE6FF486BCC013F7D7405DAFEF6863355BD1AEC8C2015E2855317F74E0E6B8A922B550733C96858E78C9DA8F1A2D7DE07DAA286F6F1B5F66608B44F9BC1C6EFDBFC68AB403B7AB936B3D850A1082A089A6D15D9AAF52D2A6C55B9A11BBCDDE086CC1DDD0D22B6CE6E6DAABC23AFB8B62AD1D106E0168241E7F1B5169BB331C3755B6C45AB5BB5D856D406E58BCDA3B059031BFB28B66A315853FD13349B152B360AD3295BD3E8F00D2D6FEED766C06C9D4DB48F366ED0240008FC279FFADF6043D31B46BDB93D28118973DE8A5D9A6A94103A76B03624013791DAB1145C4F804DCCA9B8A95A6F2A756C42006E686D736DDF4BEBE2FB92B0231ADC98B9F30FBCD916C54D342BB66CEE3A85BEDF51D83863F126B475531ADB4A395BB6D84CB2935F79CD6EB0ADBEE4F0264937502B6E3501E026F277D32D9EE40DE70EBAA90BE8B708EE6F7563DCF2485E6B82062EBF68C53D9DDFDFA0B4F08FD2DEA81521C496BFB67755AF5F4A0820046F2CB9084EB96CA4B8B7A8BB9328DC303337E66C6D0E751C0EBA5185AFD1F19B1A81D756F5AD93A4BD7BF7DECAA04724B284449639A54208CE7900A6CD2A46C4583CA187439260B6E3F9CF25701E8BC725421CD74144CE395E332BB45038118FC8B22238A7946EDC7FF1F348B2128F462CD36CD6D9FC92731E89465CCB16C19F9D9537858FC5A29148C8303614ECA85C0801D1583C1C0EABB2645956241E731D27D8FADEAA4E4264829E4765450B47A30A611C5555E29489CE6C92AC00A71C88AEAA9452CEB9A22884104A29693262414E420809DAF227613398030142709423BA02282108D6CA2078733A3487A3A9582144381CA19ECBB9B8F13CEFE2FE26E40BC5FA927A626004298D27E2BDFD7D99540A1192A9A4633B7CA3CD8BC713E14894313A3A3E160B8751927A52897836E3B95E7F5FBF659A23E3138E51A38CB720C2199BDCB6BD56A9C41209046968A0DF71BD4C3AD1308CD6B4E29C0F4F6F23540C8F0C48B2D6DF9302594F46C3B17862686C24A26902A588AEF50E0EBA46BDB37201223B30AEBA75359A8A84F5FE813E4029110D350CB30D7D21504B4C0E246AB69B88C5FBFA7A084A7A283238D81F0DE9C96C8FD3A853DE21B090C6467AC726B7590E4D26A391B02ACB2A736CAF03F79CD1A99DFB63AA27E4F8E8705F2A9D4EC4E3083C144BF66793A54AB573564712095D5528C7A98951CA78269D0CC753E94444D3C32849E393DB75B0EA96D73F3C125189613B3DBDBDB178425389E3D1E1B1F181BE6CA56A8E8D8FA88A1209EB440DF766E2956A1DC92D6DF66F753F870B91C9F66989A464DB54D6C02EABF1C8E0D070281A69542A1E651DF811B669A01AC9F6F7DBE5B5683A93CAF6A08456A3D137D8B79EAFEFDCBD877886934EAFE6D63BA009B2AA25E3512D164D25521E87C101706D7B13CF812825E31182285024FB46F4D07AD9449D966DDB2A9A7CE7D468AD612A5AA82C11E1B1F6E14BCE1CD7E586111FEACBC6A365DB4B4581527B03998460999667CBBD0303E5DC2AEAC974B411EB1DF39CC6C5A5D5E9ED3D45B2614D03EA485ACAA3626AAC3F57A8ECD936F1E2E9C56858361CD63A1F41D4484C675A6C82E68AA64784918FA4127AA88FA37085A2E1922B60C34A09383D35B6B098DF393D52AEDA618D7329DC1B0973C73C7F65753041F47024129121DCBF56A864D2192472ADE8D588158BE9C58A3BD81BD522694D062A442A15CE57AD988686B7A18DAEBD7F7D89201AB54AB15A771C1738ADD76B8E47EB0DA35A2ED70D73131983088C51D7B16CCBB23D56A9D68D4AB9DCB0B96737EA46A356F13814F279BED127E78CE672EB02B05EAB71CF2E142B2849B665890D7E94109C556B5521D073EC6AB55AAF56B570C4739D5AA5EABA4EA954713DC69963BB74A3838BD4B3552DD2308C742ABABA9A9324D2308C8D1E1A08C16BA62511D96E941C26950A8572A5160E6BA6E930EAB81EEBCC2FA95A6EFE2243A5DEA8AFE68A614DAAD51A94B7ED7D281229E6566BB6471D0781D7EB35DBA3866199A66518A66B591C3AD71B482492B55A3D110B556B4624AC50D065F0161797F2A54A26152B97CB8E4719A58661BA8EADA96AB556051086610ACE0DC34040EEB9D56AD5B6ED86E9AA8496AA0DB8B50D3E7EEC631FBBE543DBAD09DF2DE327D17AA27BD39408F62CAE753D5BCEF48DC3C4B6F1F76350E0CD03A4A4638304C8B5912F2072CE6545D155C530AD1B05975BB2AC48AEA992379F536A19D4CD15FA07395B813EE9D4C6F55A17009AA6A3E092A232CFB11D37087548F0D42BB462A44DB1F5A688E8D60F6DE5D1D1D12EABF5234BD9AE0A6E11DC6FDBB6ED9626CE5BCFB404FF25CDE3C71BF9B5EBDB4BB85E7E82B8212C6E3DED71FD0A114960FAAF272DF1EFBFC09689DCA2475B1AF88EA7F1A0E3C9826B1A406CD129D72AEA86C2FBBC10E7BCB3B3D7ABE4066B505B10D169ECDB8CE80D8BDE1AFEFDA38F3E7ACBBA37B2AC64D2692D144EC66392ACEAAAE408797420EB79941029994A3146A3D1081259918840A248C4A3B45D03E7914432918887225119A8404522402439934D3326628928004A922411A49CA733D958384405867525964CD8968BC09BCC5D307FA46C6FAF2A4B96696B9A26CBB2A2AA1242329301C139634A28DC934E114992258984E2A908B12CAF455F06FE04191E1E5435555564CBF5E2B1884799044252142D124F4543B2AAA7B309DB7215599224E279B4D31B91156D6478987AAEA2488CA3A6A99AA6BAAE1B4B2433A984E7D14838AC86A392F01091D20DFBEC9158B2BF27A5288AE3D26422A6A88A00224B184B240982E77A7A34DE934E722E744D25A15844E11E15BC430342084909655351974B3D99A41E89AA122A12BA0CFAFBFB644992658579AC7FB8DF6C348480CEB25D3EE775201F095155A53711B7849AE24EA95CB225391D8F546AC6E048AFA66BCE92928970399CD635A5B05E649EB5B2966F39978CF3C989B1B3A7CF640786B3BD7D8954DAAAD7CBD546DFF030772FC752A96C8F4C2998D5C27AB192884751403C93150012F07834B13C7FB513394492E2C964B9282626C7354D45C6282182095957EBAA5E29E686A62657AF5C1E99DA56ADD4F448586696AE475773EBEEC6D1D743A1703824242593B2CA0D7BF7D8A86353D72C557938223B0A28B178BC37DB5B6F5846ADBCBCBADE59D6A38C7BAEACEA139313A5F5755760261E3A77FE42B627631AEE8EE9F1D5A29D4CEADC4B58D5C2D27AA513B24C8063DAA17864241AF3185765399E88BAA6697190389F9BBD323236925F599D9C1C5F2F36628930A1F168BDBA942B76865604C5C8C4F6414EF36BEBC9445425E9D5A5050867753431D11B976D9B6543115D97D5E59515CBB26F5DBEE456F671344D8FC4A29586AD835D68581201D7B688A28575D576DC46DD49C4C2A661D8AE67D5AB0EE3E190DEB9C012822BB9C2B6E969A08E6DDBA6436BF59A160AD7CAA57822C528B36CDB71692412618C334124E0AE631996532ED52261C513D87940A1E95DC8C24DA4520BCB798F32B3517729B32D1A098775555D9C5D1C1B1FA78E51AE36986332CF95B490DB69B00190488A2433EA354CCBB09D743262D62A7A24B2B656706D2B5F2833463DD76D988E69989150F8DA45D034CD7038C219009193B13091358560AD66F6A62235DBADD46A9E65C46391527D33E618F56CDBE64C7090241400DCF178AD56E50C543DA42BF2EAF2DAF0409F65DBE56A9D3996224916854DAE20005F5F5BA366BD6CB88E6599B6AB694ABDB01AC90C2884170B45219052CE04788E734BFBCF9FFDEC676F6593CFB9E8DC404504CE3B1F666B4EDD36D9B2050FB3F972A30DCC7C8B85E9606C44281CD36452ABD7C535D2801F6360071E9A87150862736547424070914867996318D6E6E1E71D9B509D414BEBC95908DCE4ADE8A1D6D90791ED1B00CF2A942AAD00A6E9C0134949C663956AF55A37233871DCBA5CB1ED9713427C6D37A31820C954CA6CD43AE76DA74A09B6AFCF09489EE658F05024A6CBA45CADDDCAAC0E7EE10B5FE846F75B62EBFB1C36D17CA2FD8736F6CDF0742B925C702E3A0F237CCF26E77BE3E0DF10A774B05C2E7781DE4D6FB5F406A09CBAA99BDE52716D37755317F7DDD44D5DDC7753377571DF4DDDD4C57D37755317F7DDD44D3F36DCB76E2E7A4DD6F475F1AA9DE7BFC50D2BD97075D28D8E544297D6EDE2FEFB47FBA667445A174F892DB1DB9173F3F79BA02A3ADF0CD8AC1A00003875D60AE52DEF5378E1E96F563D2C160AFE158E1D6270CE2AA552673DB0F16EA92D65E8A62EEEB74C88889FFBCC1FFD3FFFEE337665E9939FFCE42FFCD2AF981411D16CD44BA552B95C6E1816085EA9941B86E93A76A552599CBBFC99FFFC9F96D7CB88601A8D5ABDDE6834AA95AA4769B552B61DD768D46BB5BA6559A552A9D1300E1F7CF2BF7DFE8B02C0B6ADDFFAF54F2D2CCF7FF19BCF52D76ED65FAD3500A05EAB0A802FFFCD5F954CEFF1AFFF43C5B08BC5A2E37A947A954AD9F5A8E73A870E3DFF5BBFFE6B472E5C755DAF5AA9D88E53AB554AA552A552B16CC7B5AD4AA54A19EB22E6CD917EE8E79093FD43D67A514F0EFFEBDFF8177FFC277F5A33DC7042FD8D5FFE040EDE5659BC9A9ABAEB533F73DFEFFEF15F6DDBBD6F246CFDDD3327FEE93FFBF9DCD2ECAB27CE0D3E7CDF67FFE8771A989C397DBC582E3FFAD31F5FBC78F6C31FFDE89FFCC1EF796A6230138BF6F4CECFE5FED75FFED88B2FBCF8D863EF8F28D27A6EE9C84B47978BE65F7FF6F71F7F652E130B2DAE1B9FFBCFBFF3898F7FA267D7FD9AED0AC18BEB4BFFF6F77F5FB30ABC67EFDB46A57FFBEFFFF413BFFAAF7EF1A7DFB3BE9E07993CFD8DAF14A6C7FEEF3FF8C30F7FFC67BFF59527EED93F7571A9F89E0FFD74B27EFE4B2FCD7FFAD3BFBD677AB80B9AAEBD7F6D3FE78E3BEFE6CC338CEADC4A4121B89E2F010065E2E3BFF02BEF7FD703CC33D716AFF48EEE509145B363EFBC73C7F9992B03C313D393C3424034917ECF3BDF2647D33FFBB18F72B332BC7DDFF681D85CDEFAE8477F32A4E027FEF9AF6BB5D99AD0F7EFDD1DD1430090C9F64D4F4F0ACE01F0BDEFFFE0A38F7D2C4BAAA56A598AF53DF2AE070058B158119C5125F6AF7EF37F39F1CAD172B9FCAEF77D607430CB85E09C790EBDEF9DEF6DACCF6D3F70EFED7BA6A5D4E0A7FEE9CFEDBFF31EA4C6D0D4BEBB768DCC2E2C7711F3E648D2A73FFDE91FAA9F43195354B52F9D7CF1D04BBBEE7CF0817BF62280E3D8D3BBF646542995E97DF7231F6AE41776ECBFA72FA5E72AE6073FF46808DC9249A7C7473CD7DDBEEF9E89DEC85AD9FCE0873F52CBCDF1C8D0A3EF3CB056AEEFDABD6B7C625225E2AE7BDFBE78F5C2D0C4F67844572428548CD1F1C9C9E1BE4CFF705F36138F86EE7CFBC3BD51498924DFF9E0BD960D430399FEC191A9B12141F40F7DE07D6BABB9FD77DD9349442965F73D70FF89232FDFFFC84774D6189AD8964E26F7EDDE4ED4F0F8E8A8C49DBA471E7AFB83F188DE05CD9B20FDA8CFA55D7B48555CE79E15F103BB9552FC00EFB7DC747140377571DF4DDDD4F5EFBBA99BBAB8EFA66EEAE2BE9BBAA98BFB6EEAA63719EE6F3268DEFA0C423775D30F2DFDD0F99C179F7B36148D2F2DAF3CF4DE87BFFBC493FBEEDA777976F5BDEF7AB0B83A776266254EEAE1E1DBF74CF6BE72E8D0E8AEDD178F1D4E0CEFD8BB63A23B30DDF4C6F67376EEB9EDC4F94BF7EE1978F1F8E5742C34383282323979F4A5D985051E8AF4C595F58A71E9DC295D0F71C0A1A1BEF9F9A5EEA874D31B1EF7275F79F96D77DF7565A9BA6B7A3CDBDB73EEECF9A1BEDE9D7B0F0CF4F4A0E324B243A958686AC7EE5432A12BC8A5683611E98E4A37BDE1FD9C7AAD262BAA000887744A29A3D4B4DD5432CEB960CC536499729025C2194342AA954A2295C21FE80E6B3775D38F1AF737B9AB7FED7BD4B6F85308D17CDDFC3597FE6D556AF38B063B2F13BF36A8DE54BFFF7E43F1DA6D6DAA76D3BB21E0FB3ED7F0BA8AB715F57A9ADC707DE25BE614C60FD7CFB9811239E79665314A4DD34200C7B619E7B665B9AEB7A914221E7ABE46114108C3E446C53B71C6620C1C879B06AB14A8E988F95957009826B76D6E341865E079E2F449CB72A0985B325DCE18E59CBBAE3B7F65E6F091E38C0BC668A998F73820F053274E5040213802AC2C2E7B8C8110AEEB9A9562D57000800BC119A38C05EF1804E6DAD55ADD71696E6515114BEB79C7A39C7AAE4719638C73B35AACD46DEABF8691B9AE4B29A594722E84108C31CBB29AAF01A4AD573572E6382E638C0BC118139C33CE39F36AB53A659C73CE196B16619432CE85101E15D4135C88E68B1E73CB1E4714CDD7110AEED80E631C009AAF34648C0108DBE21E159436DF5C28848095258F7A22B7B68E886F112EEDC7760F78B552F9F2DFFFED3B1E79E4F19271DB490000200049444154AF3DF9ABBFF2F3CF3DF5F46DF7DFF7B5CFFFD5D08E3B3EFC81776DCA7CE18293C858610DFFECF3A5DBFBA4F08EF0D1978AD904B972C1EA1D09F54CE9A79EA9DEFB48FCD053D5704A1E4C02C968ABCBDE685A1EDB117AE599AF0C3FF889732F7E6574E7FE33475F641C3DBDE7CE3BF69F3B7D6CF6EAE5D4E0E4806C1D9AB1F4B05E6FD09E887CF8C899EC60CF3BDEF38EAFFEDD97778C2696A1B72F445DD4746ED52C67FB6D07B0BE6680522F976BAB4BEBCAA8B774E2A10F7E68F1CC69884564DB284132424C4922495DBE546492B03FF0F0BB4FBCFA72B5CE5484ECD820B3848476281E79EA6BCF3FF8CE07B2096566A91A556C9B6BFB27324F1DCBDDBE2DB1943734E16A2195CA89D1DEF8D599B343BBDE565E3C57AD9BA148580AC56AAB4B537BF6A21B3F73CE6404078634A34EAB6BD471616A974A05EED9A953B7F1CDAF7E676C7A389E4C98E5828BA16824BC6BE7F417FEBCB8FFED91A539FADE07F4E3175C0FE1ECCBE63B1F4D5F3D77F0D18FFCD45BE4D0DD8FF3FE7B01229AEC19ED4F356AB54CB62FAC490E03CEE9B5ABB0A6E3E1438D6DBB745D120D2E3FB857FF2FCFD6F63D96B874C94EC7F1F869D36EB06F7FB711950109C82ABA0D56B38465714902CF73BFF9E5BF5D9D3D5D32BD93AF1E490FECBEEDC024123876E4A8C7E86AA9218DF46DDB79E099A7BFAC28615A6DF48D8FD61A86E35282D4765C217BDF79F6D9C11D07B05A8E8570B177724F7FE433FFF1F3BB46E2B1D470B5B61E9194E2EAA20BF244CC7BF67C5EC8061A957DDB13B3465A93A4B5D52200CC5EBD6C78AA912BFCDCFD777EEE4FFE5C0B2B7B6EBF9D79C68593473935C293EF38FFCAB75323BBEED93DEC18F5EFBE707276ADD6AF90C19DDBE6572F8C7FE4831AB2832FBC6017E628F70C2A4FEDDA5D9E5B9FD866CECE84748BE6E2A1E35FA9565DD61796932A9C303D1656A35A7978245EC82F2F2C9C890E4C0CEADE7C19B23DD9A91D93B1302EAED2C6AAFB8DAF59C51AA67684572E5B474E382311A5EBDFFFD013E7DC711C4DD33CCF531499312E4992E33844923455EDCCE9B8E28FFE2077F77D5104701C2E49A869C4B6B8AAA1EB0A45468F09C100250001840063A06AC8285C3A677FE8A792033D9E4B0522C8B2E4BAAE24C948245D535DC7E6029AAF41E62051CF2644E28CCBB2C4015455F51CA779AF36A3AE2CAB9C31421088A4C8A4D13015592292E4512611942589732149E87A54082088B28C8C63F36A624D533DCF658C83003DACDBA68548884418A5CD2BBC2545E5D443495665623B1EE7CCB1CC83075F7CDBDB1F8AE83A11DEF25AA1B76F40911001B800455518A5AA2A2FCCB3D95987015047700099345F5F87D934136AF18E7D53A6692091AAF9E543875F79E8FD3F195385A669875F326A752611A4541002282373443C25219C7ADBDBEE7B8B700AB77A5CFBFD475A6FB858ED26BBFF9AFDBA26946FBF7FEA4DA3AB5B37AE752C930B615A360070C65CC7F6FC304E78AE0B00CD177C0BCE058051AFF18D8FA17CFFC3F0861BC89B7C21E66BF6ABF5B6CD8E2F5EE33EFEB7CE23353F743FE7FCB9B3B95C4E9744DFF4DEB3870F3DF4C87B0FBF7CE491F7BC6775F6FCF965234ED7E4A13B0F6CEB7FF5D08B83DB77368AF9F56AFD817BEEEE12CCDDF406B6F700A0225DAB799343B10BF3F94C3454AF967AFB470F3EFBC4D27A81294A5F3254AE9BC78FBCA885A292ACD4D6177B06BA8773BAE98D8FFBB3E766F64D0DBD7466F5FEDB77F50CF4170AA57261FDC1F77C6072745834EAA9C1A9DE64F4F67B1EC8A612D19072E1CA2252AB3B2ADDF4568F6BBBA99BDE9071ED0F6AFE5C7B6BDF7532DE38C3F7F848C0353F894DD718C2357709DEBC41F91E8A74D3ADEEE75C2F5946E3D0A1C3F5D2FA379E7816114FBE7A6421573A79F4C5F9D5C286D922FCF3338870F1ECA9A3C74F1E3F7AEAFAD30911452E57D894A1B472F5CCCC92595ECB95AD2DCB728F2D3C7B79F964BEB3A2F24C61FED979E679335F395F3CB5B476D5B2F30DE6BFE31E1171F1D9CB179F9C4344A7EA509BB6F893D2D2A5C5B27D3373DEF3C4DA9A8788B4B176FEEA6A7795FB91A51FDB7E6D28128DC4C25F7DE2990F3EB0F3AB4F1D7AFBFED133F3175797AC9EDAB1B181F76D5C32C47FFB8BCFFFE44F7EB0EE88BBEFD8FF87FFD7EF55AC3A67AE5DCC573CB27B225BA8B9F9626972FBF6E2EAFA871E7DFF57FEF68BFBEFD85D75E8D450AFED986B0678F3174A106F0C256263FBCB578FCD146846366C3951595D8AC7C2EB35E7E77EEAA76A97CB83E3A9A37F7A2C3A18F1F206D7B490A678A65B5BAAC989B0E23A67BF747E6C7F7C75A69A9E4ED5AE940EFCF25D85B38581F76C3BFBD7A7CDA29DE8510B791CBC2DA4441297AC953D83F513F9A1F913CF4E6EDB79F2ECF9896DBBD7AE5E7CF8277FE295279C572F3B83D3E1A4C44C94964E1ABBF68757F3CE6D0FA6EB0BCFED9A1CE822F24D6EEF1BB54AA3529B181F5F2E34A62747CFCDCC6D1B190E6B3C124B5E6BC5F7EEBB4D5554E074BD54BCFD6D0F815D595D5F25A1E4CEBE68AE6632ABEE80A6484453A061BB3B77EF6A58F6F8E860229D397CEC6A6DF6787A74D2705C5DE2AEC724240478AE64964BF354A8C5623EA24A1431B5B3579579F68E516AB85A4203D7B3AA6EB8474F4C64A446A3B04A99EB498C0DDC3FCDEB8D704AB1EB343A189735A28650EB89277AF5D147B655672B9EE32A2840D672AB8B9A1E5A5E9AE76A4CD3C8CE3DFB627AC874F1631F896732F2D20A2B94DC6D3BC3962DEEBD37B234672291BA707C93C4B53748D4F3F2EBF94C4F2AB756EECF26CA3543D5C3E0996A241109699B9CDFA603502D976CCA23BA2E04B31C57D7749988E5C5391B42BDA958341E371A46B6A7A752C829A18861D8FD7D3DB55A0D8408E92A13C4A8D7C3F14479655E84D3B2702555BB70FAC4D48E5D28297DA9D4EAF19C1251CA170B7A4FD4A9DA00A884154543C6D12A9AD19EB040E2D61C25AE0BD7B16B34361CB7D6EAAEC343291D18A336535311B7D4484C6549CA24E1AC55C92B9AAE87238D6A399ECA7A96194B464F1D773D4FB81C6A25AA46884650D7716199DE7D07132A1B1DE8E922F24D8EFBD7C5027580FF1AD79C31404248FBE47DEB7CC9F54EDB4370349E714E24A9F9A67A4EF90FE4950F282191900BD8F255DF1E15CD43C2D03C4A131422444832E93E70F3E6C7BD10DCF3A822CB8EE7E99AC618238450CF434992256923507DF452EA358555941B9C1CDCE22DF59C312E4022C80125825BCE34EE32204452DA0539E58209A212E63022A12084A0808E19C61C2A00654D125C00B6E7256754A0B465435BF25484A0108C3190E5AEABF3234A3FD4FB906F4865B8CEE123471B95C2CC85F35A2C3D77E1BC1A4F3CFDCD2FC5B2C3896878435C8B6276763E160D9D3975B2E178079F7EAE6F64C8308C5AB958A83408732A35A3522E795C542B95582C76E885C3F158A458AEA0E09CBA15C3593A73F4FC4255F22A654F97BD7AB1667A56AD61D37261CDB19D42B91A0F452E7DF18C07925BB118E356DE702D563A9B5F3D9A8B0C842E3D795575CDC54B2EB1ADDA9A05088DD57A281D9AF9EB93E575478FCAE54B25AFE6340A3641CE3D9CBB7CD2E432214A616D8510925BCB510685B55C281A29AFB1ABF3AEED8163B19A2166679C4A8597AB8C60FDF485D9E1C1DE2E22DFE47C0E804826E2A7CF5FFCE0FD5347AFAE65B96B3BCEED77DDB378E5CA687F66D3A2F4DDE70F7DF8271EA6A0EE989A3CF4D4F32F1D7CBE6A9A8A079A24C23D19C9B52EAEDB7B768C378A85E4FB1E5E595CAF540BE3D3134679FDD0ABE735AC47D5F8E9F9B389FBB7B9990CF2A5637305E2D40D6A6952DAA9AF82A47FF4673E2E49922EB9A5B2563F743114516C4B800D4A440A65A2E981506DD9BCF0D46CF42323859A5C38BD2A1C1A1A4A094E261E18BAF2A5D375431ADFA6E569829C5C08F76556D0DC85974F15C70BE79E57357DA98EDBC70725CA47C7475FF856399CC5D357145A716B4CA855A1C6C8DDF7A84F1CD247C2AB00B77511F926B7F796699E3B7DEEAE3BF71E3E3977FBEE71A2847A7AD3675E7DA56774AA279DD89479D7AEEDD148249F5B9CCBE527C6C6E251950A32323C3E3A9435CDDA7A9DA7A2DAD8C458A3618C4D4C374A0B3D8343C552E3F6BBEE762C339B4AEFDCB57D647CC2B1ACBEA1E1FCDC59A66764E6F40C8DADCECE0C0E0FA9F1EC8EB1B19563AB24A25EF8FC7139A2AD9F5EAB2ED5040759A1854B9599AFCEC8114D8E28A5737929A25BCBF9B5334539AAAD1E9EBBF8ED2524401B5661A620C5236B87672383691EAB64A7F75D3E7924964C0F8C4D51B332B56B8FCC59B237F9CA11970B912FF3932F376C010A9090065FFA46FDA107C1A195C9F1B12E22BB71ED4DC5B5F9B55525144BC6A33719D73AB62DAB218980E07C71716168745CFA814792C2AB5B2216566FBE04770D8F4434B91BD7BEB570BF61BC5FEBAE84EB67E8B81BE1669EC9B8FEF478CD073EA0156E5FF76E859B3E65F483BA7CA19B6E3EFDD8F6ADA8EBCC5C98599E9F7DE9F0CB0C70E1CA85F95CF1E4D1435717735B9E5300C12E9E3F7BEEE2A593C7CE5C0B0EFF1B4444B1B4B8B6298359CA5D9ACBB946AD62B81BF2079FB9C7560ECE15E76A9D5F1AB9C6E2730BAEE1CC7F77BE7A7EB5B0EC7A0D27288B88B8FCDDD9A557D610D1AE38D466AD730A6BF397F206BD490437EA0C11C12D9FBFB2D805FD9B3FAE9514C573EC533367B8537F9EA969D5324AA5E51CEDB7CE4E8EF46F4434FBCDFFE377FFE56FFC9AE9F00307B6FDE1EFFCDE7AB5A8C858989FABB9B86BB2B758B5EB0EEBE94914F38D8FFD0F8F3DF9F56F4C4C8F3848463209DB73560D615E3C59557A6F1B8B28C3F784ABE74EAF793BFA94E58A5B5A594D262385B2F13F7EE21FAFBFB29295C9CB8F5FD693B29333E49E84E250D0A4F4EE64F16A2D190D9FF8C2DCE41D89E54B8DF464AC78AEFCD0FF797FEEE5E5D4BD1327FFE215AB21B259797915B7BD3D4DA9B22856C76B85A3CAC4F9835FDDB76FFFB9D9A54C265BCDAD7EE8671E7BEEEFAD53734E7632BCA31F174A7CEEA8B96D6FC872E9F8FE28D64EEC9A1AE922F24D6EEF1189A2280FBCE35D3625DBB78FF70D0D1915CAEAEB8C299B9C0000E953BFF68B2AB25AADBCB0BAB27BDF3D763977E2E409399CDA3D185F6B580AD2F9957C6FFF702621AD571B0343FDA6D9E8ED49F78F4E3C77F85CF5C2A1F1DB0E789EDD7C5BB3AAAA4458DF79F154A1B404929E5F5DD6231121446A675FB2570B8FA4EDB213E90F594BF972C19580612894CDC0DC2B55CFB0A9497BEF9AA0C54666545DBD580FF5C5922311E002085134187EC7E4B9BF3B6DD76C000845C3F3B35706FBB217AF5C5C5C2BF70DF44F4FEF88685ADD828F7C20968A495FFA5A7D76D19DD816B20C3E36AA2E2D7952F74AF6B7887FEF79D4B5EA448FABC2592BD57BFB7A5DA3A644120AD9DAFDB51A35C3E5515D17C06CC755554D26B0307BB1EC2ADB467AD550A4D130FA7A7B6AE582164D346A8D4C26E5BA2EE3A0494210B55E298763F195D919BD675C1706C8A163475EBCEDC05D5C405F3A9D3BB5268594C66C29D41F6BACD65191F5A822EB926B31AB6C2707C31C25A7682A8990F0DCC6BA9DDE9E36162B8D8A971A8DA3E076C3D35361DAB0A2C369162A626A8C34D6B8A4279269B3B2AE46D382BAE1A87EE694EB389C011A652A858946201C210B8BF49EDBEDB2EBEE98E8BE1CF7CD8EFBD77B53C0F7F008CB2D1726BE165BD38D6BDF0A7ECEEBB8F6B1337FAD567F9D4D08DBA8556A26B50DC3A6372FA15DB4CCBCE9F38CA66DD529355D2E3A1DB0EBB29235D3DD4AA06B323261181C00A855B7297441FFA30B2F7F5CFB568E653CFDF4D3F397670E3EFF9D48CFE8A5932F9D5BAE3CF7F57F58AB58DBA6C637C1379F2FC8C89E7DEAA9B2ED3EF3A5AF0F4F4F16F2F94A616DB5549785BB9E2FAF2E2F487A7469F64AA6A7E7BFFFF9E707C786D6D6F3B2E08E6B966AF6EACCF14BCB356ED75C39EED5F385AAB5B67495495A6E79C9361B0B2BF94C247EFC8F0ED250C85CA9A0A254AF14AACB8695B7965F5CD67BD4539F3BAD5267659E4A9E93BF5856627AE1E46A742471F4779FAB949916C6A517978DD54679BEC65D17507BF5951722B1982BE4E5D98B5490B9AB1789AACF5EBE144FA78A2BF4D5531665B8B260BB48CE1C353C814BCB5E3C09075F7C696A72BC8BC837399FA38522936313AE59595B5DAA562A1494E1DED405DB725CEF5A8BFF677FFA97BFFAA9FF299EEAD93E3576F1D5332F3CF3AD9261AA5C89CADE4C3A09B67376A1B473DB9546CD1CDFB143D743CF3DF9447A7088F6F57EE7E0514934B2E1E499E5DA3BF7F603EB499B170F5E2EA5246BF58517541106B75CAA7BDB7EFD7F0F65A31A37172E38CE335725815C57658FC486743D19962570EA74E6EB67B477F636B464FEAF8E981591BD6B842844892A57BF76C1F294A101ACA7476A07E7E464C549CB7269F6D963BC7CF9C8F0C8C0F1CB6BBBB6E7E212D9B177C7B7BE581D9A92BFBD24A068CFD7EA8384E831273B404ECEEB9351B70BC7B7445C5BAD545499ACE68B837D3D2BB97C22992897CA915874A0AF6FA3978388C0A9975BCB1135C46C8F73BB6139D1705497C4A52B33265347464686067BCB8542B67F686D694E51350E647068F0E2C5CB2A78996C6FA56E11E18553FDE5F9B3969626CCD542F2B1C347B7EFDED3D3D73F98C92E1E5CD0535AFE62450E494099677A20A9A1B8A46522E67285C892E30819859C8EB16A1D00B4BE84BD5CC1B0CA1D4F7021A3907A52F52B6BFD770C37D4A54876AC5629477499097429EFEFEF33ABF5BEC1EC779E34151DAA16E496DD48828425A228D030C5D4B4C548E9EE037BBA88ECC6B5379599524F002AF24D2E5C82314E88D4ACCC755D595608C1F6F9FBD6A9780C22D14DDEF9A66FC4E60F4810805FEF1C32A5CD8BE15A7BBD81BB49B84094BB5CE65BC1DE0B211080722E4B52F37D279452422469C3F0B70FE073EEDFEB2E49D28DC3E04D9384332600090A0EE47AE7EF05130040E40DE7EF9BDF70CA114100220AC0F6F3249C722184A4489B8F51707EBD83FED7B6CB394812DE7C916E7A63FBF78C7AF3F30B8253D3300647A78C4ADE91345A2B36A87CF7EDB775727F88D86834C2BA76F5EA15351A9F3971FA6DEF7C88B92E30D7E22415562D8F7BB6194B678D6A25DBD373E6C4A9A91DD3B586918AC764092D0AA5D9736511EF89028F0CA435D7E692700D2D92B68DB2A6E9A6CB7A13C9D543F391E91E70DC505FDCAB590289B5DA300B56FF3D7DF973C56492D4683812E694416C24EE148CD84862F98539391D4D8DC7ADBC41148951114A6972485F5FBD48627DA944CCAC95439158B55C8CA7B395423ED3D7474D5C5EA7A9940C8CAB1139BFE8A821890A18EA352E2E55F7EEE8C6B56F76DC2362617D9D536775EE9C1D1A8CBB355BCDE84E4D4B6FDB940F40FCF97FF9DC273FF9B3C58A71F7F66DDFFEDA53C75E7EA96E59E05099886836058E7D65AD31DC9FF16CE7910FBCEFFCF9B97C293F343A5C5B5FBA389F4734B1E19E5D313EFCD076CB4B70BA7276A511E2D59269A952C233D62B35FB1F7DE29F94CEAE3314548DD65F3C23235259513850870D3E30505F2843593AF6D4E5FB3E3ABC5EC0FCA955AB68EFFBA53BF327D7061F4ECE3F39532DE1F08452E6715DAC49D1E8025FDFDE5B3B5F9D5C38F674B6277B65AD31D49B8DE9FAE0F0E0B34F544944342455B1BC758BAB75A1C5A4DBF6294F5C56D3E4227471FFA34A3F36879248724F6FEFC8609FA30F8E45CDF35797B9E72D37BC7D5BDDA5F1CF7EF193B158C4352B2F1F3F3DB16D9A53A75AAF69A1685F32C63CBB503189E0C323435CD0BA4523BA2DA1B83AB730B263AF69185EDD98DA39B56FF7C4FC625E96B0905BAED72B2BEB15490D95D7970892CCF0A82A4166DFC0F03D83E5D3CB7A36CC1169CD725D4C4F84AD1AF5EA36EADAE47DBDA579233E9656085322B259F6F4849A9F290A558D26D128598989546DB122A912208D0F0E9F3EFC8C1A8E78A812C186C7C73865B6E7281AD9B55D4F27C8D20A5534D2DBAF8E0D4AC78FD9A3E3B22BBACEFD5B38AE7DBD9BB597CF9DC6487A6A6C68CB46AED92BE295623194E8D164E08C1E3D7264CF813BA3218D51963BBE462D2AA94470818880FE5150C105914833140144C179D3C5E78C1389B4C20901009C0321F1A178244BF34E682015BA56A0B367ED52994AA4F94C2D0800210001FB53E5D850A627AE7711F9E68F6BAF07EB1FF07599D7B956E1877D9C616313F07A9F0AB8F6EBCEF3FDD7E47C8D7719769F67B955FC1C10BC542A99F5F2D1E3A711F1CAA59962B972FCD56397AECC5DFB3EC3A71FAF1C3B6E142B6CE98A5DA9D0170F19F3F31E00D40BDE2B27CC42DE5B59A707BF5D5B5AA167CED94CC0EC052B5FA4730BEED38FD736913B8EE3388EDBF9C6CFE667CF756C77F3CE11B50DCA0100AE5E9E07806AB9787976BEF56BADB46E7310DC2B1773C74F9C58585878E9F0CB6B8532005CBD3A8B88AEEBCD5FBEEA07295B1DCD989BBDBAA9A7D709856065D96D9DEFAF566AD7E444442895361FFA9FBDE4AEAEAD3046A17BF3E62D12D7BAAE7BFEEC999595DC9D3B079E3D78ECC074E6D8CCC203DBB287CE17379D530080B575BA7D5FF8CA79E31B5FAEFDEABF194A47C457BE5A21040E4C49E5B03673B27AFFC3C9037786FFD35F9492023209F80F7F9CFFF82F64E69699B7E83A404FBE7C249948CEAF1663219520B8F5EA6ADDBD77CFD8D9D9B5773FFCDE67BFFCF72587F5F6F6A7638AD053B5C54B4BA5EA43EF7AC7A553A742AAB6664993A3E9179F7CE6EE873FD01B9672AB2BA78FBF3A3831CD8DC6D440F462AEF6ADAF3F7EC78EC1F8D0F481E1E163678FDF97BDD7AC955E38F8D2E4E4C4A9E3AF9E3E7A32D29FBAEBCE7BE617979D4AA15037FA0687E2324F4FDC361AAE9F5BA855D78ED8E8122D4DEBEB1E0525128A8553FD3D937FF5170525A37CFC4391AF3D614C4EAB9E0D07BF5DCB4E85DE7D7FE4D9C7BFB1F79EBB97E7E68816E6CCA9561AF7DEFF403C4A3EFBEF9D03B7EB2421EB1C1A4577B126B2BA3438B45298D2F78EA5BB58BF25ECBDAAE9D94CF67DEF79C7B3CFBFBC6BEF9ECBB32B77EE9C3874E8D8430FDEDEB939145C700C8B3356D5424D16B30BCEF1F3DE83F745F60E60E4B644246762527BF289EA3FFC4DE99FFF525668F8ECB38D6C1273794A08100402444272FEE2A50B572E54F2B9DC7AA952F78655FADDD357778DF7D61BA61AEE8987E24EAD11D2F4AB7373B627EF181A5C59CC194E7D76753D99ED1F1CE8D9B9F72EBBB4AC459331C99DB8E35DF3972F24E299DEA97D8F7FFE2FEFBD73577C7467D2593B7EA510D2B5FCEA9229D4BE64040092A99E6CEFC0071EBCEDF16F3ED9F0B8A4C413E1A459AEAEACE56CD3B22B15590D2DCDCFC5A2D18B57AE9C3F77BEB05EDEB173CFCE9D93024422A9C4089E386DCDCE58893ED5AEB8452AD70B2E00C4D3FD6130E7162E57A86CD48DB0EC191E86C3C9ED7B425695EFDDA35DBA60956A6252E7B379CAA966D41A5DA0DF42FE7DA3DEA076A3608AC118B9BA528CC6538A0A43FD03D73AA97FFDB9623C2E0D4FE911495026CE5EF606B264A5C8A7FBA55C5DA4C2A0C6E4CBA7ACF480128B4993536A61C9A512360CBE74D17DF4E3F1F5A539CF6336C3E9C17495AAC23654198C46E9F0F18B8F3EF658A354648C1144C19DA2E16663514522A828B3B3B3432323F9DC8AA48512D1B8A260241C5335E5CCF15787B7DDA6008B27E2B3737313A30373F3B952B978DBBE03E572BEAFA70F00D672B9BEFEFE523E975BAF6E9B1A28D65CD3A845A3094EA9AA4886518FA47AD331F5F0CB2732E984A24AA607D9A856B7D8F8E8C0E2D27A323978E1AC456494049F5BA17BF785CC3A2FAD3B5CB7F66CE70AF242C504E0C5F5D5862B0DF624FB4746754579F53073804C4D28E72ED8BD1925240345A95CBA70E703BB5211B5EBE1BFC1F81CCF13950A1300820981000224A9C99D20E7FE23DE004D864408019C03124001808008A9A4ACA85B5DD9E7D80C88AEA93FD82EB44E4DDF4CB8CC19235BED3D1B06ABD779B33421C898400444541548A6DAAEA9659A5A28DCDCE4E51C4A25CAB9BF01CC8303D3BA0E89B82CA07BC8F90DC5E7741CBEFFDE39899BB9A001006E70A9C196571E5C875A796D49361DA578BD356C8A82373D9FD04D37937E6CE7EF05A357AFCE1A95FCC1C3AF4E4C4FCF5F9A9134F5C5E79E5BCAD7C646063B790A44FCCC1FE6F6DF175BBB6C7DED7973E7A4BABEE67DF745A35174BF73D44293CE2E79DF7EAA9E1AD67257ADC525FAE22B5688B3A79F6F2C2FD181018573170028F53C8F09CE19638C5200705C1700ACF5B953F3467F26CA285D5A5CD635950BB06BA5E75F7EB5BF272B9A2699104AE9779E7F5657439148C4759C86615D9EB994C96628A500502FE6968BF5783442A9CB9960947240CF719010CED07604A5020018139E2B66CE3AC91E597090089A66A358A8A8AA8A205CD7658C0BC1092117CF39B124711D2111705C81041EFF726D6C4A3E71FCF8D0D020C286F771BEE6DB39BBE916E2739810EBB955D3B4B252EDF0B119515A5292D95D5383EB2C75AD814C6695BFFC9375CF867BDE1DF98B3F2FBEEB7DF150088F1DB76B150665293D15BE77AF72F0A8358EDED85DF1679E6F7CF4C3BDC74E5A1C8944C873CF7C5389F5EA4E75C58E81B1206931E4CE687FEF859C95D0684438B30DADB23A532C558D6AF5AEDB779C9B2FDD7FC7DE5444FFD6E34F52220DA6120FBEEB81AF7EE5EB855A91386C61253B77E63C24523DBA7CE6F24C3C148AC5634303C3BC78F50C0DAF1C7F82A8E192E18E4D6F5F3A7BFABD8F7DF0F22BCACCACE585957494346C56BAE2F60CA84BCBB617567FE25D916AB9F8F2A16375A3D2373AA6798D959A989E9A387060DF91838D0B17E5AB17BD5FF8D9C8DF7CCB0C6795996F57B54139EA5401BA8EFA1B19F7B2AC0C8F8C8664FEC2D1530FDDD953894AC958E4CCE5CA7DF7EFF5B7790263C698B872C5715D2E50120C16E6DDD3A7AC4B330E786C25CF240556AAC6098BA606424E2F3CFD447575C5FBEA174B97E6BC740DD8FD9158346A234A8AB277E7FEE5B315A125B86BEAA1D0ED77EFCF9D7B1E48F8BE03F797AE1E61C9647F4F8A28BA2631251CDDBE3D56AF35A8A40E0F0F212AE9744A8F47A3911027A2582C6F9F9852B905AE94409385A765A424D5BF7AF97838D5C319D33949C423FA8EDD614D5E2BB39E2459E1E4E5EFD61D0D86136AB9E8AD5760609CBFF4D2E57DB78D4763BAED4A44964BB98214EA6F829AA1B8BAE8F524E1FFFD6C31D3AF8B2A3318E466EDF141D685EC1BDEBFE79C83E0AC7910570021843126CBF2B5FEEEC1EFD4F6DF172554C82A7A8E681A3C82C038481208018C81AA210AA04C7001128265F2B53CDBB65D03E10112E09CC83270CE014008420820724601904892E0BCD968F37759561081514F209108218450CFE50209418B434A0B000020004944415424B0BA98EB1F1E00CE91E0A58B97B6EFDC25A86D385C53242249CDBBBD2559169C13829E8742342514CD2015011817AA226CD78D45439EE701A259292CE46BBBB64F83E0B2ACD836674C2832DA8E50D5D6497D6EDBF5743A2536BED2BD9BDEA871ED8DEF096C6DC1C36B9E2CB8897B02BFB7578B6E11985E270EBEA94BFF36FED659E4FAF1A9AFA2EE9D0B3F90F463DBB7628CE6F3F95AA5BCB0B02800CB85B552A5B1BCB45037AC4DF704B69E74CAAFAFFDFFED7D57B024D779DE499DA67BF2CC4D7373DA7C171B11184091104552A2449196ECA264ABCA2FAEF2839FFDE00757B9CA6FAAB21CAA6C9565C92E5A92254A0205308824B84B00DC4558009BE3BD7BE3E4D8D3B9FB043FCCDD8BBB01C082024070D1DFC3EEDC99EED3A77BBE3EF3FD7FFFA1DE6A552BF577FCE221845098A67DAF27D4B35A1D8B85BE17B207B399F1FE5AD7EDFABB470AADB0B7D26321EDAE76FD46DFEE511EBEDDB4104268AE76CD2D0B42487D3A4852197C6477DB76C8DF8D9DBB3E0B030E2104CCABB7CD77B54FE17DBBC6F825D4F70080CDB5F576A36C5BDDCDEA618C98E5FA9DAD9B473EFDA5A4AEDD4D11FE3FFFF85BFFEC9B5F5F5FDB5CD8BFF0AD3FFDD6A7BFFC458C44AF56B523383D9635ED20A0C2486A56DF7FFAB34FFEE0EFBFB7F7E04220403199E082B77C615E7BA301F24B5386281ECC465BAB3D3699939A7664B5DA465233FBDE173EF7F9DBCF5ECD3D3EE5363D3945A2B68F73066F39BE1DCDFDFAD4CA0BEBF34BC695D7BCE9837ABB16A4278CFE9A75E8F7F62FFFCD15E3D044E75ACD6E8699BCD4E9A3C9231946C9EDCE95917CB6664CAC5D3C33373FB7516D1A46D2EE744E3EFDD4E597825B95283BA64C0FA19AC9B72E7BC31332C060640AB46B17873FF79998918FF87A8F319165E9B163273CD72B14B2A1E7B45BBD279E7CFAFA858BF74FF289A78E8128B01CDBF583A1D1C99B97CE7DFF873FD82CB7885DBFB6BEDE6B6CFEE467E7A84056B7D2306D4CD0AD1B57290D644DFFABEFBC70F1856F9354616B73BDD7ED385E1878CEC6C6F25F7FE7476F5D7C6DABD679F3D5339BD51A0320335FCC8F4821941B171B911FD45F5DADDDB2311652CE181E235B57ECCE8DBAD770482EDBBD5A8391D3DCF4B46272EC70C1BCDDB51A1E701CAD5438FF27E7DAAB5D9F8124F2CE5DB8E6F5DB67CEBC78EA95F39110184AAA84976F84FB6749DF12FFEBCFBA2FBFE6D0086DAD850A116F5CC79288EB297C32F4BDEFFB816372256D10DEEDBBD97C76F5C6F5A9C5FD0A79F03326B3DDB4429E543500A2BEE3E99A2E1370EDD29B0D5F3EBC38AEA7B2BD6E6F6666BA51D9D0D205B36B8E8F8FF6FB16E72221230AE57EBB91CC15D72E9F53C6F625585728A9D33FF8FB279FFE0217706E6262F5D4AA9452DB97AAC664C65CED0159D2D3B29C24A1CFAD8A5D9849528183862D170DE1F9E69633727CAC77BDDEEFD0C27C1A72E19941622415B6FBD93DA3345941C3FB41779D132D5F1C361B1B46BEC4032F934FBD78CA0B7C1E08D8A986520AEB182653E8E672F46B9F739B8173F2F0DE98918F38EFE33A813FB7CD1DE39758E7FCDC750283207CBF878802CFF5424E033F7A1FFEEFD00E436BFB58228C229FB390DE6D70BFA387D60DE83B9BA6772108380080051E8BBD931FA5CCFE05D6093C7DFA74736BF3F5D77FA6E5C62FBCF9AAC7C04F9E7BB6EBD2A9C9D23DFE1C0801F59D9F9EFA49D3765FFADE3FCCECDB6BF64CCFEAB6ED5041BCD3B3CD4E5D4D66EA5B1BA974E66FFEF26FA6E6669BCDA6823104D4F67973E5E27AC30D5D9312837BA617D046655D31329D665D70D6361D1DCB97FFE41CD71361AB2FA7757BAB67373CAFE5965F2E2B39E9DAB3D7A530687720F4FCEE7A5F2B1AE6ADA65AD02FFCD757FA5DAAE5E4FA1B55BBEE5A555B308615F5E29B67E4640641D26D542924ADEAA69C30365657B56432B0C5C56B3EC1A05609659D5CBFE00A842A553A54642F9E3D3F3D19D7437ED4FD398AA64F8E4FF6CA376FDEAE1C7E8A1AAADC2CDF06853916F5EE5BB4C53FFFFD7FF55FFEDB1F668BA5C70E1FBAF9C6A5533FFCBE1B46911DC830328A39108597D65A6343190495DFFFE62421891F3DFFECF0D44CBB0AAFDC5A67C293DDE87A33F8ADA7E6AA41BA18ACBCBC62CE64F8777F724AC549E6362BF5EEBFFD77FF5E5011961B755BB9FAEC8B1222289F947C2A65142DA7719F454EF4C61FBF7EF2B7C75B8E5C7EF98CD5649FFF0F45EA45449797BF7DC90D958949D44205AF5E09A3A69DE77CEBD2D96074F995EFEE5D9C3E7BB53C313A3A964D4FCF4FFDF9FFE9A686E0B96BD20861FFE76FCD0247B2E12EEC2567AE903DD97E4CC7477FBD0700846110093C353E8488222BB2A46589D7C88FCE0E177377AB1CF8F56F7C95205EAF95DBB6974B65340D475C4C4E4CCF94869CD0A742298D8F7FFA534F1210EAD921A757CE0F8D00440E1D39B659AEE615B274FC58369713401447C7835E15AA9AD9F726A64B66A339393B7BE8F81313857CE0D0DC62B675B16E8CA5240D47A6CB8992CC130649D8EC4711D48A09EAD1C4780ED1402FC8019768D765020A2610E62C88B4F17CEDB5F5C28111AAD9F9F1D9F5955B0B73934036F285FC934F9C405C1486F35BEBBC34257301AF5CF287C6C8508EE473A8DA648B8B00626762BC143332B66B1F6A63ABD7A150CAA6930F7958CF71E48431E861D8A8D732F9A24CB0E0C2EB7A2CE45842DB0F86210062BB8E1A24080C1ED3020076EA29508E087AFB512B0080714890A44900FA014A18CA0302EB4D93793EC71020BC1DBF30B07535D9E784A4F4B89EC22789F70F5340E1BD1C35DBB52DB7AB7AFCA3FB197E1837F63B1F288E41F824F1BEDBEDAA125A5E2B1F38B09F7A9615887EBB961D1ECFA6F47B2841292518D7AB5B1194DAD5C6D291438C312004170063C805109C612271C624496A37DB995C86314E08860030CEDB9BCB1D961C4B320B174A39997200388798084621425C0809E1E6852ACA18E9D10496B1A01C12D4BED40C7D367A72A47EBE914C2317E80939C2A98462489C32A290C61BE590A3D2B191D00A204110214420C2D86E6FF561662CAF531A2144188D3091288D2449161C8491C0040221108296C91C871786651434B66C323B16677F3FEA762D8D828B6F9DF7BA4D2FF2029470B72ED443993ABE2A5FFFFAD77FEB1EDFDFDF3FFBFC33CF7CF6C6CAC691E3879FFDD65FBA91EFBA2EF0DD80A3D258CE71FCAD5A6B7661A157AF3DF3C55F7DF6DBCF1F3EBE8F636928A5754CDB8D286D5437FAE0C8BE316538BD76FDE66A9712AFC1B46C68D912A2CD9EFF8DDFFCADE61BB591A727575E686209D19E130162A414BBEA24277573BD8BD2E8DA9BE57D9FCED75EAEA6C612E672FBE0BF3C5A395B9EF8F29EDBDFBFD12BFBF911B9EB4A99025072999BBD5B07A60BD79DF18D0BA747C627AE2FAFCDCC2F3ACDC6935FF8CC1B3FF6D71A516A44C55E14AAB8BF1A9466D56BD7DD6C296D964FCF8EFD5ACCC8479CF792AC4E4D4D761470E9E66D5D12A9D278D0C71259538A73F7FF36CCCCCDCA8A8A01DBAAD6F71C386CB76BD5AE99D573431A6DB6DB5EDF361DC6A9EFFABE13D0919174BBD94C6432C9E9C9532FBFA5417B6E660158DD4EBD9A4CCE4ADD76A3E1C3C0E692C51C4E802FE41440D028A5140D4581086D1B843C0AA39E49B393AA94D2829615243204736BC34C2D4CF8D757008481CB3111F5AB6DE08644C3804685C3339D3397529206A15054F5FCD9332AF7EB8DBA1D300880914C4B1875DAFC5327B46B75B8B1CCA8C6C6D372E830A8888EC549AC703E093A0700C018139C33CE31C60841CE01E714130923748F3F0742008408A36850924F00C105471041206E5CBEC0D5ECE2DC944430638C48120D038810E74056E4300800008460CE05E71C63DCA995496A282143C6E82B3FFBD9A1632732A9240168EBD532E022F229C248703190DA084380200F19C4080020B8800401C6850048C63C646057303194080FA2CC6C5EC9BB7D90C9EB18420421648C4B92C419936472EE75CFB2991080520111440020048208CC8C99DA9031399C8919F9E8F37E37B9C1C3D5097C78CBEF9EE48C0FB8F6E0FBB36B77CCD6F77822FBB6557E6F70FFC31ABE6F6F2004D8CE5978981CF9BB06FE2498D7BFC03A81C275DD28F0CB952A8090D3D0717D2098D9B7EFAF13D8B9DEB4AA56E86E87BFF7374DBFE77B6660574CBB6A710042D337CB36A73C347D73C3B41B1E84C0AAD89C0AB3DB6A75CDFBC71442304A7BBD0FEC6951BBDDE48CB5DA2D71E7103B47E39CF7CD3E17FC813BFA9ED76AB45CCF83BBA2FB6DCBEEF5FA104216855CC0D0319D778FE9DF392F2EC2707087410841785FBF3008611409C6C4DDB9E9A056A551E4FB7EF049F029FDC2F47D1485972F5D92A9BF52A91D79F2734167BD15E85962F77CF1E9279FB867E3F553AB43C74671D365960F38B33DE455FB58C241B923673475612CDCACA5F78FD346B76F09ECBBBC38E4563B8D2BFD03DFD8F7FDE79FFBEC177FE3C29BE7B2F9FCADE555D5488DE452B54EFF53278FDEB878FEFCB5D59189F1A5F9B172A3CB18ED59EEF06809848E8042D632B39363B7966F094A93D95C6D63BD383E0E01AA6E6D14C6A69AE58DA1626E63A3B6B877DAB4FC280CAF2EDFFCED2F7DF9D5D33F490E4F8F14126DD3D365D4E97567F71F4FCBD1737FFDBDC2E4F0C9279EBC75E3FA81A523AB572F344CBB303C9C52954EBB5B2B3726A6C7221A8C4FCFDEBA7E7D6266CE33CD6EBB2D30322494185DE86C5C9E9C9AEE4AE9EAEAB5D9B9F95BCBB7B285D16EA3F6D8E3C7572F86D7D6C2C9052DC15988F1E6356F6641D9A884273E932A26D16B3F3B3331335DAED64B43A976D70A51A294372028DD5EF77D936A19E9E01C397BDE9F5C50CFFDD05A386ECE4CA863638FFEE3B35FD87A2FC94A52D7B7EAAD91B4DC31DD7A79EDD6ED6B2FBF7A697D6BEB011BEB4A72246DADB4BB6B8DABCF2DE36CD2C892C6CD2E4EE8E34787CD4D6BE16B072A2FACDCFEE99A6B06AD4D6F7C51BDF5C2A6D776288BBEFC1B5F7DEEDB7F97CAE9A79E7F1E67C7CB6B8DD3A74E6F2DDF0C042018A772A3A0B5F99D1FFFB453DBF018EE34832B172E9EFDD9CB51109EBB700963D4ACAD5FB855C5A1B9BAB5FCA31F9F7EFDCC8B97D7DBF5EA566DB376EEC215E2B67F70EAA5F51B175D949431171067138A91197EF3D20D60569797379385F1D7CF5E942449528C0353D96FFFC55FDC2CF75CC7EC76BD76A3BB797BEDF2F9B36F5EBE1584E1FACABA2C821F3FFFAC3671A8B2721D4250AFB6FBCDCD4ABD93CEE6FB5688FA95E5CD56B3BC76FA87CF5FD9E8542B5BD96C5E25D25BAF7813C3F8FAF5F0A767DC1F9E32DB0DFE93D3CE13C794BFFBAE0300909464BDBA7EFE95539756363142372E9C3386C77D978E8E927A836F5DF53697BD1EC517CFDA3FFE6E4F520063FC935042F61719A780319E281557EBF6E2D4D8CC9E8313A5A95F79FA53F9B4914AA5EFD9B2F2DA56E447D9C5BCDB0AE6BEBACF5B69A84563FA99592DAD20194199785B5D692473E06B7B8D615D4EC9895CC26DBA589686F60FBDF9E699F90387CD4EEFC8B163B97CB19035F62C4C4692313759F2438F093E333BB5FFC05EDB8D1616F7E4B2C9B1D1E2586994602CAB89F1D1A18E690D6713A61B11923874F4F889234BBED998DD7BB050C80CA5E4EFFCF8953FF817BF0BE534703BB99199B1E1BCA26A9962B194551ABE7272693E932F665289745AB7ECEEC4CCECD4E2411874A7E616354D192A1647860A88C8E3935307F68C71293535559A59D8FBD2F7FF5F7278CFCCD4703AA53A3E9B5A9C8F7C5B04FDC2DEE3B5E58BC95C61EFD1C7A1DB5E38B014DA5632979625323C26677224E8B385FDDACCA4FCF809F5B91FBADFF84D71E1FCF2E890E2F8CCC816D30A5BDE6C0F8F8EC0309A991BB974D52B95E4A5C7947357C2E3C712B90CFCD41732CD466774544D2653B15DFB11987DEFF111F5A3DEBA2938109C238C04E5102321C4A0418300004120008010B088430821829C712C63C1786E318F25FC7E27F090702C9342396D681FE885E1E572AD541ABBFF7D2FE09AF2005D7A7B35B06D8E21C004720E84105C008261B1800AC5B7AB209ABDAEAA27158900006C87953723CA05E74022905231A83D552CA24281408862DEFF82FD39BB7C1B1FCC3DB63BA2063ED0CBB1FDFE833B29BCFDEE2E97CB7B4EF0AE8A09EF703EF7D55800F76FF9BE2297DEC99105DEEB82C6FE9C0F93EA9C6D6D6E0611BBF6D63906616075CAF5F6B9B32FDD5AAFECBEE88375E87FFF8FC66B6FB8E5CDE0FFFE79C7B4D9CB67EC174FF56B3D060078F5ACBD518900009C8B6BE79DB33FB3D6AA746BD93DF3AA7BF97210F4EBB55E00216C34EA954A636B7D0D4278FBDA4D2F0CEF6F9CD0697576DD0C104270FE8D4B3B93A151B47C631942B871FBF64EA1BEB7CEBD0E1FDCA2E4DEC15B4DEAFB7CBB1043AF1F450F70B3B45A348AC4DBE70D616FC57DEB46AF5229330E1EC8D787F1F0DCF3E7FBDD25F6E77CA0FE1C4A976FDD4291F5B7DF79EE0F4A13AB97CEF560A15FBEF9A5FD47EF5F7BB08A5E7DC93E3A8B6B7DF49FFF63E5EBBF57B8743EDA2AF77225E5C61BCE319FFDF55F065FFDB2FEA77FD6FEF5DF2F7CEF3BFD8305565313477388DABDEBD76EFED434A7C786CE9E3EB37F69A9D56E9C7FE3C6EFCCCD5C7AF5C58D464F4054A975C6A7A7A34EC574E9ECCC089587C60A1AF72D338467FFE187CD6EB3DBED1D9C2FDD28F799D34BA48CCA466575F90655929F7FFAD39BE5AA65BEA848D42506B29BB53E9D1A2B62453B71ECB1FFFE878D7A9F7DFD9BB933FF6096A6D5AD269FCC82E52DFAAFFF4DB1BABEDA7422E1D67C94EA356AAA2266F69D3464B6766B24EA87E76B626F09279058AE447BC6A52B4D71604FC330D2A9940162FCB2AFF7B2AC4C4F4F579BBD037B6643265249830BF66B5FFCCA1BAF9DBB7FEDE976D8E404B9B141F71F50F58C74EAF95E7152AE36D8701E8F8D9157DEF02BCBEE732FFBD3334AF9862B34549A90BB6DDAEB7146298DA2B9BD07AD4E73CFFE7D88878D4615A9388C44B5D9D16434B5B07F7E661F0C7D026132939BD97FAC72E5B49619B57D3A3D35B674EC89C8E91028D61BE663071781E0CD46BDEF78444A2CCC8C3A7E0418083C8B71E07A5EBDD9D224295F18D9B7770F00D009C0E179F9AD735EB51D5DBCEC2753F8EA4A9893F96B572AC9747A7A2257EB783DB31A44209F4E375AAD52A9242720F3E8ECFEC4CA55EFF5F3C1678EA967CF79EBEB1E061CC62D9D1F197D1FF8BEA2AA81E770006559619C376BD56C7124A1DE55935E00F0EDBF68EF3B9C3034C4001421B37C904BE328E0AD3E4F27A024A3662B9A9E53039BF56C5E2C1011F1AD1AD55474601FF4038A248953EABB7D80548C388050492465483B3D2B95C9D230A251B8B5B139B730DB6EB59A1DF3C8634BA1EFB64D27A92710E04E10E5D3FA56A595CDA6753DE1BBAE0040922549566EDDB83E323AE2792122C45049DFA5B9B4E17A7E3A9DBC7AD9576428106C34A35C96600221E38D9E280D35A666261AAD2E8F4280F0F2CD9B33B333896486001EF8898D8D2095977C8BFA11182E60DBE6984400BB73B3C37137F34F903F67F09A468248EFEF5B175C0800107A7F95E981104C88BB02847EAEB3789790847BCE6E1035F45E0789CBA43D92FE9C18313E21FA3E468C98F73162C4BC8F11E3430679EDB5D7E2AB10E31367D77EED6B5F8BAF428C4FDC7A9F4824E2AB1023D6F73162C4BC8F1123E67D8C1831EF63C488791F2346CCFB183162DEC78811F33E468C98F73162C4BC8F1123E67D8C181F0E3ED27A0A9C33CE05C67857A21DE75C4088EE4F08BCB744EF20790F6D17AF197C2A8440080D52C676B6DF5DA9460801EF0CBD9349C88580BB6A05EF0CB5FBDFC1B0BBC7E49C0300204442F07B2A9DBCDBE100E09CEF4C7267E3DD871B94ECD9755000811854FC18FC09C0EE2AC770A7A5D1F60808815D032214AF65EF0D7CE8D0A18FE6484288CCD0D8FEF9A956BB4D29134208CE492235313DA501A7EF4670177B84108661044120B689001535A127D430080480B2AC643369C641219BB66C3B994C524A53A924655C2284520A000010C98A323C5470FA16174208A1696A144500917C360D899CD2558825599272F95C14FAE97416639C4AEA9481744A775D8F285A219781002AB2140661325B48269420F0B3D97C10F8AAAA2A8A4229E59C0B2190246B8A92CB656DCB1A505353B73FCDE5F2AEEB4892048018DC3C00A1A1A1211AF8C9745670A6E96A18D15432E9FB3E222495D4653521131C86112252D248E8BAC1281542E8C9A4A2289A22056194C9646559CAA4938EE34A929C4EA7C28815B229C7F5E264DC8FD77A9FC81421B50F3E76CC20DC8E0806613FE486A1F5BD866E280995241209D77614DD887C874394309218018CA54EA31A710EA034F842C33010D06034C4521E0040880484189D98319B5501A024CB7E10124C024A15028A23A3188A200893994CAFD3F57D2FA25136950A0532641A056ECFF673299D61420856355556B4BEE34D4C8C791140DC8744325449D5534632D969541182B22C13220D8D9634CC362AAD62211784514429C238218BB152298A281054D353F55A3593C9688A8C89A427643FA432917ADD76E0FBDDBE9B4BA765952094521412863C99346CDB5265C548A61A8D9691D008868AA22AAA1231A110CC04CC64D2B54A6DA89087102BAADA69358D4C56C13D239DE49496C6C7CD761D4228E2D6E71F2B7DEFBB76A5D161814501F47D0F229248E822F428038A2A0B8020A78C73DBB630C2080DBA678A66BBA769320480600C205615599215048010024130A87D0011E9342B58968388222C4B58F42C479171B7D3956439628C60E47BAEE7B9940904614429E08C32C6041CCE1BCDAE1D043EC698731E86A12CC981E759DD76843495404A1906C2B26C383816848C311ABA3DDB55140561E27B1E801002DEEB998890308A1449765C5B401CFA8E1F705596A290420829A59C512AC0502ED9316DC6A1EFB961188581E787545154CFF3224A352D01805014D5716CCE05671C622038B56C17212800773DCF756CDD30023F2404F44D0B611CFA6E22958580C7B47E4FC06F7EF39B1F99CEC1920C58A4249258508865040165348A4204611851C6B8AA2A5114428431848C6F57D58B284350080165590AC2502638625C91E5200C55590E82409295300C110294718209219852CA0772993308314670601E200CA3881A8984E707080AC601808060CC18C58850C6088641C424820440080208414419028003A0C83244C8731CDD302CCB1E7C8C202204478306440008C11122000004011780334A2449700E111E583284E08846400022499C4610114A238410630C633C5068841084B0103C8A2208212604631485A11000218C3002820F3A0871CE09C1BE17C88A0C84A08C138282208C75CEC788F73BC6DF077F0EBB2CCB87DEFCE7990CBC630E7F9827F28F1D3B26FDC74EDF7FA85FC9FB1DFCE79CCC2E97D12FE1458AF18BD0F731627CD279CF39E7EFDC5166DBDF779F4C629C833BE5F5765E8877D0549452B10DCE078D3CDF4B4330C6067B0DC678E03418633B138811F3FEA1F43DA594312E8448E58AB9944629E39CB33B108233C62865D95C7A47E70E36E09C63459F1A2D70CE352D91CBE6A328E242148A054EA31DF273CE691431CED58471E4B1C7244238176A2299CF26E5543EA74B11A58C31BA7DB8BB0EC1182D4D2F1C5B3A90D0138C51C6403E9FD9E1F79D9D5869621C4294C965E96028BAFD7E7C27C4FAFEC148E8C6679EFE7CA7BAFCFA5BD79E78FCC4FADAC6FC5ECDF183A482A1AC63E0BF75B379787194FBC1E8DCF44FBEFB5DD38D04630BFB97C6470AD72FBFA565860EEE59689F79F333C7F673AC4A12F4AD6EB9E72CEE5BAADC3ABF5EEB72CE17F72F9D3C76E4D2B9172B6D2F8A8262697AEFDC54D7EC4C968A37377B92F096129A1DF1B4AE992E5DBF75A5D9310100A5C9D99142EAEAD5AB7BE667AE5E7AE3E0E1438E151041A7F64C7FEF6F9FA34208CE3FFB852F2BC27BE9E597F72E1DCD65D68AA343916D87441B4AEB1B1B6543D77AADF2959B1B18C7D2315EEFEF33D91455912509491A02CC48A5AD565993E5F5CDB2EB474288A17CC6759D9ED9AB966B5EC8070D8B892C298A8C309125C98EF8ECF8506563B5DD6E54EBE5AEEB255479656D2BA127066B3796242DA1C9126E369B7A2A33313A64D98E6D59E5CDAD9EE56282AB95B2222B44D12CDB49EAFA60C1C704CB129124E9B5D7CE1D3BF978A3DA24186452998DB54D2600004000202BAAA2C818E35EBB717B75CDF7032E18F3ADD5F266DF0B7519321133FE97061FA91F134264240D1A060249A3C51CE5209D497BAEABEB89280C6D37CCE752A6D907806B7A7A63F59665BB000045D56482FD2000008494EB0A51F5A4EF393B529D528E000FC268B0B19ED03CD7A60CA49246AF6F65D229C7B6152D018408439FD168B8349352C146A519F99E1F860000495624827CCF4F657280857EC4F5841AFA1E9454D7EA51C6010046320501771C475135DFF31286818188181302D028D27523F01C3F8C62774CCCFB07E8FB9D85FF8145DF77C7A20DF4377C6867F9C37BF17762CE1E72AF871F39267DACEFDF83218273C605C608000804E300823B41693B1C22922438634CBC1311099120148CF14170D8C3B07670CBED18B5BBDE1F843E887B6E8C07FE6A0D3A87DE63C862421000D1202AEEEE09EC1E0A610CEEB899766F4388C418DD3DE6EE70D1DD33952432B0F4776EE3FBF78AF1EEF8E8E23107CC2816872402422E1F5C18174A666CB8981F2D15930462390C3CC60526249BCD110CC2881E79FC490543499610107A2A9BD03409A34CBE983212C9A4E185FCE0813DD94C2A9BCF5B7DA750C84A8A26119CC964648924742391482008C228020020228D8E8C1886C6009E5FD85B4C6B5E04129A9C4AA51191D3860665259FCB270D8346D1ECEC9C9E4C61C0552D81108AA208028030C964D28053941A7EE2D0AC178084264B8AA210A82753BEE71D3C7ABC902F82C81310E5F27999605D3706CE2508512A9DC9E7D2B6E32CEC5F1A4E263C0AB299342612864037F420089F7EE699C8ED038865554B25752DA12BA9FCD490DA68DB10020160A15050248921E989E387BBBDBE22A16426AFCA646A7ECE733CDD30344D45824594C5D4FF78F13E6124BFF895AFA655717B6DFDD8539F9F991CEA5A5E26A3EF999F69B45A8E6D5326743DF9E4A73FAB1356A9B70E1F3B09B134339A43441F1B2FE672C5A4A64CCCCFE4B205C7E933393744BA37B63A7B97962401978E9D50659C2B9674608FCE2DED9D1F1748CEA7F56ABD09019093D97FFA4FBEB1677EFCEAF595423E6BD9EEE2E262696434934BCFCCEF491A5AB76BEE3DB0DF8BA4FD7B6750142C1C38989051BA38A1A1A8D1EE210815553FF9F8C9C8EDFB24BD6F225F2CCD0F6754222B7B0F1D9D1EC96E566A7B0E1C6AD66BD9FCC8A1438784DD98AC47B1A200000A2F49444154D87B6C7E7AA45CAE8661840879ECF8C9CF3E75F4C25B17A7F6EE1B4B678AA5F14C3A6DA452870E1D54615469744B13638EE5CCCDCECC2DECCDE692504A9626C6E4A0BD59B710828CA167BEF4AB854CAA5ADE0C423E325A1C2FCD0C0D678BC5D1742EE585786E7CF8F1A79EBC79E562C044CCFB8F17EF2184849076A3DEEEF41867E5D5E5A6E951CFAE946B0270B3D7E70240840846DD4EC7B4EC300C1BD58A66A4EAE535281B82D35EBB6D5AFD7EDF434034CAEBF9893DB984B4556D70CA15096E6C6C345BEDD9C5832A74D62B6D16852C0C9A9D2E841041244BA4D5686C6E555CC7AE541AA5F131CBEC4F4C8C5FBF799B30BF5C6F2104CAE53A881CD9305AEDAE6BF52CDBB26CC7711C0021448810DCEB74BC30B23AB56AA3030969D7CB3E131BEB1B7DB32784585B5D49245356B7559AD98722B3526B775AAD88B28138093C6763ABCC38AB57ABD556379F4D2E5FBD8C657579E57618D189A919DBB2BB8D4AD70E300B36CA75B7DBCA0D8F9537B7004200024D55BA9DB669B9337373BD7A25912DDCBE71D50BA2BE1DA67509617CE9FC455525A6E5A298F71F37BB96730E00D4F5C478A9C48518782A0100BEEFD76A75CED96E8B73206D39E710A141A3B67B129D06A3C1DDFDC5119E2C8D95B73629DF5EF606F9473B4F58D1762C31608C278CA426936EAFC70540BB92AD841083301CB0ABD1F1EEF4AB418214E7DBB94E104200A0101C21C8391788CC4C94D6D7D7B98008EDA44D899D8CAA815EE77C1031CA07E1CD9C73082118E49309309826E71C613C38BFC1B3390821674CD153098977FB2EDCE530400809F13E5AD9C5BCFFA821841804D9EE1071F0E2DE8EF2DB3981DB8CBC27836E40E57B3A1F220419E3F70CF52ED318ECF5010B032118E708E10F6FD915DBF7464CF15F067F8E1082D208428C31DE7BE0A0D36B13555D5F5DBF273F683B2A81906C61B898D63BA699CA0DB9DD7AB5D9C1080DEE1900A09230F62FCC5AFD2E0384FA5E3A97F31D6B7DABF25E6D31EFD25D1F8A147E072FED07AB18632DF34BC37B554B1C3BFEB8D9DAB87C6D757ECFE2CD4BE7874A636A229B4F4A3DD35E5F5F0B82900B303E393D315EBA7EE9CD2008004ACFCCCFC95AC2CF655B8D97984008A167BEF455E6345F79FD4D2EE775D80C24B5BCD9A052B29494D7E3B6A4311E021FE9A3752249E3535343851C00A0DDAC878C0300171766430E12AA224BD260B3643A3D3E5E52656C18C9C0B3FC30CAE60AB7AF5EA0104308208453B37313E36308C141301965E8E4C9C70EEF9BBE70ED364228267E8C8F973F8733D669352B956A18510460108494F15AA526431E50D1E97628A50082C0F71BF55AD7B414CD48A8A4D56CADADAC747BE6403C0821DACDE6FADA5ADF727CCF69774D3D99EC76FB9C468A4CFA961D4B80181F3B7F8EE01C40284992AEEB03CB15DC2965E338CE4E54FD2ED7CAB6F4DF316A77CCD95D597F7CD078FD7EDBF7839DFC87176C0C2194EEFCDCC578D4F43D8410620C00A094763A9D7B683AF02D0E5C31F01DD2F9186300ECB21AB737C39CF177312577FCA7FF9820618CF1A143878686867E3EEAEF0E97D8E50CDD2E051586E1E9D3A763EA3F9ABC07004892C41943AAF1D489A3DD66F9D6EAD660111582330A8F9E38502B575BAD0E0000411846D1C09F4D088110067E70E489A764EABC7EFE32C118008110119C5126968E1EB876E9DA4E39354AE9E0C9802C2B10020EE0D2D26391D3BE7CE3368270E0E71E04C33CBC264208CDCCCCECDBB78F31F67E39CF190DC28886919ED4050041E0634408645EC82559912562DBD60B2FBC10F3FED1E47D424FFEEA97BED2DABAFEF22B6F6DD56D60750E9D38913312CD569F70DF775DDDD0276667F7EDDF1F445025F4851F9D8244628C1D7BF2331915BD72F66C2AA5EB89E21180A2482455592F16DD5EB7D1688F4D4EA7341DAB8665F61444CFBE7E1E421846E2777EEF77530AF9AB3FFFD3A06F5D5D5E3BF1F8534444922ADB1EEFD5D66EDEDE785F0EC7EDB4C6F7ED3212972EBE0595646B732B5BD0014E689AE259261174A3DA4F0D0FE773E952213958FD633C82BCE79C99BDAEE3781042D7E9612AFA9D96D966CDB6373796715C979B4A1805FD5E4F56925C6277640CF01C0747900B615936F5BC5EAF0BA06C28F2E6FA0A822A0062F5E67584349D02C771B47442DC9116BD6E27943017B0EF5810125982A1C37305A3D56D4A987C649E1FDBEA634E72B98CE59892828C547AA624ADD7AC6C86DBAE6DC9122824632E3EB276ED40250B21386710A21DA5CB8540DB462A1A042E0800308411A503EB76B02A73CE312683C0E38105200010603BC460B790DED139038144EF8C430851353D9D4CD41BCD41D6EEC3EB1C42C857BEF2957DFBF6FD1CFA7EE7E1F4CE1411845C88C0733BFDFED0F068E0D8FFE98FFE4855D598918FA6BE1F88E34108C25D3F0503538FD31D7ED03B77C5A02EDFF69B34BAEBAE054000C077C5B8EF3688E19DE4951D8392526AF57BFD7E0FEE922EF79B9E0FBC191863E7CE9DBB7EFDFA075834EAED93A53416F78F2CEF072B3D005052D4422E1B065ECFEC730E5269A3D7352184AAAAFABEBFE3E7D971592284309130468AA2B0C08192AE2AC4F33CCBB2D584CE233F8C188448927018463BC13903D2634C24594208B13008291B944D05406022E58B4516F9BD6E8F0B90D075DBB204009AA6067E70BF3F9473BEB9B9F9E1554AFBB0431B62FCC2782F2BCADCFCA26B36B7EA9DB18979AFBD964817241E1527C6EA5B5504F8C8D4747DAB629BED4199035951C627263DAB536B740E1C5AEAD95E2E67385BD77AD4C8258D30138C8C4F2B093D686D9244C6EA7566F72D6EAEAC962B35C61817607A6E7E7468E8DAE5B70A937B86B3A9DB972FE4C6277B9D96221306F1D646399B29A60CB002E5F1912C5113B55A3BA34BC448955796DB3DEB9EA8AF989A8F12D047CB7BF5B1E32717E6A678143A5E08A1D8BB30BD51A92F1E589A181D9E98284958586E3834541C4C4B51B57D070E4D8C0D03488E1C393C3A322C4B0441107A9E6DBBC97CA994973922B3FB0E4D0E6732F9BCEBDA85E29024110000E3607ECFBE5FF9FCE7338662BB7EA9549AD97B68AA688C8C4F1F3F7E6266629431D6EFF525553DBAB46FF9F6FAF0D8C4D281C5C25829A9914EA7173FF27DB4F191C62900217CCFAD57AB7DDB6694B98EDD34DDD952F1D2C58B3E8356B7D5EA85C3F954AFD3E9DBCE6087C0F35AAD5600E4B56B171ACD0E0DC2908A5EDF8AA2C873BA113242AB53DE58038A51DF5C53F42208BD66ABCD398710304A1BF5DAD656D90F826A656B6B6D454AE56B1B2B1BD56E6D73C50F19072CF0BD5B2BE5A5838BCB376E541A3D42BD9B6BCD9162AA675A71B843ECCFF9C0F43D630C4284101A04170CB229EE7E7C2920440823785748C220E97C60860E5AE90821C020EA619080B2935EBDD34768279E7910F00011628C0DCAEA0338F85F700E1004947184201C7896101202C4E59F627DFF415A6F84903BAF07C47A377EED96D4F72DBE10420076E5AC805D313CDBBF65186FEF7E67E9DE39FAAEF1010040DA19276644ACEF63C488791F2346CCFB183162DEC78811F33E468C98F73162C4BC8F1123E67D8C1831EF63C488791F2346CCFB183162DEC78811F33E468CF78BFF0F94738817ADED923E0000000049454E44AE426082'
config /config 41
1559781666 'timeline-plaintext' value '1'
config /config 11144
1472992109 'th1-setup' value '
#-- Pre-increment [++ varname]
proc ++ {varname} {
upvar 1 $varname i
return [uplevel 1 "set {$varname} [expr 1+$i]"]
}
#-- ternary / if-shorthand (cond/then/else may be literals, or {[expressions]} themselves)
proc ?: {cond then else} {
uplevel 1 "if {$cond} { return $then; } else { return $else; }"
}
#-- info exists shorthand
proc isset {varname} {
return [uplevel 1 "info exists {$varname}"]
}
#-- string equality shorthand
proc eq {str1 str2} {
return [expr {$str1 eq $str2}]
}
#-- while loop
proc while {condition code} {
return [uplevel 1 "for {} {$condition} {} {$code}"]
}
#-- foreach VAR "abc xyz 123" { puts "($VAR) " }
proc foreach {varname list code} {
upvar 1 $varname val
for {set i 0} {$i < [llength $list]} {++ i} {
set val [lindex $list $i]
uplevel 1 "$code"
}
}
#-- A switch statement.
#
# switch "val" {
# "cmp1" {code1}
# "cmp2" {code2}
# "cmp3" {code3}
# {{default}} {codeN}
# }
#
proc switch {compare_value val_code_pairs} {
set len [llength $val_code_pairs]
# loop over compare values + code pairs
for {set n 0} {$n < $len} {++ n} {
set cmp [lindex $val_code_pairs $n];
if {[expr $cmp eq $compare_value || $cmp eq {{default}} ]} {
return [uplevel 1 [lindex $val_code_pairs [++ n]]];
}
}
}
#-- Ordered list of project statistics (will populate global $stats() array)
proc ui::stats {} {
uplevel 1 { query {SELECT
(SELECT count(objid) FROM event WHERE type=''ci'' LIMIT 1) AS `stats_checkins`,
(SELECT count(name) FROM filename LIMIT 1) AS `stats_files`,
(SELECT count(status) FROM ticket LIMIT 1) AS `stats_tickets`,
(SELECT count(DISTINCT user) FROM event LIMIT 1) AS `stats_developers`,
(SELECT count(DISTINCT value) FROM tagxref WHERE tagid=8) AS `stats_branches`,
(SELECT count(tagname) FROM tag WHERE tagname LIKE ''sym-%'') AS `stats_tags`,
(SELECT count(tagname) FROM tag WHERE tagname REGEXP ''^sym[-a-z0-9_.]+\d+\.\d+'') AS `stats_releases`
} {} }
}
#-- Language/Content statistics (outputs colored bar graph)
proc ui::lang_stats {} {
# fetch $lang(js/...), $lang_color(js), $lang_list, $total_size
query {SELECT name, value FROM fx_stats ORDER by VALUE DESC} {
set $name $value
}
# output color bar for language proportions
#html ""
foreach name $lang_list {
set percent "[expr $lang($name)*100]%"
html "";
}
#html "
";
}
#-- print two table rows for last commit
proc ui::last_commit {} {
query {
SELECT *, CAST(julianday(''now'')-mtime AS INT) AS age, substr(comment,0,199) AS msg, substr(uuid, 0, 10) AS short_uuid
FROM event JOIN blob ON blob.rid=event.objid
WHERE type=''ci'' ORDER BY mtime DESC LIMIT 1
} {
html " | $msg |
";
html " | $user authored $age days ago
last checkin $short_uuid ⎘ |
";
}
}
#-- outputs table rows containing top-level filenames and recent checkin comments
proc ui::recent_files {dirname} {
set seen "(.gitignore)"
# search files using directory as base path
set branch "trunk"
set cutname 0
set AND_DIR ""
if {[string length $dirname]} {
set dirname "$dirname/"
set cutname [string length $dirname]
set AND_DIR " AND substr(name, 0, \$cutname+1) = \$dirname "
}
# files // vcache.rid=mlink.fid would be easier to skip deleted files, but access is prohibited(?)
query "
SELECT DISTINCT
m.fnid,
INSTR(SUBSTR(name,\$cutname+1),''/'')>0 AS is_dir,
name AS pathname,
bf.rid AS fn_rid, bf.uuid AS fn_uuid,
bm.rid AS ci_rid, bm.uuid AS ci_uuid,
SUBSTR(comment, 0, 70) AS comment,
CAST(JULIANDAY(''now'')-e.mtime AS INT) AS age
FROM
filename
LEFT JOIN mlink m ON m.fnid = filename.fnid
LEFT JOIN tagxref ON m.mid = tagxref.rid
LEFT JOIN blob bf ON bf.rid = m.fid
LEFT JOIN blob bm ON bm.rid = m.mid
LEFT JOIN event e ON e.objid = m.mid
WHERE
--tagxref.value = \$branch AND
m.fnid NOT IN (SELECT fnid FROM mlink m LEFT JOIN tagxref x ON m.mid=x.rid WHERE fid=0 AND x.value=\$branch)
$AND_DIR
GROUP BY
name
ORDER BY
is_dir DESC, name ASC, e.mtime DESC
" {
# separate directories and files
set name [string range $pathname $cutname 2048]
set dir [string first "/" $name]
if {$dir>0} { set name [string range $name 0 [expr $dir-1]] }
# skip seen files
if [str::contains "($name)" $seen] { continue } else { set seen "($name),$seen" }
# output table entries
html " | ";
if {$dir>0} {
# if there is an equivalent wiki page for a directory, then we mix filebox + wiki
set display "wiki"
#set display [?: [sql::page_exists "$dirname$name"] "wiki" "tree"]
html "๐ [htmlize $name]";
} else {
html "๐ [htmlize $name]";
}
html " | [htmlize $comment]โนโบ | [htmlize $age] days ago |
\n";
}
}
#-- social media share links
proc ui::social_links {baseurl} {
html "
g+ ·
fb ·
tw ·
rd ·
in ·
su ·
dl
";
}
# Outputs a textual /changelog
proc webpage_changelog {} {
html " \n\n";
set version "trunk"
puts "$version (unreleased)\n";
query {
SELECT event.mtime, tag.tagname, MAX(tag.tagid), DATE(event.mtime) AS d,
REPLACE(TRIM(REPLACE(event.comment, char(10,10), char(10)), char(8,10,13,32)), char(10), char(10,32,32,32)) AS comment
FROM event
LEFT JOIN tagxref ON event.objid=tagxref.rid
LEFT JOIN tag ON tagxref.tagid=tag.tagid
WHERE type=''ci''
GROUP BY objid
ORDER BY event.mtime DESC
LIMIT 750
} {
if {[regexp {^sym-.*\d+\.\d+} $tagname]} {
for {} {[string length $tagname] >= 3 && [regexp {^\d+\.} $tagname] == 0} {} {
set tagname [string range $tagname 1 100]
}
puts "\n$tagname ($d)\n";
}
puts " * $comment\n";
}
puts "\n\n";
}
# Alternative to /raw trunk file access without ?name=uuid,
# Doesn''t work with CONTENT() yet.
proc webpage_cat {} {
set name [getParameter name ""]
if {![string length $name]} { puts "No filename given."; break; }
query {
SELECT uuid
FROM blob LEFT JOIN mlink ON blob.rid=mlink.fid
LEFT JOIN filename ON mlink.fnid=filename.fnid
WHERE name = $name
ORDER BY rid DESC LIMIT 1
} { html [artifact "$uuid"]; }
}
# Generate a text/uri-list for available files
proc webpage_uri-list {} {
query {
SELECT filename.name, uuid
FROM blob LEFT JOIN mlink ON blob.rid=mlink.fid LEFT JOIN filename ON mlink.fnid=filename.fnid
GROUP BY filename.name ORDER BY rid DESC
} { puts "$name?name=$uuid\n" }
}
# Invokes web request page procs
proc webpage_hook {} {
#if {! [anycap ro]} { break }
catch { "webpage_$::web_name"; return -code 2 found; } rc
if {"$rc" eq "found"} { break continue }
}
#-- Whitelist for SQL params
# Just realized this is redundant; because query {} accepts
# uninterpolated \$varnames as parameter placeholders.
proc sql::allowed {str} {
return [regexp {^[-a-zA-Z0-9 !$&/(){}=<>,.;:_+#*@]+$} $str]
}
#-- Also prohibit regex special chars
proc sql::allowed_regexp {str} {
return [regexp {^[-a-zA-Z0-9 !$&/ =<>,.;:_ # @]+$} $str]
}
#-- Check for existence of wiki page
proc sql::page_exists {name} {
query {SELECT 1 FROM tag WHERE tagname = (''wiki-'' || $name)} { return 1 }
return 0
}
#-- Check if exact file name (including path) exists in repository
proc sql::file_exists {name} {
query {SELECT 1 FROM filename WHERE name = $name} { return 1 }
return 0
}
#-- Find file by basename
proc sql::find_file {path} {
if {![sql::allowed_regexp $path]} { return 0 }
query {SELECT name FROM filename WHERE name REGEXP (''(^|/)'' || $path || ''\$'')} { return $name }
return ""
}
#-- Check if directory exists
proc sql::dir_exists {path} {
if {![sql::allowed_regexp $path]} { return 0 }
query {SELECT name FROM filename WHERE name REGEXP (''^'' || $path || ''/.+'')} { return 1 }
return 0
}
#-- returns true if string contained in another string
proc str::contains {needle haystack} {
return [expr {-1 != [string first $needle $haystack]}]
}
#-- wrapper for [string first ...] to support startindex
proc str::next {search content start} {
# cut out $content at $start before searching
set p [string first $search [string range $content $start [string length $content]]]
if [expr $p>=0] {
set p [expr $start+$p]
}
return $p
}
#-- enclose string in e.g. html tags
proc str::wrap {content search before after} {
set len [string length $search]
set p 0
while {[expr [set p [str::next $search $content $p]]>=0]} {
set content "[string range $content 0 [expr $p-1]]$before$search$after[string range $content [expr $p+$len] 2000]";
set p [expr $p+[string length "$before+$search+$after"]]; # skip a little further
}
return $content
}
#-- Split string into list on delimiter character
# (basically just turns delimiter into space)
#
proc str::explode {delim str} {
set r ""
set len [string length $str]
while {-1 != [set p [string first $delim $str]]} {
set r "$r [string range $str 0 [expr $p-1]]"
set str [string range $str [++ p] $len]
}
return [list [string trim "$r $str"]]
}
#-- Extract dirname from path/file/name
proc str::dirname {path} {
return [string range $path 0 [expr [string last "/" $path]-1]]
}
'