/*************************************************************************** * Copyright (C) 2005 by Christof Donat * * cdonat@gmx.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "httpclient.h" #include "logger.h" #include #include #include #include #include using std::string; using std::streamsize; using std::iostream; using boost::lexical_cast; using boost::bad_lexical_cast; TCPDevice::TCPDevice(const string& address, const short int port) { this->init(address.c_str(),port); } TCPDevice::TCPDevice(const char* address, const short int port) { this->init(address,port); } void TCPDevice::init(const char* address, const short int port) { struct sockaddr_in addr; bzero(&addr,sizeof(addr)); addr.sin_family = AF_INET; if( (addr.sin_addr.s_addr = inet_addr(address)) == INADDR_NONE ) { struct hostent* hp = gethostbyname(address); if( hp == 0 ) throw("can't resolve hostname '"+string(address)+"'"); bcopy(hp->h_addr, (char*) &addr.sin_addr, hp->h_length); } addr.sin_port = htons(port); if( (m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0 ) throw(string("can't open socket")); if( ::connect(m_socket, (struct sockaddr*) &addr, sizeof(addr)) < 0 ) { ::close(m_socket); throw("can't connect to '"+string(address)+"' port "+(lexical_cast(port))); } } TCPDevice::TCPDevice(const int socket) : m_socket(socket) {} TCPDevice::TCPDevice(const TCPDevice& other) : m_socket(other.m_socket) { } TCPDevice::~TCPDevice() { } void TCPDevice::closeSocket() { ::close(m_socket); } streamsize TCPDevice::read(char* s, streamsize n) { return (streamsize)::read(m_socket,(void*)s,(size_t)n); } streamsize TCPDevice::write(const char* s, streamsize n) { return (streamsize)::write(m_socket,(const void*)s,(size_t)n); } GenericHttpClient::GenericHttpClient(const string &url, const unsigned short defaultPort = 80): m_url(url), m_defaultPort(defaultPort) {}; string GenericHttpClient::post(string postcontent) { iostream *connection; try { connection = this->parseUrl(); } catch(string &e) { Logger::log(Logger::FATAL,"connection failed: "+e); exit(-1); } if( connection == 0 ) return ""; string outbuf = "POST "+m_path+" HTTP/1.1\r\n"; outbuf += "Connection: close\r\n"; outbuf += "User-Agent: hsadmin CLI client\r\n"; outbuf += "Content-Type: text/xml\r\n"; outbuf += "Content-Length: "+boost::lexical_cast(postcontent.length())+"\r\n"; outbuf += "Host: "+m_hostname+"\r\n\r\n"; outbuf += postcontent; for( int i = 0; i < outbuf.length(); i++ ) (*connection) << outbuf[i];; connection->flush(); string reply = ""; char buf[257]; do { // we simply ignore the http header in the response bzero(buf,257); connection->getline(buf,256); } while( string(buf) != "" && string(buf) != "\r" ); string tmp; do { tmp = ""; (*connection) >> tmp; reply += " "+tmp; } while( tmp.length() ); this->close(); delete connection; return reply; }; iostream * GenericHttpClient::parseUrl() { int protocolend = m_url.find("://"); m_protocol = m_url.substr(0,protocolend); if( ! this->checkProtocol(m_protocol) ) return (iostream *)0; int hostnameend = m_url.find("/",protocolend+3); m_hostname = m_url.substr(protocolend+3,hostnameend-(protocolend+3)); m_port = m_defaultPort; m_path = m_url.substr(hostnameend); int portstart = m_hostname.find(":"); if( portstart >= 0 ) { string portstring = m_hostname.substr(portstart+1); if( portstring.size() > 0 ) { try { m_port = lexical_cast(portstring.c_str()); m_hostname = m_hostname.substr(0,m_hostname.find(":")); } catch(bad_lexical_cast &) { } } } return this->getConnection(m_hostname, m_port); }; GenericHttpClient *createHttpClient(const string &url) { int protocolend = url.find("://"); string protocol = url.substr(0,protocolend); if( protocol == "http" ) return (GenericHttpClient *) new HttpClient(url); if( protocol == "https" ) return (GenericHttpClient *) new HttpClient(url); return 0; }