Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Servidor FTP - desenvolvido em ambiente windows
- //Luiz Vinicius Soglia
- /* Glossario:
- DTP = data transfer port*/
- /* linkar as seguintes bibliotecas:
- libws2_32
- */
- /*==============================================================================
- Para criar uma lista de clientes que podem acessar o servidor FTP siga os seguintes passos:
- 1) No mesmo diretório onde se encontra o executável do programa crie um arquivo de texto
- do tipo .txt, chamado Clientes.txt (com C maiúsculo no início)
- 2) No arquivo Clientes.txt adicione os clientes, da seguinte forma:
- Nome do cliente
- Senha do cliente
- permissão para escrita (digite 0 para não ou 1 para sim)*
- *permissão para escrita consiste em permitir a um cliente:
- - Fazer upload de arquivos para o servidor
- - Renomear e Deletar arquivos
- - Criar, Renomear e Deletar Diretórios
- Exemplo:
- Cadastro dos clientes Maria (senha 1234abcd) e Gabriel (senha xyz4321),
- sendo que Maria tem permissão para escrita e Gabriel não tem permissão para escrita:
- ====== Início do arquivo Clientes.txt ======
- Maria
- 1234abc
- 1
- Gabriel
- xyz4321
- 0
- ====== Fim do arquivo Clientes.txt =========
- ==============================================================================*/
- #ifdef _WIN32 //windows
- #ifndef WIN32_LEAN_AND_MEAN //evita conflitos entre a biblioteca winsock, incluida em windows, e winsock2
- #define WIN32_LEAN_AND_MEAN
- #endif
- #include <winsock2.h>
- #include <iostream>
- #include <dir.h> // classe para manipular diretórios
- #include <dirent.h> // classe para manipular diretórios
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <time.h>
- #endif
- #define MAX_MSG 2048 //tamanho máximo da msg
- #define MAX_CLIENTES 64 //maximo de clientes que podem se conectar ao servidor
- #define MAX_TRANSF 64 //Suporta MAX_TRANSF transferencias simultaneamente
- using namespace std;
- HANDLE Hmutex; // Um mutex é basicamente é um objeto que pode ser utilizado para sincronizar threads,
- //evitando acessos a um ponto de memoria ao mesmo tempo, como variaveis globais
- int thread [MAX_CLIENTES]; //identificadores das Threads
- HANDLE Hthread [MAX_CLIENTES]; //Handles das Threads
- int thread_transf [MAX_TRANSF]; //identificadores das Threads
- HANDLE Hthread_transf [MAX_TRANSF]; //numero de Handles dimensionado para Suportar MAX_TRANSF transferencias ao mesmo tempo
- int n_clientes_conectados=0; //numero de clientes conectados
- //estrutura utilizada para guardar dados de cliente
- struct cliente_estrutura {
- char ID[64]; //guarda ID de cliente com ate 64 caracteres
- char Senha[64]; //guarda a senha do cliente
- char IP[64]; //guarda o IP do cliente
- int Socket; //guarda Socket de cliente
- int pos; //guarda a posicao do cliente nas matrizes de handles e identificadores de Threads
- };
- typedef cliente_estrutura cliente_tipo;
- struct struct_dados_transferencia //estrutura que guarda os dados que serão passados para as funções de transferencia de arquivos
- {
- int data_Socket;
- int controle_Socket;
- int pos; //guarda a posicao da transferencia atual nas matrizes de handles e identificadores de Threads
- char endereco_arq[260];
- };
- typedef struct_dados_transferencia dados_transferencia;
- char dir_fisico[260], IP_server[64], host_server[260], padrao_listagem;
- int porta_pasv, server_DTSocket, anonymous_enable = 0;
- //callback de funcoes
- int Aceita_Conexoes (int serverSocket, int max_clientes, char *ID_servidor);
- int Aceita_msgs (cliente_tipo *Cli);
- int Listen_Socket (int porta, int n_conexoes);
- int Connect_Socket (int porta, char *host);
- void Desconecta_Cliente (cliente_tipo *Cli, bool msg_on, int info_type);
- void Finaliza_Conexao (int serversocket);
- void formata_IP (char *IP_server, char *IP_formatado);
- void obtem_ip_porta (char *host_port, char *IP_Cliente, int *user_DTP);
- int arquivo_existe (const char *filename);
- int envia_listadir (char padrao_listagem, char *gpath, int user_DTSocket);
- int tamanho_dir (char *dir, unsigned long *tamanho);
- int envia_arquivo(dados_transferencia *dados);
- int recebe_arquivo(dados_transferencia *dados);
- int deleta_arquivo(dados_transferencia *dados);
- int deleta_diretorio(char *gdir);
- int carrega_cliente (char *ID, char *Senha, int *permissao_escrita);
- //===============================================================================
- //FUNCAO PRINCIPAL DO SERVIDOR
- int main()
- {
- char ID_servidor[64], op;
- int serverSocket, porta, max_clientes, n;
- bool config_load = false; //se torna true se configuracoes anteriores sao carregadas
- for (n=0; n<MAX_CLIENTES; n++) //inicializa identificadores de Threads com um valor nulo
- {thread[n]=-1;}
- for (n=0; n<MAX_TRANSF; n++)
- {thread_transf[n]=-1;}
- if (arquivo_existe ("CONFIG_SERVIDOR.txt") == 1) //existe uma configuracao salva
- {
- FILE *config;
- if ((config = fopen ("CONFIG_SERVIDOR.txt", "r")) != NULL)
- {
- int teste=0;
- //faz a leitura de dados do arquivo CONFIG_SERVIDOR.txt
- host_server[0]='\0';
- fscanf (config, "%259[^\n]\n", host_server);
- ID_servidor[0]='\0';
- fscanf (config, "%63[^\n]\n", ID_servidor);
- dir_fisico[0]='\0';
- fscanf (config, "%259[^\n]\n", dir_fisico);
- fscanf (config, "%d %d %d", &porta, &porta_pasv, &max_clientes);
- fclose (config);
- //faz testes para saber se os dados lidos estão corretos
- if (strlen(host_server) < 1) {teste=1;}
- if (strlen(ID_servidor) < 1) {teste=1;}
- DIR *pdir;
- if (strlen(dir_fisico) < 1 || strlen(dir_fisico) > PATH_MAX)
- {teste=1;}
- else
- {
- pdir = opendir (dir_fisico);
- if (pdir == NULL) //diretorio nao existe
- {teste=1;}
- else //caso exista
- {closedir (pdir);}
- }
- if (porta < 1 || porta > 1023) {teste = 1;}
- if (porta_pasv < 1024) {teste = 1;}
- if (max_clientes < 1 || max_clientes > MAX_CLIENTES) {teste = 1;}
- //se os testes apontarem que os dados estão corretos
- if (teste == 0)
- {
- cout << "Existe uma configuracao salva:\n" << endl;
- cout << "Host do servidor: " << host_server << endl;
- cout << "Porta para conexao de controle: " << porta << endl;
- cout << "Porta inicial para conexao de dados no modo passivo: " << porta_pasv << endl;
- cout << "ID de Boas Vindas do servidor: " << ID_servidor << endl;
- cout << "Diretorio fisico compartilhado:\n" << dir_fisico << endl;
- cout << "Maximo de clientes conectados ao servidor: " << max_clientes << endl;
- cout << "\nDeseja carrega-la? ([s] para SIM e [n] para NAO): ";
- op = getchar(); fflush(stdin);
- if (op == 's' || op == 'S')
- {config_load = true; cout << "Configuracao carregada!" << endl;}
- }
- }
- }
- if (!config_load) //se nao foi carregada uma configuracao entra no modo manual
- {
- system ("CLS");
- cout << "Deseja utilizar Dynamic DNS - URL Passiva - para acesso externo?" << endl;
- cout << "[s] para SIM ou [n] para NAO): ";
- op = getchar(); fflush (stdin);
- if (op == 's' || op == 'S')
- {
- cout << "Host do Servidor (URL passivo):" << endl;
- host_server[0]='\0';
- scanf("%259[^\n]", host_server); fflush (stdin);
- //tratamento contra erros de digitacao
- if (strlen(host_server)<1) {strcpy(host_server, "localhost");}
- }
- else
- {
- cout << "O Servidor utiliza o IP local" << endl;
- strcpy(host_server, "localhost");
- }
- cout << "Digite a porta para conexao de controle do servidor (Padrao: 21): ";
- scanf ("%d", &porta); fflush (stdin);
- if (porta < 1 || porta > 1023) {porta=21;} //tratamento contra erros de digitacao - até a porta 1023 elas são
- //consideradas reservadas (alta prioridade) - usadas em FTP para conexão de controle
- cout << "Digite a porta inicial para conexao de dados no modo passivo (Ex: 7700): ";
- scanf ("%d", &porta_pasv); fflush (stdin);
- if (porta_pasv < 1024) {porta_pasv=1024;} //tratamento contra erros de digitacao - a partir de 1024 as portas
- //são consideradas de baixa prioridade - usadas em FTP para conexão de dados no modo passivo
- cout << "Crie uma ID de Boas Vindas para o Servidor: ";
- ID_servidor[0]='\0';
- scanf("%63[^\n]", ID_servidor); fflush (stdin);
- //tratamento contra erros de digitacao
- if (strlen(ID_servidor)<1) {strcpy(ID_servidor, "Servidor FTP"); cout << "ID de Boas Vindas do servidor: " << ID_servidor << endl;}
- bool teste;
- do
- {
- teste=false;
- DIR *pdir;
- cout << "Diretorio fisico que sera compartilhado (Ex: C:/Arquivos/Textos):" << endl;
- dir_fisico[0]='\0';
- scanf("%259[^\n]", dir_fisico); fflush (stdin);
- if (strlen(dir_fisico) > PATH_MAX)
- {teste=true;}
- else
- {
- pdir = opendir (dir_fisico);
- if (pdir == NULL)
- {teste=true;}
- }
- if (teste)
- {cout << "Erro! diretorio nao existe!" << endl;}
- else {closedir (pdir);}
- }
- while (teste);
- cout << "Numero de clientes que podem se conectar ao servidor (maximo de " << MAX_CLIENTES << "): ";
- scanf ("%d", &max_clientes); fflush (stdin);
- if (max_clientes<1 || max_clientes>MAX_CLIENTES) {max_clientes=MAX_CLIENTES;} //se digitado errado assume o valor maximo de MAX_CLIENTES
- cout << " " << endl;
- //salva configuracoes
- cout << "Deseja salvar esta configuracao? ([s] para SIM e [n] para NAO): ";
- char op = getchar(); fflush (stdin);
- if (op == 's' || op == 'S') //salvar
- {
- FILE *config;
- if ((config = fopen ("CONFIG_SERVIDOR.txt", "w")) != NULL)
- {
- fprintf (config, "%s\n%s\n%s\n%d %d %d", host_server, ID_servidor, dir_fisico, porta, porta_pasv, max_clientes);
- fclose (config);
- cout << "Configuracao salva!" << endl;
- }
- else
- {cout << "Erro ao salvar configuracao!" << endl;}
- }
- }
- //pergunta sobre login como anonymous
- cout << "\nPermitir login no servidor como anonymous?\n";
- cout << "Cliente anonymous tem permissao somente para navegacao entre diretorios\ne uso da funcao download. Digite [0] para Nao ou [1] para Sim: ";
- scanf ("%d", &anonymous_enable); fflush (stdin);
- if (anonymous_enable != 1) {anonymous_enable=0;} //se digitado um valor diferente de 1, assume o valor "desativado" para o uso de login anonymous
- //pergunta sobre o padrão de envio de informações (listagem de diretórios no padrão UNIX ou MS-DOS)
- cout << "\nQual o padrao de envio da listagem de diretorios?\nDigite [0] para UNIX ou [1] para MS-DOS: ";
- padrao_listagem = getchar(); fflush (stdin);
- if (padrao_listagem != '0') {padrao_listagem = '1';}
- //cria o Socket do servidor e o coloca em modo de escuta
- serverSocket = Listen_Socket (porta, MAX_CLIENTES);
- if (serverSocket == -1)
- {
- cout << "\nErro: erro na criacao do socket para escuta do servidor!\n" << endl;
- Finaliza_Conexao (serverSocket);
- cout << "Pressione uma tecla para sair...\n" << endl;
- fflush(stdin); getchar();
- return 0;
- }
- //cria um socket inicial para conexao de dados
- int DTP_padrao=porta-1; //porta para transferencia de dados - se a porta de controle é a 21, logo porta de dados será 21-1=20
- do{
- server_DTSocket = Listen_Socket (DTP_padrao, 10);
- DTP_padrao += 2; //se a porta 20 nao for possivel vai incremetando a porta de 2 em 2 ate obter um socket válido
- }
- while (server_DTSocket == -1);
- Hmutex = CreateMutex(NULL, false, NULL);// Create the mutex
- if (Hmutex == NULL)
- {
- cout << "\nErro: problemas ao criar o Mutex!\n" << endl;
- Finaliza_Conexao (serverSocket);
- cout << "Pressione uma tecla para sair...\n" << endl;
- fflush(stdin); getchar();
- return 0;
- }
- //obtem o IP e host do servidor e coloca na tela
- char hostname[260];
- gethostname(hostname,260);
- struct in_addr addr;
- struct hostent *remoteHost = NULL;
- if (stricmp (host_server, "localhost") != 0) //se o host não for o localhost, uma URL passiva esta sendo utilizada
- {strcpy(hostname, host_server);}
- remoteHost = gethostbyname(hostname);
- if (remoteHost != NULL && remoteHost->h_addrtype == AF_INET /*IPv4*/ )
- {
- cout << "\nServidor: Online!" << endl;
- cout << "Host do Servidor: " << hostname << endl;
- n=0;
- while (remoteHost->h_addr_list[n] != 0)
- {
- addr.s_addr = *(u_long *) remoteHost->h_addr_list[n];
- strcpy (IP_server, inet_ntoa(addr));
- printf("\nIP do Servidor: %s\n", IP_server);
- if (stricmp (host_server, "localhost") == 0) //se o host for o localhost, assume como host o IP local
- {
- if (anonymous_enable == 1)
- {printf("Acesso anonymous: ftp://anonymous:anonymous@%s:porta\n", IP_server);}
- printf("Acesso login: ftp://username:senha@%s:porta\n", IP_server);
- }
- else //se não for localhost assume a URL passiva como host
- {
- if (anonymous_enable == 1)
- {printf("Acesso anonymous: ftp://anonymous:anonymous@%s:porta\n", host_server);}
- printf("Acesso login: ftp://username:senha@%s:porta\n", host_server);
- }
- n++;
- }
- cout << "\nO Servidor criado pode receber conexoes de ate " << max_clientes << " clientes simultaneamente\n" << endl;
- Aceita_Conexoes(serverSocket, max_clientes, ID_servidor); //funcao em loop que recebe uma conexao e cria uma Thread
- } //exclusiva para cada cliente, que receberá as msgs de comando
- cout << "\nOcorreu um erro ou uma solicitacao de encerramento do servidor\n\nPressione uma tecla para sair...\n" << endl;
- fflush(stdin); getchar();
- return 0;
- }
- //===============================================================================
- // Aceita_Conexoes() - aceita conexões dos clientes e guarda seus dados, como socket e ID
- int Aceita_Conexoes (int serverSocket, int max_clientes, char *ID_servidor)
- {
- struct sockaddr_in client;
- int size_client = sizeof(struct sockaddr), nbytes, n;
- char buffer[MAX_MSG];
- cliente_tipo Cliente; //variavel que guarda ID e socket de cliente
- for (;;)// loop infinito
- {
- Cliente.Socket = accept (serverSocket, (struct sockaddr*)&client, &size_client); //aceita conexao
- if (Cliente.Socket != SOCKET_ERROR)
- {
- if (n_clientes_conectados >= max_clientes) //servidor lotado
- {
- strcpy (buffer, "421 Service not available, closing control connection - Servidor Lotado.\r\n");
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {cout << "Erro no envio de msg - 421 - Servidor Lotado" << endl;}
- closesocket(Cliente.Socket); continue;
- }
- else //conexao estabelecida
- {
- //envia informações sobre o servidor
- snprintf (buffer, MAX_MSG, "220 Service ready - Servidor ID: %s.\r\n", ID_servidor);
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {cout << "Erro no envio de msg 220 - Service ready" << endl; closesocket(Cliente.Socket); continue;}
- WaitForSingleObject(Hmutex, INFINITE); //obtem mutex - isso faz com que somente esse "processo" esteja ativo no programa
- //isso é necessario pq sera acessada variaveis globais, isso evita que outros processos acessem essas variaveis ao mesmo tempo
- strcpy (Cliente.IP, inet_ntoa (client.sin_addr)); //guarda o ip do cliente
- for (n=0; n<MAX_CLIENTES; n++)
- {if (thread[n]==-1) {break;}} //busca uma posicao vazia para guardar a handle e identificador da Thread que será criada
- Cliente.pos=n; //guarda essa posicao, para passar para a Thread
- strcpy (Cliente.ID, "Cliente Desconhecido"); //usuario desconhecido enquanto nao faz login
- //cria a Thread que receberá as msgs de comando vindas do cliente FTP
- Hthread[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Aceita_msgs, &Cliente, 0, (LPDWORD)&thread[n]);
- if (Hthread[n] == NULL) //erro ao criar a Thread
- {thread[n]=-1; closesocket (Cliente.Socket);}
- else {n_clientes_conectados++;}
- ReleaseMutex(Hmutex);// libera o mutex - os outros "processos" voltam a rodar
- Sleep (100); //aguarda a Thread se estabelecer para retornar ao inicio do loop
- }
- }
- } //fim do loop infinito
- Finaliza_Conexao (serverSocket);
- return 0;
- }
- //==============================================================================
- int Aceita_msgs (cliente_tipo *Cli) //receberá as msgs de comando vindas do cliente FTP
- {
- int nbytes, result, p1, p2, user_DTSocket;
- char buffer [MAX_MSG], senha_rec[64], arq_rename[260];
- char type_char='A', sec_type_char='N', transfer_mode='S', structure_code='F'; //parâmetros - seta inicialmente com valores padrão
- cliente_tipo Cliente;
- FD_SET clientSet;
- bool nao_implem=true, login=false;
- int permissao_escrita=0, ID_Ok=1;
- char dir_atual[260], dir_virtual[260], dir_fis[260];
- strcpy (dir_fis, dir_fisico); //cópia local do diretorio fisico compartilhado
- strcpy (dir_virtual, "/"); //inicializa o diretorio virtual como o padrão
- strcpy (dir_atual, dir_fis); //inicializa o diretorio fisico atual com o inicial escolhido pelo usuario
- struct stat stStat;
- WaitForSingleObject(Hmutex, INFINITE); //obtem mutex - ja que vamos acessar uma variavel global, queremos exclusividade!
- Cliente = *Cli; //cópia local
- ReleaseMutex(Hmutex);
- timeval waitTime; //estrutura que guarda o tempo de espera por atividade no socket, sera usada na funcao select
- waitTime.tv_sec = 10; //segundos - fará a funcao select esperar 10 segundos por atividade nos Sockets
- waitTime.tv_usec = 0; //microsegundos
- for (;;) // loop infinito
- {
- FD_ZERO(&clientSet); //zera lista
- FD_SET(Cliente.Socket, &clientSet); //guarda na lista o socket récem conectado
- //funcao select - espera que o socket que foi passado como parametro esteja pronto para ser lido
- result = select (Cliente.Socket+1, &clientSet, NULL, NULL, &waitTime);
- if (result == 0) //se nenhum socket mostrou atividade, nao esta pronto para ser lido
- {continue;} //volta o loop
- if (result == SOCKET_ERROR) //se houve erro na funcao select
- {Desconecta_Cliente(&Cliente, false, 0); break;} //termina o loop
- nbytes = recv(Cliente.Socket, buffer, MAX_MSG, 0); //Recebe a msg de comando vinda do cliente FTP
- if (nbytes == 0 || nbytes == SOCKET_ERROR) //se houve desconexao inesperada do cliente ou erro no envio do comando
- {Desconecta_Cliente(&Cliente, false, 0); return 1;}
- buffer[nbytes] = '\0'; //define o fim da msg recebida
- nao_implem=true; //define se uma funcao foi implementada ou nao
- cout << Cliente.ID << " diz: " << buffer << endl; //coloca na tela o conteudo da msg enviada pelo cliente
- //========================== LISTA DE COMANDOS FTP =============================
- if (strncasecmp(buffer,"USER",4) == 0) //Recebe ID do usuario - USER <SP> <usuario> <CRLF>
- {
- nao_implem=false;
- int desconecta=0;
- //extrai o nome do usuario
- int n=5; int k=0;
- while (buffer[n] != '\r' && n<nbytes)
- {Cliente.ID[k] = buffer[n]; n++; k++;}
- Cliente.ID[k] = '\0';
- if (stricmp (Cliente.ID, "anonymous") == 0 && anonymous_enable == 1) //login como anônimo
- {
- snprintf (buffer, MAX_MSG, "230 anonymous logged in, proceed.\r\n");
- strcpy (Cliente.Senha, "anonymous"); login=true; permissao_escrita=0;
- }
- else
- {
- login=false;
- ID_Ok = carrega_cliente (Cliente.ID, Cliente.Senha, &permissao_escrita);
- if (ID_Ok == 0) //retorna 0 se a ID existe na lista
- {snprintf (buffer, MAX_MSG, "331 User: %s - name okay, need password.\r\n", Cliente.ID);}
- else
- {snprintf (buffer, MAX_MSG, "530 Not logged in.\r\n"); desconecta=1;}
- }
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- if (desconecta == 1) //User name incorreto
- {Desconecta_Cliente(&Cliente, false, 0); return 1;}
- if (login == true)
- {
- //coloca na tela um aviso de que um cliente anônimo se conectou
- WaitForSingleObject(Hmutex, INFINITE);
- cout << Cliente.ID << " [Socket " << Cliente.Socket << " - IP: " << Cliente.IP << "] conectado." << endl;
- cout << "Agora sao " << n_clientes_conectados << " clientes conectados.\n" << endl;
- ReleaseMutex(Hmutex);
- }
- continue;
- }
- if (strncasecmp(buffer,"PASS",4) == 0) //Recebe a senha de acesso - PASS <SP> <senha> <CRLF>
- {
- nao_implem=false;
- //extrai a senha de acesso recebida e guarda em senha_rec
- int n=5; int k=0;
- while (buffer[n] != '\r' && n<nbytes)
- {senha_rec[k] = buffer[n]; n++; k++;}
- senha_rec[k] = '\0';
- if (strcmp (senha_rec, Cliente.Senha) == 0 && ID_Ok == 0) //se a senha recebida confere com a da lista de clientes e a ID esta Ok
- {
- strcpy (buffer, "230 User logged in, proceed.\r\n");
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- login=true; //logado!
- WaitForSingleObject(Hmutex, INFINITE);
- cout << Cliente.ID << " [Socket " << Cliente.Socket << " - IP: " << Cliente.IP << "] conectado." << endl;
- cout << "Agora sao " << n_clientes_conectados << " clientes conectados.\n" << endl;
- ReleaseMutex(Hmutex);
- }
- else //senha incorreta
- {
- strcpy (buffer, "530 Not logged in.\r\n");
- send(Cliente.Socket,buffer,strlen(buffer),0);
- Desconecta_Cliente(&Cliente, false, 0);
- return 1;
- }
- continue;
- }
- if (login == false) //se não estiver logado não passa daqui!
- {
- snprintf (buffer, MAX_MSG, "530 Not logged in.\r\n");
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"SIZE",4) == 0) //SIZE <SP> <pathname> <CRLF> - tamanho total dos arquivos no diretorio especificado
- {
- nao_implem=false;
- //extrai pathname
- char pathname[260], dir[260];
- int n=5; int k=0;
- if (buffer[5] != '/' && buffer[5] != '\\') //se pathname não está em formato de diretorio
- {pathname[0]= '/'; k=1;}
- while (buffer[n] != '\r' && n<nbytes)
- {pathname[k] = buffer[n]; n++; k++;}
- pathname[k] = '\0';
- if (pathname[1] == '.') //evita o uso de /../ para chamar diretórios anteriores ao definido como inicial
- {strcpy (pathname,"/");}
- if (strlen (pathname) > 1 && pathname[k-1] == '/') //se não é o diretorio inicial e existe uma barra '/' indevida no fim do pathname
- {pathname[k-1] = '\0';}
- strcpy (dir, dir_fis); //copia o diretorio fisico
- if (strlen (pathname) > 1) //se pathname nao for o diretorio inicial
- {strcat (dir, pathname);} //adiciona pathname
- //Verifica se o diretorio existe
- if (stat (dir_atual, &stStat) == 0) //existe
- {
- unsigned long size=0;
- int r = tamanho_dir(dir, &size); //chama a funcao que calcula o tamanho de arquivos em um diretorio
- if (r < 0)
- {snprintf (buffer, MAX_MSG, "501 Syntax error in parameters or arguments.\r\n");}
- else
- {snprintf (buffer, MAX_MSG, "213 %lu\r\n", size);}
- }
- else //nao existe
- {snprintf (buffer, MAX_MSG, "501 Syntax error in parameters or arguments.\r\n");}
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"CWD",3) == 0)
- {
- //Makes the given directory be the current directory on the remote host
- //CWD <SP> <pathname> <CRLF>
- nao_implem=false;
- char pathname [260], dir_virt_teste[260], dir_atual_teste[260];
- //cópias locais
- strcpy (dir_virt_teste, dir_virtual);
- strcpy (dir_atual_teste, dir_atual);
- //extrai pathname
- int n=4; int k=0;
- if (buffer[4] != '/' && buffer[4] != '\\') //se pathname não está em formato de diretorio
- {pathname[0]= '/'; k=1;}
- while (buffer[n] != '\r' && n<nbytes)
- {pathname[k] = buffer[n]; n++; k++;}
- pathname[k] = '\0';
- if (pathname[1] == '.') //evita o uso de /../ para chamar diretórios anteriores ao definido como inicial
- {strcpy (pathname,"/");}
- if (strlen (pathname) > 1 && pathname[k-1] == '/') //se não é o diretorio inicial e existe uma barra '/' indevida no fim do pathname
- {pathname[k-1] = '\0';}
- if (buffer[4] != '/' && buffer[4] != '\\') //se pathname não está em formato de diretorio
- {
- if (strlen (dir_virt_teste) > 1) //se nao for o diretorio virtual inicial
- {strcat (dir_virt_teste, pathname);} //adiciona pathname ao diretorio virtual atual
- else //se for o inicial
- {strcpy (dir_virt_teste, pathname);}
- strcat(dir_atual_teste, pathname); //adiciona pathname ao diretorio fisico atual
- }
- else //se pathname está em formato de diretorio
- {
- strcpy (dir_virt_teste, pathname); //copia pathname para o diretorio virtual atual
- strcpy (dir_atual_teste, dir_fis); //copia o diretorio fisico inicial para o diretorio fisico atual
- if (strlen (pathname) > 1) //se nao for o diretorio virtual inicial
- {strcat(dir_atual_teste, dir_virt_teste);} //adiciona pathname ao diretorio fisico atual
- }
- if (stat (dir_atual_teste, &stStat) == 0) //Verifica se o diretorio existe
- {
- if(S_ISDIR(stStat.st_mode)) //É um diretório
- {
- snprintf (buffer, MAX_MSG, "250 CWD Command okay.\r\n");
- //passa para as variaveis globais
- strcpy (dir_virtual, dir_virt_teste);
- strcpy (dir_atual, dir_atual_teste);
- }
- else //Não é um diretório
- {snprintf (buffer, MAX_MSG, "550 That is not a directory.\r\n");}
- }
- else
- {snprintf (buffer, MAX_MSG, "550 That is not a directory.\r\n");} //nao existe
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"CDUP",4) == 0)
- {
- //Up directory - CDUP <CRLF>
- nao_implem=false;
- int n;
- if (strlen(dir_virtual) > 1) //se nao for o diretorio inicial
- {
- n=strlen(dir_virtual)-1;
- for (n; n>=0; n--)
- {if (dir_virtual[n] == '/') {break;}}
- dir_virtual[n]='\0';
- strcpy (dir_atual, dir_fis);
- if (strlen (dir_virtual) <= 1) //voltou para o diretorio inicial
- {strcpy (dir_virtual, "/");}
- else
- {strcat(dir_atual, dir_virtual);}
- }
- //Verifica se o diretorio existe
- if (stat (dir_atual, &stStat) == 0)
- {snprintf (buffer, MAX_MSG, "200 CDUP Command okay.\r\n");} //existe
- else
- {snprintf (buffer, MAX_MSG, "550 Requested action not taken.\r\n");} //nao existe
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"PWD",3) == 0) //Print the current working directory name - PWD <CRLF>
- {
- nao_implem=false;
- snprintf (buffer, MAX_MSG, "257 \"%s\" is current directory.\r\n", dir_virtual);
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"TYPE",4) == 0)
- {
- /*
- TYPE <SP> <type-code> ::= | A [<sp> <form-code>] <CRLF>
- | E [<sp> <form-code>] <CRLF>
- | I <CRLF>
- | L <sp> <byte-size> <CRLF>
- The following codes are assigned for type:
- A - ASCII | | N - Non-print
- |-><-| T - Telnet format effectors
- E - EBCDIC| | C - Carriage Control (ASA)
- I - Image
- L <byte size> - Local byte Byte size
- */
- nao_implem=false;
- type_char = buffer[5]; //A, E, I ou L
- sec_type_char = '-'; //N, T, C ou <byte size>
- if (type_char == 'A')
- {sec_type_char = buffer[8];}
- if (type_char == 'E' || type_char == 'L')
- {snprintf (buffer, MAX_MSG, "504 Command not implemented for that parameter.\r\n");}
- else
- {snprintf (buffer, MAX_MSG, "200 Type set to %c.\r\n", type_char);}
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"MODE",4) == 0) //MODE <SP> <mode-code> <CRLF>
- {
- /* Modos de transferência
- S - Stream - padrão
- B - Block
- C - Compressed
- */
- transfer_mode = buffer[5]; //S, B, ou C
- snprintf (buffer, MAX_MSG, "200 transfer mode set to %c.\r\n", transfer_mode);
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"STRU",4) == 0) //STRU <SP> <structure-code> <CRLF>
- {
- /* Estruturas
- F - File (no record structure) - padrão
- R - Record structure
- P - Page structure
- */
- structure_code = buffer[5]; //F, R, ou P
- snprintf (buffer, MAX_MSG, "200 structure code set to %c.\r\n", structure_code);
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"PORT",4) == 0) //PORT <SP> <host-port> <CRLF>
- {
- nao_implem=false;
- char host_port[64], IP_Cliente[48];
- int user_DTP;
- //extrai parametro <host-port>
- int n=5; int k=0;
- while (buffer[n] != '\r' && n<nbytes)
- {host_port[k] = buffer[n]; n++; k++;}
- host_port[k] = '\0';
- obtem_ip_porta (host_port, IP_Cliente, &user_DTP); //obtem IP e porta a partir de <host-port>
- snprintf (buffer, MAX_MSG, "200 PORT Command okay.\r\n");
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- user_DTSocket = Connect_Socket (user_DTP, IP_Cliente); //se conecta ao IP e porta enviados pelo cliente, criando o Socket
- continue;
- }
- if (strncasecmp(buffer,"PASV",4) == 0) //ENTRA NO MODO PASSIVO - PASV <CRLF>
- {
- nao_implem=false;
- char IP_formatado[64];
- formata_IP (IP_server, IP_formatado); //coloca o IP formato h1,h2,h3,h4
- int port_pasv = porta_pasv; //port_pasv é uma cópia local da variavel global porta_pasv
- do {
- p1=port_pasv/256; p2=port_pasv%256;
- server_DTSocket = Listen_Socket (port_pasv,10); //cria o socket para DT e o coloca em modo de escuta
- port_pasv += 1; //vai incrementando a porta de 1 em 1 até encontrar uma porta disponível
- }
- while (server_DTSocket == -1);
- snprintf (buffer, MAX_MSG, "227 Entering Passive Mode (%s,%d,%d).\r\n", IP_formatado,p1,p2); //envia h1,h2,h3,h4,p1,p2
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- user_DTSocket = accept (server_DTSocket,0,0); //aceita conexao de dados
- continue;
- }
- if (strncasecmp(buffer,"LIST",4) == 0) //lista arquivos e diretorios - LIST [<SP> <pathname>] <CRLF>
- {
- nao_implem=false;
- //obs: se nao for enviado o argumento pathname entao usar diretorio virtual corrente ou diretorio default
- if (buffer[4] == '[') //ha o argumento pathname
- { //extrai pathname
- char pathname[260];
- int n=6; int k=0;
- if (buffer[n] != '/' && buffer[n] != '\\') //se nao vier formatado como diretorio
- {pathname[0]= '/'; k=1;}
- while (buffer[n] != ']' && n<nbytes)
- {pathname[k] = buffer[n]; n++; k++;}
- pathname[k] = '\0';
- strcpy (dir_atual, dir_fis); //copia diretorio inicial
- if (strlen(pathname) > 1)
- {strcat (dir_atual, pathname);} //adiciona pathname
- }
- if (user_DTSocket > 0 && user_DTSocket != INVALID_SOCKET ) //se nao houve erro na criacao da conexão de dados
- {snprintf (buffer, MAX_MSG, "150 Data connection ready.\r\n");}
- else
- {snprintf (buffer, MAX_MSG, "425 Can't open data connection.\r\n"); closesocket (user_DTSocket); continue;}
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {closesocket (user_DTSocket); Desconecta_Cliente(&Cliente, true, 2); return 1;}
- if (envia_listadir (padrao_listagem, dir_atual, user_DTSocket) == 0) //chama a funcao que envia a lista de pastas e arquivos do diretorio requistado
- {snprintf (buffer, MAX_MSG, "226 Transfer complete - Closing data connection.\r\n");} //se o envio foi bem sucedido
- else
- {snprintf (buffer, MAX_MSG, "426 Connection closed; transfer aborted.\r\n");}
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0); //envia msg
- if (nbytes <= 0 || nbytes == SOCKET_ERROR) //erro ao enviar mensagem
- {closesocket (user_DTSocket); Desconecta_Cliente(&Cliente, true, 2); return 1;}
- closesocket (user_DTSocket); //fecha conexao de transferencia de dados
- continue;
- }
- if (strncasecmp(buffer,"RETR",4) == 0) //envia arquivo para o cliente - RETR <SP> <pathname> <CRLF>
- {
- char pathname[260];
- bool cancela=false;
- //extrai parametro <pathname>
- int n=5; int k=0;
- if (buffer[n] != '/' && buffer[n] != '\\') //se nao vier formatado como diretorio
- {pathname[0]= '/'; k=1;}
- while (buffer[n] != '\r' && n<nbytes)
- {pathname[k] = buffer[n]; n++; k++;}
- pathname[k] = '\0';
- if (user_DTSocket > 0 && user_DTSocket != INVALID_SOCKET ) //se nao houve erro na criacao da conexão de dados
- {snprintf (buffer, MAX_MSG, "150 Data connection ready.\r\n");}
- else
- {snprintf (buffer, MAX_MSG, "425 Can't open data connection.\r\n"); closesocket (user_DTSocket); continue;}
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {closesocket (user_DTSocket); Desconecta_Cliente(&Cliente, true, 2); return 1;}
- dados_transferencia dados; //guarda os dados para a transferencia do arquivo e passa para a Thread
- WaitForSingleObject(Hmutex, INFINITE);
- for (n=0; n<MAX_TRANSF; n++)
- {if (thread_transf[n]==-1) {break;}} //busca uma posicao vazia para guardar a handle e identificador da Thread que será criada
- dados.pos=n; //guarda a posicao na matriz de handles, para passar para a Thread
- dados.data_Socket = user_DTSocket; //Socket conexao transf. dados
- dados.controle_Socket = Cliente.Socket;//Socket conexao de controle
- //endereco do arquivo a enviar
- strcpy (dados.endereco_arq, dir_atual);
- strcat (dados.endereco_arq, pathname);
- if (arquivo_existe (dados.endereco_arq) != 1) //o arquivo não existe, tenta outro modo de construir o endereço do arquivo
- {
- strcpy (dados.endereco_arq, dir_fis);
- strcat (dados.endereco_arq, pathname);
- if (arquivo_existe (dados.endereco_arq) != 1) //o arquivo não existe
- {cancela=true;}
- }
- if (cancela==true) //cancela envio de arquivo
- {
- snprintf (buffer, MAX_MSG, "426 Connection closed; transfer aborted.\r\n");
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- closesocket (user_DTSocket);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- //Cria a Thread com a funcao de envio de arquivo
- Hthread_transf[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)envia_arquivo, &dados, 0, (LPDWORD)&thread_transf[n]);
- if (Hthread_transf[n] == NULL) //erro ao cria a Thread
- {
- thread_transf[n]=-1;
- snprintf (buffer, MAX_MSG, "426 Connection closed; transfer aborted.\r\n");
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- closesocket (user_DTSocket);
- }
- ReleaseMutex(Hmutex);// libera o mutex - os outros "processos" voltam a rodar
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"SYST",4) == 0) //retorna um identificador do sistema e uma word type
- {
- //Returns a word identifying the system, the word "Type:", and the default transfer type (as would be set by the TYPE command).
- nao_implem=false;
- snprintf (buffer, MAX_MSG, "215 UNIX Type: L8\r\n"); //um padrao usado por muitos servidores
- nbytes = send (Cliente.Socket, buffer, strlen(buffer), 0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"FEAT",4) == 0) //FEAT <CRLF>
- {
- nao_implem=false;
- snprintf (buffer, MAX_MSG, "211-Extensions supported:\r\n");
- nbytes = send (Cliente.Socket, buffer, strlen(buffer), 0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- snprintf (buffer, MAX_MSG, "SIZE\r\n");
- nbytes = send (Cliente.Socket, buffer, strlen(buffer), 0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- snprintf (buffer, MAX_MSG, "PASV\r\n");
- nbytes = send (Cliente.Socket, buffer, strlen(buffer), 0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- snprintf (buffer, MAX_MSG, "211 End.\r\n");
- nbytes = send (Cliente.Socket, buffer, strlen(buffer), 0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"SITE",4) == 0) //SITE <SP> <string> <CRLF>
- {
- nao_implem=false;
- snprintf (buffer, MAX_MSG, "202 Command not implemented, superfluous at this site.\r\n");
- nbytes = send (Cliente.Socket, buffer, strlen(buffer), 0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"HELP",4) == 0) //HELP [<SP> <string>] <CRLF>
- {
- nao_implem=false;
- snprintf (buffer, MAX_MSG, "211 System help reply.\r\n");
- nbytes = send (Cliente.Socket, buffer, strlen(buffer), 0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"NOOP",4) == 0) //Somente retorna um OK - NOOP <CRLF>
- {
- nao_implem=false;
- nbytes = send(Cliente.Socket,"250 okay.\r\n",11,0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"QUIT",4) == 0) //Termina conexao com o cliente - QUIT <CRLF>
- {
- nao_implem=false;
- Desconecta_Cliente(&Cliente, true, 1);
- return 1;
- }
- if (permissao_escrita == 0) //se não tiver permissão para escrita não passa daqui!
- {
- snprintf (buffer, MAX_MSG, "530 Not logged in.\r\n");
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"STOR",4) == 0) //recebe arquivo do cliente - STOR <SP> <pathname> <CRLF>
- {
- char pathname[260];
- //extrai parametro <pathname>
- int n=5; int k=0;
- if (buffer[n] != '/' && buffer[n] != '\\') //se nao vier formatado como diretorio
- {pathname[0]= '/'; k=1;}
- while (buffer[n] != '\r' && n<nbytes)
- {pathname[k] = buffer[n]; n++; k++;}
- pathname[k] = '\0';
- if (user_DTSocket > 0 && user_DTSocket != INVALID_SOCKET ) //se nao houve erro na criacao da conexão de dados
- {snprintf (buffer, MAX_MSG, "150 Data connection ready.\r\n");}
- else
- {snprintf (buffer, MAX_MSG, "425 Can't open data connection.\r\n"); closesocket (user_DTSocket); continue;}
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {closesocket (user_DTSocket); Desconecta_Cliente(&Cliente, true, 2); return 1;}
- dados_transferencia dados; //guarda os dados para a transferencia do arquivo e passa para a Thread
- WaitForSingleObject(Hmutex, INFINITE);
- for (n=0; n<MAX_TRANSF; n++)
- {if (thread_transf[n]==-1) {break;}} //busca uma posicao vazia para guardar a handle e identificador da Thread que será criada
- dados.pos=n; //guarda a posicao na matriz de handles, para passar para a Thread
- dados.data_Socket = user_DTSocket; //Socket conexao transf. dados
- dados.controle_Socket = Cliente.Socket;//Socket conexao de controle
- //endereco do novo arquivo que será recebido
- strcpy (dados.endereco_arq, dir_atual);
- strcat (dados.endereco_arq, pathname);
- //Cria a Thread com a funcao de recebimento de arquivo
- Hthread_transf[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)recebe_arquivo, &dados, 0, (LPDWORD)&thread_transf[n]);
- if (Hthread_transf[n] == NULL) //erro ao cria a Thread
- {
- thread_transf[n]=-1;
- snprintf (buffer, MAX_MSG, "426 Connection closed; transfer aborted.\r\n");
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- closesocket (user_DTSocket);
- }
- ReleaseMutex(Hmutex);// libera o mutex - os outros "processos" voltam a rodar
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"DELE",4) == 0) //deleta arquivo - DELE <SP> <pathname> <CRLF>
- {
- char pathname[260];
- //extrai parametro <pathname>
- int n=5; int k=0;
- if (buffer[n] != '/' && buffer[n] != '\\') //se nao vier formatado como diretorio
- {pathname[0]= '/'; k=1;}
- while (buffer[n] != '\r' && n<nbytes)
- {pathname[k] = buffer[n]; n++; k++;}
- pathname[k] = '\0';
- dados_transferencia dados; //guarda os dados que serão passados para a Thread que deletará o arquivo
- WaitForSingleObject(Hmutex, INFINITE);
- for (n=0; n<MAX_TRANSF; n++)
- {if (thread_transf[n]==-1) {break;}} //busca uma posicao vazia para guardar a handle e identificador da Thread que será criada
- dados.pos=n; //guarda a posicao na matriz de handles, para passar para a Thread
- dados.controle_Socket = Cliente.Socket;//Socket conexao de controle
- //endereco do arquivo a deletar
- strcpy (dados.endereco_arq, dir_atual);
- strcat (dados.endereco_arq, pathname);
- //Cria a Thread com a funcao para deletar arquivos
- Hthread_transf[n] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)deleta_arquivo, &dados, 0, (LPDWORD)&thread_transf[n]);
- if (Hthread_transf[n] == NULL) //erro ao cria a Thread
- {
- thread_transf[n]=-1;
- snprintf (buffer, MAX_MSG, "450 Erro ao deletar arquivo.\r\n");
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- }
- ReleaseMutex(Hmutex);// libera o mutex - os outros "processos" voltam a rodar
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"RNFR",4) == 0) //define arquivo a ser renomeado - RNFR <SP> <pathname> <CRLF>
- {
- char pathname[260];
- //extrai parametro <pathname>
- int n=5; int k=0;
- if (buffer[n] != '/' && buffer[n] != '\\') //se nao vier formatado como diretorio
- {pathname[0]= '/'; k=1;}
- while (buffer[n] != '\r' && n<nbytes)
- {pathname[k] = buffer[n]; n++; k++;}
- pathname[k] = '\0';
- //endereco do arquivo a renomear
- strcpy (arq_rename, dir_atual);
- strcat (arq_rename, pathname);
- if (strlen (pathname) > 1) //se pathname é um nome de arquivo válido
- {snprintf (buffer, MAX_MSG, "350 Comando RNFR Ok! Aguardando comando RNTO.\r\n");}
- else
- {snprintf (buffer, MAX_MSG, "450 Requested file action not taken.\r\n");}
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0); //envia msg
- if (nbytes <= 0 || nbytes == SOCKET_ERROR) //erro ao enviar mensagem
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"RNTO",4) == 0) //define o novo nome do arquivo a ser renomeado (o arquivo foi definido pelo comando RNFR)
- { //RNTO <SP> <pathname> <CRLF>
- char pathname[260], arq_new_name[260];
- //extrai parametro <pathname>
- int n=5; int k=0;
- if (buffer[n] != '/' && buffer[n] != '\\') //se nao vier formatado como diretorio
- {pathname[0]= '/'; k=1;}
- while (buffer[n] != '\r' && n<nbytes)
- {pathname[k] = buffer[n]; n++; k++;}
- pathname[k] = '\0'; //pathname guarda o novo nome do arquivo que foi definido para ser renomeado pelo comando RNFR
- //endereco do arquivo que será renomeado
- strcpy (arq_new_name, dir_atual);
- strcat (arq_new_name, pathname);
- if (rename (arq_rename, arq_new_name) == 0) //se igual a 0 o arquivo foi renomeado de arq_rename para arq_new_name
- {snprintf (buffer, MAX_MSG, "250 Comando RNTO Ok! Renomeado.\r\n");}
- else
- {snprintf (buffer, MAX_MSG, "553 Requested action not taken.\r\n");}
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0); //envia msg
- if (nbytes <= 0 || nbytes == SOCKET_ERROR) //erro ao enviar mensagem
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"MKD",3) == 0) //Cria um novo diretório - MKD <SP> <pathname> <CRLF>
- {
- char pathname[260], dir_new[260];
- //extrai parametro <pathname>
- int n=4; int k=0;
- if (buffer[n] != '/' && buffer[n] != '\\') //se nao vier formatado como diretorio
- {pathname[0]= '/'; k=1;}
- while (buffer[n] != '\r' && n<nbytes)
- {pathname[k] = buffer[n]; n++; k++;}
- pathname[k] = '\0'; //pathname guarda o nome do novo diretório
- //endereco do novo diretório
- strcpy (dir_new, dir_atual);
- strcat (dir_new, pathname);
- if ( _mkdir(dir_new) == 0 ) //se igual a 0 o novo diretório foi criado
- {snprintf (buffer, MAX_MSG, "257 \"%s\" created.\r\n", pathname);}
- else
- {snprintf (buffer, MAX_MSG, "550 Requested action not taken.\r\n");}
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0); //envia msg
- if (nbytes <= 0 || nbytes == SOCKET_ERROR) //erro ao enviar mensagem
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (strncasecmp(buffer,"RMD",3) == 0) //Remove um diretório - RMD <SP> <pathname> <CRLF>
- {
- char pathname[260], dir_delete[260];
- //extrai parametro <pathname>
- int n=4; int k=0;
- if (buffer[n] != '/' && buffer[n] != '\\') //se nao vier formatado como diretorio
- {pathname[0]= '/'; k=1;}
- while (buffer[n] != '\r' && n<nbytes)
- {pathname[k] = buffer[n]; n++; k++;}
- pathname[k] = '\0';
- strcpy (dir_delete, dir_atual);
- strcat (dir_delete, pathname);
- int retorno = deleta_diretorio (dir_delete); //varre o diretorio e sub diretorios e os deleta
- if (retorno == 0) //o diretorio foi deletado corretamente
- {snprintf (buffer, MAX_MSG, "250 Deletado.\r\n");}
- else //erro ao deletar
- {snprintf (buffer, MAX_MSG, "550 Requested action not taken.\r\n");}
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- continue;
- }
- if (nao_implem) //se for true o comando recebido nao foi implementado
- {
- //comando nao implementado
- strcpy (buffer, "502 Command not implemented.\r\n");
- nbytes = send(Cliente.Socket,buffer,strlen(buffer),0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {Desconecta_Cliente(&Cliente, true, 2); return 1;}
- }
- } //fim do loop
- Desconecta_Cliente(&Cliente, false, 0);
- return 1;
- }
- //==============================================================================
- int Listen_Socket (int porta, int n_conexoes) //Cria um socket e o coloca em modo de escuta
- {
- int error;
- WSAData wsaData;
- if ((error = WSAStartup(MAKEWORD(2, 2), &wsaData)) == SOCKET_ERROR) //versao 2.2 do Winsock DLL
- {return -1;}
- int serverSocket = socket(AF_INET, SOCK_STREAM, 0); //cria o socket
- if (serverSocket == SOCKET_ERROR)
- {return -1;}
- struct sockaddr_in server;
- server.sin_family = AF_INET;
- server.sin_port = htons(porta);
- server.sin_addr.s_addr = INADDR_ANY; //aceita conexoes em qualquer endereco
- if (bind(serverSocket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
- {
- closesocket(serverSocket);
- return -1;
- }
- if (listen(serverSocket, n_conexoes) == SOCKET_ERROR) //coloca o servidor em escuta
- {
- closesocket(serverSocket);
- return -1;
- }
- return serverSocket; //caso tudo ocorra corretamente a funcao retorna o socket criado
- }
- //==============================================================================
- int Connect_Socket (int porta, char *host) //Cria um socket faz a conexao cliente-servidor
- {
- int error;
- WSAData wsaData;
- if ((error = WSAStartup(MAKEWORD(2, 2), &wsaData)) == SOCKET_ERROR) //versao 2.2 do Winsock DLL
- {return -1;}
- int Socket = socket(AF_INET, SOCK_STREAM, 0); //cria o socket
- if (Socket == SOCKET_ERROR)
- {return -1;}
- struct hostent *host_entry;
- if ((host_entry = gethostbyname(host)) == NULL || host_entry->h_addrtype != AF_INET /*IPv4*/) //obtem o host a partir do nome passado pelo usuario
- {return -1;}
- struct sockaddr_in server;
- server.sin_family = AF_INET;
- server.sin_port = htons(porta);
- server.sin_addr.s_addr = *(unsigned long*) host_entry->h_addr;
- if (connect(Socket, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) //conecta ao servidor
- {return -1;}
- return Socket; //caso tudo ocorra corretamente a funcao retorna o socket criado
- }
- //==============================================================================
- void Desconecta_Cliente (cliente_tipo *Cli, bool msg_on, int info_type)
- {
- if (msg_on) //se desejar enviar msg, msg_on é true
- {
- char buffer [64];
- switch (info_type)
- {
- case 1: //caso seja uma desconexao apropriada, o parametro info_type é true
- strcpy (buffer, "221 Service closing control connection.\r\n"); break;
- case 2: //caso seja uma desconexao inesperada, o parametro info é false
- strcpy (buffer, "421 Service not available, closing control connection.\r\n"); break;
- }
- send(Cli->Socket,buffer,strlen(buffer),0);
- }
- closesocket(Cli->Socket); //fecha o socket do cliente
- WaitForSingleObject(Hmutex, INFINITE); //obtem mutex
- cout << Cli->ID << " [Socket " << Cli->Socket << "] desconectado." << endl;
- n_clientes_conectados--;
- thread[Cli->pos] = -1; //seta a posicao com um valor nulo
- CloseHandle (Hthread[Cli->pos]);
- cout << "Agora sao " << n_clientes_conectados << " clientes conectados.\n" << endl;
- ReleaseMutex(Hmutex); // libera o mutex
- }
- //==============================================================================
- void Finaliza_Conexao (int serversocket)
- {
- for (int n=0; n<MAX_CLIENTES; n++)
- {if (thread[n] != -1) {CloseHandle(Hthread[n]);}} //fecha Handles das Threads ativas
- CloseHandle(Hmutex); //fecha o mutex utilizado
- closesocket(serversocket); //fecha Socket de escuta que aceita conexoes ao servidor
- WSACleanup();
- cout << "Servidor: desconectado!\n" << endl;
- }
- //==============================================================================
- void formata_IP (char *IP_server, char *IP_formatado) //Troca ponto por virgula no endereco IP
- { // ex: 127.0.0.1 torna-se 127,0,0,1
- int size=strlen(IP_server), n;
- for (n=0; n<size; n++)
- {
- if (IP_server[n] == '.')
- {IP_formatado[n] = ',';}
- else
- {IP_formatado[n] = IP_server[n];}
- }
- IP_formatado[n]='\0';
- }
- //==============================================================================
- void obtem_ip_porta (char *host_port, char *IP, int *porta) //obtem IP e porta a partir do formato h1,h2,h3,h4,p1,p2
- {
- int n, k=0;
- for (n=0; k<4; n++)
- {
- if (host_port[n] == ',')
- {IP[n] = '.'; k++;}
- else
- {IP[n] = host_port[n];}
- }
- IP[n-1] ='\0';
- char aux[5];
- k=0;
- for (n; host_port[n]!=','; n++)
- {
- aux[k] = host_port[n]; k++;
- }
- aux[k] = '\0'; *porta = atoi(aux)*256;
- k=0;
- n++;
- int size = strlen(host_port);
- for (n; n<size; n++)
- {
- aux[k] = host_port[n]; k++;
- }
- aux[k] = '\0'; *porta = *porta + atoi(aux);
- }
- //==============================================================================
- //funcao que verifica se um arquivo existe
- int arquivo_existe (const char *filename)
- {
- FILE *arquivo;
- if (strlen(filename) > PATH_MAX)
- {return 0;} //nao existe, ultrapassa PATH_MAX
- if(arquivo = fopen(filename, "rb"))
- {
- fclose(arquivo);
- return 1; //existe
- }
- return 0; //nao existe
- }
- //==============================================================================
- int envia_listadir (char padrao_listagem, char *gpath, int user_DTSocket)
- {
- //padrao_envio = '0': Padrao UNIX de listagem de arquivos e diretorios
- //padrao_envio = '1': Padrao MS-DOS de listagem de arquivos e diretorios
- char path[260], pathname[260];
- char datamod[24], permissao[16], tipo_path[16], tamanho_str[128];
- struct stat statbuf;
- struct tm *tm;
- char *accesses[] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
- unsigned short link;
- unsigned long tamanho;
- int i=0, nbytes=0;
- if (strlen(gpath) > PATH_MAX)
- {return 1;}
- strcpy (path, gpath); //copia local da variavel global path
- // ponteiro para entrada do arquivo na pasta
- struct dirent *pent = NULL;
- // Ponteiros para os diretórios:
- DIR *pdir;
- // Tentando inicializar o ponteiro para o diretório
- pdir = opendir (path);
- // caso o pdir não seja inicializado corretamente, aborta a função
- if (pdir == NULL)
- {return 1;}
- while (pent = readdir (pdir)) // enquanto houver um diretorio ou arquivo para listar
- {
- if (pent == NULL) // se o pent (ponteiro entrada) não retornar nada
- {closedir (pdir); return 1;}
- strcpy (pathname, path);
- strcat (pathname, "/");
- strcat (pathname, pent->d_name);
- if (strlen(pathname) > PATH_MAX)
- {return 1;}
- /* Obter informacoes de entrada */
- if (stat(pathname, &statbuf) != 0)
- {return 1;}
- if (pent->d_name[0] != '.') //evita envio de hierarquia de pastas fora da compartilhada
- {
- /* tipo de arquivo */
- strcpy(permissao,"-"); //por default
- if(S_ISREG(statbuf.st_mode)) { strcpy(permissao,"-"); strcpy (tipo_path, " ");} //Arquivo regular
- if(S_ISDIR(statbuf.st_mode)) { strcpy(permissao,"d"); strcpy (tipo_path, " <DIR>");} //Diretorio
- if(S_ISCHR(statbuf.st_mode)) { strcpy(permissao,"c"); strcpy (tipo_path, " ");} //Dispositivo de caracter
- /* permissão.*/
- for(i = 6; i >= 0; i -=3)
- {strcat(permissao, accesses[(statbuf.st_mode >> i) & 7]);}
- fflush(stdin);
- /* numero de link */
- link = statbuf.st_nlink;
- /* tamanho do arquivo.*/
- tamanho = (intmax_t)statbuf.st_size;
- tm = localtime(&statbuf.st_mtime); //obtem hora local
- /* monta as informações no formato de envio */
- if (padrao_listagem == '0') //Padrao UNIX de listagem de arquivos e diretorios
- {
- /* Obter data em string. */
- strftime(datamod, 24, "%b %d %H:%M", tm);
- /*Monta informações no formato UNIX*/
- snprintf (pathname, 260, "%s %u user group %lu %s %s\r\n", permissao, link, tamanho, datamod, pent->d_name);
- }
- else //Padrao MS-DOS de listagem de arquivos e diretorios
- {
- /* Obter data em string. */
- strftime(datamod, 24, "%m-%d-%y %I:%M%p", tm);
- /*testa o tipo de path*/
- if (strcmp (tipo_path, " <DIR>") == 0) //é um diretório - não possui um tamanho associado a ele
- {strcpy (tamanho_str," ");}
- else //não é um diretório - logo possui um tamanho em bytes
- {snprintf (tamanho_str, 128, "%lu ", tamanho);}
- /*Monta informações no formato MS-DOS*/
- snprintf (pathname, 260, "%s%s%s%s\r\n", datamod, tipo_path, tamanho_str, pent->d_name);
- }
- /*envia os dados da listagem*/
- nbytes = send(user_DTSocket, pathname, strlen(pathname), 0);
- if (nbytes <= 0 || nbytes == SOCKET_ERROR)
- {return 1;}
- }
- }
- // Encerra o ponteiro para o diretório
- closedir (pdir);
- return 0;
- }
- //==============================================================================
- //funcao que guarda em uma variavel o tamanho em bytes dos arquivos em um diretorio
- int tamanho_dir (char *dir, unsigned long *tamanho)
- {
- struct stat statbuf;
- *tamanho = 0;
- char pathname[260];
- if (strlen(dir) > PATH_MAX)
- {return -1;}
- // ponteiro para entrada do arquivo na pasta
- struct dirent *pent = NULL;
- // Ponteiros para os diretórios:
- DIR *pdir;
- // Tentando inicializar o ponteiro para o diretório
- pdir = opendir (dir);
- // caso o pdir não seja inicializado corretamente, dir guarda o caminho para um arquivo
- if (pdir == NULL)
- {
- if (stat(dir, &statbuf) != 0)
- {return -1;}
- /* tamanho do arquivo.*/
- *tamanho = (intmax_t)statbuf.st_size;
- return 0;
- }
- //se dir guarda o caminho para um diretorio
- while (pent = readdir (pdir)) // enquanto houver um diretorio ou arquivo para listar
- {
- if (pent == NULL) // se o pent (ponteiro entrada) não retornar nada
- {closedir (pdir); return -1;}
- strcpy (pathname, dir);
- strcat (pathname, "/");
- strcat (pathname, pent->d_name);
- if (strlen(pathname) > PATH_MAX)
- {return -1;}
- /* Obter informacoes de entrada */
- if (stat(pathname, &statbuf) != 0)
- {return -1;}
- /* tamanho do arquivo.*/
- *tamanho = *tamanho + (intmax_t)statbuf.st_size;
- }
- closedir (pdir);
- return 0;
- }
- //==============================================================================
- //funcao para enviar arquivos binarios (como .mp3, .txt, .bmp, .pdf, etc) para um Socket
- //retorna 0 se o arquivo foi enviado com sucesso ou 1 se não foi
- int envia_arquivo(dados_transferencia *dados)
- {
- FILE* arquivo;
- char msg[64];
- int nBytes, Bytes_lidos, retorno=0;
- unsigned long file_size=1, size_check=0; //atribui 1 e 0 só para iniciarem com valores diferentes
- const int TAMANHO_PACOTE = 1024; //1 kbyte
- dados_transferencia d;
- WaitForSingleObject(Hmutex, INFINITE); //obtem mutex
- d = *dados; //cópia local dos dados para a transferencia de arquivo
- ReleaseMutex(Hmutex);
- if (d.data_Socket < 0 || d.data_Socket == SOCKET_ERROR) //verifica se o Socket de dados passado no parametro da funcao é válido
- {retorno=1;} //erro
- if (d.controle_Socket < 0 || d.controle_Socket == SOCKET_ERROR) //verifica se o Socket de controle passado no parametro da funcao é válido
- {retorno=1;} //erro
- if (strlen(d.endereco_arq) > PATH_MAX)
- {retorno=1;} //ultrapassa PATH_MAX
- if ((arquivo = fopen (d.endereco_arq, "rb"))!=NULL && retorno!=1)
- {
- retorno = 1; //retorno assume 1, só mudará para 0 caso a transferência seja bem sucedida
- //obtém o tamanho do arquivo
- fseek (arquivo, 0, SEEK_END);
- file_size=ftell(arquivo);
- rewind(arquivo);
- if (file_size != -1L) //se não houve erro no cálculo do tamanho do arquivo
- {
- //n = 2 vezes o número de pacotes necessarios, segurança para garantir uma parada ao while abaixo, responsavel pelo loop de envio
- unsigned int n = ((file_size/TAMANHO_PACOTE) + 1)*2;
- unsigned int k=0, i;
- char* buffer;
- buffer = (char*)malloc(TAMANHO_PACOTE + 128); //aloca memoria para guardar os dados que serão enviados
- if (buffer != NULL) //se a memoria foi alocada
- {
- size_check=0;
- while(size_check < file_size && k<n)
- {
- Bytes_lidos = fread (buffer, sizeof(char), TAMANHO_PACOTE, arquivo);
- nBytes = send(d.data_Socket, buffer, Bytes_lidos, 0);
- if (nBytes == SOCKET_ERROR) //se houve erro no envio, tenta reenvio ate 10 vezes
- {
- i=0;
- while (i<10 && nBytes == SOCKET_ERROR)
- {nBytes = send(d.data_Socket, buffer, Bytes_lidos, 0); i++;}
- }
- size_check += nBytes;
- if (nBytes == SOCKET_ERROR || feof(arquivo)!=0)
- {break;}
- k++;
- }
- free(buffer);
- }
- }
- }
- fclose (arquivo);
- if (size_check == file_size) //o arquivo foi enviado corretamente
- {snprintf (msg, 64, "226 Download complete - Closing data connection.\r\n"); retorno=0;}
- else //erro no envio
- {snprintf (msg, 64, "426 Connection closed - Download aborted.\r\n"); retorno=1;}
- send(d.controle_Socket,msg,strlen(msg),0);
- closesocket (d.data_Socket); //fecha conexao de transferencia de dados
- WaitForSingleObject(Hmutex, INFINITE); //obtem mutex
- thread_transf[d.pos] = -1; //seta com um valor nulo a posicao identificadora da thread de transferencia
- CloseHandle (Hthread_transf[d.pos]); //fecha handle de transferencia
- ReleaseMutex(Hmutex); // libera o mutex
- return retorno;
- }
- //==============================================================================
- //funcao para receber arquivos binarios (como .mp3, .txt, .bmp, .pdf, etc) de um Socket
- //retorna 0 se o arquivo foi recebido com sucesso ou 1 se não foi
- int recebe_arquivo(dados_transferencia *dados)
- {
- FILE* arquivo;
- char msg[64];
- int nBytes = SOCKET_ERROR, size_buffer, Bytes_escritos, retorno=0;
- const int TAMANHO_PACOTE = 4096; //4 kbytes
- dados_transferencia d;
- WaitForSingleObject(Hmutex, INFINITE); //obtem mutex
- d = *dados; //cópia local dos dados para a transferencia de arquivo
- ReleaseMutex(Hmutex);
- if (d.data_Socket < 0 || d.data_Socket == SOCKET_ERROR) //verifica se o Socket de dados passado no parametro da funcao é válido
- {retorno=1;} //erro
- if (d.controle_Socket < 0 || d.controle_Socket == SOCKET_ERROR) //verifica se o Socket de controle passado no parametro da funcao é válido
- {retorno=1;} //erro
- if (strlen(d.endereco_arq) > PATH_MAX)
- {retorno=1;} //ultrapassa PATH_MAX
- if ((arquivo = fopen (d.endereco_arq, "wb"))!=NULL && retorno!=1)
- {
- retorno = 1; //retorno assume 1, só mudará para 0 caso a transferência seja bem sucedida
- char* buffer;
- size_buffer = TAMANHO_PACOTE + 128;
- buffer = (char*)malloc(size_buffer); //aloca memoria para guardar os dados que serão enviados
- int i;
- if (buffer != NULL) //se a memoria foi alocada
- {
- while(true)
- {
- nBytes = recv(d.data_Socket, buffer, size_buffer, 0);
- if (nBytes == SOCKET_ERROR) //se houve erro no recebimento, tenta receber de novo ate 10 vezes
- {
- i=0;
- while (i<10 && nBytes == SOCKET_ERROR)
- {nBytes = recv(d.data_Socket, buffer, size_buffer, 0); i++;}
- }
- if (nBytes == 0 || nBytes == SOCKET_ERROR)
- {break;}
- Bytes_escritos = fwrite (buffer, sizeof(char), nBytes, arquivo);
- }
- free(buffer);
- }
- }
- fclose (arquivo);
- if (nBytes != SOCKET_ERROR) //o arquivo foi recebido corretamente
- {snprintf (msg, 64, "226 Upload complete - Closing data connection.\r\n"); retorno=0;}
- else //erro no recebimento
- {snprintf (msg, 64, "426 Connection closed - Upload aborted.\r\n"); retorno=1;}
- send(d.controle_Socket,msg,strlen(msg),0);
- closesocket (d.data_Socket); //fecha conexao de transferencia de dados
- WaitForSingleObject(Hmutex, INFINITE); //obtem mutex
- thread_transf[d.pos] = -1; //seta com um valor nulo a posicao identificadora da thread de transferencia
- CloseHandle (Hthread_transf[d.pos]); //fecha handle de transferencia
- ReleaseMutex(Hmutex); // libera o mutex
- return retorno;
- }
- //==============================================================================
- //funcao para deletar arquivos
- int deleta_arquivo(dados_transferencia *dados)
- {
- char msg[64];
- int retorno=2;
- dados_transferencia d;
- WaitForSingleObject(Hmutex, INFINITE); //obtem mutex
- d = *dados; //cópia local dos dados para deletar arquivo
- ReleaseMutex(Hmutex);
- if (d.controle_Socket < 0 || d.controle_Socket == SOCKET_ERROR) //verifica se o Socket de controle passado no parametro da funcao é válido
- {retorno=1;} //erro
- if (strlen(d.endereco_arq) > PATH_MAX)
- {retorno=1;} //ultrapassa PATH_MAX
- if (retorno == 2)
- {
- retorno = remove(d.endereco_arq); //deleta arquivo, retorna 0 se deletou ou um valor diferente de 0 se nao deletou
- if (retorno == 0) //o arquivo foi deletado corretamente
- {snprintf (msg, 64, "250 Arquivo deletado.\r\n");}
- else //erro ao deletar
- {snprintf (msg, 64, "450 Erro ao deletar arquivo.\r\n"); retorno=1;}
- send(d.controle_Socket,msg,strlen(msg),0);
- }
- WaitForSingleObject(Hmutex, INFINITE); //obtem mutex
- thread_transf[d.pos] = -1; //seta com um valor nulo a posicao identificadora da thread
- CloseHandle (Hthread_transf[d.pos]); //fecha handle
- ReleaseMutex(Hmutex); // libera o mutex
- return retorno;
- }
- //==============================================================================
- //função que varre um diretorio com seus sub diretorios e os deleta
- int deleta_diretorio(char *gdir)
- {
- if (strlen(gdir) > PATH_MAX)
- {return 1;} //ultrapassa PATH_MAX
- char dir[260], pathname[260];
- struct stat statbuf;
- struct dirent *pent = NULL;
- strcpy (dir, gdir); //cópia local do endereço do diretório
- // Ponteiros para os diretórios:
- DIR *pdir;
- // Tentando inicializar o ponteiro para o diretório
- pdir = opendir (dir);
- // caso o pdir não seja inicializado corretamente
- if (pdir == NULL)
- {return 1;}
- while (pent = readdir (pdir)) // enquanto houver um diretorio a ser lido
- {
- if (pent == NULL) // se o pent (ponteiro entrada) não retornar nada, a pasta esta vazia
- {break;}
- strcpy (pathname, dir);
- strcat (pathname, "/");
- strcat (pathname, pent->d_name);
- if (strlen(pathname) > PATH_MAX)
- {break;}
- // Obter informacoes de entrada
- if (stat(pathname, &statbuf) != 0)
- {break;}
- if (pent->d_name[0] != '.') //evita hierarquia de pastas fora da compartilhada
- {
- if(S_ISREG(statbuf.st_mode)) {remove(pathname);} //Arquivo
- if(S_ISDIR(statbuf.st_mode)) {deleta_diretorio (pathname);} //Diretorio - faz chamada recursiva da funcão
- }
- }
- closedir (pdir);
- if ( _rmdir (dir) == 0 ) {return 0;} else {return 1;}
- }
- //==============================================================================
- //função que carrega dados de clientes cadastrados a partir de um arquivo-lista - retorna 0 caso ID seja encontrada
- int carrega_cliente (char *ID, char *Senha, int *permissao_escrita)
- {
- FILE *clientes;
- if ((clientes = fopen ("Clientes.txt", "r")) != NULL)
- {
- char senha_teste[64], id_teste[64];
- int p_escrita, teste;
- while (feof(clientes)==0)
- {
- teste=0;
- id_teste[0]='\0';
- fscanf (clientes, "%63[^\n]\n", id_teste);
- if (strlen(id_teste) < 1) {teste=1;}
- senha_teste[0]='\0';
- fscanf (clientes, "%63[^\n]\n", senha_teste);
- if (strlen(senha_teste) < 1) {teste=1;}
- fscanf (clientes, "%d\n", &p_escrita);
- if (p_escrita != 1) {p_escrita = 0;}
- if (teste == 0)
- {
- if (strcmp (ID, id_teste) == 0) //se a ID passada no parametro confere com uma do arquivo
- {
- strcpy (Senha, senha_teste);
- *permissao_escrita = p_escrita;
- fclose (clientes);
- return 0;
- }
- }
- }
- fclose (clientes);
- }
- return 1;
- }
- //==============================================================================
Advertisement
Add Comment
Please, Sign In to add comment