To jest test
Code Rulers
Programując przez Życie
  • Strona Główna
  • Blog
  • Programowanie
    • C#
    • C++
    • SQL
    • PHP
  • Projekty
    • BitRace
    • ReadGame
  • Download
  • Twórczość
  • Usługi
  • O mnie
Browse: Home / Blog

Captcha obroni przed wszyskim – włączając w to użytkowników..

By Real_Noname on 27/03/2011

Dzisiaj tak z innej beczki – rzecz dosyć prosta. Człowiek chce ściągnąć jakiś plik który ma znajomy, a że nie każdy wynajmuje serwer 2GB, więc skorzystał z jednej z licznych firm „udostępniające” swoją przestrzeń dyskową za „darmo” w zamian za oglądanie reklam. No, ale żeby się upewnić, że żaden bot nie ściąga masowo nie oglądając żadnych reklam, to zrobili Captche.

Za to użytkownicy zrobili boty, które potrafią czytać Captche.

Wtedy firmy ulepszyli Captche.

Użytkownicy nie byli dłużni – i tak nastała wojna, której efekt najnowszy przydarzył mi się niedawno:

I bądź człowieku normalny na tym świecie…

Posted in Internet, Komputery, Życie | Tagged głupota ludzka, internet, komputery, www | Leave a response

Rodzic kontra nowoczesność

By Real_Noname on 20/02/2011

Jakiś czas temu przeglądając rytmicznie pewną stronkę (niektórzy wnet się zorientują którą :) ) natknąłem się na dosyć zabawny wątek. W skrócie autor przedstawiał swoje przeżycia będąc tłumaczem technologii dla swojego rodzica – wywiązał się dość zabawny dialog.

Oryginał bez zmian pisowni i cenzury :)

Houraayyyy /b/rothers !!
I finally managed to explain my mum how to remove megavideo limitation !! It took me 2 hours. Yes, 2 fucking hours of facepalms and epic fails. If my mum was an animal, she would be a duck. Here is the phone conversation as I remember it:
Anon: Ok mom, you gotta watch this movie, it’s the best movie I’ve ever seen.
Mom: M’kay…
Anon: But first I’ll show you how to remove the megavideo limitation, first of all what’s your web browser?
Mom: What ?
Anon: huh, what’s the name of the program you use to go on internet ?
Mom: Hoo, it’s Yahoo!
Anon: Mom….it’s not Yahoo!
Mom: but it says : W..W..W… Dot… Yaehoo… Dot…
Anon: Ok ok, close everything
Mom: Shall I turn the computer off ?
Anon: Nooooo, go back to the huh… “main menu”, put your mouse over the icon and tell me what’s written.
Mom: Internet explorer 7, it’s asking me if I want to upgrade to windows 8 everytime, how can I get rid of it ?
Anon: *sigh* choose the “don’t ask me anymore” option
Mom: Ohhhhhh you’re so good with those things.
Anon: Whatever….

I skip the part where I tell her to download Chrome as she managed to do it quiet well.

Anon: Ok, now tip “illimitux” on google, click the first link, and download it
Mom: I can’t…
Anon: Why ?
Mom: Wizard ( I’m dead serious, she said wizard) tells me it’s dangerous
Anon: *Epic wut face* ignore it and install it now .
Mom: DONE !
Anon: now search “cacaoweb”
Mom: Where ?
Anon: google it !
Mom: google or cacaoweb ? anon can you explain
Anon: *sigh and use a stupid voice as I was talking to a retard kid* use the keyboard to select the letters in the right order to write CA-CA-O-WEB on the top bar
Mom: Don’t talk like that, it’s hard it’s not my fault
Anon: Download the chrome version
Mom: but …
Anon: FUCK THE WIZARD !
Mom: okay….

Skip the 6 minutes I needed to explain where the downloads go.
Skip the 15 minutes needed to find a streaming website working.

Anon: Does it work ? do you have the illimitux window on your bottom left ?
Mom: No….
Anon: WTF ?? *thinking about what I may have forgotten, can’t find when suddently*
Mom: Hooo noooo ! My pc is crashed because of you, it’s says Internet explorer don’t respond
Anon: Why………..The………..FUCK…..IS ….INTERNET EXPLORER OPEN ?
Mom: But you asked me to open internet.
Anon: WITH GOOGLE CHROME !!!!

Mom: But I AM on google right now, I can see the page.
Anon: *manly tear of despair as I tell her how to open Chrome, I guide her through the internet hostile jungle to try illimitux on a movie, she does it right and soon she’s at the register page*
What do you see ?
Mom: there’s a pirate with a cannon and some ducks, ho and also Ipads….
Anon: WHAT ? *Took me 15 minutes to understand she was talking about the banners and adds.*
MOM !! FFS tell me what is on the MIDDLE OF THE FUCKING PAGE !
Mom: Register… may I put my real name or what ?
Anon: Yes and also your bank account number
Mom: Really ?
Anon: NO ! put something else.

Osobiście leżałem ze śmiechu jak to czytałem pierwszy raz :)

Posted in Internet, Komputery, Rozrywka, Życie | Tagged 4chan, anonymous, b, głupota ludzka, internet | Leave a response

Pamięć w C# i jego tajemnicze kodowanie znaków

By Real_Noname on 22/01/2011

Lubię pisać w C#, zwłaszcza na dedykowanym dla niego edytorze w pakiecie Visual Studio. Ale czasami szlag mnie trafia, kiedy jego największa zaleta czasami daje o sobie znać w najgorszy możliwy sposób – a mianowicie zarządzanie pamięcią.

W C++ mamy jasno określoną sytuację – char zajmuje jeden bajt; jak go zapiszemy do pliku, to dalej zajmuje jeden bajt, a jak go odczytamy – dalej zajmuje to samo. Sprawa w C# okazuje się nie być tak banalna jeżeli chodzi o typ danych przechowujących znaki czytane.

Oczywiście całe cyrki zaczynają się gdy chcemy zapisać tekst do pliku binarnego. Zakładam, że chcemy zapisać „Józek” – jak widać posiada polski znak, więc wypadało by go zapisać z odpowiednim kodowaniem. Ale jakiego kodowania używa pakiet .NET i w ogóle cały C#?

Po krótkim grzebaniu w MSDN dowiadujemy się, że Unicode – to wydawało się dosyć oczywiste od początku. Bakcyl polega na fakcie, że nie wiadomo którego z kilku standardów. Ale i tego udało mi się dowiedzieć. Wprawdzie nie znalazłem tego na MSDN – są na nim wszystkie informacje o wszystkich standardach, ale jakoś informacja o tym którego oni używają gdzieś im umknęła – a znalazłem ją dopiero w dymku z podpowiedziami do obieku System.Text.Encoding.Unicode – a mianowicie jest to UTF-16.

Dobra, wiemy już jak to jest zapisane w pamięci – po 2 bajty na każdy znak (standard przynajmniej na to wskazuje). Jak się dogrzebiemy do opisu obiektu „char”, to też mamy potwierdzenie tej teorii, ponieważ zajmuje on w pamięci 2 bajty. A więc zróbmy eksperyment i zapiszmy naszego stringa raz bezpośrednio, a raz jako łańcuch char’ów.

  1. BinaryWriter BinWr = new BinaryWriter(new FileStream("test.bin", FileMode.Create));
  2.  
  3. string strText = "Józek"; // 5 znaków * 2 bajty = 10 bajtów
  4.  
  5. BinWr.Write(strText); // zapisanych = 7 bajtów
  6.  
  7. BinWr.Write(strText.ToCharArray()); // zapisanych = 6 bajtów

No ok – niby byliśmy mądrzy – już pisaliśmy kod czytania plików oparty na adresowaniu pamięci, a tu niespodzianka – string nie zajmuje tyle co powinien? WTF?!

Oczywiście najpierw z kamienną miną szukałem odpowiedzi na MSDN. Znalazłem tam jedynie, że metoda Write(string Text) klasy BinaryWriter najpierw zapisuje liczbę znaków, a potem tekst. Szczegół, że to w ogóle nie tłumaczy dlaczego napis zajmuje 7 a nie 14 bajtów.

Dopiero głębsza analiza pliku dała jakieś odpowiedzi. Okazuje się, że BinaryWriter (i Reader) używają do określenia ilości znaków tzw. int’a zmiennej długości. Oznacza to że jeżeli długość tekstu nie przekroczy 127 znaków – to używa jednego bajtu w pamięci. Jeżeli przekroczy, to dwóch. A jak piszemy jakąś przemowe pojedziemy ponad 32 tysiące, to 3 itd.

No dobra – to tłumaczy jeden bajt. Pozostało jeszcze do wyjaśnienia te tajemnicze 6 bajtów. Okazuje się (a nie jest to absolutnie nigdzie napisane), że BinaryWriter i BinaryReader używają do kodowania tekstu standardu UTF-8, czyli zmiennej długości znaku. Innymi słowy, dopóki znak mieści się w podstawowym A-Z zwykłego ASCII, to zajmuje 1 bajt – jeżeli jest to coś innego to 2, 3 lub w razie potrzeby 4. Dlatego nasz tekst zajmuje 6 bajtów = 4 zwykłe znaki + 2 bajty dla specjalnego.

Wszystko fajnie – niby to oszczędza pamięć, ale dla człowieka który pisze dosyć zaawansowany kod czytający dane z różnego miejsca pliku (a jak w dodatku robi to w C++, to zabawa robi się jeszcze przedniejsza), to już nie jest fajnie. Oczekujemy że dane będą miały stałą długość. Na szczęście można to rozwiązać w dosyć prosty sposób:

  1. public static void WriteString(string strText, BinaryWriter BinWr)
  2. {
  3. BinWr.Write((Int32)strText.Length);
  4. BinWr.Write(strText.ToCharArray());
  5. } 
  6.  
  7. // gdzieś w kodzie
  8. BinaryWriter BinWr = new BinaryWriter(new FileStream("test.bin", FileMode.Create), Encoding.Unicode); // <- ważna rzecz
  9. WriteString("Józek", BinWr);

I wtedy nasz tekst powinien zająć nasze upragnione, pamięciożerne 14 bajtów.

Posted in C#, Programowanie | Tagged c#, programowanie | Leave a response

Rozpakowywanie Archiwów na Serwerze WWW

By Real_Noname on 31/10/2010

Czasami mamy potrzebę wysłania na serwer dużej ilości małych plików. Robiąc to na piechotę (wysłanie każdego pliku oddzielnie) szybko się przekonamy, że zajmuje to wieczność. Dzieje się tak dlatego, że w połączeniu FTP na każdy pojedynczy plik tworzona jest oddzielna sesja wysyłania (czyli kilka  komend musi przejść i być rozpoznanych w tę i tamtą stronę, co zajmuje parę sekund), co powoduje, że przy większych ilościach możemy spędzić noc nad tym.

Dlatego popularną praktyką jest wpierw pakowanie takich plików jako archiwum zip, wysłanie na serwer i ich rozpakowanie na miejscu. Taka kolej czynności jest z wiadomych względów o wiele mniej zajmująca czasowo (zwłaszcza, że serwery to często potężne maszyny obliczeniowe, dla których algorytmy dekompresji to pikuś). Pierwszą i drugą kwestię z listy na pewno większość wykona bez problemu. A co z rozpakowaniem na serwerze?

Jest kilka sposobów na odzyskanie zawartości archiwum bezpośrednio na serwerze.

Najprostsza z nich, to użycie konta shellowego jakie udostępniła nam firma hostingowa. Programy FTP takie jak WinSCP obsługują tego typu połączenia i z ich poziomu zazwyczaj wystarczy wybrać polecenie „UnZip” z menu, by wszystko wykonało się samo.

Jeżeli nie mamy takiego programu i z jakiego powodu nie chcemy (dziwny by musiał to być powód, ale i takie się zdarzają), to zawsze możemy ręcznie się połączyć pod Shell’a używając np. darmowego Putty. Z jego poziomu już wystarczy tylko wydać odpowiednia komendę, np:

unzip -ou mojplik.zip -d ./

Gdzie zapis „./” oznacza rozpakuj do obecnego folderu.

No tak – ale często jest tak, że firma hostingowa nie udostępnia na danym serwerze konta shellowego. Aczkolwiek często dalej mamy możliwość wykonania powyższego polecenia – o ile serwer nie ma zablokowanego wykonania funkcji „shell_exec” będącego de facto wykonaniem komendy shellowej. Czyli możemy umieścić sobie na serwerze plik php o treści:

  1. <?php
  2.  
  3. shell_exec("unzip -ou mojplik.zip -d ./");
  4.  
  5. ?>

Ok, ale w przypadku zablokowania owej funkcji jesteśmy praktycznie zdani na sam PHP i FTP. Najprościej wtedy sprawdzić, czy mamy w interpreterze php na serwerze zainstalowany moduł ZipLib (standardowe php_info(); i powinno się dać znaleźć w którejś linijce). Jeżeli tak, to też tworzymy plik php, tyle, że o trochę innej treści.

  1. <?php
  2.  
  3. $arch = new ZipArchive;
  4. $arch->open("mojplik.zip");
  5. $arch->extractTo("./");
  6. $arch->close();
  7.  
  8. ?>

Użyliśmy w tutaj klasy ZipArchive udostępnionej przez dany moduł. Na efekt działania trzeba będzie trochę poczekać (co przy restrykcyjnych czasach wykonania na niektórych serwerach, może być problemem) lecz to jest dobra alternatywa.

A co zrobić, jeżeli nawet i to nie jest dostępne?

Należało by się wtedy posilić czystym PHP i poszukać  jakiejś całej klasy z algorytmem rozpakowującym w jednym pliku php. W internecie można bez większych problemów takową znaleźć. Aczkolwiek – ja osobiście, przy tylu restrykcjach, prędzej bym zmienił serwer lub dostawcę. Może trwało by i dłużej, ale za to na przyszłość mniej nerwów i większa wygoda…

Posted in PHP, Programowanie | Tagged php, programowanie, trik, wordpress, zip | Leave a response

Argumenty z Linii Komend w Windows Forms

By Real_Noname on 30/10/2010

Jak wiadomo czasami czasami projektuje się aplikację, by odpowiednio reagował na argumenty linii komend (tzw. command line arguments). Służą one różnym celom – od pokazywania dodatkowy informacji, po udostępnienie dodatkowej funkcjonalności użytkownikom zaawansowanym.

Przykład wywołania programu z takimi argumentami:

iexplorer http://www.google.pl

Jak umożliwić wykorzystanie takich możliwości w C#? Jeżeli utworzymy projekt C# który będzie korzystał z konsoli, to praktycznie nic dodatkowego nie musimy robić – potrzebna zmienna jest dostępna już na starcie:

  1. class MyApp
  2. {
  3. static void Main(string[] args) // tutaj :)
  4. {
  5. }
  6. }

Lista args zostanie wypełniona odpowiednimi danymi automatycznie przy starcie programu.

Co innego jeżeli chcemy to samo zrobić, gdy mamy projekt oparty na Windows Forms. Bez modyfikacji kodu generowanego przez Visual Studio, nie mamy bezpośrednio dostępu do zmiennej args w metodzie Main. Jest jednak na to inny sposób:

  1. // gdzieś w kodzie
  2. string[] args = Environment.GetCommandLineArgs();

I problem rozwiązany. Możemy wykorzystywać uzyskane dane jak chcemy.

Inna ważna uwaga jest co do samych danych, co otrzymujemy. Spójrzmy na przykład:

C:\MyProg.exe 124 "This prog is Gut"

Ile jest argumentów? Laik powiedziałby, że pięć, obeznany stwierdzi, że dwa, a poprawna odpowiedź to trzy. Dlaczego? Ponieważ każda lista argumentów zaczyna się od łańcucha znaków zawierającą ścieżkę do uruchomionego programu. Dodatkowo, każdy ciąg znaków objęty w cudzysłów traktowany jest jako osobny argument. Dlatego lista „args” będzie zawierała:

args[0] = C:\MyProg.exe
args[1] = 124
args[2] = This prog is Gut

Posted in C#, Programowanie | Tagged c#, command line, programowanie, trik | Leave a response

Polimorfizm w Destruktorze, czyli jak nie działa virtual

By Real_Noname on 10/10/2010

Ostatnio wzięło mnie na prototypowanie swoich starych bibliotek. Chciałem zobaczyć które z moich starych bibliotek, które pisałem jako młody koder jeszcze nadają się do użytku, a głębi tego miałem zamiar posprawdzać parę rzeczy nt. C++, na które nigdy nie miałem czasu. Jedną z bardziej zaskakujących jest dziedziczenie połączone z polimorfizmem i destruktorem.

Sprawa wyglądała dosyć prosto:

  1. class CRef
  2. {
  3. public:
  4. virtual ~CRef()
  5. {
  6. std::cout << "Destructor Pierwszy" << std::endl;
  7. Free();
  8. } 
  9.  
  10. virtual void Free()
  11. {
  12. std::cout << "Czyszczenie Pierwsze" << std::endl;
  13. }
  14. };
  15.  
  16. class CSomeClass : public CRef
  17. {
  18. public:
  19. virtual ~CSomeClass()
  20. {
  21. std::cout << "Destructor Drugi" << std::endl;
  22. }
  23.  
  24. virtual void Free()
  25. {
  26. std::cout << "Czyszczenie Drugie" << std::endl;
  27. }
  28. };

Mamy klasy z destruktorami, gdzie pierwszy wywołuje metodę czyszczącą. W zamyśle, gdy skasujemy obiekt klasy drugiej, to klasa bazowa wywoła przez destruktor metodę czyszczącą klasy wyższej – proste? Oczywiście. Działa? Oczywiście, że nie….

Wynik jaki powinienem otrzymać:

Destruktor Pierwszy
Czyszczenie Drugie
Destruktor Drugi

Co otrzymałem:

Destruktor Pierwszy
Czyszczenie Pierwsze
Destruktor Drugi

To, że wywołują się oba destruktory, jest zjawiskiem normalnym i mnie nawet nie zainteresowało. Delikatnie mnie zdziwiła za to inna sytuacja, że wywoła się metoda klasy bazowej, a powielone testy tylko utwierdziły mnie w przekonaniu, że dany kod nie ma prawa działać poprawnie. Destruktor jest typem metody, w której możemy uruchamiać jedynie metody klasy bazowej – wymuszenie polimorfizmu poprzez zerowanie metody (virtual void Free() = 0;) w tej klasie prowadzi jedynie do błędu linkera.

Innymi słowy – jedyny sposób, żeby polimorfizm działał poprawnie w takim wypadku, jest wywołanie metody Free(); przez inną, normalnie stworzoną metodę.

  1.  class CRef
  2. {
  3. public:
  4. virtual ~CRef()
  5. {
  6. std::cout << "Destructor Pierwszy" << std::endl;
  7. } 
  8.  
  9. virtual void Free()
  10. {
  11. std::cout << "Czyszczenie Pierwsze" << std::endl;
  12. }
  13.  
  14. void Release()
  15. {
  16. Free();
  17. }
  18. };
  19.  
  20. class CSomeClass : public CRef
  21. {
  22. public:
  23. virtual ~CSomeClass()
  24. {
  25. std::cout << "Destructor Drugi" << std::endl;
  26. }
  27.  
  28. virtual void Free()
  29. {
  30. std::cout << "Czyszczenie Drugie" << std::endl;
  31. }
  32. };
  33.  
  34. …
  35. pClass->Release();
  36. delete pClass;
  37. …

Taki kod już się wykona się już poprawnie, a wywołana zostanie metoda klasy dziedziczącej.  Trochę to wkurzające, ale nic co nie da się ominąć paroma sprytnymi makrami :)

Posted in C++, Programowanie | Tagged c#, polimorfizm, programowanie | 2 Responses

Read Game – Potencjał Czytania

By Real_Noname on 02/09/2010

Od bodajże pół roku pracuje w wolnych chwilach nad dosyć osobliwym projektem. Oczywiście biorąc z faktu mojego zamiłowania jest to gra – aczkolwiek gra dosyć jak na dzisiejsze czasy nietypowa. Nie uświadczymy w niej trójwymiaru, efektów specjalnych, cieni ani reszty tego nowoczesnego badziewia, ponieważ głównym tłem rozgrywki gry będzie… tekst.

Gra ma czerpać z korzeni komputerowej rozrywki, gdzie bardziej stawiano na fabułę i klimat. Gracza będą wprowadzać poprzez dialogi, w których możemy wybierać kwestie do wypowiedzenia i czynności do wykonania niczym w starych przygodówkach tekstowych. Co mnie skłoniło do napisania gry o charakterze i mechanice wyciągniętej niemal sprzed 20-30 lat?

A było to ni mniej ni więcej niż zagranie w klasyka gier komputerowych – a mianowicie w Planescape: Torment. Jak pewnie niektórzy starzy wyjadacze pamiętają siła tej gry cRPG nie tkwiła w multum potworków do ubicia, czy setkom cyferek opisujących postać, lecz w tych małych literkach, co składały się na długie, acz fascynujące i klimatyczne dialogi. Gdy raz kolejny przechodziłem przez iście mistrzowsko wyreżyserowaną rozmowę, która czasami tryskała humorem, a innym razem patosem nagle doszło mnie uczucie pojęcia, czym była gruntowna istota tej gry. Jak już wcześniej wspomniałem – dialogi, klimat i fabuła. Całą resztę, łącznie z grafiką uznałem za zbędny dodatek, który może być jak również może i zostać usunięty bez szkody.

Uznałem wtedy, że można by było zrobić taką grę – minimalistyczną w swoich założeniach, lecz wciągająca i grywalna na swój sposób. Sercem byłby świat rozmów, gdzie każde zdarzenie jest opisany dialogiem, czy to z postacią, czy z samym sobą.

Lecz czy istnieje miejsce na takie gry w dzisiejszym świecie? Po dłuższym zastanowieniu stwierdziłem – tak, są. Najgłupszym przykładem mogą chociażby być gry erotyczne sprzedawane na komórki, gdzie wizję takiej gry wypaczono na odwrót. Komórka, pomimo swoich zalet jest urządzeniem zbyt małym by dawała pełnie walorów wizualnych (pewnie znajdą się zastępy co twierdzą inaczej, ale no cóż, tak jest zbudowany świat). Więc dlaczego nie wykorzystać potencjału jaki niesie czytanie i granie w praktycznie każdym miejscu i czasie? W tramwaju, autobusie, samolocie? Jako, że techniczne wymagania spadają wielokrotnie (poza pamięcią na potrzebne dialogi, rzecz jasna) można by to rozwinąć na wiele platform.

Nawet komputer stacjonarny tu ma wiele do zyskania, gdyż brakuje gier, które nie muszą brać całe nasze zainteresowanie, a mogły być gdzieś blisko, na pulpicie, i które by nie przeszkadzały w codziennym życiu. W dzisiejszych czasach komunikatorów, witryn internetowych, programów użytkowych na pewno przydało by się umilenie czasu, które nie uszczupla priorytetom tych pierwszych.

Taka jest moja wizja tej gry – wielofunkcyjny edytor, potrafiący tworzyć pliki „światów” który jest podstawą gry, a następnie sama gra co z niego korzysta. Napisanie której będzie szybkie i mało kosztowne z powodu wymagań technicznych jakie musi spełnić.

Zarówno Edytor jak i Gra w moim wykonaniu przez te pół roku zbliża się do pierwszej Alphy. Czas jest wydłużony ze względu na moje obowiązki i pierwsze kroki, aczkolwiek wyniki są bardzo obiecujące. Zarys fabuły do pierwszej gry też mam gotowy – trzeba go tylko rozpisać na rozdziały, sceny i dialogi. A tych będzie sporo, gdyż planuję intrygę nieliniową.

Całość technologii jakich używam zamyka się w XNA i .NET używając do tego języka C#. Niesamowite wsparcie jakie dają mi tę technologię pozwoliło już mi nie raz skrócić ogromny kawał czasu. I o ile gra na inne platformy pewnie będzie musiała być portowana czy przepisana (co jak wyżej wspomniałem nie powinno stanowić problemów) to Edytor skończony może służyć wszystkim rozwiązaniom.

Zobaczymy co przyniesie przyszłość z tym projektem…

Posted in Projekty, ReadGame | Tagged info, projekt, readgame | Leave a response

Delegate i Event’y w C#

By Real_Noname on 01/09/2010

Jako, że już sporo czasu pracuje w C# jako narzędziu, gdzie szybko można robić narzędzia (paradoksalnie) z przyjaznym interfejsem – w dodatku szybko i wygodnie, to w pewnym momencie musiałem dodać do nowej klasy własnego tzw. „Event’a” (trigger’a, wyzwalacz, zdarzenie, czy jak to zwą). Jak to zrobić było oczywiście napisane w Bibliotece MSDN, aczkolwiek trzeba było dokładnie wiedzieć czego się szuka, żeby tam dotrzeć.

No ok – przyjrzyjmy się strukturze tego Event’a.

  1. public event EventHandler CosZrob;

Jak wiadomo słowo „public” udostępnia dane pole klasy na zewnątrz, a „CosZrob” jest nazwą danego pola. „Event” oczywiście deklaruje, że mamy do czynienia ze zdarzeniem. Najciekawszy jest „EventHandler”. Jest to tzw. „delegat”, czyli twór programistyczny wyspecjalizowany w funkcjonalności do przechowywania adresów metod tej klasy, czy innej klasy – widać tu zagubioną funkcjolność C++ do przechowywania adresów metod klas. Samo słowo kluczowe delegate ma trochę więcej funkcjonalności (jak, np. tworzenie beznazwowych metod), lecz nam się przyda do czego innego. „EventHadnler” jest już wbudowanym delegatem, mający już określoną strukturę – jego deklaracja powinna wyglądać mniej-więcej tak (jak zresztą napisane to jest w MSDN):

  1. public delegate void EventHandler( object sender, EventArgs e );

Jak widać strukturą przypomina deklarację funkcji. Pierwszy argument jest chyba oczywisty, drugi natomiast przedstawia klasę stworzoną w celu właśnie użycia w eventach:

  1. public class EventArgs
  2. {
  3.  public static readonly EventArgs Empty;
  4.  public EventArgs();
  5. }

Jak widać klasa jest prościutka – jest podstawą tworzenia tzw. argumentów zdarzenia. Jako że chce stworzyć zdarzenie posiadające własne argumenty (a nie pusty zapełniacz), więc muszę napisać trochę kodu:

  1. public class CosEventArgs : public EventArgs
  2. {
  3.  public string Cos { get; set; }
  4.  public CosEventArgs( string _Cos )
  5.  {
  6.   Cos = _Cos;
  7.  }
  8. }

Ok, teraz chciałbym użyć tak stworzonego elementu. Dlatego jestem zmuszony stworzyć nowego delegata dla takiego zadania, co by przyjmował moją nową klasę:

  1. public delegate void CosEventHandler( object sender, CosEventArgs ce );

Mała uwaga – wcale nie musimy używać EventArgs przy tworzeniu delegata – możemy go olać. Struktura argumentów może być dowolna – to co teraz piszemy jest po prostu ustaloną konwencją, żeby wszystko miało ręce i nogi – chociaż i widziałem zastąpienie EventArgs np. string’iem.

Ok – jest już EventHandler – teraz należało by go użyć.

  1. public event CosEventHandler CosZrob;

To już jest w praktyce gotowy do działania event – będzie widoczny na odpowiedniej zakładce VisualStudio we właściwościach obiektu. Inna sprawa, że tworzenie Eventu jest bez sensu, o ile go się gdzieś nie będzie wywoływało, np. W jakieś metodzie:

  1. CosZrob.Invoke( this, new CosEventArgs( "Coś Zrobiłem" ) );

A dalej obsługa eventu przebiega tak jak zwykle. Została ostatnia kwestia – pilnowanie, żeby sam Event nie był pusty – wywołanie w takim przypadku metody Invoke, skończy się błędem. Najłatwiej jest to zrobić, ładując do środka metodę – kukłę.

  1. void OnCosZrob( sender object, CosEventArgs ce ) { }
  2. …
  3. //gdzieś w kodzie inicjującym
  4. CosZrob += new CosEventHandler( OnCosZrob );

Oczywiście nic nie stoi na przeszkodzie, żeby dany kod „kukiełkowy” od razu coś robił. Trzeba tylko pamiętać działanie operatora „+=” – wszelkie metody jakie za jego pomocą zostaną przypisane do eventu zostaną wywołane (wszystkie!) przy wywołaniu Invoke. Jeżeli chcemy się jakiegoś pozbyć – używamy operatora „-=”.

Posted in C#, Programowanie | Tagged c#, delegate, event, programowanie | 2 Responses

WordPress – konwersja z path na domain

By Real_Noname on 31/08/2010

Pracując już dłużej z WordPress’em dostałem zadanie zainstalowania całego serwisu na nowym serwerze. Serwis korzystał ze starej wersji (2.8 bodajże) oraz wtyczki MU (Multi Site, do tej wersji jako plugin), a celem była nowa wersja 3.0.0 która już MU obsłygiwała wewnętrznie. W skutek różnych niuansów w trakcie rozmowy zainstalowałem całość pod strukturę ścieżkową (path install), przez co dostęp do podstron serwisu odbywał się przez dopisanie ścieżki (www.domena.pl/strona/). Jak się okazało – nie o to chodziło. I takim sposobem zostałem postawiony przed zadaniem przemianowania istniejącej instalacji WordPress na strukturę subdomenową (strona.domena.pl).

Wszystko fajnie i tak dalej – ale jak to zrobić?

Wewnętrzne mechanizmy WordPress’a nie udostępniają potrzebnej funkcjonalności – przewidziano tylko, że jak zdecydujemy się na instalacje sieciową (MU) to wybór struktury podstron jest ostateczny i  co najwyżej możemy wszystko zainstalować jeszcze raz. Taki stan rzeczy był dla mnie nie do zaakceptowania. Więc zacząłem grzebać w plikach i w bazie danych.

Pierwsza rzecz jaka się rzuciła w oczy to wpisy w wp-config.php, które powstają po instalacji.

  1. define( ‘MULTISITE’, true );
  2. define( ‘SUBDOMAIN_INSTALL’, false );
  3. $base = ‘/’;
  4. define( ‘DOMAIN_CURRENT_SITE’, ‘domena.pl’ );
  5. define( ‘PATH_CURRENT_SITE’, ‘/’ );
  6. define( ‘SITE_ID_CURRENT_SITE’, 1 );
  7. define( ‘BLOG_ID_CURRENT_SITE’, 1 );

Jak widać wszystko sugeruje, że mamy do czynienia z instalacją ścieżkową. Trzeba poprawić ten fakt.

  1. define( ‘MULTISITE’, true );
  2. define( ‘SUBDOMAIN_INSTALL’, true );
  3. $base = ‘/’;
  4. define( ‘DOMAIN_CURRENT_SITE’, ‘domena.pl’ );
  5. define( ‘PATH_CURRENT_SITE’, ‘/’ );
  6. define( ‘SITE_ID_CURRENT_SITE’, 1 );
  7. define( ‘BLOG_ID_CURRENT_SITE’, 1 );

W praktyce to wszystko co trzeba pozmieniać w plikach na serwerze. Teraz troszkę trudniejsze zadanie  - baza danych.

Na początek do zmian zachęca tabelka pod wiele mówiącą nazwą „wp_blogs” (oczywiście prefix może być inny, ale wiadomo o co chodzi). Są tam wpisy nt. wszystkich aktualnych podstron. Posiada dwa nas interesujące pola – domain i path. Przy instalacji ścieżkowej (path install) pole domain zawiera zwykle domenę główną bez niczego (np. „domena.pl”), a path ścieżkę do strony (np. „/strona/”).

domain = domena.pl
path = /strona/

Należy odpowiednio to zamienić miejscami.

domain = strona.domena.pl
path = /

Dalej trzeba się zainteresować samymi podstronami. Każda ma minimalny układ tabel w postaci „prefix_ID_tabela”. Dla każdej strony należy zajrzeć do tabeli „options” (np. „wp_2_options”) i tam znaleźć dwa wpisy posiadających w polach  option_name wartości „home” i „siteurl”. W nich trzeba dokonać odpowiedniej zamiany z „domena.pl/strona/” na „strona.domena.pl”. Dany zabieg trzeba powtórzyć dla każdej tabeli options każdej z podstron.

Ostatnia rzeczą jaką trzeba wykonać, to zaktualizować posty. W tabeli „posts” (np. wp_2_posts) każda wiadomość ma swój tzw. guid, który między innymi zawiera ścieżkę do danego postu. Należy je zaktualizować, aczkolwiek z uwagi na fakt, że to jest czasochłonne (zwłaszcza przy większej liczbie postów) to można się tu wyręczyć dobrodziejstwami języka SQL i użyć następującego zapytania.

  1. UPDATE prefix_ID_posts SET guid = REPLACE(guid,‘domena.pl/strona/’,‘strona.domena.pl/’);

Dzięki czemu zaoszczędzimy sobie sporo pracy. Praktycznie to wszystko co trzeba wykonać, żeby instalacja działa poprawnie na nowej strukturze.

Posted in PHP, Programowanie, SQL | Tagged domain install, mysql, path install, php, programowanie, sql, wordpress | Leave a response

Kopiowanie całych tabel

By Real_Noname on 30/08/2010

Ostatnio podczas swojej pracy dostałem zadanie skopiowania całych podstron WordPress’a (tzw. stron MultiSite). O ile miałem ciężką przeprawę, żeby go przestawić z Path Install na Domain Install, to jednak to zadanie okazało się łatwiejsze.

Większość babrania się polegała na kopiowaniu tabel (i być może ich zawartości – w zależności od widzimisie użytkownika) – sposób na piechotę oczywiście polegał znajomość struktury tabeli w każdej wersji WordPress i jej tworzeniu, a później wystarczy odpytywać serwer o zawartość, żeby ją wysłać ponownie, w skrócie – nie ma lepszego sposobu by zarżnąć swój serwer.

Na całe szczęście – MySQL ma w swoim standardzie przewidziane te sytuacje.

  1. CREATE TABLE new_table LIKE old_table;

Jak widać w tym kodzie nie musimy wiedzieć, jaką strukturę ma stara tabela – Baza Danych sprawdzi to za nas i stworzy odpowiednią kopię.

No, ale jeszcze trzeba przenieść dane.

  1. INSERT INTO new_table SELECT * FROM  old_table;

Ale o dziwo – wcale nie trzeba rozdzielać tych dwóch procesów – można od razu lecieć z kopyta i zrobić dwie rzeczy na raz

  1. CREATE TABLE new_table SELECT * FROM old_table;

I wszystko zostanie wykonane jak za pstryknięciem palcami. Oczywiście wszystkie „modyfikacje” zapytania też mają tu sporo do powiedzenia.

  1. CREATE IF NOT EXISTS new_table SELECT new_field=old_field,second_field FROM old_table WHERE thidrd_field=’3′;

Więc jak widać stare porzekadło „Jeżeli chcesz coś zrobić w PHP – zrób to o wiele szybciej w SQL” dalej ma swoje podstawy istnienia.

Posted in Programowanie, SQL | Tagged copy, mysql, programowanie, sql, table, trik | Leave a response

Next »

Szukaj

Archiwum

  • Marzec 2011
  • Luty 2011
  • Styczeń 2011
  • Październik 2010
  • Wrzesień 2010
  • Sierpień 2010
  • Listopad 2009
  • Październik 2009
  • Wrzesień 2009
  • Sierpień 2009
  • Luty 2009
  • Marzec 2008
  • Styczeń 2008

Tagi

4chan anonymous b batman c# copy devil may cry dzieci error film gry głupota ludzka hiphopolo historia hobby info internet joomla komiks komputery kreacjonizm laptop lifting mysql nauka php pisanie polska pomysł programowanie projekt religia simple machines forum slasher sql strona table transformers trik vendetta wordpress www wychowanie wygląd wykształcenie

Copyright © 2012 Code Rulers.

Powered by WordPress and Hybrid.