W poprzedniej części artykułu dotyczącego instalacji oraz uruchamiania przykładowych programów wykorzystujących bibliotekę Libgadu poznaliśmy budowę tej biblioteki. W drugiej części artykułu pobawimy się kodem edytując go. Zgłębimy strukturę gg_login_params oraz spróbujemy napisać program masowo wysyłający wiadomość pod numery znajdujące się w pliku tekstowym.
Zacznijmy od czegoś prostego, czym jest plik status.c
[codesyntax lang=”c”]
/* * przykład prostego programu łączącego się z serwerem i zmieniającego opis. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include "libgadu.h" int main(int argc, char **argv) { struct gg_session *gs; struct gg_login_params glp; if (argc < 4) { fprintf(stderr, "użycie: %s <mójnumerek> <mojehasło> <opis>n", argv[0]); return 1; } gg_debug_level = 255; memset(&glp, 0, sizeof(glp)); glp.uin = atoi(argv[1]); glp.password = argv[2]; // glp.encoding = GG_ENCODING_UTF8; // glp.protocol_version = 0x2d; glp.status = GG_STATUS_INVISIBLE_DESCR; glp.status_descr = argv[3]; if (!(gs = gg_login(&glp))) { printf("Nie udało się połączyć: %sn", strerror(errno)); gg_free_session(gs); return 1; } gg_notify(gs, NULL, 0); printf("Połączono.n"); if (gg_change_status_descr(gs, GG_STATUS_NOT_AVAIL_DESCR, argv[3]) == -1) { printf("Połączenie przerwane: %sn", strerror(errno)); gg_free_session(gs); return 1; } gg_logoff(gs); gg_free_session(gs); return 0; }
[/codesyntax]
Plik jest identyczny z zademonstrowanym w poprzednim artykule, jedynie komentarze zostały usunięte. Ponadto do struktury gg_login_params dodajemy wartości takie jak status oraz status_descr. W poprzednim przykładzie linie te zostały skomentowane, ponieważ zależało nam jedynie na zmianie opisu po zalogowaniu.
Czym więc różni się ustawienie opisu poprzez użycie funkcji gg_change_status_descr(), a ustawieniem parametrów dla struktury gg_login_params?
Odpowiedź jest prosta. Funkcja gg_change_status_descr() zmienia status na podany w parametrze podczas połączenia z serwerem, czyli wtedy, kiedy mamy już nadaną sesje. Natomiast parametr status jak i status_descr w strukturze gg_login_params ustawiają wartości dla naszego statusu już w trakcie łączenia się z serwerem, czyli natychmiast po zalogowaniu.
glp.uin = atoi(argv[1]); glp.password = argv[2]; glp.status = GG_STATUS_INVISIBLE_DESCR; glp.status_descr = argv[3];
Wszystkie opisane parametry tejże struktury znajdują się poniżej
[codesyntax lang=”text”]
uin_t uin - Numer Gadu-Gadu. char * password - Hasło. int async - Flaga asynchronicznego połączenia (domyślnie nie). int status - Początkowy status użytkownika (domyślnie GG_STATUS_AVAIL). char * status_descr - Początkowy opis użytkownika (domyślnie brak). uint32_t server_addr - Adres serwera Gadu-Gadu (domyślnie pobierany automatycznie). uint16_t server_port - Port serwera Gadu-Gadu (domyślnie pobierany automatycznie). int protocol_version - Wersja protokołu wysyłana do serwera (domyślnie najnowsza obsługiwana). char * client_version - Wersja klienta wysyłana do serwera (domyślnie najnowsza znana). int has_audio - Flaga obsługi połączeń głosowych. int last_sysmsg - Numer ostatnio odebranej wiadomości systemowej. uint32_t external_addr - Adres publiczny dla połączeń bezpośrednich (6.x). uint16_t external_port - Port publiczny dla połączeń bezpośrednich (6.x). int image_size - Maksymalny rozmiar obsługiwanych obrazków w kilobajtach. int hash_type - Rodzaj skrótu hasła (GG_LOGIN_HASH_GG32 lub GG_LOGIN_HASH_SHA1, domyślnie SHA1). gg_encoding_t encoding - Rodzaj kodowania używanego w sesji (domyślnie CP1250). gg_resolver_t resolver - Sposób rozwiązywania nazw. int protocol_features - Opcje protokołu (flagi GG_FEATURE_*).
[/codesyntax]
Napiszmy program, który wypełni kilka parametrów interesującej nas struktury.
[codesyntax lang=”c”]
/* * przykład prostego programu łączącego się z serwerem i zmieniającego opis. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include "libgadu.h" int main(int argc, char **argv) { struct gg_session *gs; struct gg_login_params glp; if (argc < 3) { fprintf(stderr, "użycie: %s <mójnumerek> <mojehasło>n", argv[0]); return 1; } gg_debug_level = 255; memset(&glp, 0, sizeof(glp)); //Wypełniamy wartość struktury dla loginu glp.uin = atoi(argv[1]); //Wypełniamy wartość struktury dla hasła glp.password = argv[2]; //Początkowy status glp.status = GG_STATUS_BUSY_DESCR; //Początkowy opis glp.status_descr = "<3 :***"; //Maksymalny rozmiar odbieranego obrazka, tutaj 255kb glp.image_size = 255; if (!(gs = gg_login(&glp))) { printf("Nie udało się połączyć: %sn", strerror(errno)); gg_free_session(gs); return 1; } gg_notify(gs, NULL, 0); printf("Połączono.n"); //Czekamy 3 sekundy, aby //Zaobserwować zmiany :-) sleep(3); gg_logoff(gs); gg_free_session(gs); return 0; }
[/codesyntax]
Nie jest to nic wielkiego, ale myślę, że w wystarczający sposób wyjaśnia w jaki sposób działają struktury. Z kompilacją powinniśmy już sobie dać radę samodzielnie 🙂
Dobra, dość przynudzania… Czas na napisanie programu, który wczytuje numery z pliku tekstowego oraz wyświetla je na ekranie. Numery z założenia będą oddzielone znakiem nowej linii.
[codesyntax lang=”c”]
//Niezbędne biblioteki #include <string.h> //strlen #include "libgadu.h" //libgadu :-) int main(int argc, char **argv) { /* Deklarujemy zmienne potrzebne do zliczenia ilości wierszy w pliku */ FILE *plik; int wiersz = 0; char znak; //Jeśli nie ma pliku z numerami if((plik = fopen("numery.txt", "r")) == NULL) { //Informujemy o błędzie i kończymy działanie programu printf("Nie mogę otworzyć pliku n"); return 1; } //Dopóki nie dojedziemy do końca pliku while((znak = getc(plik)) != EOF) { if(znak == 'n') { //Zliczamy ilość wierszy ++wiersz; } } /* Odczytujemy wiersz po wierszu z pliku i wypisujemy wartość */ FILE *pFile; int i=0; char numerek[3]; pFile = fopen("numery.txt", "r"); /* Jeśli nie ma pliku z numerami Informujemy o błędzie i kończymy działanie programu */ if(pFile == NULL) { printf("Błąd odczytu pliku"); return 1; } else { /* Jazda ;D */ for(i=0;i<=wiersz-1;i++) { fgets(numerek, 131072, pFile); //Deklaracja zmiennej pomocniczej, //Aby pozbyć się znaku spacji //Na końcu zmiennej char x; x=strlen(numerek); numerek[x-1]='�'; //Wypisujemy numer printf("%sn", numerek); } } return 0; //Zakończenie programu }
[/codesyntax]
Kod zapiszmy pod nazwą wczytywanie.c. Poza nim potrzebujemy także plik tekstowy o nazwie numery.txt z kilkoma przypadkowymi numerami
451664
1234567
7654321
1122334
4455663
5897514
48541858
Kompilujemy i uruchamiamy
gcc -o wczytywanie wczytywanie.c
komeniusz@cyber-jadro:~/libgadu-1.9.0-rc2/examples$ ./wczytywanie 1234567 7654321 1122334 4455663 5897514 48541858
Pozostało nam połączyć powyższy program z programem przedstawionym w poprzednim artykule o nazwie send.c w jeden, którego celem będzie połączenie się z serwerem, wczytanie listy numerów z pliku tekstowego oraz wysłanie do nich określonej wiadomości.
[codesyntax lang=”c”]
/* Autor: Komeniusz -Nie odpowiadam za czynności wykonane poprzez użycie tego programu- Program masowo wysyła wiadmości GG na numery podane w pliku tekstowym Może zostać wykorzystany np. do szybkiego wysyłania informacji znajomym z okazji świat. Download Libgadu: http://toxygen.net/libgadu/ Dokumentacja Libgadu: http://toxygen.net/libgadu/doc/ */ //Niezbędne biblioteki #include <string.h> //strlen #include "libgadu.h" //libgadu :-) #include <errno.h> //błędy int main(int argc, char **argv) { struct gg_session *sess; struct gg_event *e; struct gg_login_params p; if (argc < 5) { fprintf(stderr, "użycie: %s <numer> <hasło> <plik> <wiadomość>n", argv[0]); return 1; } gg_debug_level = 0; /* Deklarujemy zmienne potrzebne do zliczenia ilości wierszy w pliku */ FILE *plik; int wiersz = 0; char znak; //Jeśli nie ma pliku z numerami if((plik = fopen(argv[3], "r")) == NULL) { //Informujemy o błędzie i kończymy działanie programu printf("Nie mogę otworzyć pliku n"); return 1; } //Dopóki nie dojedziemy do końca pliku while((znak = getc(plik)) != EOF) { if(znak == 'n') { //Zliczamy ilość wierszy ++wiersz; } } /* Odczytujemy wiersz po wierszu z pliku i wypisujemy wartość */ FILE *pFile; int i=0; char numerek[3]; pFile = fopen(argv[2], "r"); /* Jeśli nie ma pliku z numerami Informujemy o błędzie i kończymy działanie programu */ if(pFile == NULL) { printf("Błąd odczytu pliku"); return 1; } else { //Dane do zalogowania na serwer memset(&p, 0, sizeof(p)); p.uin = atoi(argv[2]); p.password = argv[2]; //Aby dostarczać polskie znaczki :-) p.encoding = GG_ENCODING_UTF8; if (!(sess = gg_login(&p))) { printf("Nie udało się połączyć: %sn", strerror(errno)); gg_free_session(sess); return 1; } //Wysyłamy userliste if (gg_notify(sess, NULL, 0) == -1) { printf("Połączenie przerwane: %sn", strerror(errno)); gg_free_session(sess); return 1; } /* Jazda ;D */ for(i=0;i<=wiersz-1;i++) { fgets(numerek, 131072, pFile); //Deklaracja zmiennej pomocniczej, //Aby pozbyć się znaku spacji //Na końcu zmiennej char x; x=strlen(numerek); numerek[x-1]='�'; //Wysyłamy wiadomość w pętli if (gg_send_message(sess, GG_CLASS_MSG, atoi(numerek), (unsigned char*) argv[4]) == -1) { printf("Połączenie przerwane: %sn", strerror(errno)); gg_free_session(sess); return 1; } //Informacja printf(">>Wysłano do: %sn", numerek); } //Log out gg_logoff(sess); gg_free_session(sess); } return 0; //Zakończenie programu }
[/codesyntax]
Zapiszmy go pod nazwą wysylanie.c. Program pobiera od użytkownika numer, hasło, plik z numerami oraz wiadomość do wysłania.
$ ./wysylanie nasz_numer nasze_haslo numery.txt "Siemka :*" >>Wysłano do: 1234567 >>Wysłano do: 7654321 >>Wysłano do: 1122334 >>Wysłano do: 4455663 >>Wysłano do: 5897514 >>Wysłano do: 48541858 komeniusz@cyber-jadro:~/libgadu-1.9.0-rc2/examples$
UWAGA!
W programie zawarte jest zabezpieczenie anti script kiddie, aby ktoś, kto nie rozumie programu nie miał możliwości bezmyślnego SPIM’owania innych użytkowników.
Jeśli komuś uda się już uruchomić program może go wykorzystać np. do informowania znajomych o jakiejś uroczystości takiej jak impreza urodzinowa lub do składania z życzeń z okazji świat.
a tym, którzy chcą bezproblemowo wysłać 😉 paczkę kurierem, szybko i tanio, polecam serwis http://www.kurjerzy.pl/