Sari la conținut

Postări Recomandate

  • Moderators
Postat

** Obiective **

  • Construim o structura de Utilizatori LGCS cu campuri precum : ID , Nume , Adresa de Mail , Parola , NrPosturi , isBanned dar si rolurile din care face parte ;
  • Constituim o lista inlantuita (generica) cu toate componentele acestuia (POINTER DE REFERINTA SI INFORMATIE) 
  • Inseram date  dintr-un fisier text  (pe care l voi pune in atasament) .  
  • Completam lista cu toate datele din fisier ; 
  • Afisam & Eliberam Toata Lista . 

NOTA ** : Vom folosi proiectul din tutorialele trecute de Structuri . (Cu Roluri)

** Declarare Structura Utilizatori LGCS ** 

// User.h

typedef struct User
{
	// INFORMATIE UTILIZATOR 
     unsigned id;  // ID UTILIZATOR 
	 char* username;  // NUME UTILIZATOR 
	 char* email;  // ADRESA MAIL UTILIZATOR 
	 char* password;   // PAROLA UTILIZATOR 
	 unsigned nrPosts;  // NUMAR POSTURI 
	 unsigned isBanned; // NU AVEM VALOARE BOOLEANA IN C (bool) ==> "1" E TRUE  && "0" E FALSE 
	 Role* roles; // Colectie de grupuri din care face parte utilizatorul 
}User;

** Declarare Lista Inlantuita ** 

// Lists.h   ----> FISIER NOU  

typedef struct Linked_List{  // LISTA INLANTUITA GENERICA (O PUTEM FOLOSI CU ORICE TIP DE DATE FARA SA DECLARAM MAI MULTE STRUCTURI)
	void* Data;           // Pastram informatia pentru elementul curent 
Linked_List* nextElement;  // Ne corelam cu urmatorul element 
}LinkedList; // Asta reprezinta o eticheta pentru structura ==> Scriem "LinkedList" inloc de "struct Linked_List"  

NOTA ** :  "void*" REPREZINTA un caz particular in C , o modalitatea de a substitui mai multe tipuri de date pentru a EVITA declararea Listei  pentru fiecare tip de date . De exemplu ,  daca doresc ca lista sa fie folosita apoi , pentru structura "studenti" sau "masini" sau altceva , o putem refolosi fara sa facem lista pentru fiecare tip de structura . (tip de date) 

** Preluare Utilizator din Fisier ** 

 Declaram o functie pentru incarcarea datelor din fisier in vederea initializarii structuri : 

// User.h 

/// Structura & Restu Codului 

#include "roles.h" // Avem nevoie pentru tipul de date Role 

#define FILENAME_USER_INPUT "dateIntrareUtilizatoriLeagueCS.txt"  // Definim un nume pentru intrare 

User* fetchUsersFromTxtFile(FILE* inputTxt,Role* roles); // Incarcam o colectie de utilizatori din fisier  

Ne asiguram ca putem stoca suficient spatiu pentru fiecare linie : 

// stringHandling.h 

// Restu Codului 

#define MAX_STRING_LINE 256 // Alocam maxim 256 de caractere pentru linii 

Trecem la implementarea codului pentru incarcarea utilizatorului din fisier !! 

// user.c 

#include "User.h"  // legam cu fisierul asociat acestuia (de unde vin declaratiile)

User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles)  // Implementam functia de inserare a datelor 
{ 
     // Implementare
}

Verificam daca fisierul este eligibil pentru inserare :

// user.c

User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles)  // Implementam functia de inserare a datelor 
{ 
     if (!checkFile(inputTxt))
	return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei  
}

Daca totul e ok , declaram o colectie de utilizatori dar si un contor pentru indexare : 

// user.c

User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles)  // Implementam functia de inserare a datelor 
{ 
     if (!checkFile(inputTxt))
	return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei  
    
    unsigned i = 1;  // Pentru accesarea elementelor curente va fi (i-1)
    User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) 
  
}

Adaugam o colectie de caractere , ca intermediar , pentru preluare a linie cu linie din fisier :

// user.c

User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles)  // Implementam functia de inserare a datelor 
{ 
     if (!checkFile(inputTxt))
	return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei  
    
    unsigned i = 1;  // Pentru accesarea elementelor curente va fi (i-1)
    User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) 
  
    char bufferLine[MAX_STRING_LINE]; // Cu spatiu alocat explicit mai sus 
  
}

Citim linie cu linie din fisier cu "fgets" (pana la finalul fisierului) iar continutul (toata linia) o oferim colectiei declarate mai sus : 

// user.c

User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles)  // Implementam functia de inserare a datelor 
{ 
     if (!checkFile(inputTxt))
	return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei  
    
    unsigned i = 1;  // Pentru accesarea elementelor curente va fi (i-1)
    User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) 
  
    char bufferLine[MAX_STRING_LINE]; // Cu spatiu alocat explicit mai sus 
  
    while ((fgets(bufferLine, MAX_STRING_LINE, inputTxt)) != NULL)  // Citim Linie cu Linie din Fisier 
    {
      // Implementare
    }
  
}

 Citim si inseram in colectia de Utilizatori , informatiile despre ID , NUME , EMAIL , PAROLA , NUMAR POSTURI SI DACA E BANAT : 

// user.c

User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles)  // Implementam functia de inserare a datelor 
{ 
     if (!checkFile(inputTxt))
	return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei  
    
    unsigned i = 1;  // Pentru accesarea elementelor curente va fi (i-1)
    User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) 
  
    char bufferLine[MAX_STRING_LINE]; // Cu spatiu alocat explicit mai sus 
  
    while ((fgets(bufferLine, MAX_STRING_LINE, inputTxt)) != NULL)  // Citim Linie cu Linie din Fisier 
    {
       char*Token, *nextToken; // Prima va retine informatia curenta iar cealalta referinta la cea mai ramas din linie 

// Inseram Date

/// ID 
Token = strtok_s(bufferLine,DELIMITATER,&nextToken); // Preluam ID-ul din linie in format de STRING
newUser[i-1].id = atoi(Token); // Convertim din string in intreg + Il Incarcam in Structura 

// NUME 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMELE din linie in format de STRING 
allocAndFetchString(&newUser[i-1].username,Token); // Il Incarcam in Structura 


// Adresa de Mail 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING 
allocAndFetchString(&newUser[i-1].email, Token);  // Il Incarcam in Structura 

// Parola
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING 
allocAndFetchString(&newUser[i-1].password, Token);  // Il Incarcam in Structura 

// NrPosts 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMARUL DE POSTURI DIN STRUCTURA 
newUser[i-1].nrPosts = atoi(Token); // CONVERTIM DIN STRING IN INTREG SI IL INCARCAM 

// e Banat 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // IDEM 
newUser[i-1].isBanned = atoi(Token);
    }
}

Acum , traversam toate rolurile inserate din tutorialul anterior iar apoi le vom asocia cu id-urile rolurilor din care face parte utilizatorul curent : 

// user.c

User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles)  // Implementam functia de inserare a datelor 
{ 
     if (!checkFile(inputTxt))
	return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei  
    
    unsigned i = 1;  // Pentru accesarea elementelor curente va fi (i-1)
    User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) 
  
    char bufferLine[MAX_STRING_LINE]; // Cu spatiu alocat explicit mai sus 
  
    while ((fgets(bufferLine, MAX_STRING_LINE, inputTxt)) != NULL)  // Citim Linie cu Linie din Fisier 
    {
       char*Token, *nextToken; // Prima va retine informatia curenta iar cealalta referinta la cea mai ramas din linie 

// Inseram Date

/// ID 
Token = strtok_s(bufferLine,DELIMITATER,&nextToken); // Preluam ID-ul din linie in format de STRING
newUser[i-1].id = atoi(Token); // Convertim din string in intreg + Il Incarcam in Structura 

// NUME 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMELE din linie in format de STRING 
allocAndFetchString(&newUser[i-1].username,Token); // Il Incarcam in Structura 


// Adresa de Mail 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING 
allocAndFetchString(&newUser[i-1].email, Token);  // Il Incarcam in Structura 

// Parola
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING 
allocAndFetchString(&newUser[i-1].password, Token);  // Il Incarcam in Structura 

// NrPosts 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMARUL DE POSTURI DIN STRUCTURA 
newUser[i-1].nrPosts = atoi(Token); // CONVERTIM DIN STRING IN INTREG SI IL INCARCAM 

// e Banat 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // IDEM 
newUser[i-1].isBanned = atoi(Token);
    
   // Grupurile din care face parte 

unsigned j = 1; // (Accesul la itemul curent se va face la (j-1))

while ((Token = strtok_s(NULL, DELIMITATER, &nextToken)) != NULL) // Preluam ID cu ID
{
	unsigned targetIdRole, k = 0;
	targetIdRole = atoi(Token); // Convertim ID-ul din string in intreg 

	do {
		if (targetIdRole == roles[k].id) // DACA AM REGASIT ID-UL IN COLECTIE DE ROLURI 
		{
			newUser[i-1].roles = j == 1 ?
				(Role*)malloc(sizeof(Role)) // DACA SUNTEM LA PRIMA ITERATIE 
				: (Role*)realloc(newUser[i-1].roles, sizeof(Role) * j); // DACA SUNTEM LA J ITERATIE
			// Preluam Referintele (ODATA ELIBERATE ROLURILE SI ELE ISI VOR PIERDE INFORMATIA )
			newUser[i-1].roles[j-1].id = roles[k].id;
			newUser[i-1].roles[j-1].nameRole = roles[k].nameRole;
			newUser[i-1].roles[j-1].isLastRole = 0; // NU ESTE ULTIMUL ELEMENT DIN LISTA 
			break; // NU ARE ROST SA PARCURGEM TOATA STRUCTURA 
		}
		k++; // Incrementam cu un pas 
	} while(!roles[k-1].isLastRole); // Parcurgem toate rolurile PANA AJUNGEM LA ULTIMUL 
	j++;  // Marim colectia cu un element 
}
newUser[i-1].roles[j-2].isLastRole = 1; // ESTE ULTIMUL ELEMENT DIN LISTA 
    
    }
}

Verificam daca mai avem continut in fisier . Daca da , vom realoca un nou utilizatori (in functie de cati utilizatori sunt introdusi in fisier) . Daca nu , se opreste iteratia si se returneaza ce am adaugat : 

// user.c

User* fetchUsersFromTxtFile(FILE* inputTxt, Role* roles)  // Implementam functia de inserare a datelor 
{ 
     if (!checkFile(inputTxt))
	return NULL; // Fisier Invalid + Returnam o valoare NULA Colectiei  
    
    unsigned i = 1;  // Pentru accesarea elementelor curente va fi (i-1)
    User* newUser = (User*)malloc(sizeof(User)); // Alocam pentru un utilizator (MOMENTAN) 
  
    char bufferLine[MAX_STRING_LINE]; // Cu spatiu alocat explicit mai sus 
  
    while ((fgets(bufferLine, MAX_STRING_LINE, inputTxt)) != NULL)  // Citim Linie cu Linie din Fisier 
    {
       char*Token, *nextToken; // Prima va retine informatia curenta iar cealalta referinta la cea mai ramas din linie 

// Inseram Date

/// ID 
Token = strtok_s(bufferLine,DELIMITATER,&nextToken); // Preluam ID-ul din linie in format de STRING
newUser[i-1].id = atoi(Token); // Convertim din string in intreg + Il Incarcam in Structura 

// NUME 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMELE din linie in format de STRING 
allocAndFetchString(&newUser[i-1].username,Token); // Il Incarcam in Structura 


// Adresa de Mail 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING 
allocAndFetchString(&newUser[i-1].email, Token);  // Il Incarcam in Structura 

// Parola
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam EMAIL din linie in format de STRING 
allocAndFetchString(&newUser[i-1].password, Token);  // Il Incarcam in Structura 

// NrPosts 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // Preluam NUMARUL DE POSTURI DIN STRUCTURA 
newUser[i-1].nrPosts = atoi(Token); // CONVERTIM DIN STRING IN INTREG SI IL INCARCAM 

// e Banat 
Token = strtok_s(NULL, DELIMITATER, &nextToken); // IDEM 
newUser[i-1].isBanned = atoi(Token);
    
   // Grupurile din care face parte 

unsigned j = 1; // (Accesul la itemul curent se va face la (j-1))

while ((Token = strtok_s(NULL, DELIMITATER, &nextToken)) != NULL) // Preluam ID cu ID
{
	unsigned targetIdRole, k = 0;
	targetIdRole = atoi(Token); // Convertim ID-ul din string in intreg 

	do {
		if (targetIdRole == roles[k].id) // DACA AM REGASIT ID-UL IN COLECTIE DE ROLURI 
		{
			newUser[i-1].roles = j == 1 ?
				(Role*)malloc(sizeof(Role)) // DACA SUNTEM LA PRIMA ITERATIE 
				: (Role*)realloc(newUser[i-1].roles, sizeof(Role) * j); // DACA SUNTEM LA J ITERATIE
			// Preluam Referintele (ODATA ELIBERATE ROLURILE SI ELE ISI VOR PIERDE INFORMATIA )
			newUser[i-1].roles[j-1].id = roles[k].id;
			newUser[i-1].roles[j-1].nameRole = roles[k].nameRole;
			newUser[i-1].roles[j-1].isLastRole = 0; // NU ESTE ULTIMUL ELEMENT DIN LISTA 
			break; // NU ARE ROST SA PARCURGEM TOATA STRUCTURA 
		}
		k++; // Incrementam cu un pas 
	} while(!roles[k-1].isLastRole); // Parcurgem toate rolurile PANA AJUNGEM LA ULTIMUL 
	j++;  // Marim colectia cu un element 
}
newUser[i-1].roles[j-2].isLastRole = 1; // ESTE ULTIMUL ELEMENT DIN LISTA 
    
      	if (!feof(inputTxt))  // Daca mai sunt date in fisier 
		newUser = realloc(newUser, sizeof(User) * (++i)); // Mai alocam un utilizator 

     }

return newUser; // Returnam colectia 
}

IN TUTORIALUL ACESTA NU VOI INTRODUCE IN LISTE , UTILIZATORI  DAR VOM AFISA CONTINUTUL SI LE VOM STERGE (SUB FORMA DE ARRAY) (ASA CA BONUS :) ) 

Declaram functiile de afisare si stergere : 

// User.h 

// Restu codului 

void printUser(User user);
void freeUser(User user);

Le implementam : 

/// User.c 

// Restu Codului

void printUser(User user)
{
	static unsigned i = 0;  // Retinem i pe toate apelurile 
	printf_s("User %d : { \n",i);
	printf_s("\tID UTILIZATOR: %d ,\n",user.id);
	printf_s("\tNUME UTILIZATOR: %s ,\n",user.username);
	printf_s("\tADRESA MAIL UTILIZATOR: %s ,\n",user.email);
	printf_s("\tPAROLA : %s ,\n",user.password);
	printf_s("\tNUMAR POSTURI : %d ,\n", user.nrPosts);
	printf_s("\tESTE BANAT : %s ,\n", user.isBanned ? "DA" : "NU");
	printf_s("\t\tROLURI DETINUTE : {\n");
	unsigned j = 0;
	do {
		printf_s("\n\tID ROL : %d | NUME ROL :%s",user.roles[j].id,user.roles[j].nameRole);
		j++;
	} while(!user.roles[j-1].isLastRole);

	printf_s("\n}\n}");

	i++;
}

void freeUser(User user)
{
	//Stergem sirurile de caractere  
	free(user.username);
	free(user.email);
	free(user.password);
	
	// ROLURILE VOR FI STERSE SEPARATE in functia freeRoles() 
}

Acum , afisam in functia principala utilizatorii iar pe urma , ii stergem : 

// entryPoint.c

/* Legam toate entry point toate headerele dependente */
#include "../StructuriDate/roles.h" 
#include "../StructuriDate/fileHandling.h"
#include "../StructuriDate/User.h"
#include "../StructuriDate//Lists.h"

// stringHandling.h nu este dependent de entry point
// 

// CONSTANTELE MACRO SUNT UTILE CA LE PUTEM UTILIZA LA NIVEL GLOBAL (PE TOT FISIERUL)
// NOTA** :  E O PRACTICA BUNA DE A FOLOSI MACRO SPRE DEOSEBIRE DE CONSTANTE "MAGICE" (NUMERE PRIN COD)

#define NR_FILES   2  // STABILIM UN NUMAR DE FISIERE


int main()
{
	FILE** file = NULL; 

	file = (FILE**)malloc(sizeof(FILE*)*NR_FILES); // DECLARAM O COLECTIE DE FISIERE 

	file[0] = openFile(FILENAME_INPUT_ROLES, READMODE_TXT); // CITIM ROLURILE DINTR-UN FISIER TEXT 
	file[1] = openFile(FILENAME_USER_INPUT, READMODE_TXT); // CITIM UTILIZATORI DINTR-UN FISIER TEXT 

	// dateIntrareLeagueCS.txt && dateIntrareRoluriLeagueCS.txt TREBUIE SA EXISTE IN DIRECTOR (ALTFEL VA ESUA)

	Role* roles = fetchRoles(file[0]); // Am primit lista cu rolurile 

	User* users = fetchUsersFromTxtFile(file[1],roles); // Am primit informatia despre utilizatori 

	for (int i = 0; i < 6; i++) {  // CUNOASTEM CA SUNT SASE ENTITATI 
		printUser(users[i]); // Accesul prin index (Array) --> AFISAM UTILIZATORUL CURENT 
		freeUser(users[i]); // STERGEM UTILIZATORUL CURENT 
	}

	// ELIBERAM RESURSELE 
	freeRoles(&roles); // Eliberam resursele ocupate de entitate 
	free(users); // Stergem colectia
	closeFiles(&file,NR_FILES); // Eliberam resursele ocupate de fisiere 

	if (file == NULL)
		printf("COLECTIA DE FISIERE A FOST ELIBERATA CU SUCCES !! ");


	return 0;
}

Si primim ca output : 

**FISIERUL dateIntrareRoluriLeagueCS.txt S-A DESCHIS CU SUCCES !**
**FISIERUL dateIntrareUtilizatoriLeagueCS.txt S-A DESCHIS CU SUCCES !**
User 0 : {
        ID UTILIZATOR: 0 ,
        NUME UTILIZATOR:  Alin  ,
        ADRESA MAIL UTILIZATOR:  alidsadan@gmail.com  ,
        PAROLA :  dsdasdadsadadc  ,
        NUMAR POSTURI : 100 ,
        ESTE BANAT : NU ,
                ROLURI DETINUTE : {

        ID ROL : 0 | NUME ROL : Membru

        ID ROL : 3 | NUME ROL : Super Moderator

        ID ROL : 4 | NUME ROL : Administrator
        ID ROL : 1 | NUME ROL : Utilizator Premium

}
}User 1 : {
        ID UTILIZATOR: 1 ,
        NUME UTILIZATOR:  Alinds  ,
        ADRESA MAIL UTILIZATOR:  alidasdsan@gmail.com  ,
        PAROLA :  dsavvcvdc  ,
        NUMAR POSTURI : 50 ,
        ESTE BANAT : NU ,
                ROLURI DETINUTE : {

        ID ROL : 0 | NUME ROL : Membru

        ID ROL : 1 | NUME ROL : Utilizator Premium

}
}User 2 : {
        ID UTILIZATOR: 2 ,
        NUME UTILIZATOR:  Alivcxvxcn  ,
        ADRESA MAIL UTILIZATOR:  alidsadvfcn@gmail.com  ,
        PAROLA :  dsewqqewqadc  ,
        NUMAR POSTURI : 550 ,
        ESTE BANAT : NU ,
                ROLURI DETINUTE : {

        ID ROL : 3 | NUME ROL : Super Moderator

        ID ROL : 1 | NUME ROL : Utilizator Premium

}
}User 3 : {
        ID UTILIZATOR: 3 ,
        NUME UTILIZATOR:  Alifdsfn  ,
        ADRESA MAIL UTILIZATOR:  alewewin@gmail.com  ,
        PAROLA :  dsfdsfsdfsadc  ,
        NUMAR POSTURI : 3300 ,
        ESTE BANAT : NU ,
                ROLURI DETINUTE : {

        ID ROL : 0 | NUME ROL : Membru

        ID ROL : 1 | NUME ROL : Utilizator Premium

        ID ROL : 2 | NUME ROL : Moderator

        ID ROL : 3 | NUME ROL : Super Moderator

        ID ROL : 4 | NUME ROL : Administrator
}
}User 4 : {
        ID UTILIZATOR: 4 ,
        NUME UTILIZATOR:  Alie2qweqn  ,
        ADRESA MAIL UTILIZATOR:  alcxsaxcadsain@gmail.com  ,
        PAROLA :  dsvcvvvvadc  ,
        NUMAR POSTURI : 11100 ,
        ESTE BANAT : NU ,
                ROLURI DETINUTE : {

        ID ROL : 0 | NUME ROL : Membru

}
}User 5 : {
        ID UTILIZATOR: 5 ,
        NUME UTILIZATOR:  Alidasdadan  ,
        ADRESA MAIL UTILIZATOR:  alidasdassdadn@gmail.com  ,
        PAROLA :  dsvvvvvvvvradc  ,
        NUMAR POSTURI : 134300 ,
        ESTE BANAT : NU ,
                ROLURI DETINUTE : {

        ID ROL : 0 | NUME ROL : Membru

        ID ROL : 2 | NUME ROL : Moderator

        ID ROL : 1 | NUME ROL : Utilizator Premium

        ID ROL : 3 | NUME ROL : Super Moderator

}
}COLECTIA DE FISIERE A FOST ELIBERATA CU SUCCES !!

NOTA ** : PENTRU A FUNCTIONA ALGORITMUL , SE POT ADAUGA UTILIZATORI LA DISCRETIA VOASTRA DOAR SA PASTREZE MODELUL : 

id | nume | email | parola | nrPosturi | banat(1/0) | (AICI SE ADAUGA ID-URILE ROLURILOR DIN CARE FACE PARTE DESPARTITE DE "|")     ==> LINIE 
.... 
....
... 

AVETI SABLONUL IN ATASAMENT 

dateIntrareUtilizatoriLeagueCS.txt

Vizitator
Acest topic este acum închis pentru alte răspunsuri.
  • Navigare recentă   0 membri

    • Nici un utilizator înregistrat nu vede această pagină.
×
×
  • Creează nouă...

Informații Importante

Termeni de Utilizare & Politică Intimitate