Kadu_logoW 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

/*
 * 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;
}

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

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_*).

Napiszmy program, który wypełni kilka parametrów interesującej nas struktury.

/*
 * 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;
}

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.

//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
}

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.

/*
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
}

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.