Files @ 79b50300351f
Branch filter:

Location: libtransport.git/backends/libyahoo2/httpfetch.cpp

Jan Kaluza
Check if the user is in room before sending information about nick change. Fixes bug when users have been added to all rooms when they changed their IRC nickname

#include "httpfetch.h"
#include "transport/logging.h"

#if WIN32
#define snprintf sprintf_s
#endif

DEFINE_LOGGER(logger, "HTTPFetch");

static int url_to_host_port_path(const char *url,
	char *host, int *port, char *path, int *ssl)
{
	char *urlcopy = NULL;
	char *slash = NULL;
	char *colon = NULL;

	/*
	 * http://hostname
	 * http://hostname/
	 * http://hostname/path
	 * http://hostname/path:foo
	 * http://hostname:port
	 * http://hostname:port/
	 * http://hostname:port/path
	 * http://hostname:port/path:foo
	 * and https:// variants of the above
	 */

	if (strstr(url, "http://") == url) {
		urlcopy = strdup(url + 7);
	} else if (strstr(url, "https://") == url) {
		urlcopy = strdup(url + 8);
		*ssl = 1;
	} else {
		return 0;
	}

	slash = strchr(urlcopy, '/');
	colon = strchr(urlcopy, ':');

	if (!colon || (slash && slash < colon)) {
		if (*ssl)
			*port = 443;
		else
			*port = 80;
	} else {
		*colon = 0;
		*port = atoi(colon + 1);
	}

	if (!slash) {
		strcpy(path, "/");
	} else {
		strcpy(path, slash);
		*slash = 0;
	}

	strcpy(host, urlcopy);

	free(urlcopy);

	return 1;
}

HTTPFetch::HTTPFetch(Swift::BoostIOServiceThread *ioService, Swift::ConnectionFactory *factory) : m_ioService(ioService), m_factory(factory) {
	m_afterHeader = false;
}

HTTPFetch::~HTTPFetch() {
}

void HTTPFetch::_connected(boost::shared_ptr<Swift::Connection> conn, const std::string url, bool error) {
	if (error) {
		_disconnected(conn);
	}
	else {
		char host[255];
		int port = 80;
		char path[255];
		int ssl = 0;
		if (!url_to_host_port_path(url.c_str(), host, &port, path, &ssl))
			return;

		static char buff[2048];
		snprintf(buff, sizeof(buff),
			"GET %s HTTP/1.1\r\n"
			"Host: %s\r\n"
			"User-Agent: Mozilla/4.5 [en] (1/1)\r\n"
			"Accept: */*\r\n"
			"%s" "\r\n", path, host,
			"Connection: close\r\n");
		LOG4CXX_INFO(logger, "Sending " << buff << "\n");
		conn->write(Swift::createSafeByteArray(buff));
	}
}

void HTTPFetch::_disconnected(boost::shared_ptr<Swift::Connection> conn) {
	conn->onConnectFinished.disconnect_all_slots();
	conn->onDisconnected.disconnect_all_slots();
	conn->onDataRead.disconnect_all_slots();

	if (m_buffer.size() == 0) {
		onURLFetched("");
	}
	else {
		std::string img = m_buffer.substr(m_buffer.find("\r\n\r\n") + 4);
		onURLFetched(img);
	}
}

void HTTPFetch::_read(boost::shared_ptr<Swift::Connection> conn, boost::shared_ptr<Swift::SafeByteArray> data) {
	std::string d(data->begin(), data->end());
// 			std::cout << d << "\n";
	std::string img = d.substr(d.find("\r\n\r\n") + 4);
	if (d.find("Location: ") == std::string::npos) {
		m_buffer += d;
	}
	else {
		d = d.substr(d.find("Location: ") + 10);
		if (d.find("\r") == std::string::npos) {
			d = d.substr(0, d.find("\n"));
		}
		else {
			d = d.substr(0, d.find("\r"));
		}
		LOG4CXX_INFO(logger, "Next url is '" << d << "'");
		fetchURL(d);
		conn->onConnectFinished.disconnect_all_slots();
		conn->onDisconnected.disconnect_all_slots();
		conn->onDataRead.disconnect_all_slots();
	}
}

bool HTTPFetch::fetchURL(const std::string &url) {
	char host[255];
	int port = 80;
	char path[255];
	char buff[1024];
	int ssl = 0;
	if (!url_to_host_port_path(url.c_str(), host, &port, path, &ssl)) {
		LOG4CXX_ERROR(logger, "Invalid URL " << url);
		return false;
	}

	LOG4CXX_INFO(logger, "Connecting to " << host << ":" << port);

	boost::asio::ip::tcp::resolver resolver(*m_ioService->getIOService());
	boost::asio::ip::tcp::resolver::query query(host, "");
	boost::asio::ip::address address;
	for(boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query); i != boost::asio::ip::tcp::resolver::iterator(); ++i) {
		boost::asio::ip::tcp::endpoint end = *i;
		address = end.address();
		break;
	}

	boost::shared_ptr<Swift::Connection> conn = m_factory->createConnection();
	conn->onConnectFinished.connect(boost::bind(&HTTPFetch::_connected, this, conn, url, _1));
	conn->onDisconnected.connect(boost::bind(&HTTPFetch::_disconnected, this, conn));
	conn->onDataRead.connect(boost::bind(&HTTPFetch::_read, this, conn, _1));
	conn->connect(Swift::HostAddressPort(Swift::HostAddress(address), port));
	return true;
}