Exemple #1
0
/*
* Verifica se url informada e http ou https
*/
void webcrawler::parse_link(string &url, bool &secure)
{
    size_t aux;

    if ((aux = str_find_ci(url, "http://")) != string::npos) //Verifica se o início do link é http://
    {
        secure = false; //Marca como http
        url.erase(aux, 7); //Remove está string
    } else if ((aux = str_find_ci(url, "https://")) != string::npos) //Verifica se o início do link é https://
    {
        secure = true; //Marca como https
        url.erase(aux, 8); //Remove está string
    }
}
Exemple #2
0
/*
* Filtra os novos links da página recebida
*/
void httpclient::parse_page()
{
	size_t pos = 0, pos_max = 0, aux = 0; //Auxiliares para manipulação de strings
	s_trace trace; //Estrutura local que será utilizada como base para inserção de novas urls no vetor
	char symbol[2] = "";
	if (deep >= webc->get_deep()) //Verifica se a profundidade atual é igual ou maior que a limite
		return;
	trace.deep = deep + 1; //Links desta página serão de profundidade K+1
	while (pos != string::npos)
	{ //Busca novos links <a href=
		if ((pos = str_find_ci(page, "<a ", pos)) != string::npos)
		{ //Verifica se existe alguma tag 'a' após a posição atual
			pos_max = page.find(">", pos); //Procura o final desta tag para evitar transtornos
			pos = str_find_ci(page, string("href="), pos); //Procura o atributo 'href' da tag 'a' encontrada
			if (pos < pos_max)
			{ //Verifica se o atributo 'href' foi encontrado até o limite da tag
				symbol[0] = page[pos + 5]; //Salva o simbolo após =, pois pode ser ' ou "
				pos = page.find(symbol, pos); //Procura o início do valor do atributo
				aux = page.find(symbol, pos + 1); //Procura o fim do valor do atributo

				trace.url = page.substr(pos + 1, aux - pos - 1); //Obtém a nova url a ser colocada no vetor
				if (trace.url.substr(0, 11) != "javascript:" && trace.url[0] != '#') //Verifica se o link não é um javascript ou algum outro truque
				{
					if ((aux = str_find_ci(trace.url, "http://")) != string::npos) //Verifica se o início do link é http://
						trace.url.erase(aux, 7); //Remove está string
					aux = trace.url.find("/"); //Procura o caracter '/'
					if (aux == string::npos) //Verifica se o caracter '/' não foi encontrado
						trace.url = host + "/" + trace.url; //Então a url será: host_atual+/+nova_url
					else if (aux == 0) //Verifica se o caracter foi encontrado na primeira posição do novo link
						trace.url = host + trace.url; //Então a url será: host_atual+nova_url
					else if ((aux = trace.url.substr(0, aux - 1).find(".")) == 0 || aux == string::npos) //Verifica se o caracter '.' foi encontrado na primeira posição do novo link ou não foi encontrado
						trace.url = host + "/" + trace.url; //Então a url será: host_atual+/+nova_url
					while ((aux = trace.url.find("\r\n")) != string::npos) //Procura \r\n perdidos no meio do link
						trace.url.erase(aux, 2); //Remove os \r\n do meio do link

					webc->push_trace(new s_trace(trace)); //Adiciona a nova url no vetor
				}
			}
		}
		if (pos != string::npos)
			pos = pos_max;
	}
	pos = 0;
	while (pos != string::npos)
	{ //Busca novos links <img src=
		if ((pos = str_find_ci(page, "<img", pos)) != string::npos)
		{ //Verifica se existe alguma tag 'img' após a posição atual
			pos_max = page.find(">", pos); //Procura o final desta tag para evitar transtornos
			pos = str_find_ci(page, string("src="), pos); //Procura o atributo 'src' da tag 'img' encontrada
			if (pos < pos_max)
			{ //Verifica se o atributo 'src' foi encontrado até o limite da tag
				symbol[0] = page[pos + 4]; //Salva o simbolo após =, pois pode ser ' ou "
				pos = page.find(symbol, pos); //Procura o início do valor do atributo
				aux = page.find(symbol, pos + 1); //Procura o fim do valor do atributo

				trace.url = page.substr(pos + 1, aux - pos - 1); //Obtém a nova url a ser colocada no vetor
				if ((aux = str_find_ci(trace.url, "http://")) != string::npos) //Verifica se o início do link é http://
					trace.url.erase(aux, 7); //Remove está string
				aux = trace.url.find("/"); //Procura o caracter '/'
				if (aux == string::npos) //Verifica se o caracter '/' não foi encontrado
					trace.url = host + "/" + trace.url; //Então a url será: host_atual+/+nova_url
				else if (aux == 0) //Verifica se o caracter foi encontrado na primeira posição do novo link
					trace.url = host + trace.url; //Então a url será: host_atual+nova_url
				else if ((aux = trace.url.substr(0, aux - 1).find(".")) == 0 || aux == string::npos) //Verifica se o caracter '.' foi encontrado na primeira posição do novo link ou não foi encontrado
					trace.url = host + "/" + trace.url; //Então a url será: host_atual+/+nova_url
				while ((aux = trace.url.find("\r\n")) != string::npos) //Procura \r\n perdidos no meio do link
					trace.url.erase(aux, 2); //Remove os \r\n do meio do link

				webc->push_trace(new s_trace(trace)); //Adiciona a nova url no vetor
			}
		}
		if (pos != string::npos)
			pos = pos_max;
	}
}
Exemple #3
0
/*
* Cria a conexão com o dominio desejado
*/
void *httpclient::make_connection(void *client_ptr)
{
	httpclient *me = (httpclient *)client_ptr; //Ponteiro para o cliente atual
	struct addrinfo hints, *result, *rp; //Estruturas auxiliares para criação do socket
	string &url = me->get_surl(); //Url base do cliente atual
	string host; //Host para conexão
	int ret = 0; //Valor a ser retornado pela thread
	int s; //SocketID
	size_t pos; //Auxiliar para manipulação de strings

#ifdef WIN32
	WSADATA wsaData;
	DWORD timeOut;

	timeOut = 5000;//5 segundos
#else
	struct timeval timeOut;

	timeOut.tv_usec = 0;
	timeOut.tv_sec = 5;  //5 segundos de timeout
#endif

	me->count(); //Incrementa o contador de execuções do cliente
#ifdef WIN32
	ret = WSAStartup(MAKEWORD(1, 1), &wsaData); //Inicia o uso do dll winsock, com socket versão 1.1
	if (ret != 0)
	{
		webc->write_error(to_string(me->get_id()) + "|WSAStartup:" + url + " ~ " + host + " ~ " + to_string(WSAGetLastError()));
		webc->push_client(me); //Coloca o cliente de volta na lista
	}
#endif

	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;	//Permite que ip seja IPV4 ou IPV6
	hints.ai_socktype = SOCK_STREAM; //Socket STREAM para utilização do TCP
	hints.ai_flags = 0;
	hints.ai_protocol = IPPROTO_TCP; //Define que o protocolo utilizado será TCP

	if ((pos = str_find_ci(url, "/")) != string::npos)
		host = url.substr(0, pos); //Caso exista um diretório na url base o mesmo é filtrado
	else
		host = url;

	if ((pos = str_find_ci(host, "www.")) != string::npos && pos == 0)
		host = host.substr(4); //Caso seja encontrado o www., o mesmo também é removido

	s = getaddrinfo(host.c_str(), "80", &hints, &result); //Obtém lista de estruturas de endereços
	if (s != 0)
	{
		webc->write_error(to_string(me->get_id()) + "|Getaddrinfo:" + url + " ~ " + host + " ~ " + gai_strerror(s));
		webc->push_client(me); //Coloca o cliente de volta na lista
		pthread_exit((void*)-1);
	}

	// Tenta conectar em toda a lista de enderecos fornecidos pelo getaddrinfo, ate conseguir se conectar a algum
	for (rp = result; rp != NULL; rp = rp->ai_next)
	{
		s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
		if (s == -1)
			continue;
		if (connect(s, rp->ai_addr, rp->ai_addrlen) != -1)
			break;//Sucesso na conexão
		closesocket(s);
	}

	if (rp == NULL)
	{ //Nao foi possivel se conectar a nenhum dos enderecos

		webc->write_error(to_string(me->get_id()) + "|Socket:" + url + " ~ " + host + " ~ " + gai_strerror(s));
		webc->push_client(me); // Coloca este cliente de volta na lista
		pthread_exit((void*)-2);
	}

	freeaddrinfo(result); //Nao e mais necessario

	setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeOut, sizeof(timeOut)); //Define um timeout para o recebimento

	me->set_socket(s); //Passa o socket para a classe

	if (me->send_req() >= 0 && me->read_page() >= 0) //Envia requisição e recebe a resposta
	{
		me->parse_page(); //Verifica novas urls na pagina recebida
	}

	webc->push_client(me); //Coloca este cliente de volta na lista

	closesocket(s); //Fecha o socket utilizado

#ifdef WIN32
	WSACleanup();
#endif
	pthread_exit((void*)ret); //Coloca o valor do erro no retorno
	return 0;
}
Exemple #4
0
/*
* Recebe a resposta da requisição enviada
*/
int httpclient::read_page()
{
	ofstream out_file(webc->create_dir("webs/" + host + "/" + dir).c_str(), ofstream::binary); //Cria arquivo de saída para o conteúdo
	ofstream header_file(webc->create_dir("webs/" + host + "/" + dir + ".header").c_str(), ofstream::binary); //Cria arquivo de saída para o cabeçalho
	int tmp; //Auxiliar para controle do recebimento
	bool content = false, chunked = false;
	size_t pos; //Auxiliar para manipulação de strings
	tmp = recv(s, buffer, sizeof(buffer)-1, 0); //Solicita o recebimento de dados
	page = string("");
	header = string("");

	while (tmp > 0)
	{ //Enquanto tmp maior que 0 continua tentando receber
		if (content)
		{ //Verifica se o cabeçalho já foi todo recebido
			page.append(buffer, tmp); //Insere a parte do conteúdo recebida na string de conteúdo
		}
		else
		{ //O cabeçalho ainda não foi totalmente recebido
			char *ptr = strstr(buffer, "\r\n\r\n"); //Procura o final do cabeçalho GET HTTP/1.1
			if (ptr)
			{
				header.append(buffer, ptr - buffer + 4); //Insere na string de cabeçalho a parte deste pacote que faz parte do cabeçalho
				/* Verificação de conteúdo codificado */
				pos = str_find_ci(header, "Transfer-Encoding:"); //Procura a string que identifica a codificação de transferencia
				if (pos != string::npos)
				{ //Caso exista a codificação é analisada qual o tipo da mesma
					string encoding = header.substr(pos + 19, header.find("\r\n", pos) - (pos + 19));
					if (encoding == "chunked") //Verifica se é do tipo chunked
						chunked = true;
				}
				while (*ptr == '\r' || *ptr == '\n') ptr++;
				tmp = tmp - (ptr - buffer); //É obtido então quantos bytes do pacote atual fazem parte do corpo da mensagem
				if (tmp >= 0) //Verifica se o número de bytes de corpo remanescentes é válido
					page.append(ptr, tmp); //Insere na string de corpo a parte deste pacote que faz parte do corpo
				content = true; //Confirma que a partir deste momento todos os bytes serão de conteúdo
			}
			else
			{
				header.append(buffer, tmp); //Escreve todos os bytes recebidos na string de cabeçalho
			}
		}
		memset(buffer, 0, sizeof(buffer)-1);
		tmp = recv(s, buffer, sizeof(buffer)-1, 0); //Solicita o recebimento de dados
		buffer[tmp] = '\0';
	}

	if (errno != 0)
	{ //Verifica se houve algum erro no recv
		if (chunked)
		{ //Caso o Transfer-Encoding utilizado seja chunked
			size_t old = 0, next = 0, pos; //Auxiliares
			pos = page.find("\r\n", 0) + 2; //Procura o final da informação do chunk
			next = stoi(page, nullptr, 16); //Obtém a quantidade de bytes do chunk
			page.erase(old, pos - old); //Remove a informação do chunk do conteúdo da page
			old = next;
			while (next)
			{
				pos = page.find("\r\n", old + 2) + 2; //Procura o final da informação do chunk
				if (page[old + 2] != '0')
					next = stoi(&page[old + 2], nullptr, 16); //Obtém a quantidade de bytes do chunk
				else
					next = 0; //Chunk final
				page.erase(old, pos - old); //Remove a informação do chunk do conteúdo da page
				old += next;
			}
		}
	}
	header_file.write(page.c_str(), page.size()); //Escreve no arquivo do cabeçalho a string que contém o cabeçalho
	out_file.write(page.c_str(), page.size()); //Escreve no arquivo do corpo a string que contém o corpo

	header_file.close(); //Fecha os arquivos
	out_file.close();

	return 0;
}