164 lines
6.2 KiB
C
164 lines
6.2 KiB
C
|
/***************************************************************************
|
||
|
* 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 <iosfwd>
|
||
|
#include <string>
|
||
|
#include <iostream>
|
||
|
#include <boost/lexical_cast.hpp>
|
||
|
#include <boost/iostreams/stream.hpp>
|
||
|
|
||
|
#include "sslclient.h"
|
||
|
|
||
|
#ifndef HSADMIN_HTTPCLIENT
|
||
|
#define HSADMIN_HTTPCLIENT
|
||
|
|
||
|
using std::string;
|
||
|
using std::iostream;
|
||
|
using std::streamsize;
|
||
|
using boost::lexical_cast;
|
||
|
using boost::bad_lexical_cast;
|
||
|
|
||
|
//! A Socket as a Device
|
||
|
class TCPDevice : public boost::iostreams::device<boost::iostreams::bidirectional> {
|
||
|
public:
|
||
|
//! create a TCP-Stream by connecting to the given port at the given address
|
||
|
TCPDevice(const string& address, const short int port);
|
||
|
//! create a TCP-Stream by connecting to the given port at the given address
|
||
|
TCPDevice(const char* address, const short int port);
|
||
|
//! create a TCP-Stream from a connected socket - use this with accept
|
||
|
TCPDevice(const int socket);
|
||
|
//! copy constructor
|
||
|
TCPDevice(const TCPDevice& other);
|
||
|
//! does not close the socket - use closeSocket before deleting the Device.
|
||
|
virtual ~TCPDevice();
|
||
|
//! closes the socket
|
||
|
void closeSocket();
|
||
|
|
||
|
//! read n Bytes from socket
|
||
|
virtual streamsize read(char* s, streamsize n);
|
||
|
//! write n Bytes to socket
|
||
|
virtual streamsize write(const char* s, streamsize n);
|
||
|
private:
|
||
|
void init(const char* address, const short int port);
|
||
|
int m_socket;
|
||
|
};
|
||
|
|
||
|
//class SSLDevice;
|
||
|
|
||
|
const int HTTP = 0;
|
||
|
const int HTTPS = 1;
|
||
|
|
||
|
//! the basic HTTP Client - can only handle POST method.
|
||
|
class GenericHttpClient {
|
||
|
public:
|
||
|
//! initialize HTTP CLient with URL and default Port (usually 80)
|
||
|
GenericHttpClient(const string &url, const unsigned short defaultPort);
|
||
|
//! Post
|
||
|
string post(string postcontent);
|
||
|
|
||
|
protected:
|
||
|
//! get a buffered iostream for the connection - must be overridden by derived classes
|
||
|
virtual iostream * getConnection(const string &host, unsigned short port) = 0;
|
||
|
//! check if this class can handle the protocol - must be overridden by derived classes
|
||
|
virtual bool checkProtocol(const string &protocol) { return false; };
|
||
|
//! close the underlying connection
|
||
|
virtual void close() = 0;
|
||
|
|
||
|
private:
|
||
|
iostream * parseUrl();
|
||
|
const string& m_url;
|
||
|
string m_protocol;
|
||
|
string m_hostname;
|
||
|
string m_path;
|
||
|
unsigned short m_port;
|
||
|
const unsigned short m_defaultPort;
|
||
|
};
|
||
|
|
||
|
//! This template should usually be used in one of the specialized Versions below.
|
||
|
template <int protocol> class HttpClient: public GenericHttpClient {
|
||
|
public:
|
||
|
HttpClient(const string &url, unsigned short defaultPort = 80): GenericHttpClient(url,defaultPort) {};
|
||
|
protected:
|
||
|
iostream * getConnection(const string &host, unsigned short port) { return (iostream *)0; };
|
||
|
bool checkProtocol(const string &p) { return false; };
|
||
|
virtual void close() { };
|
||
|
};
|
||
|
|
||
|
//! a HTTP CLient with a plain TCP socket as transport
|
||
|
template <> class HttpClient<HTTP>: public GenericHttpClient {
|
||
|
public:
|
||
|
//! initialize HTTP CLient with URL and default Port (usually 80)
|
||
|
HttpClient(const string &url, unsigned short defaultPort = 80): GenericHttpClient(url,defaultPort), device(0) {};
|
||
|
protected:
|
||
|
//! get a buffered iostream for the connection
|
||
|
iostream * getConnection(const string &host, unsigned short port) {
|
||
|
if( device == 0 ) device = new TCPDevice(host,port);
|
||
|
return (iostream *) new boost::iostreams::stream<TCPDevice>(*device);
|
||
|
}
|
||
|
//! check if this class can handle the protocol
|
||
|
bool checkProtocol(const string &protocol) { return (protocol == "http"); };
|
||
|
//! close the underlying connection
|
||
|
virtual void close() { device->closeSocket(); };
|
||
|
private:
|
||
|
TCPDevice *device;
|
||
|
};
|
||
|
//! a HTTP CLient with a SSL stream as transport
|
||
|
template <> class HttpClient<HTTPS>: public GenericHttpClient {
|
||
|
public:
|
||
|
//! initialize HTTPS CLient with URL and default Port (usually 443)
|
||
|
HttpClient(const string &url, unsigned short defaultPort = 443): GenericHttpClient(url,defaultPort), device(0) {};
|
||
|
protected:
|
||
|
//! get a buffered iostream for the connection
|
||
|
iostream * getConnection(const string &host, unsigned short port) {
|
||
|
try {
|
||
|
if( device == 0 ) device = new SSLDevice(host,port);
|
||
|
return (iostream *) new boost::iostreams::stream<SSLDevice>(*device);
|
||
|
} catch( SSLDevice::CertificateError &e ) {
|
||
|
if( device != 0 ) {
|
||
|
delete(device);
|
||
|
device = 0;
|
||
|
}
|
||
|
std::cerr << e.msg << std::endl;
|
||
|
return (iostream *)0;
|
||
|
}
|
||
|
}
|
||
|
//! check if this class can handle the protocol
|
||
|
bool checkProtocol(const string &protocol) { return (protocol == "https"); };
|
||
|
//! close the underlying connection
|
||
|
virtual void close() { device->closeSocket(); };
|
||
|
private:
|
||
|
SSLDevice *device;
|
||
|
};
|
||
|
|
||
|
/** \brief get the best HTTP client for the defined Protocol
|
||
|
*
|
||
|
* returns HttpClient<HTTP> or HttpClient<HTTPS> depending on the protocol
|
||
|
*/
|
||
|
GenericHttpClient *createHttpClient(const string &uri);
|
||
|
|
||
|
#else /* HSADMIN_HTTPCLIENT */
|
||
|
class TCPDevice;
|
||
|
class GenericHttpClient;
|
||
|
genericHttpClient *createHttpClient(url);
|
||
|
|
||
|
extern const int HTTP = 0;
|
||
|
extern const int HTTPS = 1;
|
||
|
#endif /* HSADMIN_HTTPCLIENT */
|