From: <at...@us...> - 2007-08-23 23:00:00
|
Revision: 489 http://cadcdev.svn.sourceforge.net/cadcdev/?rev=489&view=rev Author: atani Date: 2007-08-23 15:59:57 -0700 (Thu, 23 Aug 2007) Log Message: ----------- fixes for POST and uploading file(s). a few cleanups of RefPtr uses, still have some problems with memory leaks in HttpUserAgent Modified Paths: -------------- tiki/examples/net/chatd/src/main.cpp tiki/examples/net/httpclient/src/main.cpp tiki/include/Tiki/net/address.h tiki/include/Tiki/net/buffer.h tiki/include/Tiki/net/http/request.h tiki/include/Tiki/net/http/useragent.h tiki/include/Tiki/net/socket.h tiki/include/Tiki/net/tcpserversocket.h tiki/include/Tiki/net/tcpsocket.h tiki/src/net/http/request.cpp tiki/src/net/http/useragent.cpp tiki/src/net/socket.cpp tiki/src/net/tcpserversocket.cpp tiki/src/net/tcpsocket.cpp Modified: tiki/examples/net/chatd/src/main.cpp =================================================================== --- tiki/examples/net/chatd/src/main.cpp 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/examples/net/chatd/src/main.cpp 2007-08-23 22:59:57 UTC (rev 489) @@ -82,7 +82,7 @@ { uint8 *data = line->getData(); string cmd = ""; - for(int i = 0; i < line->getUsedDataLen(); i++) + for(size_t i = 0; i < line->getUsedDataLen(); i++) { cmd.push_back(data[i]); } Modified: tiki/examples/net/httpclient/src/main.cpp =================================================================== --- tiki/examples/net/httpclient/src/main.cpp 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/examples/net/httpclient/src/main.cpp 2007-08-23 22:59:57 UTC (rev 489) @@ -31,17 +31,12 @@ Tiki::Net::init(); Hid::callbackReg( tkCallback, NULL ); - if(argc < 2) { - Tiki::Debug::printf("Need to pass request url on commandline\n"); - return -1; - } - RefPtr<HttpUserAgent> useragent = new HttpUserAgent(); //useragent->setProxyHost("proxy.example.com"); //useragent->setProxyPort(80); RefPtr<Request> request = new Request(); - request->setUrl(argv[1]); + request->setUrl("http://www.example.com/"); RefPtr<Response> response = useragent->get(request); Tiki::Debug::printf("response code: %d\n", response->getResultCode()); @@ -51,12 +46,12 @@ iter != content.end(); ++iter) { - RefPtr<Buffer> responseBuf = response->getContentPart(*iter); + Buffer *responseBuf = response->getContentPart(*iter); Tiki::Debug::printf("Content Part: %s [%u bytes]\n", (*iter).c_str(), responseBuf->getUsedDataLen()); Tiki::Debug::printf("%s\n", responseBuf->getData()); } - Tiki::Net::shutdown(); + return 0; } Modified: tiki/include/Tiki/net/address.h =================================================================== --- tiki/include/Tiki/net/address.h 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/include/Tiki/net/address.h 2007-08-23 22:59:57 UTC (rev 489) @@ -18,6 +18,9 @@ { public: Address(); + Address(std::string hostname, int port) : m_port(port) { + setHostName(hostname); + } typedef enum AddressType { AddressUnknown = 0x00000000, Modified: tiki/include/Tiki/net/buffer.h =================================================================== --- tiki/include/Tiki/net/buffer.h 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/include/Tiki/net/buffer.h 2007-08-23 22:59:57 UTC (rev 489) @@ -22,14 +22,16 @@ class Buffer : public Object { public: - Buffer(size_t len, std::string contentType = "application/octet-stream") : m_contentType(contentType) { + Buffer(size_t len, std::string contentType = "application/octet-stream") : + m_contentType(contentType) { m_data = new uint8[len]; memset(m_data, 0, len); m_dataLen = len; m_usedDataLen = 0; } - Buffer(size_t len, uint8 *data, std::string contentType = "application/octet-stream") : m_contentType(contentType) { + Buffer(size_t len, uint8 *data, std::string contentType = "application/octet-stream") : + m_contentType(contentType) { m_data = new uint8[len]; memset(m_data, 0, len); m_dataLen = len; @@ -39,13 +41,9 @@ Buffer(std::string filename, std::string contentType, std::string fieldName = "") : m_fileName(filename), m_contentType(contentType), m_fieldName(fieldName) { - std::ifstream stream(filename.c_str(), std::ios::in | std::ios::binary); - stream.seekg(0, std::ios::end); - m_dataLen = m_usedDataLen = stream.tellg(); - stream.seekg(0); - m_data = new uint8[m_dataLen]; - stream.read((char *)m_data, m_dataLen); - stream.close(); + File file(filename, "rb"); + read(file); + file.close(); } Buffer(Tiki::File file, std::string contentType, std::string fieldName = "") : @@ -58,12 +56,12 @@ m_fileName = file.getFileName(); m_dataLen = m_usedDataLen = file.total(); m_data = new uint8[m_dataLen]; - file.read(m_data, m_dataLen); + file.read(m_data, static_cast<int>(m_dataLen)); } void write(Tiki::File file) { assert(file.isValid()); - file.write(m_data, m_usedDataLen); + file.write(m_data, static_cast<int>(m_usedDataLen)); } void append(RefPtr<Buffer> buf) { Modified: tiki/include/Tiki/net/http/request.h =================================================================== --- tiki/include/Tiki/net/http/request.h 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/include/Tiki/net/http/request.h 2007-08-23 22:59:57 UTC (rev 489) @@ -1,61 +1,74 @@ -/* - Tiki - - useragent.h - - Copyright (C)2007 Atani Software -*/ -#ifndef __TIKI_NET_HTTP_REQUEST_H -#define __TIKI_NET_HTTP_REQUEST_H - -#include "Tiki/refcnt.h" - -namespace Tiki { - -namespace Net { - -namespace Http { - -extern std::string DEFAULT_CONTENT_PART; - -class Request : public RefCnt { - public: - Request(); - - std::string getUrl() const { - return m_url; - } - - void setUrl(string url) { - m_url = url; - } - - void removeHeaderParam(std::string param); - void setHeaderParam(std::string param, std::string value); - std::string getHeaderParam(std::string param) const; - std::list<std::string> getHeaderParamNames() const; - - void addContentPart(std::string name, RefPtr<Buffer> input); - std::list<std::string> getContentPartNames() const; - RefPtr<Buffer> getContentPart(std::string name) const; - - std::string getBoundaryMarker() const { - return m_boundaryMarker; - } - - private: - std::string m_url; - std::string m_boundaryMarker; - typedef std::map<std::string, std::string> StringStringMap; - typedef std::map<std::string, RefPtr< Buffer > > StringBufferMap; - StringStringMap m_params; - StringBufferMap m_parts; -}; - -}; // namespace Http - -}; // namespace Net - -}; // namespace Tiki - -#endif // __TIKI_NET_HTTP_REQUEST_H +/* + Tiki + + useragent.h + + Copyright (C)2007 Atani Software +*/ +#ifndef __TIKI_NET_HTTP_REQUEST_H +#define __TIKI_NET_HTTP_REQUEST_H + +#include "Tiki/refcnt.h" + +namespace Tiki { + +namespace Net { + +namespace Http { + +extern std::string DEFAULT_CONTENT_PART; + +class Request : public RefCnt { + public: + Request(); + /* + virtual ~Request() { + m_params.clear(); + if(!m_parts.empty()) { + for(StringBufferMap::iterator iter = m_parts.begin(); + iter != m_parts.end(); + ++iter) { + delete iter->second; + } + } + m_parts.clear(); + } + */ + + std::string getUrl() const { + return m_url; + } + + void setUrl(string url) { + m_url = url; + } + + void removeHeaderParam(std::string param); + void setHeaderParam(std::string param, std::string value); + std::string getHeaderParam(std::string param) const; + std::list<std::string> getHeaderParamNames() const; + + void addContentPart(Buffer *input, std::string name = ""); + std::list<std::string> getContentPartNames() const; + Buffer *getContentPart(std::string name) const; + + std::string getBoundaryMarker() const { + return m_boundaryMarker; + } + + private: + std::string m_url; + std::string m_boundaryMarker; + typedef std::map<std::string, std::string> StringStringMap; + typedef std::map<std::string, RefPtr<Buffer> > StringBufferMap; + StringStringMap m_params; + StringBufferMap m_parts; +}; + +}; // namespace Http + +}; // namespace Net + +}; // namespace Tiki + +#endif // __TIKI_NET_HTTP_REQUEST_H Modified: tiki/include/Tiki/net/http/useragent.h =================================================================== --- tiki/include/Tiki/net/http/useragent.h 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/include/Tiki/net/http/useragent.h 2007-08-23 22:59:57 UTC (rev 489) @@ -1,82 +1,89 @@ -/* - Tiki - - useragent.h - - Copyright (C)2007 Atani Software -*/ -#ifndef __TIKI_NET_HTTP_USERAGENT_H -#define __TIKI_NET_HTTP_USERAGENT_H - -#include "Tiki/refcnt.h" -#include "Tiki/net/tcpsocket.h" -#include "Tiki/net/http/cookie.h" -#include "Tiki/net/http/request.h" -#include "Tiki/net/http/response.h" - -namespace Tiki { - -namespace Net { - -namespace Http { - -using Tiki::Net::TCP::TCPSocket; - -class HttpUserAgent : public RefCnt { - - public: - HttpUserAgent(); - - void setUserAgentName(std::string name) { - m_userAgentName = name; - } - - std::string getUserAgentName() const { - return m_userAgentName; - } - - void setProxyHost(std::string host) { - m_proxyHost = host; - } - - std::string getProxyHost() const { - return m_proxyHost; - } - - void setProxyPort(int port) { - m_proxyPort = port; - } - - int getProxyPort() const { - return m_proxyPort; - } - - std::list< RefPtr< Cookie > > getCookies() const { - return m_cookies; - } - - RefPtr<Response> get(RefPtr<Request> req); - - RefPtr<Response> post(RefPtr<Request> req); - - private: - std::string m_userAgentName; - std::string m_proxyHost; - int m_proxyPort; - std::list< RefPtr< Cookie > > m_cookies; - - void parseUrl(const std::string url, std::string &host, std::string &resource, int &port); - void buildRequest(const std::string host, const std::string resource, const int port, - const std::string mode, RefPtr<Request> request, std::string &requestText, - RefPtr<Address> address); - void readResponse(RefPtr<Response> response, RefPtr<TCPSocket> socket); - -}; - -}; // namespace Http - -}; // namespace Net - -}; // namespace Tiki - -#endif // __TIKI_NET_HTTP_USERAGENT_H +/* + Tiki + + useragent.h + + Copyright (C)2007 Atani Software +*/ +#ifndef __TIKI_NET_HTTP_USERAGENT_H +#define __TIKI_NET_HTTP_USERAGENT_H + +#include "Tiki/refcnt.h" +#include "Tiki/net/tcpsocket.h" +#include "Tiki/net/http/cookie.h" +#include "Tiki/net/http/request.h" +#include "Tiki/net/http/response.h" + +namespace Tiki { + +namespace Net { + +namespace Http { + +using Tiki::Net::TCP::TCPSocket; + +class HttpUserAgent : public RefCnt { + + public: + HttpUserAgent(); + virtual ~HttpUserAgent() { + for(std::list< RefPtr< Cookie > >::iterator iter = m_cookies.begin(); + iter != m_cookies.end(); + ++iter) { + delete *iter; + } + m_cookies.clear(); + } + + void setUserAgentName(std::string name) { + m_userAgentName = name; + } + + std::string getUserAgentName() const { + return m_userAgentName; + } + + void setProxyHost(std::string host) { + m_proxyHost = host; + } + + std::string getProxyHost() const { + return m_proxyHost; + } + + void setProxyPort(int port) { + m_proxyPort = port; + } + + int getProxyPort() const { + return m_proxyPort; + } + + std::list< RefPtr< Cookie > > getCookies() const { + return m_cookies; + } + + Response *get(Request *req); + + Response *post(Request *req); + + private: + std::string m_userAgentName; + std::string m_proxyHost; + int m_proxyPort; + std::list< RefPtr< Cookie > > m_cookies; + + void parseUrl(const std::string url, std::string &host, std::string &resource, int &port); + void buildRequest(const std::string host, const std::string resource, const int port, + const std::string mode, Request *request, std::string &requestText); + void readResponse(Response *response, TCPSocket *socket); + +}; + +}; // namespace Http + +}; // namespace Net + +}; // namespace Tiki + +#endif // __TIKI_NET_HTTP_USERAGENT_H Modified: tiki/include/Tiki/net/socket.h =================================================================== --- tiki/include/Tiki/net/socket.h 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/include/Tiki/net/socket.h 2007-08-23 22:59:57 UTC (rev 489) @@ -20,24 +20,24 @@ { public: Socket(); - Socket(RefPtr<Address> address); + Socket(Address *address); - RefPtr<Address> getPeerAddress() + Address *getPeerAddress() { return m_peerAddress; } - void setPeerAddress(RefPtr<Address> address) + void setPeerAddress(Address *address) { m_peerAddress = address; } - RefPtr<Address> getLocalAddress() + Address *getLocalAddress() { return m_localAddress; } - void setLocalAddress(RefPtr<Address> address) + void setLocalAddress(Address *address) { m_localAddress = address; } @@ -62,9 +62,9 @@ m_reuse = reuse; } - virtual void send(RefPtr<Buffer> data) = 0; + virtual void send(Buffer *data) = 0; - virtual void recv(RefPtr<Buffer> data) = 0; + virtual void recv(Buffer *data) = 0; virtual void open() = 0; Modified: tiki/include/Tiki/net/tcpserversocket.h =================================================================== --- tiki/include/Tiki/net/tcpserversocket.h 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/include/Tiki/net/tcpserversocket.h 2007-08-23 22:59:57 UTC (rev 489) @@ -20,11 +20,11 @@ { public: TCPServerSocket() : TCPSocket() {}; - TCPServerSocket(RefPtr<Address> address) : TCPSocket(address) {}; + TCPServerSocket(Address *address) : TCPSocket(address) {}; void bind(size_t maxwaiting = 10); - RefPtr<TCPSocket> accept(); + TCPSocket *accept(); }; } // namespace TCP Modified: tiki/include/Tiki/net/tcpsocket.h =================================================================== --- tiki/include/Tiki/net/tcpsocket.h 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/include/Tiki/net/tcpsocket.h 2007-08-23 22:59:57 UTC (rev 489) @@ -32,27 +32,27 @@ #define SOCKET_ERROR -1 #endif TCPSocket() : Socket(), m_open(false) {}; - TCPSocket(RefPtr<Address> address) : Socket(address), m_open(false) {}; + TCPSocket(Address *address) : Socket(address), m_open(false) {}; #if TIKI_PLAT == TIKI_WIN32 - TCPSocket(RefPtr<Address> address, SOCKET socket) : Socket(address), m_socket(socket), m_open(true) {setNonBlocking(false);}; + TCPSocket(Address *address, SOCKET socket) : Socket(address), m_socket(socket), m_open(true) {setNonBlocking(false);}; #else TCPSocket(RefPtr<Address> address, int socket) : Socket(address), m_socket(socket), m_open(true) {setNonBlocking(false);}; #endif - virtual void send(RefPtr<Buffer> data); + virtual void send(Buffer *data); - virtual void recv(RefPtr<Buffer> data); + virtual void recv(Buffer *data); virtual bool isOpen() { return m_open; } - uint32 getPort() + uint16 getPort() { return m_port; } - void setPort(uint32 port) + void setPort(uint16 port) { m_port = port; } @@ -63,7 +63,7 @@ virtual void setNonBlocking(bool blocking); protected: - uint32 m_port; + uint16 m_port; bool m_open; #if TIKI_PLAT == TIKI_WIN32 SOCKET m_socket; Modified: tiki/src/net/http/request.cpp =================================================================== --- tiki/src/net/http/request.cpp 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/src/net/http/request.cpp 2007-08-23 22:59:57 UTC (rev 489) @@ -1,96 +1,100 @@ -/* - Tiki - - request.cpp - - Copyright (C)2007 Atani Software -*/ - -#include "pch.h" -#include "Tiki/tiki.h" -#include "Tiki/net.h" -#include "Tiki/net/http/request.h" - -namespace Tiki { - -namespace Net { - -namespace Http { - -std::string DEFAULT_CONTENT_PART = "__TIKI__DEFAULT__"; - -Request::Request() { - setHeaderParam("Connection", "close"); - m_boundaryMarker = "-----------------------09f911019d74e35bd84156c5635688c0"; - -} - -void Request::removeHeaderParam(std::string param) { - if(m_params.find(param) != m_params.end()) { - m_params.erase(m_params.find(param)); - } -} - -void Request::setHeaderParam(std::string param, std::string value) { - if(!param.compare("User-Agent")) { - Tiki::Debug::printf("Setting User-Agent via Request::setHeaderParam() is not allowed. Use HttpUserAgent::setUserAgentName() instead.\n"); - return; - } - m_params.insert(std::make_pair(param, value)); -} - -std::string Request::getHeaderParam(std::string param) const { - if(m_params.find(param) != m_params.end()) { - return m_params.find(param)->second; - } - return ""; -} - -std::list<std::string> Request::getHeaderParamNames() const { - std::list<std::string> params; - - for( StringStringMap::const_iterator param = m_params.begin(); - param != m_params.end(); - ++param) { - - params.push_back(param->first); - } - - return params; -} - -void Request::addContentPart(std::string name, RefPtr<Buffer> input) { - //if(m_parts.find(name) != m_parts.end()) { - // m_parts.erase(m_parts.find(name)); - //} - - m_parts.insert(std::make_pair(name, input)); -} - -RefPtr<Buffer> Request::getContentPart(std::string name) const { - if(m_parts.find(name) != m_parts.end()) { - return m_parts.find(name)->second; - } - return NULL; -} - -std::list<std::string> Request::getContentPartNames() const { - std::list<std::string> parts; - - for( StringBufferMap::const_iterator part = m_parts.begin(); - part != m_parts.end(); - ++part) { - - parts.push_back(part->first); - } - - return parts; -} - - -}; // namespace Http - -}; // namespace Net - -}; // namespace Tiki - +/* + Tiki + + request.cpp + + Copyright (C)2007 Atani Software +*/ + +#include "pch.h" +#include "Tiki/tiki.h" +#include "Tiki/net.h" +#include "Tiki/net/http/request.h" + +namespace Tiki { + +namespace Net { + +namespace Http { + +std::string DEFAULT_CONTENT_PART = "__TIKI__DEFAULT__"; + +Request::Request() { + setHeaderParam("Connection", "close"); + m_boundaryMarker = "-----------------------09f911019d74e35bd84156c5635688c0"; + +} + +void Request::removeHeaderParam(std::string param) { + if(m_params.find(param) != m_params.end()) { + m_params.erase(m_params.find(param)); + } +} + +void Request::setHeaderParam(std::string param, std::string value) { + if(!param.compare("User-Agent")) { + Tiki::Debug::printf("Setting User-Agent via Request::setHeaderParam() is not allowed. Use HttpUserAgent::setUserAgentName() instead.\n"); + return; + } + m_params.insert(std::make_pair(param, value)); +} + +std::string Request::getHeaderParam(std::string param) const { + if(m_params.find(param) != m_params.end()) { + return m_params.find(param)->second; + } + return ""; +} + +std::list<std::string> Request::getHeaderParamNames() const { + std::list<std::string> params; + + for( StringStringMap::const_iterator param = m_params.begin(); + param != m_params.end(); + ++param) { + + params.push_back(param->first); + } + + return params; +} + +void Request::addContentPart(Buffer *input, std::string name) { + if(!name.empty()) { + m_parts.insert(std::make_pair(name, input)); + } + else if(!input->getFileName().empty()) { + m_parts.insert(std::make_pair(input->getFileName(), input)); + } + else { + m_parts.insert(std::make_pair(DEFAULT_CONTENT_PART, input)); + } +} + +Buffer *Request::getContentPart(std::string name) const { + if(m_parts.find(name) != m_parts.end()) { + return m_parts.find(name)->second; + } + return NULL; +} + +std::list<std::string> Request::getContentPartNames() const { + std::list<std::string> parts; + + for( StringBufferMap::const_iterator part = m_parts.begin(); + part != m_parts.end(); + ++part) { + + parts.push_back(part->first); + } + + return parts; +} + + +}; // namespace Http + +}; // namespace Net + +}; // namespace Tiki + Modified: tiki/src/net/http/useragent.cpp =================================================================== --- tiki/src/net/http/useragent.cpp 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/src/net/http/useragent.cpp 2007-08-23 22:59:57 UTC (rev 489) @@ -1,397 +1,396 @@ -/* - Tiki - - useragent.cpp - - Copyright (C)2007 Atani Software -*/ - -#include "pch.h" -#include "Tiki/tiki.h" -#include "Tiki/net.h" -#include "Tiki/net/http/useragent.h" - -#include <sstream> -#include <math.h> - -namespace Tiki { - -namespace Net { - -namespace Http { - -using namespace Tiki::Net::TCP; - -#define READ_ONE_LINE(res, socket) \ - { \ - RefPtr<Buffer> recvBuf = new Buffer(1); \ - char tbuf[2]; \ - res = ""; \ - while(socket->isOpen()) { \ - recvBuf->reset(); \ - socket->recv(recvBuf); \ - if(recvBuf->getUsedDataLen() > 0) { \ - tbuf[0] = recvBuf->getData()[0]; \ - tbuf[1] = '\0'; \ - if(tbuf[0] != '\n' && tbuf[0] != '\r' ) { \ - res.append((char *)tbuf); \ - } \ - else if(tbuf[0] != '\r' ) { \ - break; \ - } \ - } \ - } \ - } - -HttpUserAgent::HttpUserAgent() { -#if TIKI_PLAT == TIKI_WIN32 - setUserAgentName("Tiki/1.0 (Windows)"); -#elif TIKI_PLAT == TIKI_NDS - setUserAgentName("Tiki/1.0 (Nintendo DS)"); -#elif TIKI_PLAT == TIKI_SDL - setUserAgentName("Tiki/1.0 (SDL)"); -#elif TIKI_PLAT == TIKI_OSX - setUserAgentName("Tiki/1.0 (Mac OS X)"); -#else - setUserAgentName("Tiki/1.0 (Unknown)"); -#endif - setProxyHost(""); - setProxyPort(8080); -} - -RefPtr<Response> HttpUserAgent::get(RefPtr<Request> req) { - RefPtr<TCPSocket> socket = new TCPSocket(); - socket->setNonBlocking(false); - RefPtr<Response> response = new Response(); - response->setUrl(req->getUrl()); - response->setResultCode(200); - - std::string hostname; - int port; - std::string resource; - - parseUrl(req->getUrl(), hostname, resource, port); - - RefPtr<Address> requestAddress = new Address(); - - std::string requestText; - buildRequest(hostname, resource, port, "GET", req, requestText, requestAddress); - socket->setPeerAddress(requestAddress); - Tiki::Debug::printf("Request:\n%s", requestText.c_str()); - - socket->open(); - if(socket->isOpen()) { - Tiki::Debug::printf("Sending request...\n"); - } - else { - Tiki::Debug::printf("connect failed\n"); - response->setResultCode(504); - return response; - } - - RefPtr<Buffer> buf = new Buffer(2048); - buf->setData((uint8 *)requestText.c_str(), requestText.length()); - socket->send(buf); - - readResponse(response, socket); - - return response; -} - -RefPtr<Response> HttpUserAgent::post(RefPtr<Request> req) { - RefPtr<TCPSocket> socket = new TCPSocket(); - socket->setNonBlocking(false); - RefPtr<Response> response = new Response(); - response->setUrl(req->getUrl()); - response->setResultCode(200); - - std::string hostname; - int port; - std::string resource; - - parseUrl(req->getUrl(), hostname, resource, port); - - RefPtr<Address> requestAddress = new Address(); - - std::string requestText; - buildRequest(hostname, resource, port, "POST", req, requestText, requestAddress); - socket->setPeerAddress(requestAddress); - Tiki::Debug::printf("Request:\n%s", requestText.c_str()); - - socket->open(); - if(socket->isOpen()) { - Tiki::Debug::printf("Sending request...\n"); - } - else { - Tiki::Debug::printf("connect failed\n"); - response->setResultCode(504); - return response; - } - - RefPtr<Buffer> buf = new Buffer(2048); - buf->setData((uint8 *)requestText.c_str(), requestText.length()); - socket->send(buf); - - std::list<std::string> content = req->getContentPartNames(); - if(content.size() > 1) { - for(std::list<std::string>::iterator iter = content.begin(); - iter != content.end(); - ++iter) { - RefPtr<Buffer> buf = req->getContentPart(*iter); - std::stringstream temp; - temp << req->getBoundaryMarker() << "\r\n"; - temp << "Content-Disposition: form-data: name=\""; - if(!buf->getFieldName().empty()) { - temp << buf->getFieldName(); - } - else { - temp << "File"; - } - temp << "\"; filename=\"" << buf->getFileNameShort() << "\"\r\nContent-Type: " << buf->getContentType() << "\r\n"; - RefPtr<Buffer> headerBuf = new Buffer(2048); - std::string headerText = temp.str(); - headerBuf->setData((uint8 *)headerText.c_str(), headerText.length()); - socket->send(headerBuf); - socket->send(buf); - } - std::string footerText = "--"; - footerText.append(req->getBoundaryMarker()); - footerText.append("--\r\n"); - RefPtr<Buffer> footerBuf = new Buffer(2048); - footerBuf->setData((uint8 *)footerText.c_str(), footerText.length()); - socket->send(footerBuf); - } - else if(content.size() == 1) { - RefPtr<Buffer> buf = req->getContentPart(*content.begin()); - socket->send(buf); - } - - readResponse(response, socket); - - return response; -} - -void HttpUserAgent::parseUrl(const std::string url, std::string &host, std::string &resource, int &port) { - std::string temp_url = url; - - // set defaults - host = ""; - port = 80; - resource = "/index.html"; - - if(temp_url.find("http://") == 0) { - temp_url = temp_url.substr(std::string("http://").length()); - } - else if(temp_url.find("https://") == 0) { - temp_url = temp_url.substr(std::string("https://").length()); - } - host = temp_url.substr(0, temp_url.find("/")); - if(temp_url.find("/") != std::string::npos) { - resource = temp_url.substr(temp_url.find("/")); - } - if(host.find(":") != std::string::npos) { - std::string portstr = url.substr(host.find(":")); - port = atoi(portstr.c_str()); - host = host.substr(0, host.find(":")); - } -} - -void HttpUserAgent::buildRequest(const std::string host, const std::string resource, const int port, - const std::string mode, RefPtr<Request> request, std::string &requestText, - RefPtr<Address> address) { - - std::stringstream req; - if(m_proxyHost.empty()) { - req << mode << " " << resource << " HTTP/1.1\r\n"; - req << "Host: " << host << "\r\n"; - address->setHostName(host); - address->setPort(port); - } - else { - // proxy connection - req << mode << " " << request->getUrl(); - if(port != 80) { - req << ":" << port; - } - req << " HTTP/1.1\r\n"; - req << "Host: " << host << "\r\n"; - address->setHostName(m_proxyHost); - address->setPort(m_proxyPort); - } - std::list<std::string> params = request->getHeaderParamNames(); - for(std::list<string>::const_iterator param = params.begin(); - param != params.end(); - ++param) { - req << *param << ": " << request->getHeaderParam(*param) << "\r\n"; - } - - if(!m_userAgentName.empty()) { - req << "User-Agent: " << m_userAgentName << "\r\n"; - } - - std::list<std::string> content = request->getContentPartNames(); - if(!mode.compare("POST") && content.size() > 1) { - uint64 totalSize = request->getBoundaryMarker().length() + 6; // add 6 to account for "--<boundary>--\r\n" - for(std::list<std::string>::iterator iter = content.begin(); - iter != content.end(); - ++iter) { - RefPtr<Buffer> buf = request->getContentPart(*iter); - totalSize += buf->getUsedDataLen(); - std::stringstream temp; - temp << "Content-Disposition: form-data: name=\""; - if(!buf->getFieldName().empty()) { - temp << buf->getFieldName(); - } - else { - temp << "File"; - } - temp << "\"; filename=\"" << buf->getFileNameShort() << "\"\r\nContent-Type: " << buf->getContentType() << "\r\n"; - - // add section header size - totalSize += temp.str().length(); - } - - req << "Content-Length: " << totalSize << "\r\n"; - req << "Expect: 100-continue\r\n"; - req << "Content-Type: multipart/form-data; boundary=" << request->getBoundaryMarker() << "\r\n"; - } - else if(!mode.compare("POST") && content.size() == 1) { - RefPtr<Buffer> buf = request->getContentPart(*content.begin()); - req << "Content-Type: " << buf->getContentType() << "\r\n"; - req << "Content-Length: " << buf->getUsedDataLen() << "\r\n"; - } - req << "\r\n"; - - requestText = req.str(); -} - -void HttpUserAgent::readResponse(RefPtr<Response> response, RefPtr<TCPSocket> socket) { - std::string status = ""; - READ_ONE_LINE(status, socket) - - //Tiki::Debug::printf("Status: %s\n", status.c_str()); - for(int i = 0; i < status.length(); i++) { - if(status.at(i) == ' ') { - response->setResultCode(atoi(status.c_str()+i + 1)); - break; - } - } - - while(1) { - std::string line = ""; - READ_ONE_LINE(line, socket) - if(line.size() == 0) { - // done with headers - break; - } - //Tiki::Debug::printf("HEADER_LINE: %s\n", line.c_str()); - if(line.find(":") != std::string::npos) { - std::string field = line.substr(0, line.find(":")); - std::string value = line.substr(line.find(":") + 1); - while(value.at(0) == ' ') { - value = value.substr(1); - } - - if(!field.compare("Set-Cookie")) { - - } - else { - response->setHeaderParam(field, value); - } - } - } - - RefPtr<Buffer> fullBuf = new Buffer(1); - - if(!response->getHeaderParam("Transfer-Encoding").compare("chunked")) { - Tiki::Debug::printf("Encoding is chunked\n"); - // evil chunked encoding - size_t totalSize = 0; - - long sizeDecoded = 0; - do - { - sizeDecoded = 0; - std::string size = ""; - READ_ONE_LINE(size, socket); - if(size.empty()) { - sizeDecoded = 1; - continue; - } - - while(size.find(" ") != std::string::npos) { - size.erase(size.find(" "), 1); - } - - int base = 1; - for(int i = 0; i < size.length(); i++ ) { - char ch = size.at(i); - if(ch >= 'A' && ch <= 'F') { - ch -= 'A'; - ch += 10; - } - else if(ch >= 'a' && ch <= 'f') { - ch -= 'a'; - ch += 10; - } - else if(ch >= '0' && ch <= '9') { - ch -= '0'; - } - else { - continue; - } - sizeDecoded += (ch * static_cast<int>(pow(16.0f, static_cast<int>(size.length() - i - 1)))); - } - //Tiki::Debug::printf("chunk size: %d [%s]\n", sizeDecoded, size.c_str()); - if(sizeDecoded > 0) { - - RefPtr<Buffer> chunkBuf = new Buffer(sizeDecoded); - socket->recv(chunkBuf); - if(chunkBuf->getUsedDataLen() < sizeDecoded) - { - //Tiki::Debug::printf("Buffer underflow\n"); - int needed = sizeDecoded - chunkBuf->getUsedDataLen(); - while(needed > 0) { - RefPtr<Buffer> chunkBuf2 = new Buffer(needed); - socket->recv(chunkBuf2); - chunkBuf->append(chunkBuf2); - needed -= chunkBuf2->getUsedDataLen(); - } - } - totalSize += chunkBuf->getUsedDataLen(); - fullBuf->append(chunkBuf); - } - } while(sizeDecoded > 0); - //Tiki::Debug::printf("total size: %d %x\n", totalSize, totalSize); - } - else if(response->getHeaderParam("Content-Length").compare("")) { - Tiki::Debug::printf("Encoding is inline\n"); - long sizeDecoded = atoi(response->getHeaderParam("Content-Length").c_str()); - //Tiki::Debug::printf("decodedSize: %d\n", sizeDecoded); - - RefPtr<Buffer> chunkBuf = new Buffer(sizeDecoded); - socket->recv(chunkBuf); - if(chunkBuf->getUsedDataLen() < sizeDecoded) - { - sizeDecoded -= chunkBuf->getUsedDataLen(); - while(sizeDecoded > 0) { - RefPtr<Buffer> chunkBuf2 = new Buffer(sizeDecoded); - socket->recv(chunkBuf2); - chunkBuf->append(chunkBuf2); - sizeDecoded -= chunkBuf2->getUsedDataLen(); - } - } - fullBuf->append(chunkBuf); - } - else { - Tiki::Debug::printf("Encoding is unknown\n"); - } - response->addContentPart(DEFAULT_CONTENT_PART, fullBuf); -} - -}; // namespace Http - -}; // namespace Net - -}; // namespace Tiki - +/* + Tiki + + useragent.cpp + + Copyright (C)2007 Atani Software +*/ + +#include "pch.h" +#include "Tiki/tiki.h" +#include "Tiki/net.h" +#include "Tiki/net/http/useragent.h" + +#include <sstream> +#include <math.h> + +namespace Tiki { + +namespace Net { + +namespace Http { + +using namespace Tiki::Net::TCP; + +#define READ_ONE_LINE(res, socket) \ + { \ + RefPtr<Buffer> recvBuf = new Buffer(1); \ + char tbuf[2]; \ + res = ""; \ + while(socket->isOpen()) { \ + recvBuf->reset(); \ + socket->recv(recvBuf); \ + if(recvBuf->getUsedDataLen() > 0) { \ + tbuf[0] = recvBuf->getData()[0]; \ + tbuf[1] = '\0'; \ + if(tbuf[0] != '\n' && tbuf[0] != '\r' ) { \ + res.append((char *)tbuf); \ + } \ + else if(tbuf[0] != '\r' ) { \ + break; \ + } \ + } \ + } \ + } + +HttpUserAgent::HttpUserAgent() { +#if TIKI_PLAT == TIKI_WIN32 + setUserAgentName("Tiki/1.0 (Windows)"); +#elif TIKI_PLAT == TIKI_NDS + setUserAgentName("Tiki/1.0 (Nintendo DS)"); +#elif TIKI_PLAT == TIKI_SDL + setUserAgentName("Tiki/1.0 (SDL)"); +#elif TIKI_PLAT == TIKI_OSX + setUserAgentName("Tiki/1.0 (Mac OS X)"); +#else + setUserAgentName("Tiki/1.0 (Unknown)"); +#endif + setProxyHost(""); + setProxyPort(8080); +} + +Response *HttpUserAgent::get(Request *req) { + + Response *response = new Response(); + response->setUrl(req->getUrl()); + response->setResultCode(200); + + std::string hostname; + int port; + std::string resource; + + parseUrl(req->getUrl(), hostname, resource, port); + + std::string requestText; + buildRequest(hostname, resource, port, "GET", req, requestText); + Tiki::Debug::printf("Request:\n%s", requestText.c_str()); + + RefPtr<TCPSocket> socket; + if(m_proxyHost.empty()) { + socket = new TCPSocket(new Address(hostname, port)); + } + else { + socket = new TCPSocket(new Address(m_proxyHost, m_proxyPort)); + } + + socket->setNonBlocking(false); + + socket->open(); + if(socket->isOpen()) { + Tiki::Debug::printf("Sending request...\n"); + } + else { + Tiki::Debug::printf("connect failed\n"); + response->setResultCode(504); + return response; + } + + RefPtr<Buffer> buf = new Buffer(2048); + buf->setData((uint8 *)requestText.c_str(), requestText.length()); + socket->send(buf); + + readResponse(response, socket); + + socket->close(); + + //delete socket; + + return response; +} + +Response *HttpUserAgent::post(Request *req) { + Response *response = new Response(); + response->setUrl(req->getUrl()); + response->setResultCode(200); + + std::string hostname; + int port; + std::string resource; + + parseUrl(req->getUrl(), hostname, resource, port); + + std::string requestText; + buildRequest(hostname, resource, port, "POST", req, requestText); + Tiki::Debug::printf("Request:\n%s", requestText.c_str()); + + RefPtr<TCPSocket> socket; + if(m_proxyHost.empty()) { + socket = new TCPSocket(new Address(hostname, port)); + } + else { + socket = new TCPSocket(new Address(m_proxyHost, m_proxyPort)); + } + + socket->setNonBlocking(false); + + socket->open(); + if(socket->isOpen()) { + Tiki::Debug::printf("Sending request...\n"); + } + else { + Tiki::Debug::printf("connect failed\n"); + response->setResultCode(504); + return response; + } + + RefPtr<Buffer> buf = new Buffer(2048); + buf->setData((uint8 *)requestText.c_str(), requestText.length()); + socket->send(buf); + + std::list<std::string> content = req->getContentPartNames(); + if(content.size() > 1) { + std::string status = ""; + READ_ONE_LINE(status, socket) + + for(std::list<std::string>::iterator iter = content.begin(); + iter != content.end(); + ++iter) { + RefPtr<Buffer> buf = req->getContentPart(*iter); + std::stringstream temp; + temp << req->getBoundaryMarker() << "\r\n"; + temp << "Content-Disposition: form-data: name=\""; + if(!buf->getFieldName().empty()) { + temp << buf->getFieldName(); + } + else { + temp << "File"; + } + temp << "\"; filename=\"" << buf->getFileNameShort() << "\"\r\nContent-Type: " << buf->getContentType() << "\r\n"; + RefPtr<Buffer> headerBuf = new Buffer(2048); + std::string headerText = temp.str(); + headerBuf->setData((uint8 *)headerText.c_str(), headerText.length()); + socket->send(headerBuf); + socket->send(buf); + } + std::string footerText = "--"; + footerText.append(req->getBoundaryMarker()); + footerText.append("--\r\n"); + RefPtr<Buffer> footerBuf = new Buffer(2048); + footerBuf->setData((uint8 *)footerText.c_str(), footerText.length()); + socket->send(footerBuf); + } + else if(content.size() == 1) { + RefPtr<Buffer> buf = req->getContentPart(*content.begin()); + socket->send(buf); + } + + readResponse(response, socket); + + socket->close(); + + //delete socket; + + return response; +} + +void HttpUserAgent::parseUrl(const std::string url, std::string &host, std::string &resource, int &port) { + std::string temp_url = url; + + // set defaults + host = ""; + port = 80; + resource = "/index.html"; + + if(temp_url.find("http://") == 0) { + temp_url = temp_url.substr(std::string("http://").length()); + } + else if(temp_url.find("https://") == 0) { + temp_url = temp_url.substr(std::string("https://").length()); + } + host = temp_url.substr(0, temp_url.find("/")); + if(temp_url.find("/") != std::string::npos) { + resource = temp_url.substr(temp_url.find("/")); + } + if(host.find(":") != std::string::npos) { + std::string portstr = url.substr(host.find(":")); + port = atoi(portstr.c_str()); + host = host.substr(0, host.find(":")); + } +} + +void HttpUserAgent::buildRequest(const std::string host, const std::string resource, const int port, + const std::string mode, Request *request, std::string &requestText) { + + std::stringstream req; + if(m_proxyHost.empty()) { + req << mode << " " << resource << " HTTP/1.1\r\n"; + req << "Host: " << host << "\r\n"; + } + else { + // proxy connection + req << mode << " " << request->getUrl(); + if(port != 80) { + req << ":" << port; + } + req << " HTTP/1.1\r\n"; + req << "Host: " << host << "\r\n"; + } + std::list<std::string> params = request->getHeaderParamNames(); + for(std::list<string>::const_iterator param = params.begin(); + param != params.end(); + ++param) { + req << *param << ": " << request->getHeaderParam(*param) << "\r\n"; + } + + if(!m_userAgentName.empty()) { + req << "User-Agent: " << m_userAgentName << "\r\n"; + } + + std::list<std::string> content = request->getContentPartNames(); + if(!mode.compare("POST") && content.size() > 1) { + uint64 totalSize = request->getBoundaryMarker().length() + 6; // add 6 to account for "--<boundary>--\r\n" + for(std::list<std::string>::iterator iter = content.begin(); + iter != content.end(); + ++iter) { + RefPtr<Buffer> buf = request->getContentPart(*iter); + totalSize += buf->getUsedDataLen(); + std::stringstream temp; + temp << "Content-Disposition: form-data: name=\""; + if(!buf->getFieldName().empty()) { + temp << buf->getFieldName(); + } + else { + temp << "File"; + } + temp << "\"; filename=\"" << buf->getFileNameShort() << "\"\r\nContent-Type: " << buf->getContentType() << "\r\n"; + + // add section header size + totalSize += temp.str().length(); + } + + req << "Content-Length: " << totalSize << "\r\n"; + req << "Expect: 100-continue\r\n"; + req << "Content-Type: multipart/form-data; boundary=" << request->getBoundaryMarker() << "\r\n"; + } + else if(!mode.compare("POST") && content.size() == 1) { + RefPtr<Buffer> buf = request->getContentPart(*content.begin()); + req << "Content-Type: " << buf->getContentType() << "\r\n"; + req << "Content-Length: " << buf->getUsedDataLen() << "\r\n"; + } + req << "\r\n"; + + requestText = req.str(); +} + +void HttpUserAgent::readResponse(Response *response, TCPSocket *socket) { + std::string status = ""; + READ_ONE_LINE(status, socket) + + //Tiki::Debug::printf("Status: %s\n", status.c_str()); + for(std::string::size_type i = 0; i < status.length(); i++) { + if(status.at(i) == ' ') { + response->setResultCode(atoi(status.c_str()+i + 1)); + break; + } + } + + while(1) { + std::string line = ""; + READ_ONE_LINE(line, socket) + if(line.size() == 0) { + // done with headers + break; + } + //Tiki::Debug::printf("HEADER_LINE: %s\n", line.c_str()); + if(line.find(":") != std::string::npos) { + std::string field = line.substr(0, line.find(":")); + std::string value = line.substr(line.find(":") + 1); + while(value.at(0) == ' ') { + value = value.substr(1); + } + + if(!field.compare("Set-Cookie")) { + + } + else { + response->setHeaderParam(field, value); + } + } + } + + RefPtr<Buffer> fullBuf = new Buffer(1); + + if(!response->getHeaderParam("Transfer-Encoding").compare("chunked")) { + Tiki::Debug::printf("Encoding is chunked\n"); + // evil chunked encoding + size_t totalSize = 0; + + size_t sizeDecoded = 0; + do + { + sizeDecoded = 0; + std::string size = ""; + READ_ONE_LINE(size, socket); + if(size.empty()) { + sizeDecoded = 1; + continue; + } + + std::istringstream sizestream(std::string("0x") + size); + sizestream.unsetf(std::ios::dec); + sizestream.setf(std::ios::skipws); + sizestream >> sizeDecoded; + + //Tiki::Debug::printf("chunk size: %d [%s]\n", sizeDecoded, size.c_str()); + if(sizeDecoded > 0) { + + RefPtr<Buffer> chunkBuf = new Buffer(sizeDecoded); + socket->recv(chunkBuf); + if(chunkBuf->getUsedDataLen() < sizeDecoded) + { + //Tiki::Debug::printf("Buffer underflow\n"); + size_t needed = sizeDecoded - chunkBuf->getUsedDataLen(); + while(needed > 0) { + RefPtr<Buffer> chunkBuf2 = new Buffer(needed); + socket->recv(chunkBuf2); + chunkBuf->append(chunkBuf2); + needed -= chunkBuf2->getUsedDataLen(); + } + } + totalSize += chunkBuf->getUsedDataLen(); + fullBuf->append(chunkBuf); + } + } while(sizeDecoded > 0); + //Tiki::Debug::printf("total size: %d %x\n", totalSize, totalSize); + } + else if(response->getHeaderParam("Content-Length").compare("")) { + Tiki::Debug::printf("Encoding is inline\n"); + size_t sizeDecoded = atoi(response->getHeaderParam("Content-Length").c_str()); + //Tiki::Debug::printf("decodedSize: %d\n", sizeDecoded); + + RefPtr<Buffer> chunkBuf = new Buffer(sizeDecoded); + socket->recv(chunkBuf); + if(chunkBuf->getUsedDataLen() < sizeDecoded) + { + sizeDecoded -= chunkBuf->getUsedDataLen(); + while(sizeDecoded > 0) { + RefPtr<Buffer> chunkBuf2 = new Buffer(sizeDecoded); + socket->recv(chunkBuf2); + chunkBuf->append(chunkBuf2); + sizeDecoded -= chunkBuf2->getUsedDataLen(); + } + } + fullBuf->append(chunkBuf); + } + else { + Tiki::Debug::printf("Encoding is unknown\n"); + } + response->addContentPart(fullBuf, DEFAULT_CONTENT_PART); +} + +}; // namespace Http + +}; // namespace Net + +}; // namespace Tiki + Modified: tiki/src/net/socket.cpp =================================================================== --- tiki/src/net/socket.cpp 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/src/net/socket.cpp 2007-08-23 22:59:57 UTC (rev 489) @@ -22,7 +22,7 @@ m_reuse = true; } -Socket::Socket(RefPtr<Address> address) +Socket::Socket(Address *address) { m_peerAddress = address; m_localAddress = new Address(); Modified: tiki/src/net/tcpserversocket.cpp =================================================================== --- tiki/src/net/tcpserversocket.cpp 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/src/net/tcpserversocket.cpp 2007-08-23 22:59:57 UTC (rev 489) @@ -50,7 +50,7 @@ } } -RefPtr<TCPSocket> TCPServerSocket::accept() +TCPSocket *TCPServerSocket::accept() { struct sockaddr_in sock_addr; #if TIKI_PLAT == TIKI_WIN32 Modified: tiki/src/net/tcpsocket.cpp =================================================================== --- tiki/src/net/tcpsocket.cpp 2007-08-23 18:35:40 UTC (rev 488) +++ tiki/src/net/tcpsocket.cpp 2007-08-23 22:59:57 UTC (rev 489) @@ -18,7 +18,7 @@ namespace TCP { -void TCPSocket::send(const RefPtr<Buffer> buffer) { +void TCPSocket::send(Buffer *buffer) { uint8 *data = buffer->getData(); size_t dataLen = buffer->getUsedDataLen(); int len; @@ -34,7 +34,7 @@ } while(dataLen > 0 && (len > 0 || errno == EINTR)); } -void TCPSocket::recv(RefPtr<Buffer> data) { +void TCPSocket::recv(Buffer *data) { uint8 *tmp = new uint8[data->getDataLen()]; memset(tmp, 0, data->getDataLen()); int recvlen = 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |