new trunk (base for 1.5)

windows build only
This commit is contained in:
Aleksandar Fabijanic
2012-04-23 01:14:34 +00:00
parent f9b60296f7
commit d75e68c027
3760 changed files with 1058456 additions and 0 deletions

View File

@@ -0,0 +1,131 @@
//
// AbstractHTTPRequestHandler.cpp
//
// $Id: //poco/1.4/Net/src/AbstractHTTPRequestHandler.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: AbstractHTTPRequestHandler
//
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/AbstractHTTPRequestHandler.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTMLForm.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Exception.h"
using Poco::NumberFormatter;
namespace Poco {
namespace Net {
AbstractHTTPRequestHandler::AbstractHTTPRequestHandler():
_pRequest(0),
_pResponse(0),
_pForm(0)
{
}
AbstractHTTPRequestHandler::~AbstractHTTPRequestHandler()
{
delete _pForm;
}
void AbstractHTTPRequestHandler::handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
{
_pRequest = &request;
_pResponse = &response;
if (authenticate())
{
try
{
run();
}
catch (Poco::Exception& exc)
{
if (!response.sent())
{
sendErrorResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, exc.displayText());
}
}
catch (std::exception& exc)
{
if (!response.sent())
{
sendErrorResponse(HTTPResponse::HTTP_INTERNAL_SERVER_ERROR, exc.what());
}
}
}
else
{
sendErrorResponse(HTTPResponse::HTTP_UNAUTHORIZED, "");
}
}
bool AbstractHTTPRequestHandler::authenticate()
{
return true;
}
HTMLForm& AbstractHTTPRequestHandler::form()
{
if (!_pForm)
_pForm = new HTMLForm(request(), request().stream());
return *_pForm;
}
void AbstractHTTPRequestHandler::sendErrorResponse(HTTPResponse::HTTPStatus status, const std::string& message)
{
response().setStatusAndReason(status);
std::string statusAndReason(NumberFormatter::format(static_cast<int>(response().getStatus())));
statusAndReason += " - ";
statusAndReason += response().getReason();
std::string page("<HTML><HEAD><TITLE>");
page += statusAndReason;
page += "</TITLE></HEAD><BODY><H1>";
page += statusAndReason;
page += "</H1>";
page += "<P>";
page += message;
page += "</P></BODY></HTML>";
response().sendBuffer(page.data(), page.size());
}
} } // namespace Poco::Net

304
Net/src/DNS.cpp Normal file
View File

@@ -0,0 +1,304 @@
//
// DNS.cpp
//
// $Id: //poco/1.4/Net/src/DNS.cpp#10 $
//
// Library: Net
// Package: NetCore
// Module: DNS
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/DNS.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Environment.h"
#include "Poco/NumberFormatter.h"
#include "Poco/AtomicCounter.h"
#include <cstring>
using Poco::FastMutex;
using Poco::Environment;
using Poco::NumberFormatter;
using Poco::IOException;
namespace
{
class NetworkInitializer
{
public:
NetworkInitializer()
{
Poco::Net::initializeNetwork();
}
~NetworkInitializer()
{
Poco::Net::uninitializeNetwork();
}
};
}
namespace Poco {
namespace Net {
HostEntry DNS::hostByName(const std::string& hostname)
{
NetworkInitializer networkInitializer;
#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
struct addrinfo* pAI;
struct addrinfo hints;
std::memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
int rc = getaddrinfo(hostname.c_str(), NULL, &hints, &pAI);
if (rc == 0)
{
HostEntry result(pAI);
freeaddrinfo(pAI);
return result;
}
else
{
aierror(rc, hostname);
}
#elif defined(POCO_VXWORKS)
int addr = hostGetByName(const_cast<char*>(hostname.c_str()));
if (addr != ERROR)
{
return HostEntry(hostname, IPAddress(&addr, sizeof(addr)));
}
#else
struct hostent* he = gethostbyname(hostname.c_str());
if (he)
{
return HostEntry(he);
}
#endif
error(lastError(), hostname); // will throw an appropriate exception
throw NetException(); // to silence compiler
}
HostEntry DNS::hostByAddress(const IPAddress& address)
{
NetworkInitializer networkInitializer;
#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
SocketAddress sa(address, 0);
static char fqname[1024];
int rc = getnameinfo(sa.addr(), sa.length(), fqname, sizeof(fqname), NULL, 0, NI_NAMEREQD);
if (rc == 0)
{
struct addrinfo* pAI;
struct addrinfo hints;
std::memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
rc = getaddrinfo(fqname, NULL, &hints, &pAI);
if (rc == 0)
{
HostEntry result(pAI);
freeaddrinfo(pAI);
return result;
}
else
{
aierror(rc, address.toString());
}
}
else
{
aierror(rc, address.toString());
}
#elif defined(POCO_VXWORKS)
char name[MAXHOSTNAMELEN + 1];
if (hostGetByAddr(*reinterpret_cast<const int*>(address.addr()), name) == OK)
{
return HostEntry(std::string(name), address);
}
#else
struct hostent* he = gethostbyaddr(reinterpret_cast<const char*>(address.addr()), address.length(), address.af());
if (he)
{
return HostEntry(he);
}
#endif
int err = lastError();
error(err, address.toString()); // will throw an appropriate exception
throw NetException(); // to silence compiler
}
HostEntry DNS::resolve(const std::string& address)
{
NetworkInitializer networkInitializer;
IPAddress ip;
if (IPAddress::tryParse(address, ip))
return hostByAddress(ip);
else
return hostByName(address);
}
IPAddress DNS::resolveOne(const std::string& address)
{
NetworkInitializer networkInitializer;
const HostEntry& entry = resolve(address);
if (!entry.addresses().empty())
return entry.addresses()[0];
else
throw NoAddressFoundException(address);
}
HostEntry DNS::thisHost()
{
return hostByName(hostName());
}
void DNS::flushCache()
{
}
std::string DNS::hostName()
{
NetworkInitializer networkInitializer;
char buffer[256];
int rc = gethostname(buffer, sizeof(buffer));
if (rc == 0)
return std::string(buffer);
else
throw NetException("Cannot get host name");
}
int DNS::lastError()
{
#if defined(_WIN32)
return GetLastError();
#elif defined(POCO_VXWORKS)
return errno;
#else
return h_errno;
#endif
}
void DNS::error(int code, const std::string& arg)
{
switch (code)
{
case POCO_ESYSNOTREADY:
throw NetException("Net subsystem not ready");
case POCO_ENOTINIT:
throw NetException("Net subsystem not initialized");
case POCO_HOST_NOT_FOUND:
throw HostNotFoundException(arg);
case POCO_TRY_AGAIN:
throw DNSException("Temporary DNS error while resolving", arg);
case POCO_NO_RECOVERY:
throw DNSException("Non recoverable DNS error while resolving", arg);
case POCO_NO_DATA:
throw NoAddressFoundException(arg);
default:
throw IOException(NumberFormatter::format(code));
}
}
void DNS::aierror(int code, const std::string& arg)
{
#if defined(POCO_HAVE_IPv6)
switch (code)
{
case EAI_AGAIN:
throw DNSException("Temporary DNS error while resolving", arg);
case EAI_FAIL:
throw DNSException("Non recoverable DNS error while resolving", arg);
#if !defined(_WIN32) // EAI_NODATA and EAI_NONAME have the same value
case EAI_NODATA:
throw NoAddressFoundException(arg);
#endif
case EAI_NONAME:
throw HostNotFoundException(arg);
#if defined(EAI_SYSTEM)
case EAI_SYSTEM:
error(lastError(), arg);
break;
#endif
#if defined(_WIN32)
case WSANO_DATA: // may happen on XP
throw HostNotFoundException(arg);
#endif
default:
throw DNSException("EAI", NumberFormatter::format(code));
}
#endif // POCO_HAVE_IPv6
}
#if defined(_WIN32)
static Poco::AtomicCounter initializeCount;
#endif
void initializeNetwork()
{
#if defined(_WIN32)
if (++initializeCount == 1)
{
WORD version = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(version, &data) != 0)
throw NetException("Failed to initialize network subsystem");
}
#endif // _WIN32
}
void uninitializeNetwork()
{
#if defined(_WIN32)
if (--initializeCount == 0)
{
WSACleanup();
}
#endif // _WIN32
}
} } // namespace Poco::Net

130
Net/src/DatagramSocket.cpp Normal file
View File

@@ -0,0 +1,130 @@
//
// DatagramSocket.cpp
//
// $Id: //poco/1.4/Net/src/DatagramSocket.cpp#1 $
//
// Library: Net
// Package: Sockets
// Module: DatagramSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/DatagramSocketImpl.h"
#include "Poco/Exception.h"
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
DatagramSocket::DatagramSocket(): Socket(new DatagramSocketImpl)
{
}
DatagramSocket::DatagramSocket(IPAddress::Family family): Socket(new DatagramSocketImpl(family))
{
}
DatagramSocket::DatagramSocket(const SocketAddress& address, bool reuseAddress): Socket(new DatagramSocketImpl)
{
bind(address, reuseAddress);
}
DatagramSocket::DatagramSocket(const Socket& socket): Socket(socket)
{
if (!dynamic_cast<DatagramSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
DatagramSocket::DatagramSocket(SocketImpl* pImpl): Socket(pImpl)
{
if (!dynamic_cast<DatagramSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
DatagramSocket::~DatagramSocket()
{
}
DatagramSocket& DatagramSocket::operator = (const Socket& socket)
{
if (dynamic_cast<DatagramSocketImpl*>(socket.impl()))
Socket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
void DatagramSocket::connect(const SocketAddress& address)
{
impl()->connect(address);
}
void DatagramSocket::bind(const SocketAddress& address, bool reuseAddress)
{
impl()->bind(address, reuseAddress);
}
int DatagramSocket::sendBytes(const void* buffer, int length, int flags)
{
return impl()->sendBytes(buffer, length, flags);
}
int DatagramSocket::receiveBytes(void* buffer, int length, int flags)
{
return impl()->receiveBytes(buffer, length, flags);
}
int DatagramSocket::sendTo(const void* buffer, int length, const SocketAddress& address, int flags)
{
return impl()->sendTo(buffer, length, address, flags);
}
int DatagramSocket::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
{
return impl()->receiveFrom(buffer, length, address, flags);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,82 @@
//
// DatagramSocketImpl.cpp
//
// $Id: //poco/1.4/Net/src/DatagramSocketImpl.cpp#1 $
//
// Library: Net
// Package: Sockets
// Module: DatagramSocketImpl
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/DatagramSocketImpl.h"
#include "Poco/Net/NetException.h"
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
DatagramSocketImpl::DatagramSocketImpl()
{
init(AF_INET);
}
DatagramSocketImpl::DatagramSocketImpl(IPAddress::Family family)
{
if (family == IPAddress::IPv4)
init(AF_INET);
#if defined(POCO_HAVE_IPv6)
else if (family == IPAddress::IPv6)
init(AF_INET6);
#endif
else throw InvalidArgumentException("Invalid or unsupported address family passed to DatagramSocketImpl");
}
DatagramSocketImpl::DatagramSocketImpl(poco_socket_t sockfd): SocketImpl(sockfd)
{
}
DatagramSocketImpl::~DatagramSocketImpl()
{
}
void DatagramSocketImpl::init(int af)
{
initSocket(af, SOCK_DGRAM);
}
} } // namespace Poco::Net

310
Net/src/DialogSocket.cpp Normal file
View File

@@ -0,0 +1,310 @@
//
// DialogSocket.cpp
//
// $Id: //poco/1.4/Net/src/DialogSocket.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: DialogSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/DialogSocket.h"
#include "Poco/Ascii.h"
#include <cstring>
namespace Poco {
namespace Net {
DialogSocket::DialogSocket():
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::DialogSocket(const SocketAddress& address):
StreamSocket(address),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::DialogSocket(const Socket& socket):
StreamSocket(socket),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::DialogSocket(const DialogSocket& socket):
StreamSocket(socket),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}
DialogSocket::~DialogSocket()
{
delete [] _pBuffer;
}
DialogSocket& DialogSocket::operator = (const Socket& socket)
{
StreamSocket::operator = (socket);
_pNext = _pBuffer;
_pEnd = _pBuffer;
return *this;
}
DialogSocket& DialogSocket::operator = (const DialogSocket& socket)
{
StreamSocket::operator = (socket);
_pNext = _pBuffer;
_pEnd = _pBuffer;
return *this;
}
void DialogSocket::sendByte(unsigned char ch)
{
sendBytes(&ch, 1);
}
void DialogSocket::sendString(const char* str)
{
sendBytes(str, (int) std::strlen(str));
}
void DialogSocket::sendString(const std::string& str)
{
sendBytes(str.data(), (int) str.length());
}
void DialogSocket::sendMessage(const std::string& message)
{
std::string line;
line.reserve(message.length() + 2);
line.append(message);
line.append("\r\n");
sendString(line);
}
void DialogSocket::sendMessage(const std::string& message, const std::string& arg)
{
std::string line;
line.reserve(message.length() + arg.length() + 3);
line.append(message);
if (!arg.empty())
{
line.append(" ");
line.append(arg);
}
line.append("\r\n");
sendString(line);
}
void DialogSocket::sendMessage(const std::string& message, const std::string& arg1, const std::string& arg2)
{
std::string line;
line.reserve(message.length() + arg1.length() +arg2.length() + 4);
line.append(message);
line.append(" ");
line.append(arg1);
if (!arg2.empty())
{
line.append(" ");
line.append(arg2);
}
line.append("\r\n");
sendString(line);
}
bool DialogSocket::receiveMessage(std::string& message)
{
message.clear();
return receiveLine(message);
}
int DialogSocket::receiveStatusMessage(std::string& message)
{
message.clear();
int status = receiveStatusLine(message);
if (status < 0)
{
while (status <= 0)
{
message += '\n';
status = receiveStatusLine(message);
}
}
return status;
}
int DialogSocket::get()
{
refill();
if (_pNext != _pEnd)
return std::char_traits<char>::to_int_type(*_pNext++);
else
return EOF_CHAR;
}
int DialogSocket::peek()
{
refill();
if (_pNext != _pEnd)
return std::char_traits<char>::to_int_type(*_pNext);
else
return EOF_CHAR;
}
void DialogSocket::synch()
{
sendUrgent(TELNET_DM);
}
void DialogSocket::sendTelnetCommand(unsigned char command)
{
unsigned char buffer[2];
buffer[0] = TELNET_IAC;
buffer[1] = command;
sendBytes(buffer, 2);
}
void DialogSocket::sendTelnetCommand(unsigned char command, unsigned char arg)
{
unsigned char buffer[3];
buffer[0] = TELNET_IAC;
buffer[1] = command;
buffer[2] = arg;
sendBytes(buffer, 3);
}
void DialogSocket::refill()
{
if (_pNext == _pEnd)
{
int n = receiveBytes(_pBuffer, RECEIVE_BUFFER_SIZE);
_pNext = _pBuffer;
_pEnd = _pBuffer + n;
}
}
void DialogSocket::allocBuffer()
{
_pBuffer = new char [RECEIVE_BUFFER_SIZE];
_pNext = _pBuffer;
_pEnd = _pBuffer;
}
bool DialogSocket::receiveLine(std::string& line)
{
// An old wisdom goes: be strict in what you emit
// and generous in what you accept.
int ch = get();
while (ch != EOF_CHAR && ch != '\r' && ch != '\n')
{
line += (char) ch;
ch = get();
}
if (ch == '\r' && peek() == '\n')
get();
else if (ch == EOF_CHAR)
return false;
return true;
}
int DialogSocket::receiveStatusLine(std::string& line)
{
int status = 0;
int ch = get();
if (ch != EOF_CHAR) line += (char) ch;
int n = 0;
while (Poco::Ascii::isDigit(ch) && n < 3)
{
status *= 10;
status += ch - '0';
++n;
ch = get();
if (ch != EOF_CHAR) line += (char) ch;
}
if (n == 3)
{
if (ch == '-')
status = -status;
}
else status = 0;
if (ch != EOF_CHAR) receiveLine(line);
return status;
}
int DialogSocket::receiveRawBytes(void* buffer, int length)
{
refill();
int n = static_cast<int>(_pEnd - _pNext);
if (n > length) n = length;
std::memcpy(buffer, _pNext, n);
_pNext += n;
return n;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,509 @@
//
// FTPClientSession.cpp
//
// $Id: //poco/1.4/Net/src/FTPClientSession.cpp#1 $
//
// Library: Net
// Package: FTP
// Module: FTPClientSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/FTPClientSession.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/SocketStream.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/NetException.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Ascii.h"
using Poco::NumberFormatter;
namespace Poco {
namespace Net {
FTPClientSession::FTPClientSession(const StreamSocket& socket):
_controlSocket(socket),
_pDataStream(0),
_passiveMode(true),
_fileType(TYPE_BINARY),
_supports1738(true),
_isOpen(true),
_timeout(DEFAULT_TIMEOUT)
{
_controlSocket.setReceiveTimeout(_timeout);
}
FTPClientSession::FTPClientSession(const std::string& host, Poco::UInt16 port):
_controlSocket(SocketAddress(host, port)),
_pDataStream(0),
_passiveMode(true),
_fileType(TYPE_BINARY),
_supports1738(true),
_isOpen(true),
_timeout(DEFAULT_TIMEOUT)
{
_controlSocket.setReceiveTimeout(_timeout);
}
FTPClientSession::~FTPClientSession()
{
try
{
close();
}
catch (...)
{
}
}
void FTPClientSession::setTimeout(const Poco::Timespan& timeout)
{
_timeout = timeout;
_controlSocket.setReceiveTimeout(timeout);
}
Poco::Timespan FTPClientSession::getTimeout() const
{
return _timeout;
}
void FTPClientSession::setPassive(bool flag, bool useRFC1738)
{
_passiveMode = flag;
_supports1738 = useRFC1738;
}
bool FTPClientSession::getPassive() const
{
return _passiveMode;
}
void FTPClientSession::login(const std::string& username, const std::string& password)
{
std::string response;
int status = _controlSocket.receiveStatusMessage(response);
if (!isPositiveCompletion(status)) throw FTPException("Cannot login to server", response, status);
status = sendCommand("USER", username, response);
if (isPositiveIntermediate(status))
status = sendCommand("PASS", password, response);
if (!isPositiveCompletion(status)) throw FTPException("Login denied", response, status);
setFileType(_fileType);
}
void FTPClientSession::close()
{
if (_isOpen)
{
try
{
endTransfer();
}
catch (...)
{
}
std::string response;
sendCommand("QUIT", response);
_controlSocket.close();
_isOpen = false;
}
}
void FTPClientSession::setFileType(FTPClientSession::FileType type)
{
std::string response;
int status = sendCommand("TYPE", (type == TYPE_TEXT ? "A" : "I"), response);
if (!isPositiveCompletion(status)) throw FTPException("Cannot set file type", response, status);
_fileType = type;
}
FTPClientSession::FileType FTPClientSession::getFileType() const
{
return _fileType;
}
std::string FTPClientSession::systemType()
{
std::string response;
int status = sendCommand("SYST", response);
if (isPositiveCompletion(status))
return response.substr(4);
else
throw FTPException("Cannot get remote system type", response, status);
}
void FTPClientSession::setWorkingDirectory(const std::string& path)
{
std::string response;
int status = sendCommand("CWD", path, response);
if (!isPositiveCompletion(status)) throw FTPException("Cannot change directory", response, status);
}
std::string FTPClientSession::getWorkingDirectory()
{
std::string response;
int status = sendCommand("PWD", response);
if (isPositiveCompletion(status))
return extractPath(response);
else
throw FTPException("Cannot get current working directory", response, status);
}
void FTPClientSession::cdup()
{
std::string response;
int status = sendCommand("CDUP", response);
if (!isPositiveCompletion(status)) throw FTPException("Cannot change directory", response, status);
}
void FTPClientSession::rename(const std::string& oldName, const std::string& newName)
{
std::string response;
int status = sendCommand("RNFR", oldName, response);
if (!isPositiveIntermediate(status)) throw FTPException(std::string("Cannot rename ") + oldName, response, status);
status = sendCommand("RNTO", newName, response);
if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot rename to ") + newName, response, status);
}
void FTPClientSession::remove(const std::string& path)
{
std::string response;
int status = sendCommand("DELE", path, response);
if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot remove " + path), response, status);
}
void FTPClientSession::createDirectory(const std::string& path)
{
std::string response;
int status = sendCommand("MKD", path, response);
if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot create directory ") + path, response, status);
}
void FTPClientSession::removeDirectory(const std::string& path)
{
std::string response;
int status = sendCommand("RMD", path, response);
if (!isPositiveCompletion(status)) throw FTPException(std::string("Cannot remove directory ") + path, response, status);
}
std::istream& FTPClientSession::beginDownload(const std::string& path)
{
delete _pDataStream;
_pDataStream = 0;
_pDataStream = new SocketStream(establishDataConnection("RETR", path));
return *_pDataStream;
}
void FTPClientSession::endDownload()
{
endTransfer();
}
std::ostream& FTPClientSession::beginUpload(const std::string& path)
{
delete _pDataStream;
_pDataStream = 0;
_pDataStream = new SocketStream(establishDataConnection("STOR", path));
return *_pDataStream;
}
void FTPClientSession::endUpload()
{
endTransfer();
}
std::istream& FTPClientSession::beginList(const std::string& path, bool extended)
{
delete _pDataStream;
_pDataStream = 0;
_pDataStream = new SocketStream(establishDataConnection(extended ? "LIST" : "NLST", path));
return *_pDataStream;
}
void FTPClientSession::endList()
{
endTransfer();
}
void FTPClientSession::abort()
{
_controlSocket.sendByte(DialogSocket::TELNET_IP);
_controlSocket.synch();
std::string response;
int status = sendCommand("ABOR", response);
if (status == 426)
status = _controlSocket.receiveStatusMessage(response);
if (status != 226) throw FTPException("Cannot abort transfer", response, status);
}
int FTPClientSession::sendCommand(const std::string& command, std::string& response)
{
_controlSocket.sendMessage(command);
return _controlSocket.receiveStatusMessage(response);
}
int FTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response)
{
_controlSocket.sendMessage(command, arg);
return _controlSocket.receiveStatusMessage(response);
}
std::string FTPClientSession::extractPath(const std::string& response)
{
std::string path;
std::string::const_iterator it = response.begin();
std::string::const_iterator end = response.end();
while (it != end && *it != '"') ++it;
if (it != end)
{
++it;
while (it != end)
{
if (*it == '"')
{
++it;
if (it == end || (it != end && *it != '"')) break;
}
path += *it++;
}
}
return path;
}
StreamSocket FTPClientSession::establishDataConnection(const std::string& command, const std::string& arg)
{
if (_passiveMode)
return passiveDataConnection(command, arg);
else
return activeDataConnection(command, arg);
}
StreamSocket FTPClientSession::activeDataConnection(const std::string& command, const std::string& arg)
{
ServerSocket server(SocketAddress(_controlSocket.address().host(), 0));
sendPortCommand(server.address());
std::string response;
int status = sendCommand(command, arg, response);
if (!isPositivePreliminary(status)) throw FTPException(command + " command failed", response, status);
if (server.poll(_timeout, Socket::SELECT_READ))
return server.acceptConnection();
else
throw FTPException("The server has not initiated a data connection");
}
StreamSocket FTPClientSession::passiveDataConnection(const std::string& command, const std::string& arg)
{
SocketAddress sa(sendPassiveCommand());
StreamSocket sock(sa);
std::string response;
int status = sendCommand(command, arg, response);
if (!isPositivePreliminary(status)) throw FTPException(command + " command failed", response, status);
return sock;
}
void FTPClientSession::sendPortCommand(const SocketAddress& addr)
{
if (_supports1738)
{
if (sendEPRT(addr))
return;
else
_supports1738 = false;
}
sendPORT(addr);
}
SocketAddress FTPClientSession::sendPassiveCommand()
{
SocketAddress addr;
if (_supports1738)
{
if (sendEPSV(addr))
return addr;
else
_supports1738 = false;
}
sendPASV(addr);
return addr;
}
bool FTPClientSession::sendEPRT(const SocketAddress& addr)
{
std::string arg("|");
arg += addr.af() == AF_INET ? '1' : '2';
arg += '|';
arg += addr.host().toString();
arg += '|';
arg += NumberFormatter::format(addr.port());
arg += '|';
std::string response;
int status = sendCommand("EPRT", arg, response);
if (isPositiveCompletion(status))
return true;
else if (isPermanentNegative(status))
return false;
else
throw FTPException("EPRT command failed", response, status);
}
void FTPClientSession::sendPORT(const SocketAddress& addr)
{
std::string arg(addr.host().toString());
for (std::string::iterator it = arg.begin(); it != arg.end(); ++it)
{
if (*it == '.') *it = ',';
}
arg += ',';
Poco::UInt16 port = addr.port();
arg += NumberFormatter::format(port/256);
arg += ',';
arg += NumberFormatter::format(port % 256);
std::string response;
int status = sendCommand("PORT", arg, response);
if (!isPositiveCompletion(status)) throw FTPException("PORT command failed", response, status);
}
bool FTPClientSession::sendEPSV(SocketAddress& addr)
{
std::string response;
int status = sendCommand("EPSV", response);
if (isPositiveCompletion(status))
{
parseExtAddress(response, addr);
return true;
}
else if (isPermanentNegative(status))
{
return false;
}
else throw FTPException("EPSV command failed", response, status);
}
void FTPClientSession::sendPASV(SocketAddress& addr)
{
std::string response;
int status = sendCommand("PASV", response);
if (!isPositiveCompletion(status)) throw FTPException("PASV command failed", response, status);
parseAddress(response, addr);
}
void FTPClientSession::parseAddress(const std::string& str, SocketAddress& addr)
{
std::string::const_iterator it = str.begin();
std::string::const_iterator end = str.end();
while (it != end && *it != '(') ++it;
if (it != end) ++it;
std::string host;
while (it != end && Poco::Ascii::isDigit(*it)) host += *it++;
if (it != end && *it == ',') { host += '.'; ++it; }
while (it != end && Poco::Ascii::isDigit(*it)) host += *it++;
if (it != end && *it == ',') { host += '.'; ++it; }
while (it != end && Poco::Ascii::isDigit(*it)) host += *it++;
if (it != end && *it == ',') { host += '.'; ++it; }
while (it != end && Poco::Ascii::isDigit(*it)) host += *it++;
if (it != end && *it == ',') ++it;
Poco::UInt16 portHi = 0;
while (it != end && Poco::Ascii::isDigit(*it)) { portHi *= 10; portHi += *it++ - '0'; }
if (it != end && *it == ',') ++it;
Poco::UInt16 portLo = 0;
while (it != end && Poco::Ascii::isDigit(*it)) { portLo *= 10; portLo += *it++ - '0'; }
addr = SocketAddress(host, portHi*256 + portLo);
}
void FTPClientSession::parseExtAddress(const std::string& str, SocketAddress& addr)
{
std::string::const_iterator it = str.begin();
std::string::const_iterator end = str.end();
while (it != end && *it != '(') ++it;
if (it != end) ++it;
char delim = '|';
if (it != end) delim = *it++;
if (it != end && *it == delim) ++it;
if (it != end && *it == delim) ++it;
Poco::UInt16 port = 0;
while (it != end && Poco::Ascii::isDigit(*it)) { port *= 10; port += *it++ - '0'; }
addr = SocketAddress(_controlSocket.peerAddress().host(), port);
}
void FTPClientSession::endTransfer()
{
if (_pDataStream)
{
delete _pDataStream;
_pDataStream = 0;
std::string response;
int status = _controlSocket.receiveStatusMessage(response);
if (!isPositiveCompletion(status)) throw FTPException("Data transfer failed", response, status);
}
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,257 @@
//
// FTPStreamFactory.cpp
//
// $Id: //poco/1.4/Net/src/FTPStreamFactory.cpp#1 $
//
// Library: Net
// Package: FTP
// Module: FTPStreamFactory
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/FTPStreamFactory.h"
#include "Poco/Net/FTPClientSession.h"
#include "Poco/Net/NetException.h"
#include "Poco/URI.h"
#include "Poco/URIStreamOpener.h"
#include "Poco/UnbufferedStreamBuf.h"
#include "Poco/Path.h"
using Poco::URIStreamFactory;
using Poco::URI;
using Poco::URIStreamOpener;
using Poco::UnbufferedStreamBuf;
using Poco::Path;
namespace Poco {
namespace Net {
class FTPStreamBuf: public UnbufferedStreamBuf
{
public:
FTPStreamBuf(std::istream& istr):
_istr(istr)
{
}
~FTPStreamBuf()
{
}
private:
int readFromDevice()
{
return _istr.get();
}
std::istream& _istr;
};
class FTPIOS: public virtual std::ios
{
public:
FTPIOS(std::istream& istr):
_buf(istr)
{
poco_ios_init(&_buf);
}
~FTPIOS()
{
}
FTPStreamBuf* rdbuf()
{
return &_buf;
}
protected:
FTPStreamBuf _buf;
};
class FTPStream: public FTPIOS, public std::istream
{
public:
FTPStream(std::istream& istr, FTPClientSession* pSession):
FTPIOS(istr),
std::istream(&_buf),
_pSession(pSession)
{
}
~FTPStream()
{
delete _pSession;
}
private:
FTPClientSession* _pSession;
};
FTPPasswordProvider::FTPPasswordProvider()
{
}
FTPPasswordProvider::~FTPPasswordProvider()
{
}
std::string FTPStreamFactory::_anonymousPassword("poco@localhost");
FTPPasswordProvider* FTPStreamFactory::_pPasswordProvider(0);
FTPStreamFactory::FTPStreamFactory()
{
}
FTPStreamFactory::~FTPStreamFactory()
{
}
std::istream* FTPStreamFactory::open(const URI& uri)
{
poco_assert (uri.getScheme() == "ftp");
FTPClientSession* pSession = new FTPClientSession(uri.getHost(), uri.getPort());
try
{
std::string username;
std::string password;
getUserInfo(uri, username, password);
std::string path;
char type;
getPathAndType(uri, path, type);
pSession->login(username, password);
if (type == 'a')
pSession->setFileType(FTPClientSession::TYPE_TEXT);
Path p(path, Path::PATH_UNIX);
p.makeFile();
for (int i = 0; i < p.depth(); ++i)
pSession->setWorkingDirectory(p[i]);
std::string file(p.getFileName());
std::istream& istr = (type == 'd' ? pSession->beginList(file) : pSession->beginDownload(file));
return new FTPStream(istr, pSession);
}
catch (...)
{
delete pSession;
throw;
}
}
void FTPStreamFactory::setAnonymousPassword(const std::string& password)
{
_anonymousPassword = password;
}
const std::string& FTPStreamFactory::getAnonymousPassword()
{
return _anonymousPassword;
}
void FTPStreamFactory::setPasswordProvider(FTPPasswordProvider* pProvider)
{
_pPasswordProvider = pProvider;
}
FTPPasswordProvider* FTPStreamFactory::getPasswordProvider()
{
return _pPasswordProvider;
}
void FTPStreamFactory::splitUserInfo(const std::string& userInfo, std::string& username, std::string& password)
{
std::string::size_type pos = userInfo.find(':');
if (pos != std::string::npos)
{
username.assign(userInfo, 0, pos++);
password.assign(userInfo, pos, userInfo.size() - pos);
}
else username = userInfo;
}
void FTPStreamFactory::getUserInfo(const URI& uri, std::string& username, std::string& password)
{
splitUserInfo(uri.getUserInfo(), username, password);
if (username.empty())
{
username = "anonymous";
password = _anonymousPassword;
}
else if (password.empty())
{
if (_pPasswordProvider)
password = _pPasswordProvider->password(username, uri.getHost());
else
throw FTPException(std::string("Password required for ") + username + "@" + uri.getHost());
}
}
void FTPStreamFactory::getPathAndType(const Poco::URI& uri, std::string& path, char& type)
{
path = uri.getPath();
type = 'i';
std::string::size_type pos = path.rfind(';');
if (pos != std::string::npos)
{
if (path.length() == pos + 7 && path.compare(pos + 1, 5, "type=") == 0)
{
type = path[pos + 6];
path.resize(pos);
}
}
}
void FTPStreamFactory::registerFactory()
{
URIStreamOpener::defaultOpener().registerStreamFactory("ftp", new FTPStreamFactory);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,99 @@
//
// FilePartSource.cpp
//
// $Id: //poco/1.4/Net/src/FilePartSource.cpp#1 $
//
// Library: Net
// Package: Messages
// Module: FilePartSource
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/FilePartSource.h"
#include "Poco/Path.h"
#include "Poco/Exception.h"
using Poco::Path;
using Poco::OpenFileException;
namespace Poco {
namespace Net {
FilePartSource::FilePartSource(const std::string& path):
_istr(path)
{
Path p(path);
_filename = p.getFileName();
if (!_istr.good())
throw OpenFileException(path);
}
FilePartSource::FilePartSource(const std::string& path, const std::string& mediaType):
PartSource(mediaType),
_istr(path)
{
Path p(path);
_filename = p.getFileName();
if (!_istr.good())
throw OpenFileException(path);
}
FilePartSource::FilePartSource(const std::string& path, const std::string& filename, const std::string& mediaType):
PartSource(mediaType),
_filename(filename),
_istr(path)
{
Path p(path);
if (!_istr.good())
throw OpenFileException(path);
}
FilePartSource::~FilePartSource()
{
}
std::istream& FilePartSource::stream()
{
return _istr;
}
const std::string& FilePartSource::filename()
{
return _filename;
}
} } // namespace Poco::Net

400
Net/src/HTMLForm.cpp Normal file
View File

@@ -0,0 +1,400 @@
//
// HTMLForm.cpp
//
// $Id: //poco/1.4/Net/src/HTMLForm.cpp#4 $
//
// Library: Net
// Package: HTML
// Module: HTMLForm
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTMLForm.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/PartSource.h"
#include "Poco/Net/PartHandler.h"
#include "Poco/Net/MultipartWriter.h"
#include "Poco/Net/MultipartReader.h"
#include "Poco/Net/NullPartHandler.h"
#include "Poco/Net/NetException.h"
#include "Poco/NullStream.h"
#include "Poco/CountingStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/URI.h"
#include "Poco/String.h"
#include <sstream>
using Poco::NullInputStream;
using Poco::StreamCopier;
using Poco::SyntaxException;
using Poco::URI;
using Poco::icompare;
namespace Poco {
namespace Net {
const std::string HTMLForm::ENCODING_URL = "application/x-www-form-urlencoded";
const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data";
HTMLForm::HTMLForm():
_fieldLimit(DFL_FIELD_LIMIT),
_encoding(ENCODING_URL)
{
}
HTMLForm::HTMLForm(const std::string& encoding):
_fieldLimit(DFL_FIELD_LIMIT),
_encoding(encoding)
{
}
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler):
_fieldLimit(DFL_FIELD_LIMIT)
{
load(request, requestBody, handler);
}
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody):
_fieldLimit(DFL_FIELD_LIMIT)
{
load(request, requestBody);
}
HTMLForm::HTMLForm(const HTTPRequest& request):
_fieldLimit(DFL_FIELD_LIMIT)
{
load(request);
}
HTMLForm::~HTMLForm()
{
for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it)
{
delete it->pSource;
}
}
void HTMLForm::setEncoding(const std::string& encoding)
{
_encoding = encoding;
}
void HTMLForm::addPart(const std::string& name, PartSource* pSource)
{
poco_check_ptr (pSource);
Part part;
part.name = name;
part.pSource = pSource;
_parts.push_back(part);
}
void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler)
{
clear();
if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT)
{
std::string mediaType;
NameValueCollection params;
MessageHeader::splitParameters(request.getContentType(), mediaType, params);
_encoding = mediaType;
if (_encoding == ENCODING_MULTIPART)
{
_boundary = params["boundary"];
readMultipart(requestBody, handler);
}
else
{
readUrl(requestBody);
}
}
else
{
URI uri(request.getURI());
std::istringstream istr(uri.getRawQuery());
readUrl(istr);
}
}
void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody)
{
NullPartHandler nah;
load(request, requestBody, nah);
}
void HTMLForm::load(const HTTPRequest& request)
{
NullPartHandler nah;
NullInputStream nis;
load(request, nis, nah);
}
void HTMLForm::read(std::istream& istr, PartHandler& handler)
{
if (_encoding == ENCODING_URL)
readUrl(istr);
else
readMultipart(istr, handler);
}
void HTMLForm::read(std::istream& istr)
{
readUrl(istr);
}
void HTMLForm::read(const std::string& queryString)
{
std::istringstream istr(queryString);
readUrl(istr);
}
void HTMLForm::prepareSubmit(HTTPRequest& request)
{
if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT)
{
if (_encoding == ENCODING_URL)
{
request.setContentType(_encoding);
request.setChunkedTransferEncoding(false);
Poco::CountingOutputStream ostr;
writeUrl(ostr);
request.setContentLength(ostr.chars());
}
else
{
_boundary = MultipartWriter::createBoundary();
std::string ct(_encoding);
ct.append("; boundary=\"");
ct.append(_boundary);
ct.append("\"");
request.setContentType(ct);
}
if (request.getVersion() == HTTPMessage::HTTP_1_0)
{
request.setKeepAlive(false);
request.setChunkedTransferEncoding(false);
}
else if (_encoding != ENCODING_URL)
{
request.setChunkedTransferEncoding(true);
}
}
else
{
std::string uri = request.getURI();
std::ostringstream ostr;
writeUrl(ostr);
uri.append("?");
uri.append(ostr.str());
request.setURI(uri);
}
}
void HTMLForm::write(std::ostream& ostr, const std::string& boundary)
{
if (_encoding == ENCODING_URL)
{
writeUrl(ostr);
}
else
{
_boundary = boundary;
writeMultipart(ostr);
}
}
void HTMLForm::write(std::ostream& ostr)
{
if (_encoding == ENCODING_URL)
writeUrl(ostr);
else
writeMultipart(ostr);
}
void HTMLForm::readUrl(std::istream& istr)
{
static const int eof = std::char_traits<char>::eof();
int fields = 0;
int ch = istr.get();
while (ch != eof)
{
if (_fieldLimit > 0 && fields == _fieldLimit)
throw HTMLFormException("Too many form fields");
std::string name;
std::string value;
while (ch != eof && ch != '=' && ch != '&')
{
if (ch == '+') ch = ' ';
name += (char) ch;
ch = istr.get();
}
if (ch == '=')
{
ch = istr.get();
while (ch != eof && ch != '&')
{
if (ch == '+') ch = ' ';
value += (char) ch;
ch = istr.get();
}
}
std::string decodedName;
std::string decodedValue;
URI::decode(name, decodedName);
URI::decode(value, decodedValue);
add(decodedName, decodedValue);
++fields;
if (ch == '&') ch = istr.get();
}
}
void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler)
{
static const int eof = std::char_traits<char>::eof();
int fields = 0;
MultipartReader reader(istr, _boundary);
while (reader.hasNextPart())
{
if (_fieldLimit > 0 && fields == _fieldLimit)
throw HTMLFormException("Too many form fields");
MessageHeader header;
reader.nextPart(header);
std::string disp;
NameValueCollection params;
if (header.has("Content-Disposition"))
{
std::string cd = header.get("Content-Disposition");
MessageHeader::splitParameters(cd, disp, params);
}
if (params.has("filename"))
{
handler.handlePart(header, reader.stream());
// Ensure that the complete part has been read.
while (reader.stream().good()) reader.stream().get();
}
else
{
std::string name = params["name"];
std::string value;
std::istream& istr = reader.stream();
int ch = istr.get();
while (ch != eof)
{
value += (char) ch;
ch = istr.get();
}
add(name, value);
}
++fields;
}
}
void HTMLForm::writeUrl(std::ostream& ostr)
{
for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it)
{
if (it != begin()) ostr << "&";
std::string name;
URI::encode(it->first, "=&+;", name);
std::string value;
URI::encode(it->second, "=&+;", value);
ostr << name << "=" << value;
}
}
void HTMLForm::writeMultipart(std::ostream& ostr)
{
MultipartWriter writer(ostr, _boundary);
for (NameValueCollection::ConstIterator it = begin(); it != end(); ++it)
{
MessageHeader header;
std::string disp("form-data; name=\"");
disp.append(it->first);
disp.append("\"");
header.set("Content-Disposition", disp);
writer.nextPart(header);
ostr << it->second;
}
for (PartVec::iterator ita = _parts.begin(); ita != _parts.end(); ++ita)
{
MessageHeader header(ita->pSource->headers());
std::string disp("form-data; name=\"");
disp.append(ita->name);
disp.append("\"");
std::string filename = ita->pSource->filename();
if (!filename.empty())
{
disp.append("; filename=\"");
disp.append(filename);
disp.append("\"");
}
header.set("Content-Disposition", disp);
header.set("Content-Type", ita->pSource->mediaType());
writer.nextPart(header);
StreamCopier::copyStream(ita->pSource->stream(), ostr);
}
writer.close();
_boundary = writer.boundary();
}
void HTMLForm::setFieldLimit(int limit)
{
poco_assert (limit >= 0);
_fieldLimit = limit;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,326 @@
//
// HTTPAuthenticationParams.cpp
//
// $Id: //poco/1.4/Net/src/HTTPAuthenticationParams.cpp#1 $
//
// Library: Net
// Package: HTTP
// Module: HTTPAuthenticationParams
//
// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru).
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Exception.h"
#include "Poco/Net/HTTPAuthenticationParams.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/NetException.h"
#include "Poco/String.h"
#include "Poco/Ascii.h"
using Poco::icompare;
using Poco::Ascii;
namespace
{
bool mustBeQuoted(const std::string& name)
{
return
icompare(name, "cnonce") == 0 ||
icompare(name, "domain") == 0 ||
icompare(name, "nonce") == 0 ||
icompare(name, "opaque") == 0 ||
icompare(name, "qop") == 0 ||
icompare(name, "realm") == 0 ||
icompare(name, "response") == 0 ||
icompare(name, "uri") == 0 ||
icompare(name, "username") == 0;
}
void formatParameter(std::string& result, const std::string& name, const std::string& value)
{
result += name;
result += '=';
if (mustBeQuoted(name))
{
result += '"';
result += value;
result += '"';
}
else
{
result += value;
}
}
}
namespace Poco {
namespace Net {
const std::string HTTPAuthenticationParams::REALM("realm");
HTTPAuthenticationParams::HTTPAuthenticationParams()
{
}
HTTPAuthenticationParams::HTTPAuthenticationParams(const std::string& authInfo)
{
fromAuthInfo(authInfo);
}
HTTPAuthenticationParams::HTTPAuthenticationParams(const HTTPRequest& request)
{
fromRequest(request);
}
HTTPAuthenticationParams::HTTPAuthenticationParams(const HTTPResponse& response)
{
fromResponse(response);
}
HTTPAuthenticationParams::~HTTPAuthenticationParams()
{
}
HTTPAuthenticationParams& HTTPAuthenticationParams::operator = (const HTTPAuthenticationParams& authParams)
{
NameValueCollection::operator = (authParams);
return *this;
}
void HTTPAuthenticationParams::fromAuthInfo(const std::string& authInfo)
{
parse(authInfo.begin(), authInfo.end());
}
void HTTPAuthenticationParams::fromRequest(const HTTPRequest& request)
{
std::string scheme;
std::string authInfo;
request.getCredentials(scheme, authInfo);
if (icompare(scheme, "Digest") != 0)
throw InvalidArgumentException("Could not parse non-Digest authentication information", scheme);
fromAuthInfo(authInfo);
}
void HTTPAuthenticationParams::fromResponse(const HTTPResponse& response)
{
if (!response.has("WWW-Authenticate"))
throw NotAuthenticatedException("HTTP response has no authentication header");
const std::string& header = response.get("WWW-Authenticate");
if (icompare(header, 0, 6, "Basic ") == 0)
{
parse(header.begin() + 6, header.end());
}
else if (icompare(header, 0, 7, "Digest ") == 0)
{
parse(header.begin() + 7, header.end());
}
else throw InvalidArgumentException("Invalid authentication scheme", header);
}
const std::string& HTTPAuthenticationParams::getRealm() const
{
return get(REALM);
}
void HTTPAuthenticationParams::setRealm(const std::string& realm)
{
set(REALM, realm);
}
std::string HTTPAuthenticationParams::toString() const
{
ConstIterator iter = begin();
std::string result;
if (iter != end())
{
formatParameter(result, iter->first, iter->second);
++iter;
}
for (; iter != end(); ++iter)
{
result.append(", ");
formatParameter(result, iter->first, iter->second);
}
return result;
}
void HTTPAuthenticationParams::parse(std::string::const_iterator first, std::string::const_iterator last)
{
enum State
{
STATE_INITIAL = 0x0100,
STATE_FINAL = 0x0200,
STATE_SPACE = STATE_INITIAL | 0,
STATE_TOKEN = 1,
STATE_EQUALS = 2,
STATE_VALUE = STATE_FINAL | 3,
STATE_VALUE_QUOTED = 4,
STATE_VALUE_ESCAPE = 5,
STATE_COMMA = STATE_FINAL | 6
};
int state = STATE_SPACE;
std::string token;
std::string value;
for (std::string::const_iterator it = first; it != last; ++it)
{
switch (state)
{
case STATE_SPACE:
if (Ascii::isAlphaNumeric(*it))
{
token += *it;
state = STATE_TOKEN;
}
else if (Ascii::isSpace(*it))
{
// Skip
}
else throw SyntaxException("Invalid authentication information");
break;
case STATE_TOKEN:
if (*it == '=')
{
state = STATE_EQUALS;
}
else if (Ascii::isAlphaNumeric(*it))
{
token += *it;
}
else throw SyntaxException("Invalid authentication information");
break;
case STATE_EQUALS:
if (Ascii::isAlphaNumeric(*it))
{
value += *it;
state = STATE_VALUE;
}
else if (*it == '"')
{
state = STATE_VALUE_QUOTED;
}
else throw SyntaxException("Invalid authentication information");
break;
case STATE_VALUE_QUOTED:
if (*it == '\\')
{
state = STATE_VALUE_ESCAPE;
}
else if (*it == '"')
{
add(token, value);
token.clear();
value.clear();
state = STATE_COMMA;
}
else
{
value += *it;
}
break;
case STATE_VALUE_ESCAPE:
value += *it;
state = STATE_VALUE_QUOTED;
break;
case STATE_VALUE:
if (Ascii::isSpace(*it))
{
add(token, value);
token.clear();
value.clear();
state = STATE_COMMA;
}
else if (*it == ',')
{
add(token, value);
token.clear();
value.clear();
state = STATE_SPACE;
}
else
{
value += *it;
}
break;
case STATE_COMMA:
if (*it == ',')
{
state = STATE_SPACE;
}
else if (Ascii::isSpace(*it))
{
// Skip
}
else throw SyntaxException("Invalid authentication information");
break;
}
}
if (!(state & STATE_FINAL))
throw SyntaxException("Invalid authentication information");
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,149 @@
//
// HTTPBasicCredentials.cpp
//
// $Id: //poco/1.4/Net/src/HTTPBasicCredentials.cpp#3 $
//
// Library: Net
// Package: HTTP
// Module: HTTPBasicCredentials
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPBasicCredentials.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/NetException.h"
#include "Poco/Base64Encoder.h"
#include "Poco/Base64Decoder.h"
#include "Poco/String.h"
#include <sstream>
using Poco::Base64Decoder;
using Poco::Base64Encoder;
using Poco::icompare;
namespace Poco {
namespace Net {
const std::string HTTPBasicCredentials::SCHEME = "Basic";
HTTPBasicCredentials::HTTPBasicCredentials()
{
}
HTTPBasicCredentials::HTTPBasicCredentials(const std::string& username, const std::string& password):
_username(username),
_password(password)
{
}
HTTPBasicCredentials::HTTPBasicCredentials(const HTTPRequest& request)
{
std::string scheme;
std::string authInfo;
request.getCredentials(scheme, authInfo);
if (icompare(scheme, SCHEME) == 0)
{
parseAuthInfo(authInfo);
}
else throw NotAuthenticatedException("Basic authentication expected");
}
HTTPBasicCredentials::HTTPBasicCredentials(const std::string& authInfo)
{
parseAuthInfo(authInfo);
}
HTTPBasicCredentials::~HTTPBasicCredentials()
{
}
void HTTPBasicCredentials::setUsername(const std::string& username)
{
_username = username;
}
void HTTPBasicCredentials::setPassword(const std::string& password)
{
_password = password;
}
void HTTPBasicCredentials::authenticate(HTTPRequest& request) const
{
std::ostringstream ostr;
Base64Encoder encoder(ostr);
encoder.rdbuf()->setLineLength(0);
encoder << _username << ":" << _password;
encoder.close();
request.setCredentials(SCHEME, ostr.str());
}
void HTTPBasicCredentials::proxyAuthenticate(HTTPRequest& request) const
{
std::ostringstream ostr;
Base64Encoder encoder(ostr);
encoder.rdbuf()->setLineLength(0);
encoder << _username << ":" << _password;
encoder.close();
request.setProxyCredentials(SCHEME, ostr.str());
}
void HTTPBasicCredentials::parseAuthInfo(const std::string& authInfo)
{
static const int eof = std::char_traits<char>::eof();
std::istringstream istr(authInfo);
Base64Decoder decoder(istr);
int ch = decoder.get();
while (ch != eof && ch != ':')
{
_username += (char) ch;
ch = decoder.get();
}
if (ch == ':') ch = decoder.get();
while (ch != eof)
{
_password += (char) ch;
ch = decoder.get();
}
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,66 @@
//
// HTTPBufferAllocator.cpp
//
// $Id: //poco/Main/template/class.cpp#4 $
//
// Library: Net
// Package: HTTP
// Module: HTTPBufferAllocator
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPBufferAllocator.h"
using Poco::MemoryPool;
namespace Poco {
namespace Net {
MemoryPool HTTPBufferAllocator::_pool(HTTPBufferAllocator::BUFFER_SIZE, 16);
char* HTTPBufferAllocator::allocate(std::streamsize size)
{
poco_assert_dbg (size == BUFFER_SIZE);
return reinterpret_cast<char*>(_pool.get());
}
void HTTPBufferAllocator::deallocate(char* ptr, std::streamsize size)
{
poco_assert_dbg (size == BUFFER_SIZE);
_pool.release(ptr);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,220 @@
//
// HTTPChunkedStream.cpp
//
// $Id: //poco/1.4/Net/src/HTTPChunkedStream.cpp#1 $
//
// Library: Net
// Package: HTTP
// Module: HTTPChunkedStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPChunkedStream.h"
#include "Poco/Net/HTTPSession.h"
#include "Poco/NumberFormatter.h"
#include "Poco/NumberParser.h"
#include "Poco/Ascii.h"
using Poco::NumberFormatter;
using Poco::NumberParser;
namespace Poco {
namespace Net {
//
// HTTPChunkedStreamBuf
//
HTTPChunkedStreamBuf::HTTPChunkedStreamBuf(HTTPSession& session, openmode mode):
HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode),
_session(session),
_mode(mode),
_chunk(0)
{
}
HTTPChunkedStreamBuf::~HTTPChunkedStreamBuf()
{
}
void HTTPChunkedStreamBuf::close()
{
if (_mode & std::ios::out)
{
sync();
_session.write("0\r\n\r\n", 5);
}
}
int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
static const int eof = std::char_traits<char>::eof();
if (_chunk == 0)
{
int ch = _session.get();
while (Poco::Ascii::isSpace(ch)) ch = _session.get();
std::string chunkLen;
while (Poco::Ascii::isHexDigit(ch)) { chunkLen += (char) ch; ch = _session.get(); }
while (ch != eof && ch != '\n') ch = _session.get();
unsigned chunk;
if (NumberParser::tryParseHex(chunkLen, chunk))
_chunk = (std::streamsize) chunk;
else
return eof;
}
if (_chunk > 0)
{
if (length > _chunk) length = _chunk;
int n = _session.read(buffer, length);
if (n > 0) _chunk -= n;
return n;
}
else
{
int ch = _session.get();
while (ch != eof && ch != '\n') ch = _session.get();
return 0;
}
}
int HTTPChunkedStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
_chunkBuffer.clear();
NumberFormatter::appendHex(_chunkBuffer, length);
_chunkBuffer.append("\r\n", 2);
_chunkBuffer.append(buffer, static_cast<std::string::size_type>(length));
_chunkBuffer.append("\r\n", 2);
_session.write(_chunkBuffer.data(), static_cast<std::streamsize>(_chunkBuffer.size()));
return static_cast<int>(length);
}
//
// HTTPChunkedIOS
//
HTTPChunkedIOS::HTTPChunkedIOS(HTTPSession& session, HTTPChunkedStreamBuf::openmode mode):
_buf(session, mode)
{
poco_ios_init(&_buf);
}
HTTPChunkedIOS::~HTTPChunkedIOS()
{
try
{
_buf.close();
}
catch (...)
{
}
}
HTTPChunkedStreamBuf* HTTPChunkedIOS::rdbuf()
{
return &_buf;
}
//
// HTTPChunkedInputStream
//
Poco::MemoryPool HTTPChunkedInputStream::_pool(sizeof(HTTPChunkedInputStream));
HTTPChunkedInputStream::HTTPChunkedInputStream(HTTPSession& session):
HTTPChunkedIOS(session, std::ios::in),
std::istream(&_buf)
{
}
HTTPChunkedInputStream::~HTTPChunkedInputStream()
{
}
void* HTTPChunkedInputStream::operator new(std::size_t size)
{
return _pool.get();
}
void HTTPChunkedInputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
//
// HTTPChunkedOutputStream
//
Poco::MemoryPool HTTPChunkedOutputStream::_pool(sizeof(HTTPChunkedOutputStream));
HTTPChunkedOutputStream::HTTPChunkedOutputStream(HTTPSession& session):
HTTPChunkedIOS(session, std::ios::out),
std::ostream(&_buf)
{
}
HTTPChunkedOutputStream::~HTTPChunkedOutputStream()
{
}
void* HTTPChunkedOutputStream::operator new(std::size_t size)
{
return _pool.get();
}
void HTTPChunkedOutputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,441 @@
//
// HTTPClientSession.cpp
//
// $Id: //poco/1.4/Net/src/HTTPClientSession.cpp#6 $
//
// Library: Net
// Package: HTTPClient
// Module: HTTPClientSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPHeaderStream.h"
#include "Poco/Net/HTTPStream.h"
#include "Poco/Net/HTTPFixedLengthStream.h"
#include "Poco/Net/HTTPChunkedStream.h"
#include "Poco/Net/HTTPBasicCredentials.h"
#include "Poco/Net/NetException.h"
#include "Poco/NumberFormatter.h"
#include "Poco/CountingStream.h"
#include "Poco/Base64Encoder.h"
#include <sstream>
using Poco::NumberFormatter;
using Poco::IllegalStateException;
namespace Poco {
namespace Net {
HTTPClientSession::HTTPClientSession():
_port(HTTPSession::HTTP_PORT),
_proxyPort(HTTPSession::HTTP_PORT),
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false),
_pRequestStream(0),
_pResponseStream(0)
{
}
HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
HTTPSession(socket),
_port(HTTPSession::HTTP_PORT),
_proxyPort(HTTPSession::HTTP_PORT),
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false),
_pRequestStream(0),
_pResponseStream(0)
{
}
HTTPClientSession::HTTPClientSession(const SocketAddress& address):
_host(address.host().toString()),
_port(address.port()),
_proxyPort(HTTPSession::HTTP_PORT),
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false),
_pRequestStream(0),
_pResponseStream(0)
{
}
HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port):
_host(host),
_port(port),
_proxyPort(HTTPSession::HTTP_PORT),
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
_reconnect(false),
_mustReconnect(false),
_expectResponseBody(false),
_pRequestStream(0),
_pResponseStream(0)
{
}
HTTPClientSession::~HTTPClientSession()
{
delete _pRequestStream;
delete _pResponseStream;
}
void HTTPClientSession::setHost(const std::string& host)
{
if (!connected())
_host = host;
else
throw IllegalStateException("Cannot set the host for an already connected session");
}
void HTTPClientSession::setPort(Poco::UInt16 port)
{
if (!connected())
_port = port;
else
throw IllegalStateException("Cannot set the port number for an already connected session");
}
void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port)
{
if (!connected())
{
_proxyHost = host;
_proxyPort = port;
}
else throw IllegalStateException("Cannot set the proxy host and port for an already connected session");
}
void HTTPClientSession::setProxyHost(const std::string& host)
{
if (!connected())
_proxyHost = host;
else
throw IllegalStateException("Cannot set the proxy host for an already connected session");
}
void HTTPClientSession::setProxyPort(Poco::UInt16 port)
{
if (!connected())
_proxyPort = port;
else
throw IllegalStateException("Cannot set the proxy port number for an already connected session");
}
void HTTPClientSession::setProxyCredentials(const std::string& username, const std::string& password)
{
_proxyUsername = username;
_proxyPassword = password;
}
void HTTPClientSession::setProxyUsername(const std::string& username)
{
_proxyUsername = username;
}
void HTTPClientSession::setProxyPassword(const std::string& password)
{
_proxyPassword = password;
}
void HTTPClientSession::setKeepAliveTimeout(const Poco::Timespan& timeout)
{
_keepAliveTimeout = timeout;
}
std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
{
delete _pResponseStream;
_pResponseStream = 0;
bool keepAlive = getKeepAlive();
if ((connected() && !keepAlive) || mustReconnect())
{
close();
_mustReconnect = false;
}
try
{
if (!connected())
reconnect();
if (!keepAlive)
request.setKeepAlive(false);
if (!request.has(HTTPRequest::HOST))
request.setHost(_host, _port);
if (!_proxyHost.empty())
{
request.setURI(proxyRequestPrefix() + request.getURI());
proxyAuthenticate(request);
}
_reconnect = keepAlive;
_expectResponseBody = request.getMethod() != HTTPRequest::HTTP_HEAD;
if (request.getChunkedTransferEncoding())
{
HTTPHeaderOutputStream hos(*this);
request.write(hos);
_pRequestStream = new HTTPChunkedOutputStream(*this);
}
else if (request.getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
{
Poco::CountingOutputStream cs;
request.write(cs);
_pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength() + cs.chars());
request.write(*_pRequestStream);
}
else if (request.getMethod() != HTTPRequest::HTTP_PUT && request.getMethod() != HTTPRequest::HTTP_POST)
{
Poco::CountingOutputStream cs;
request.write(cs);
_pRequestStream = new HTTPFixedLengthOutputStream(*this, cs.chars());
request.write(*_pRequestStream);
}
else
{
_pRequestStream = new HTTPOutputStream(*this);
request.write(*_pRequestStream);
}
_lastRequest.update();
return *_pRequestStream;
}
catch (Exception&)
{
close();
throw;
}
}
std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
{
delete _pRequestStream;
_pRequestStream = 0;
do
{
response.clear();
HTTPHeaderInputStream his(*this);
try
{
response.read(his);
}
catch (MessageException&)
{
close();
if (networkException())
networkException()->rethrow();
else
throw;
}
catch (Exception&)
{
close();
throw;
}
}
while (response.getStatus() == HTTPResponse::HTTP_CONTINUE);
_mustReconnect = getKeepAlive() && !response.getKeepAlive();
if (!_expectResponseBody)
_pResponseStream = new HTTPFixedLengthInputStream(*this, 0);
else if (response.getChunkedTransferEncoding())
_pResponseStream = new HTTPChunkedInputStream(*this);
else if (response.getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
_pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength());
else
_pResponseStream = new HTTPInputStream(*this);
return *_pResponseStream;
}
void HTTPClientSession::reset()
{
close();
}
bool HTTPClientSession::secure() const
{
return false;
}
int HTTPClientSession::write(const char* buffer, std::streamsize length)
{
try
{
int rc = HTTPSession::write(buffer, length);
_reconnect = false;
return rc;
}
catch (NetException&)
{
if (_reconnect)
{
close();
reconnect();
int rc = HTTPSession::write(buffer, length);
_reconnect = false;
return rc;
}
else throw;
}
}
void HTTPClientSession::reconnect()
{
if (_proxyHost.empty())
{
SocketAddress addr(_host, _port);
connect(addr);
}
else
{
SocketAddress addr(_proxyHost, _proxyPort);
connect(addr);
}
}
std::string HTTPClientSession::proxyRequestPrefix() const
{
std::string result("http://");
result.append(_host);
result.append(":");
NumberFormatter::append(result, _port);
return result;
}
void HTTPClientSession::deleteResponseStream()
{
delete _pResponseStream;
_pResponseStream = 0;
}
void HTTPClientSession::deleteRequestStream()
{
delete _pRequestStream;
_pRequestStream = 0;
}
void HTTPClientSession::setResponseStream(std::istream* pRespStream)
{
poco_assert (!_pResponseStream);
_pResponseStream = pRespStream;
}
void HTTPClientSession::setRequestStream(std::ostream* pRequestStream)
{
poco_assert (!_pRequestStream);
_pRequestStream = pRequestStream;
}
bool HTTPClientSession::mustReconnect() const
{
if (!_mustReconnect)
{
Poco::Timestamp now;
return _keepAliveTimeout <= now - _lastRequest;
}
else return true;
}
void HTTPClientSession::proxyAuthenticate(HTTPRequest& request)
{
proxyAuthenticateImpl(request);
}
void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request)
{
if (!_proxyUsername.empty())
{
HTTPBasicCredentials creds(_proxyUsername, _proxyPassword);
creds.proxyAuthenticate(request);
}
}
StreamSocket HTTPClientSession::proxyConnect()
{
HTTPClientSession proxySession(getProxyHost(), getProxyPort());
proxySession.setTimeout(getTimeout());
SocketAddress targetAddress(getHost(), getPort());
HTTPRequest proxyRequest(HTTPRequest::HTTP_CONNECT, targetAddress.toString(), HTTPMessage::HTTP_1_1);
HTTPResponse proxyResponse;
proxyRequest.set("Proxy-Connection", "keep-alive");
proxyRequest.set("Host", getHost());
proxyAuthenticateImpl(proxyRequest);
proxySession.setKeepAlive(true);
proxySession.sendRequest(proxyRequest);
proxySession.receiveResponse(proxyResponse);
if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK)
throw HTTPException("Cannot establish proxy connection", proxyResponse.getReason());
return proxySession.detachSocket();
}
void HTTPClientSession::proxyTunnel()
{
StreamSocket ss = proxyConnect();
attachSocket(ss);
}
} } // namespace Poco::Net

341
Net/src/HTTPCookie.cpp Normal file
View File

@@ -0,0 +1,341 @@
//
// HTTPCookie.cpp
//
// $Id: //poco/1.4/Net/src/HTTPCookie.cpp#1 $
//
// Library: Net
// Package: HTTP
// Module: HTTPCookie
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPCookie.h"
#include "Poco/Net/NameValueCollection.h"
#include "Poco/Timestamp.h"
#include "Poco/DateTime.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/DateTimeParser.h"
#include "Poco/NumberFormatter.h"
#include "Poco/NumberParser.h"
#include "Poco/String.h"
#include "Poco/URI.h"
using Poco::Timestamp;
using Poco::DateTime;
using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
using Poco::DateTimeParser;
using Poco::NumberFormatter;
using Poco::NumberParser;
using Poco::icompare;
namespace Poco {
namespace Net {
HTTPCookie::HTTPCookie():
_version(0),
_secure(false),
_maxAge(-1),
_httpOnly(false)
{
}
HTTPCookie::HTTPCookie(const std::string& name):
_version(0),
_name(name),
_secure(false),
_maxAge(-1),
_httpOnly(false)
{
}
HTTPCookie::HTTPCookie(const NameValueCollection& nvc):
_version(0),
_secure(false),
_maxAge(-1),
_httpOnly(false)
{
for (NameValueCollection::ConstIterator it = nvc.begin(); it != nvc.end(); ++it)
{
const std::string& name = it->first;
const std::string& value = it->second;
if (icompare(name, "comment") == 0)
{
setComment(value);
}
else if (icompare(name, "domain") == 0)
{
setDomain(value);
}
else if (icompare(name, "path") == 0)
{
setPath(value);
}
else if (icompare(name, "max-age") == 0)
{
setMaxAge(NumberParser::parse(value));
}
else if (icompare(name, "secure") == 0)
{
setSecure(true);
}
else if (icompare(name, "expires") == 0)
{
int tzd;
DateTime exp = DateTimeParser::parse(value, tzd);
Timestamp now;
setMaxAge((int) ((exp.timestamp() - now)/Timestamp::resolution()));
}
else if (icompare(name, "version") == 0)
{
setVersion(NumberParser::parse(value));
}
else if (icompare(name, "HttpOnly") == 0)
{
setHttpOnly(true);
}
else
{
setName(name);
setValue(value);
}
}
}
HTTPCookie::HTTPCookie(const std::string& name, const std::string& value):
_version(0),
_name(name),
_value(value),
_secure(false),
_maxAge(-1),
_httpOnly(false)
{
}
HTTPCookie::HTTPCookie(const HTTPCookie& cookie):
_version(cookie._version),
_name(cookie._name),
_value(cookie._value),
_comment(cookie._comment),
_domain(cookie._domain),
_path(cookie._path),
_secure(cookie._secure),
_maxAge(cookie._maxAge),
_httpOnly(cookie._httpOnly)
{
}
HTTPCookie::~HTTPCookie()
{
}
HTTPCookie& HTTPCookie::operator = (const HTTPCookie& cookie)
{
if (&cookie != this)
{
_version = cookie._version;
_name = cookie._name;
_value = cookie._value;
_comment = cookie._comment;
_domain = cookie._domain;
_path = cookie._path;
_secure = cookie._secure;
_maxAge = cookie._maxAge;
_httpOnly = cookie._httpOnly;
}
return *this;
}
void HTTPCookie::setVersion(int version)
{
_version = version;
}
void HTTPCookie::setName(const std::string& name)
{
_name = name;
}
void HTTPCookie::setValue(const std::string& value)
{
_value = value;
}
void HTTPCookie::setComment(const std::string& comment)
{
_comment = comment;
}
void HTTPCookie::setDomain(const std::string& domain)
{
_domain = domain;
}
void HTTPCookie::setPath(const std::string& path)
{
_path = path;
}
void HTTPCookie::setSecure(bool secure)
{
_secure = secure;
}
void HTTPCookie::setMaxAge(int maxAge)
{
_maxAge = maxAge;
}
void HTTPCookie::setHttpOnly(bool flag)
{
_httpOnly = flag;
}
std::string HTTPCookie::toString() const
{
std::string result;
result.reserve(256);
result.append(_name);
result.append("=");
if (_version == 0)
{
// Netscape cookie
result.append(_value);
if (!_domain.empty())
{
result.append("; domain=");
result.append(_domain);
}
if (!_path.empty())
{
result.append("; path=");
result.append(_path);
}
if (_maxAge >= 0)
{
Timestamp ts;
ts += _maxAge*Timestamp::resolution();
result.append("; expires=");
DateTimeFormatter::append(result, ts, DateTimeFormat::HTTP_FORMAT);
}
if (_secure)
{
result.append("; secure");
}
if (_httpOnly)
{
result.append("; HttpOnly");
}
}
else
{
// RFC 2109 cookie
result.append("\"");
result.append(_value);
result.append("\"");
if (!_comment.empty())
{
result.append("; Comment=\"");
result.append(_comment);
result.append("\"");
}
if (!_domain.empty())
{
result.append("; Domain=\"");
result.append(_domain);
result.append("\"");
}
if (!_path.empty())
{
result.append("; Path=\"");
result.append(_path);
result.append("\"");
}
if (_maxAge >= 0)
{
result.append("; Max-Age=\"");
NumberFormatter::append(result, _maxAge);
result.append("\"");
}
if (_secure)
{
result.append("; secure");
}
if (_httpOnly)
{
result.append("; HttpOnly");
}
result.append("; Version=\"1\"");
}
return result;
}
namespace
{
static const std::string ILLEGAL_CHARS("()[]/|\\',;");
}
std::string HTTPCookie::escape(const std::string& str)
{
std::string result;
Poco::URI::encode(str, ILLEGAL_CHARS, result);
return result;
}
std::string HTTPCookie::unescape(const std::string& str)
{
std::string result;
Poco::URI::decode(str, result);
return result;
}
} } // namespace Poco::Net

230
Net/src/HTTPCredentials.cpp Normal file
View File

@@ -0,0 +1,230 @@
//
// HTTPCredentials.cpp
//
// $Id: //poco/1.4/Net/src/HTTPCredentials.cpp#3 $
//
// Library: Net
// Package: HTTP
// Module: HTTPCredentials
//
// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru).
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPAuthenticationParams.h"
#include "Poco/Net/HTTPBasicCredentials.h"
#include "Poco/Net/HTTPCredentials.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/NetException.h"
#include "Poco/String.h"
#include "Poco/Ascii.h"
#include "Poco/URI.h"
using Poco::icompare;
namespace Poco {
namespace Net {
HTTPCredentials::HTTPCredentials()
{
}
HTTPCredentials::HTTPCredentials(const std::string& username, const std::string& password):
_digest(username, password)
{
}
HTTPCredentials::~HTTPCredentials()
{
}
void HTTPCredentials::fromUserInfo(const std::string& userInfo)
{
std::string username;
std::string password;
extractCredentials(userInfo, username, password);
setUsername(username);
setPassword(password);
// TODO: Reset digest state?
}
void HTTPCredentials::fromURI(const URI& uri)
{
std::string username;
std::string password;
extractCredentials(uri, username, password);
setUsername(username);
setPassword(password);
// TODO: Reset digest state?
}
void HTTPCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response)
{
for (HTTPResponse::ConstIterator iter = response.find("WWW-Authenticate"); iter != response.end(); ++iter)
{
if (isBasicCredentials(iter->second))
{
HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request);
return;
}
else if (isDigestCredentials(iter->second))
{
_digest.authenticate(request, HTTPAuthenticationParams(iter->second.substr(7)));
return;
}
}
}
void HTTPCredentials::updateAuthInfo(HTTPRequest& request)
{
if (request.has(HTTPRequest::AUTHORIZATION))
{
const std::string& authorization = request.get(HTTPRequest::AUTHORIZATION);
if (isBasicCredentials(authorization))
{
HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).authenticate(request);
}
else if (isDigestCredentials(authorization))
{
_digest.updateAuthInfo(request);
}
}
}
void HTTPCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response)
{
for (HTTPResponse::ConstIterator iter = response.find("Proxy-Authenticate"); iter != response.end(); ++iter)
{
if (isBasicCredentials(iter->second))
{
HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).proxyAuthenticate(request);
return;
}
else if (isDigestCredentials(iter->second))
{
_digest.proxyAuthenticate(request, HTTPAuthenticationParams(iter->second.substr(7)));
return;
}
}
}
void HTTPCredentials::updateProxyAuthInfo(HTTPRequest& request)
{
if (request.has(HTTPRequest::PROXY_AUTHORIZATION))
{
const std::string& authorization = request.get(HTTPRequest::PROXY_AUTHORIZATION);
if (isBasicCredentials(authorization))
{
HTTPBasicCredentials(_digest.getUsername(), _digest.getPassword()).proxyAuthenticate(request);
}
else if (isDigestCredentials(authorization))
{
_digest.updateProxyAuthInfo(request);
}
}
}
bool HTTPCredentials::isBasicCredentials(const std::string& header)
{
return icompare(header, 0, 5, "Basic") == 0 && (header.size() > 5 ? Poco::Ascii::isSpace(header[5]) : true);
}
bool HTTPCredentials::isDigestCredentials(const std::string& header)
{
return icompare(header, 0, 6, "Digest") == 0 && (header.size() > 6 ? Poco::Ascii::isSpace(header[6]) : true);
}
bool HTTPCredentials::hasBasicCredentials(const HTTPRequest& request)
{
return request.has(HTTPRequest::AUTHORIZATION) && isBasicCredentials(request.get(HTTPRequest::AUTHORIZATION));
}
bool HTTPCredentials::hasDigestCredentials(const HTTPRequest& request)
{
return request.has(HTTPRequest::AUTHORIZATION) && isDigestCredentials(request.get(HTTPRequest::AUTHORIZATION));
}
bool HTTPCredentials::hasProxyBasicCredentials(const HTTPRequest& request)
{
return request.has(HTTPRequest::PROXY_AUTHORIZATION) && isBasicCredentials(request.get(HTTPRequest::PROXY_AUTHORIZATION));
}
bool HTTPCredentials::hasProxyDigestCredentials(const HTTPRequest& request)
{
return request.has(HTTPRequest::PROXY_AUTHORIZATION) && isDigestCredentials(request.get(HTTPRequest::PROXY_AUTHORIZATION));
}
void HTTPCredentials::extractCredentials(const std::string& userInfo, std::string& username, std::string& password)
{
const std::string::size_type p = userInfo.find(':');
if (p != std::string::npos)
{
username.assign(userInfo, 0, p);
password.assign(userInfo, p + 1, std::string::npos);
}
else
{
username.assign(userInfo);
password.clear();
}
}
void HTTPCredentials::extractCredentials(const Poco::URI& uri, std::string& username, std::string& password)
{
if (!uri.getUserInfo().empty())
{
extractCredentials(uri.getUserInfo(), username, password);
}
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,321 @@
//
// HTTPDigestCredentials.cpp
//
// $Id: //poco/1.4/Net/src/HTTPDigestCredentials.cpp#5 $
//
// Library: Net
// Package: HTTP
// Module: HTTPDigestCredentials
//
// Copyright (c) 2011, Anton V. Yabchinskiy (arn at bestmx dot ru).
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/DateTime.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/Exception.h"
#include "Poco/MD5Engine.h"
#include "Poco/Net/HTTPDigestCredentials.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/NumberFormatter.h"
#include "Poco/StringTokenizer.h"
namespace
{
std::string digest(Poco::DigestEngine& engine,
const std::string& a,
const std::string& b,
const std::string& c = std::string(),
const std::string& d = std::string(),
const std::string& e = std::string(),
const std::string& f = std::string())
{
engine.reset();
engine.update(a);
engine.update(':');
engine.update(b);
if (!c.empty())
{
engine.update(':');
engine.update(c);
if (!d.empty())
{
engine.update(':');
engine.update(d);
engine.update(':');
engine.update(e);
engine.update(':');
engine.update(f);
}
}
return Poco::DigestEngine::digestToHex(engine.digest());
}
std::string formatNonceCounter(int counter)
{
return Poco::NumberFormatter::formatHex(counter, 8);
}
}
namespace Poco {
namespace Net {
const std::string HTTPDigestCredentials::SCHEME = "Digest";
const std::string HTTPDigestCredentials::DEFAULT_ALGORITHM("MD5");
const std::string HTTPDigestCredentials::DEFAULT_QOP("");
const std::string HTTPDigestCredentials::NONCE_PARAM("nonce");
const std::string HTTPDigestCredentials::REALM_PARAM("realm");
const std::string HTTPDigestCredentials::QOP_PARAM("qop");
const std::string HTTPDigestCredentials::ALGORITHM_PARAM("algorithm");
const std::string HTTPDigestCredentials::USERNAME_PARAM("username");
const std::string HTTPDigestCredentials::OPAQUE_PARAM("opaque");
const std::string HTTPDigestCredentials::URI_PARAM("uri");
const std::string HTTPDigestCredentials::RESPONSE_PARAM("response");
const std::string HTTPDigestCredentials::AUTH_PARAM("auth");
const std::string HTTPDigestCredentials::CNONCE_PARAM("cnonce");
const std::string HTTPDigestCredentials::NC_PARAM("nc");
int HTTPDigestCredentials::_nonceCounter(0);
Poco::FastMutex HTTPDigestCredentials::_nonceMutex;
HTTPDigestCredentials::HTTPDigestCredentials()
{
}
HTTPDigestCredentials::HTTPDigestCredentials(const std::string& username, const std::string& password):
_username(username),
_password(password)
{
}
HTTPDigestCredentials::~HTTPDigestCredentials()
{
}
void HTTPDigestCredentials::setUsername(const std::string& username)
{
_username = username;
}
void HTTPDigestCredentials::setPassword(const std::string& password)
{
_password = password;
}
void HTTPDigestCredentials::authenticate(HTTPRequest& request, const HTTPResponse& response)
{
authenticate(request, HTTPAuthenticationParams(response));
}
void HTTPDigestCredentials::authenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams)
{
createAuthParams(request, responseAuthParams);
request.setCredentials(SCHEME, _requestAuthParams.toString());
}
void HTTPDigestCredentials::updateAuthInfo(HTTPRequest& request)
{
updateAuthParams(request);
request.setCredentials(SCHEME, _requestAuthParams.toString());
}
void HTTPDigestCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPResponse& response)
{
proxyAuthenticate(request, HTTPAuthenticationParams(response));
}
void HTTPDigestCredentials::proxyAuthenticate(HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams)
{
createAuthParams(request, responseAuthParams);
request.setProxyCredentials(SCHEME, _requestAuthParams.toString());
}
void HTTPDigestCredentials::updateProxyAuthInfo(HTTPRequest& request)
{
updateAuthParams(request);
request.setProxyCredentials(SCHEME, _requestAuthParams.toString());
}
std::string HTTPDigestCredentials::createNonce()
{
Poco::FastMutex::ScopedLock lock(_nonceMutex);
MD5Engine md5;
Timestamp::TimeVal now = Timestamp().epochMicroseconds();
md5.update(&_nonceCounter, sizeof(_nonceCounter));
md5.update(&now, sizeof(now));
++_nonceCounter;
return DigestEngine::digestToHex(md5.digest());
}
void HTTPDigestCredentials::createAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& responseAuthParams)
{
// Not implemented: "domain" auth parameter and integrity protection.
if (!responseAuthParams.has(NONCE_PARAM) || !responseAuthParams.has(REALM_PARAM))
throw InvalidArgumentException("Invalid HTTP authentication parameters");
const std::string& algorithm = responseAuthParams.get(ALGORITHM_PARAM, DEFAULT_ALGORITHM);
if (icompare(algorithm, DEFAULT_ALGORITHM) != 0)
throw NotImplementedException("Unsupported digest algorithm", algorithm);
const std::string& nonce = responseAuthParams.get(NONCE_PARAM);
const std::string& qop = responseAuthParams.get(QOP_PARAM, DEFAULT_QOP);
const std::string& realm = responseAuthParams.getRealm();
_requestAuthParams.clear();
_requestAuthParams.set(USERNAME_PARAM, _username);
_requestAuthParams.set(NONCE_PARAM, nonce);
_requestAuthParams.setRealm(realm);
if (responseAuthParams.has(OPAQUE_PARAM))
{
_requestAuthParams.set(OPAQUE_PARAM, responseAuthParams.get(OPAQUE_PARAM));
}
if (qop.empty())
{
updateAuthParams(request);
}
else
{
Poco::StringTokenizer tok(qop, ",", Poco::StringTokenizer::TOK_TRIM);
bool qopSupported = false;
for (Poco::StringTokenizer::Iterator it = tok.begin(); it != tok.end(); ++it)
{
if (icompare(*it, AUTH_PARAM) == 0)
{
qopSupported = true;
_requestAuthParams.set(CNONCE_PARAM, createNonce());
_requestAuthParams.set(QOP_PARAM, *it);
updateAuthParams(request);
break;
}
}
if (!qopSupported)
throw NotImplementedException("Unsupported QoP requested", qop);
}
}
void HTTPDigestCredentials::updateAuthParams(const HTTPRequest& request)
{
MD5Engine engine;
const std::string& qop = _requestAuthParams.get(QOP_PARAM, DEFAULT_QOP);
const std::string& realm = _requestAuthParams.getRealm();
const std::string& nonce = _requestAuthParams.get(NONCE_PARAM);
_requestAuthParams.set(URI_PARAM, request.getURI());
if (qop.empty())
{
const std::string ha1 = digest(engine, _username, realm, _password);
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
_requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, ha2));
}
else if (icompare(qop, AUTH_PARAM) == 0)
{
const std::string& cnonce = _requestAuthParams.get(CNONCE_PARAM);
const std::string ha1 = digest(engine, _username, realm, _password);
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
const std::string nc = formatNonceCounter(updateNonceCounter(nonce));
_requestAuthParams.set(NC_PARAM, nc);
_requestAuthParams.set(RESPONSE_PARAM, digest(engine, ha1, nonce, nc, cnonce, qop, ha2));
}
}
bool HTTPDigestCredentials::verifyAuthInfo(const HTTPRequest& request) const
{
HTTPAuthenticationParams params(request);
return verifyAuthParams(request, params);
}
bool HTTPDigestCredentials::verifyAuthParams(const HTTPRequest& request, const HTTPAuthenticationParams& params) const
{
const std::string& nonce = params.get(NONCE_PARAM);
const std::string& realm = params.getRealm();
const std::string& qop = params.get(QOP_PARAM, DEFAULT_QOP);
std::string response;
MD5Engine engine;
if (qop.empty())
{
const std::string ha1 = digest(engine, _username, realm, _password);
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
response = digest(engine, ha1, nonce, ha2);
}
else if (icompare(qop, AUTH_PARAM) == 0)
{
const std::string& cnonce = params.get(CNONCE_PARAM);
const std::string& nc = params.get(NC_PARAM);
const std::string ha1 = digest(engine, _username, realm, _password);
const std::string ha2 = digest(engine, request.getMethod(), request.getURI());
response = digest(engine, ha1, nonce, nc, cnonce, qop, ha2);
}
return response == params.get(RESPONSE_PARAM);
}
int HTTPDigestCredentials::updateNonceCounter(const std::string& nonce)
{
NonceCounterMap::iterator iter = _nc.find(nonce);
if (iter == _nc.end())
{
iter = _nc.insert(NonceCounterMap::value_type(nonce, 0)).first;
}
iter->second++;
return iter->second;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,189 @@
//
// HTTPFixedLengthStream.cpp
//
// $Id: //poco/1.4/Net/src/HTTPFixedLengthStream.cpp#1 $
//
// Library: Net
// Package: HTTP
// Module: HTTPFixedLengthStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPFixedLengthStream.h"
#include "Poco/Net/HTTPSession.h"
using Poco::BufferedStreamBuf;
namespace Poco {
namespace Net {
//
// HTTPFixedLengthStreamBuf
//
HTTPFixedLengthStreamBuf::HTTPFixedLengthStreamBuf(HTTPSession& session, std::streamsize length, openmode mode):
HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode),
_session(session),
_length(length),
_count(0)
{
}
HTTPFixedLengthStreamBuf::~HTTPFixedLengthStreamBuf()
{
}
int HTTPFixedLengthStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
int n = 0;
if (_count < _length)
{
if (_count + length > _length)
length = _length - _count;
n = _session.read(buffer, length);
if (n > 0) _count += n;
}
return n;
}
int HTTPFixedLengthStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
int n = 0;
if (_count < _length)
{
if (_count + length > _length)
length = _length - _count;
n = _session.write(buffer, length);
if (n > 0) _count += n;
}
return n;
}
//
// HTTPFixedLengthIOS
//
HTTPFixedLengthIOS::HTTPFixedLengthIOS(HTTPSession& session, std::streamsize length, HTTPFixedLengthStreamBuf::openmode mode):
_buf(session, length, mode)
{
poco_ios_init(&_buf);
}
HTTPFixedLengthIOS::~HTTPFixedLengthIOS()
{
try
{
_buf.sync();
}
catch (...)
{
}
}
HTTPFixedLengthStreamBuf* HTTPFixedLengthIOS::rdbuf()
{
return &_buf;
}
//
// HTTPFixedLengthInputStream
//
Poco::MemoryPool HTTPFixedLengthInputStream::_pool(sizeof(HTTPFixedLengthInputStream));
HTTPFixedLengthInputStream::HTTPFixedLengthInputStream(HTTPSession& session, std::streamsize length):
HTTPFixedLengthIOS(session, length, std::ios::in),
std::istream(&_buf)
{
}
HTTPFixedLengthInputStream::~HTTPFixedLengthInputStream()
{
}
void* HTTPFixedLengthInputStream::operator new(std::size_t size)
{
return _pool.get();
}
void HTTPFixedLengthInputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
//
// HTTPFixedLengthOutputStream
//
Poco::MemoryPool HTTPFixedLengthOutputStream::_pool(sizeof(HTTPFixedLengthOutputStream));
HTTPFixedLengthOutputStream::HTTPFixedLengthOutputStream(HTTPSession& session, std::streamsize length):
HTTPFixedLengthIOS(session, length, std::ios::out),
std::ostream(&_buf)
{
}
HTTPFixedLengthOutputStream::~HTTPFixedLengthOutputStream()
{
}
void* HTTPFixedLengthOutputStream::operator new(std::size_t size)
{
return _pool.get();
}
void HTTPFixedLengthOutputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,186 @@
//
// HTTPHeaderStream.cpp
//
// $Id: //poco/1.4/Net/src/HTTPHeaderStream.cpp#1 $
//
// Library: Net
// Package: HTTP
// Module: HTTPHeaderStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPHeaderStream.h"
#include "Poco/Net/HTTPSession.h"
namespace Poco {
namespace Net {
//
// HTTPHeaderStreamBuf
//
HTTPHeaderStreamBuf::HTTPHeaderStreamBuf(HTTPSession& session, openmode mode):
HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode),
_session(session),
_end(false)
{
}
HTTPHeaderStreamBuf::~HTTPHeaderStreamBuf()
{
}
int HTTPHeaderStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
// read line-by-line; an empty line denotes the end of the headers.
static const int eof = std::char_traits<char>::eof();
if (_end) return 0;
int n = 0;
int ch = _session.get();
while (ch != eof && ch != '\n' && n < length - 1)
{
*buffer++ = (char) ch; ++n;
ch = _session.get();
}
if (ch != eof)
{
*buffer++ = (char) ch; ++n;
if (n == 2) _end = true;
}
return n;
}
int HTTPHeaderStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
return _session.write(buffer, length);
}
//
// HTTPHeaderIOS
//
HTTPHeaderIOS::HTTPHeaderIOS(HTTPSession& session, HTTPHeaderStreamBuf::openmode mode):
_buf(session, mode)
{
poco_ios_init(&_buf);
}
HTTPHeaderIOS::~HTTPHeaderIOS()
{
try
{
_buf.sync();
}
catch (...)
{
}
}
HTTPHeaderStreamBuf* HTTPHeaderIOS::rdbuf()
{
return &_buf;
}
//
// HTTPHeaderInputStream
//
Poco::MemoryPool HTTPHeaderInputStream::_pool(sizeof(HTTPHeaderInputStream));
HTTPHeaderInputStream::HTTPHeaderInputStream(HTTPSession& session):
HTTPHeaderIOS(session, std::ios::in),
std::istream(&_buf)
{
}
HTTPHeaderInputStream::~HTTPHeaderInputStream()
{
}
void* HTTPHeaderInputStream::operator new(std::size_t size)
{
return _pool.get();
}
void HTTPHeaderInputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
//
// HTTPHeaderOutputStream
//
Poco::MemoryPool HTTPHeaderOutputStream::_pool(sizeof(HTTPHeaderOutputStream));
HTTPHeaderOutputStream::HTTPHeaderOutputStream(HTTPSession& session):
HTTPHeaderIOS(session, std::ios::out),
std::ostream(&_buf)
{
}
HTTPHeaderOutputStream::~HTTPHeaderOutputStream()
{
}
void* HTTPHeaderOutputStream::operator new(std::size_t size)
{
return _pool.get();
}
void HTTPHeaderOutputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
} } // namespace Poco::Net

85
Net/src/HTTPIOStream.cpp Normal file
View File

@@ -0,0 +1,85 @@
//
// HTTPIOStream.cpp
//
// $Id: //poco/Main/template/class.cpp#5 $
//
// Library: Net
// Package: HTTP
// Module: HTTPIOStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPIOStream.h"
#include "Poco/Net/HTTPClientSession.h"
using Poco::UnbufferedStreamBuf;
namespace Poco {
namespace Net {
HTTPResponseStreamBuf::HTTPResponseStreamBuf(std::istream& istr):
_istr(istr)
{
}
HTTPResponseStreamBuf::~HTTPResponseStreamBuf()
{
}
HTTPResponseIOS::HTTPResponseIOS(std::istream& istr):
_buf(istr)
{
poco_ios_init(&_buf);
}
HTTPResponseIOS::~HTTPResponseIOS()
{
}
HTTPResponseStream::HTTPResponseStream(std::istream& istr, HTTPClientSession* pSession):
HTTPResponseIOS(istr),
std::istream(&_buf),
_pSession(pSession)
{
}
HTTPResponseStream::~HTTPResponseStream()
{
delete _pSession;
}
} } // namespace Poco::Net

206
Net/src/HTTPMessage.cpp Normal file
View File

@@ -0,0 +1,206 @@
//
// HTTPMessage.cpp
//
// $Id: //poco/1.4/Net/src/HTTPMessage.cpp#4 $
//
// Library: Net
// Package: HTTP
// Module: HTTPMessage
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPMessage.h"
#include "Poco/Net/MediaType.h"
#include "Poco/NumberFormatter.h"
#include "Poco/NumberParser.h"
#include "Poco/String.h"
using Poco::NumberFormatter;
using Poco::NumberParser;
using Poco::icompare;
namespace Poco {
namespace Net {
const std::string HTTPMessage::HTTP_1_0 = "HTTP/1.0";
const std::string HTTPMessage::HTTP_1_1 = "HTTP/1.1";
const std::string HTTPMessage::IDENTITY_TRANSFER_ENCODING = "identity";
const std::string HTTPMessage::CHUNKED_TRANSFER_ENCODING = "chunked";
const int HTTPMessage::UNKNOWN_CONTENT_LENGTH = -1;
const std::string HTTPMessage::UNKNOWN_CONTENT_TYPE;
const std::string HTTPMessage::CONTENT_LENGTH = "Content-Length";
const std::string HTTPMessage::CONTENT_TYPE = "Content-Type";
const std::string HTTPMessage::TRANSFER_ENCODING = "Transfer-Encoding";
const std::string HTTPMessage::CONNECTION = "Connection";
const std::string HTTPMessage::CONNECTION_KEEP_ALIVE = "Keep-Alive";
const std::string HTTPMessage::CONNECTION_CLOSE = "Close";
const std::string HTTPMessage::EMPTY;
HTTPMessage::HTTPMessage():
_version(HTTP_1_0)
{
}
HTTPMessage::HTTPMessage(const std::string& version):
_version(version)
{
}
HTTPMessage::~HTTPMessage()
{
}
void HTTPMessage::setVersion(const std::string& version)
{
_version = version;
}
void HTTPMessage::setContentLength(std::streamsize length)
{
if (length != UNKNOWN_CONTENT_LENGTH)
set(CONTENT_LENGTH, NumberFormatter::format(length));
else
erase(CONTENT_LENGTH);
}
std::streamsize HTTPMessage::getContentLength() const
{
const std::string& contentLength = get(CONTENT_LENGTH, EMPTY);
if (!contentLength.empty())
{
if (sizeof(std::streamsize) == sizeof(Poco::Int64))
return static_cast<std::streamsize>(NumberParser::parse64(contentLength));
else
return static_cast<std::streamsize>(NumberParser::parse(contentLength));
}
else return UNKNOWN_CONTENT_LENGTH;
}
#if defined(POCO_HAVE_INT64)
void HTTPMessage::setContentLength64(Poco::Int64 length)
{
if (length != UNKNOWN_CONTENT_LENGTH)
set(CONTENT_LENGTH, NumberFormatter::format(length));
else
erase(CONTENT_LENGTH);
}
Poco::Int64 HTTPMessage::getContentLength64() const
{
const std::string& contentLength = get(CONTENT_LENGTH, EMPTY);
if (!contentLength.empty())
{
return NumberParser::parse64(contentLength);
}
else return UNKNOWN_CONTENT_LENGTH;
}
#endif // defined(POCO_HAVE_INT64)
void HTTPMessage::setTransferEncoding(const std::string& transferEncoding)
{
if (icompare(transferEncoding, IDENTITY_TRANSFER_ENCODING) == 0)
erase(TRANSFER_ENCODING);
else
set(TRANSFER_ENCODING, transferEncoding);
}
const std::string& HTTPMessage::getTransferEncoding() const
{
return get(TRANSFER_ENCODING, IDENTITY_TRANSFER_ENCODING);
}
void HTTPMessage::setChunkedTransferEncoding(bool flag)
{
if (flag)
setTransferEncoding(CHUNKED_TRANSFER_ENCODING);
else
setTransferEncoding(IDENTITY_TRANSFER_ENCODING);
}
bool HTTPMessage::getChunkedTransferEncoding() const
{
return icompare(getTransferEncoding(), CHUNKED_TRANSFER_ENCODING) == 0;
}
void HTTPMessage::setContentType(const std::string& mediaType)
{
if (mediaType.empty())
erase(CONTENT_TYPE);
else
set(CONTENT_TYPE, mediaType);
}
void HTTPMessage::setContentType(const MediaType& mediaType)
{
setContentType(mediaType.toString());
}
const std::string& HTTPMessage::getContentType() const
{
return get(CONTENT_TYPE, UNKNOWN_CONTENT_TYPE);
}
void HTTPMessage::setKeepAlive(bool keepAlive)
{
if (keepAlive)
set(CONNECTION, CONNECTION_KEEP_ALIVE);
else
set(CONNECTION, CONNECTION_CLOSE);
}
bool HTTPMessage::getKeepAlive() const
{
const std::string& connection = get(CONNECTION, EMPTY);
if (!connection.empty())
return icompare(connection, CONNECTION_CLOSE) != 0;
else
return getVersion() == HTTP_1_1;
}
} } // namespace Poco::Net

268
Net/src/HTTPRequest.cpp Normal file
View File

@@ -0,0 +1,268 @@
//
// HTTPRequest.cpp
//
// $Id: //poco/1.4/Net/src/HTTPRequest.cpp#3 $
//
// Library: Net
// Package: HTTP
// Module: HTTPRequest
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/NameValueCollection.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Ascii.h"
#include "Poco/String.h"
using Poco::NumberFormatter;
namespace Poco {
namespace Net {
const std::string HTTPRequest::HTTP_GET = "GET";
const std::string HTTPRequest::HTTP_HEAD = "HEAD";
const std::string HTTPRequest::HTTP_PUT = "PUT";
const std::string HTTPRequest::HTTP_POST = "POST";
const std::string HTTPRequest::HTTP_OPTIONS = "OPTIONS";
const std::string HTTPRequest::HTTP_DELETE = "DELETE";
const std::string HTTPRequest::HTTP_TRACE = "TRACE";
const std::string HTTPRequest::HTTP_CONNECT = "CONNECT";
const std::string HTTPRequest::HOST = "Host";
const std::string HTTPRequest::COOKIE = "Cookie";
const std::string HTTPRequest::AUTHORIZATION = "Authorization";
const std::string HTTPRequest::PROXY_AUTHORIZATION = "Proxy-Authorization";
HTTPRequest::HTTPRequest():
_method(HTTP_GET),
_uri("/")
{
}
HTTPRequest::HTTPRequest(const std::string& version):
HTTPMessage(version),
_method(HTTP_GET),
_uri("/")
{
}
HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri):
_method(method),
_uri(uri)
{
}
HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri, const std::string& version):
HTTPMessage(version),
_method(method),
_uri(uri)
{
}
HTTPRequest::~HTTPRequest()
{
}
void HTTPRequest::setMethod(const std::string& method)
{
_method = method;
}
void HTTPRequest::setURI(const std::string& uri)
{
_uri = uri;
}
void HTTPRequest::setHost(const std::string& host)
{
set(HOST, host);
}
void HTTPRequest::setHost(const std::string& host, Poco::UInt16 port)
{
std::string value(host);
if (port != 80 && port != 443)
{
value.append(":");
NumberFormatter::append(value, port);
}
setHost(value);
}
const std::string& HTTPRequest::getHost() const
{
return get(HOST);
}
void HTTPRequest::setCookies(const NameValueCollection& cookies)
{
std::string cookie;
cookie.reserve(64);
for (NameValueCollection::ConstIterator it = cookies.begin(); it != cookies.end(); ++it)
{
if (it != cookies.begin())
cookie.append("; ");
cookie.append(it->first);
cookie.append("=");
cookie.append(it->second);
}
add(COOKIE, cookie);
}
void HTTPRequest::getCookies(NameValueCollection& cookies) const
{
NameValueCollection::ConstIterator it = find(COOKIE);
while (it != end() && Poco::icompare(it->first, COOKIE) == 0)
{
splitParameters(it->second.begin(), it->second.end(), cookies);
++it;
}
}
bool HTTPRequest::hasCredentials() const
{
return has(AUTHORIZATION);
}
void HTTPRequest::getCredentials(std::string& scheme, std::string& authInfo) const
{
getCredentials(AUTHORIZATION, scheme, authInfo);
}
void HTTPRequest::setCredentials(const std::string& scheme, const std::string& authInfo)
{
setCredentials(AUTHORIZATION, scheme, authInfo);
}
bool HTTPRequest::hasProxyCredentials() const
{
return has(PROXY_AUTHORIZATION);
}
void HTTPRequest::getProxyCredentials(std::string& scheme, std::string& authInfo) const
{
getCredentials(PROXY_AUTHORIZATION, scheme, authInfo);
}
void HTTPRequest::setProxyCredentials(const std::string& scheme, const std::string& authInfo)
{
setCredentials(PROXY_AUTHORIZATION, scheme, authInfo);
}
void HTTPRequest::write(std::ostream& ostr) const
{
ostr << _method << " " << _uri << " " << getVersion() << "\r\n";
HTTPMessage::write(ostr);
ostr << "\r\n";
}
void HTTPRequest::read(std::istream& istr)
{
static const int eof = std::char_traits<char>::eof();
std::string method;
std::string uri;
std::string version;
method.reserve(16);
uri.reserve(64);
version.reserve(16);
int ch = istr.get();
if (ch == eof) throw NoMessageException();
while (Poco::Ascii::isSpace(ch)) ch = istr.get();
if (ch == eof) throw MessageException("No HTTP request header");
while (!Poco::Ascii::isSpace(ch) && ch != eof && method.length() < MAX_METHOD_LENGTH) { method += (char) ch; ch = istr.get(); }
if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP request method invalid or too long");
while (Poco::Ascii::isSpace(ch)) ch = istr.get();
while (!Poco::Ascii::isSpace(ch) && ch != eof && uri.length() < MAX_URI_LENGTH) { uri += (char) ch; ch = istr.get(); }
if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP request URI invalid or too long");
while (Poco::Ascii::isSpace(ch)) ch = istr.get();
while (!Poco::Ascii::isSpace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); }
if (!Poco::Ascii::isSpace(ch)) throw MessageException("Invalid HTTP version string");
while (ch != '\n' && ch != eof) { ch = istr.get(); }
HTTPMessage::read(istr);
ch = istr.get();
while (ch != '\n' && ch != eof) { ch = istr.get(); }
setMethod(method);
setURI(uri);
setVersion(version);
}
void HTTPRequest::getCredentials(const std::string& header, std::string& scheme, std::string& authInfo) const
{
scheme.clear();
authInfo.clear();
if (has(header))
{
const std::string& auth = get(header);
std::string::const_iterator it = auth.begin();
std::string::const_iterator end = auth.end();
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
while (it != end && !Poco::Ascii::isSpace(*it)) scheme += *it++;
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
while (it != end) authInfo += *it++;
}
else throw NotAuthenticatedException();
}
void HTTPRequest::setCredentials(const std::string& header, const std::string& scheme, const std::string& authInfo)
{
std::string auth(scheme);
auth.append(" ");
auth.append(authInfo);
set(header, auth);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,54 @@
//
// HTTPRequestHandler.cpp
//
// $Id: //poco/1.4/Net/src/HTTPRequestHandler.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPRequestHandler
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPRequestHandler.h"
namespace Poco {
namespace Net {
HTTPRequestHandler::HTTPRequestHandler()
{
}
HTTPRequestHandler::~HTTPRequestHandler()
{
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,54 @@
//
// HTTPRequestHandlerFactory.cpp
//
// $Id: //poco/1.4/Net/src/HTTPRequestHandlerFactory.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPRequestHandlerFactory
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPRequestHandlerFactory.h"
namespace Poco {
namespace Net {
HTTPRequestHandlerFactory::HTTPRequestHandlerFactory()
{
}
HTTPRequestHandlerFactory::~HTTPRequestHandlerFactory()
{
}
} } // namespace Poco::Net

343
Net/src/HTTPResponse.cpp Normal file
View File

@@ -0,0 +1,343 @@
//
// HTTPResponse.cpp
//
// $Id: //poco/1.4/Net/src/HTTPResponse.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPResponse
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/NetException.h"
#include "Poco/NumberFormatter.h"
#include "Poco/NumberParser.h"
#include "Poco/DateTime.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/DateTimeParser.h"
#include "Poco/Ascii.h"
#include "Poco/String.h"
using Poco::DateTime;
using Poco::NumberFormatter;
using Poco::NumberParser;
using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
using Poco::DateTimeParser;
namespace Poco {
namespace Net {
const std::string HTTPResponse::HTTP_REASON_CONTINUE = "Continue";
const std::string HTTPResponse::HTTP_REASON_SWITCHING_PROTOCOLS = "Switching Protocols";
const std::string HTTPResponse::HTTP_REASON_OK = "OK";
const std::string HTTPResponse::HTTP_REASON_CREATED = "Created";
const std::string HTTPResponse::HTTP_REASON_ACCEPTED = "Accepted";
const std::string HTTPResponse::HTTP_REASON_NONAUTHORITATIVE = "Non-Authoritative Information";
const std::string HTTPResponse::HTTP_REASON_NO_CONTENT = "No Content";
const std::string HTTPResponse::HTTP_REASON_RESET_CONTENT = "Reset Content";
const std::string HTTPResponse::HTTP_REASON_PARTIAL_CONTENT = "Partial Content";
const std::string HTTPResponse::HTTP_REASON_MULTIPLE_CHOICES = "Multiple Choices";
const std::string HTTPResponse::HTTP_REASON_MOVED_PERMANENTLY = "Moved Permanently";
const std::string HTTPResponse::HTTP_REASON_FOUND = "Found";
const std::string HTTPResponse::HTTP_REASON_SEE_OTHER = "See Other";
const std::string HTTPResponse::HTTP_REASON_NOT_MODIFIED = "Not Modified";
const std::string HTTPResponse::HTTP_REASON_USEPROXY = "Use Proxy";
const std::string HTTPResponse::HTTP_REASON_TEMPORARY_REDIRECT = "Temporary Redirect";
const std::string HTTPResponse::HTTP_REASON_BAD_REQUEST = "Bad Request";
const std::string HTTPResponse::HTTP_REASON_UNAUTHORIZED = "Unauthorized";
const std::string HTTPResponse::HTTP_REASON_PAYMENT_REQUIRED = "Payment Required";
const std::string HTTPResponse::HTTP_REASON_FORBIDDEN = "Forbidden";
const std::string HTTPResponse::HTTP_REASON_NOT_FOUND = "Not Found";
const std::string HTTPResponse::HTTP_REASON_METHOD_NOT_ALLOWED = "Method Not Allowed";
const std::string HTTPResponse::HTTP_REASON_NOT_ACCEPTABLE = "Not Acceptable";
const std::string HTTPResponse::HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED = "Proxy Authentication Required";
const std::string HTTPResponse::HTTP_REASON_REQUEST_TIMEOUT = "Request Time-out";
const std::string HTTPResponse::HTTP_REASON_CONFLICT = "Conflict";
const std::string HTTPResponse::HTTP_REASON_GONE = "Gone";
const std::string HTTPResponse::HTTP_REASON_LENGTH_REQUIRED = "Length Required";
const std::string HTTPResponse::HTTP_REASON_PRECONDITION_FAILED = "Precondition Failed";
const std::string HTTPResponse::HTTP_REASON_REQUESTENTITYTOOLARGE = "Request Entity Too Large";
const std::string HTTPResponse::HTTP_REASON_REQUESTURITOOLONG = "Request-URI Too Large";
const std::string HTTPResponse::HTTP_REASON_UNSUPPORTEDMEDIATYPE = "Unsupported Media Type";
const std::string HTTPResponse::HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE = "Requested Range Not Satisfiable";
const std::string HTTPResponse::HTTP_REASON_EXPECTATION_FAILED = "Expectation Failed";
const std::string HTTPResponse::HTTP_REASON_INTERNAL_SERVER_ERROR = "Internal Server Error";
const std::string HTTPResponse::HTTP_REASON_NOT_IMPLEMENTED = "Not Implemented";
const std::string HTTPResponse::HTTP_REASON_BAD_GATEWAY = "Bad Gateway";
const std::string HTTPResponse::HTTP_REASON_SERVICE_UNAVAILABLE = "Service Unavailable";
const std::string HTTPResponse::HTTP_REASON_GATEWAY_TIMEOUT = "Gateway Time-out";
const std::string HTTPResponse::HTTP_REASON_VERSION_NOT_SUPPORTED = "HTTP Version not supported";
const std::string HTTPResponse::HTTP_REASON_UNKNOWN = "???";
const std::string HTTPResponse::DATE = "Date";
const std::string HTTPResponse::SET_COOKIE = "Set-Cookie";
HTTPResponse::HTTPResponse():
_status(HTTP_OK),
_reason(getReasonForStatus(HTTP_OK))
{
}
HTTPResponse::HTTPResponse(HTTPStatus status, const std::string& reason):
_status(status),
_reason(reason)
{
}
HTTPResponse::HTTPResponse(const std::string& version, HTTPStatus status, const std::string& reason):
HTTPMessage(version),
_status(status),
_reason(reason)
{
}
HTTPResponse::HTTPResponse(HTTPStatus status):
_status(status),
_reason(getReasonForStatus(status))
{
}
HTTPResponse::HTTPResponse(const std::string& version, HTTPStatus status):
HTTPMessage(version),
_status(status),
_reason(getReasonForStatus(status))
{
}
HTTPResponse::~HTTPResponse()
{
}
void HTTPResponse::setStatus(HTTPStatus status)
{
_status = status;
}
void HTTPResponse::setStatus(const std::string& status)
{
setStatus((HTTPStatus) NumberParser::parse(status));
}
void HTTPResponse::setReason(const std::string& reason)
{
_reason = reason;
}
void HTTPResponse::setStatusAndReason(HTTPStatus status, const std::string& reason)
{
_status = status;
_reason = reason;
}
void HTTPResponse::setStatusAndReason(HTTPStatus status)
{
setStatusAndReason(status, getReasonForStatus(status));
}
void HTTPResponse::setDate(const Poco::Timestamp& dateTime)
{
set(DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT));
}
Poco::Timestamp HTTPResponse::getDate() const
{
const std::string& dateTime = get(DATE);
int tzd;
return DateTimeParser::parse(dateTime, tzd).timestamp();
}
void HTTPResponse::addCookie(const HTTPCookie& cookie)
{
add(SET_COOKIE, cookie.toString());
}
void HTTPResponse::getCookies(std::vector<HTTPCookie>& cookies) const
{
cookies.clear();
NameValueCollection::ConstIterator it = find(SET_COOKIE);
while (it != end() && Poco::icompare(it->first, SET_COOKIE) == 0)
{
NameValueCollection nvc;
splitParameters(it->second.begin(), it->second.end(), nvc);
cookies.push_back(HTTPCookie(nvc));
++it;
}
}
void HTTPResponse::write(std::ostream& ostr) const
{
ostr << getVersion() << " " << static_cast<int>(_status) << " " << _reason << "\r\n";
HTTPMessage::write(ostr);
ostr << "\r\n";
}
void HTTPResponse::read(std::istream& istr)
{
static const int eof = std::char_traits<char>::eof();
std::string version;
std::string status;
std::string reason;
int ch = istr.get();
if (ch == eof) throw NoMessageException();
while (Poco::Ascii::isSpace(ch)) ch = istr.get();
if (ch == eof) throw MessageException("No HTTP response header");
while (!Poco::Ascii::isSpace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); }
if (!Poco::Ascii::isSpace(ch)) throw MessageException("Invalid HTTP version string");
while (Poco::Ascii::isSpace(ch)) ch = istr.get();
while (!Poco::Ascii::isSpace(ch) && ch != eof && status.length() < MAX_STATUS_LENGTH) { status += (char) ch; ch = istr.get(); }
if (!Poco::Ascii::isSpace(ch)) throw MessageException("Invalid HTTP status code");
while (Poco::Ascii::isSpace(ch)) ch = istr.get();
while (ch != '\r' && ch != '\n' && ch != eof && reason.length() < MAX_REASON_LENGTH) { reason += (char) ch; ch = istr.get(); }
if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP reason string too long");
if (ch == '\r') ch = istr.get();
HTTPMessage::read(istr);
ch = istr.get();
while (ch != '\n' && ch != eof) { ch = istr.get(); }
setVersion(version);
setStatus(status);
setReason(reason);
}
const std::string& HTTPResponse::getReasonForStatus(HTTPStatus status)
{
switch (status)
{
case HTTP_CONTINUE:
return HTTP_REASON_CONTINUE;
case HTTP_SWITCHING_PROTOCOLS:
return HTTP_REASON_SWITCHING_PROTOCOLS;
case HTTP_OK:
return HTTP_REASON_OK;
case HTTP_CREATED:
return HTTP_REASON_CREATED;
case HTTP_ACCEPTED:
return HTTP_REASON_ACCEPTED;
case HTTP_NONAUTHORITATIVE:
return HTTP_REASON_NONAUTHORITATIVE;
case HTTP_NO_CONTENT:
return HTTP_REASON_NO_CONTENT;
case HTTP_RESET_CONTENT:
return HTTP_REASON_RESET_CONTENT;
case HTTP_PARTIAL_CONTENT:
return HTTP_REASON_PARTIAL_CONTENT;
case HTTP_MULTIPLE_CHOICES:
return HTTP_REASON_MULTIPLE_CHOICES;
case HTTP_MOVED_PERMANENTLY:
return HTTP_REASON_MOVED_PERMANENTLY;
case HTTP_FOUND:
return HTTP_REASON_FOUND;
case HTTP_SEE_OTHER:
return HTTP_REASON_SEE_OTHER;
case HTTP_NOT_MODIFIED:
return HTTP_REASON_NOT_MODIFIED;
case HTTP_USEPROXY:
return HTTP_REASON_USEPROXY;
case HTTP_TEMPORARY_REDIRECT:
return HTTP_REASON_TEMPORARY_REDIRECT;
case HTTP_BAD_REQUEST:
return HTTP_REASON_BAD_REQUEST;
case HTTP_UNAUTHORIZED:
return HTTP_REASON_UNAUTHORIZED;
case HTTP_PAYMENT_REQUIRED:
return HTTP_REASON_PAYMENT_REQUIRED;
case HTTP_FORBIDDEN:
return HTTP_REASON_FORBIDDEN;
case HTTP_NOT_FOUND:
return HTTP_REASON_NOT_FOUND;
case HTTP_METHOD_NOT_ALLOWED:
return HTTP_REASON_METHOD_NOT_ALLOWED;
case HTTP_NOT_ACCEPTABLE:
return HTTP_REASON_NOT_ACCEPTABLE;
case HTTP_PROXY_AUTHENTICATION_REQUIRED:
return HTTP_REASON_PROXY_AUTHENTICATION_REQUIRED;
case HTTP_REQUEST_TIMEOUT:
return HTTP_REASON_REQUEST_TIMEOUT;
case HTTP_CONFLICT:
return HTTP_REASON_CONFLICT;
case HTTP_GONE:
return HTTP_REASON_GONE;
case HTTP_LENGTH_REQUIRED:
return HTTP_REASON_LENGTH_REQUIRED;
case HTTP_PRECONDITION_FAILED:
return HTTP_REASON_PRECONDITION_FAILED;
case HTTP_REQUESTENTITYTOOLARGE:
return HTTP_REASON_REQUESTENTITYTOOLARGE;
case HTTP_REQUESTURITOOLONG:
return HTTP_REASON_REQUESTURITOOLONG;
case HTTP_UNSUPPORTEDMEDIATYPE:
return HTTP_REASON_UNSUPPORTEDMEDIATYPE;
case HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
return HTTP_REASON_REQUESTED_RANGE_NOT_SATISFIABLE;
case HTTP_EXPECTATION_FAILED:
return HTTP_REASON_EXPECTATION_FAILED;
case HTTP_INTERNAL_SERVER_ERROR:
return HTTP_REASON_INTERNAL_SERVER_ERROR;
case HTTP_NOT_IMPLEMENTED:
return HTTP_REASON_NOT_IMPLEMENTED;
case HTTP_BAD_GATEWAY:
return HTTP_REASON_BAD_GATEWAY;
case HTTP_SERVICE_UNAVAILABLE:
return HTTP_REASON_SERVICE_UNAVAILABLE;
case HTTP_GATEWAY_TIMEOUT:
return HTTP_REASON_GATEWAY_TIMEOUT;
case HTTP_VERSION_NOT_SUPPORTED:
return HTTP_REASON_VERSION_NOT_SUPPORTED;
default:
return HTTP_REASON_UNKNOWN;
}
}
} } // namespace Poco::Net

62
Net/src/HTTPServer.cpp Normal file
View File

@@ -0,0 +1,62 @@
//
// HTTPServer.cpp
//
// $Id: //poco/1.4/Net/src/HTTPServer.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServer
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPServerConnectionFactory.h"
namespace Poco {
namespace Net {
HTTPServer::HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, const ServerSocket& socket, HTTPServerParams::Ptr pParams):
TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), socket, pParams)
{
}
HTTPServer::HTTPServer(HTTPRequestHandlerFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, HTTPServerParams::Ptr pParams):
TCPServer(new HTTPServerConnectionFactory(pParams, pFactory), threadPool, socket, pParams)
{
}
HTTPServer::~HTTPServer()
{
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,127 @@
//
// HTTPServerConnection.cpp
//
// $Id: //poco/1.4/Net/src/HTTPServerConnection.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerConnection
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPServerConnection.h"
#include "Poco/Net/HTTPServerSession.h"
#include "Poco/Net/HTTPServerRequestImpl.h"
#include "Poco/Net/HTTPServerResponseImpl.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/NetException.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Timestamp.h"
#include <memory>
namespace Poco {
namespace Net {
HTTPServerConnection::HTTPServerConnection(const StreamSocket& socket, HTTPServerParams::Ptr pParams, HTTPRequestHandlerFactory::Ptr pFactory):
TCPServerConnection(socket),
_pParams(pParams),
_pFactory(pFactory)
{
poco_check_ptr (pFactory);
}
HTTPServerConnection::~HTTPServerConnection()
{
}
void HTTPServerConnection::run()
{
std::string server = _pParams->getSoftwareVersion();
HTTPServerSession session(socket(), _pParams);
while (session.hasMoreRequests())
{
try
{
HTTPServerResponseImpl response(session);
HTTPServerRequestImpl request(response, session, _pParams);
Poco::Timestamp now;
response.setDate(now);
response.setVersion(request.getVersion());
response.setKeepAlive(_pParams->getKeepAlive() && request.getKeepAlive() && session.canKeepAlive());
if (!server.empty())
response.set("Server", server);
try
{
std::auto_ptr<HTTPRequestHandler> pHandler(_pFactory->createRequestHandler(request));
if (pHandler.get())
{
if (request.expectContinue())
response.sendContinue();
pHandler->handleRequest(request, response);
session.setKeepAlive(_pParams->getKeepAlive() && response.getKeepAlive() && session.canKeepAlive());
}
else sendErrorResponse(session, HTTPResponse::HTTP_NOT_IMPLEMENTED);
}
catch (Poco::Exception&)
{
if (!response.sent())
sendErrorResponse(session, HTTPResponse::HTTP_INTERNAL_SERVER_ERROR);
throw;
}
}
catch (NoMessageException&)
{
break;
}
catch (MessageException&)
{
sendErrorResponse(session, HTTPResponse::HTTP_BAD_REQUEST);
}
}
}
void HTTPServerConnection::sendErrorResponse(HTTPServerSession& session, HTTPResponse::HTTPStatus status)
{
HTTPServerResponseImpl response(session);
response.setVersion(HTTPMessage::HTTP_1_1);
response.setStatusAndReason(status);
response.setKeepAlive(false);
response.send();
session.setKeepAlive(false);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,65 @@
//
// HTTPServerConnectionFactory.cpp
//
// $Id: //poco/1.4/Net/src/HTTPServerConnectionFactory.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerConnectionFactory
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPServerConnectionFactory.h"
#include "Poco/Net/HTTPServerConnection.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
namespace Poco {
namespace Net {
HTTPServerConnectionFactory::HTTPServerConnectionFactory(HTTPServerParams::Ptr pParams, HTTPRequestHandlerFactory::Ptr pFactory):
_pParams(pParams),
_pFactory(pFactory)
{
poco_check_ptr (pFactory);
}
HTTPServerConnectionFactory::~HTTPServerConnectionFactory()
{
}
TCPServerConnection* HTTPServerConnectionFactory::createConnection(const StreamSocket& socket)
{
return new HTTPServerConnection(socket, _pParams, _pFactory);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,95 @@
//
// HTTPServerParams.cpp
//
// $Id: //poco/1.4/Net/src/HTTPServerParams.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerParams
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPServerParams.h"
namespace Poco {
namespace Net {
HTTPServerParams::HTTPServerParams():
_timeout(60000000),
_keepAlive(true),
_maxKeepAliveRequests(0),
_keepAliveTimeout(15000000)
{
}
HTTPServerParams::~HTTPServerParams()
{
}
void HTTPServerParams::setServerName(const std::string& serverName)
{
_serverName = serverName;
}
void HTTPServerParams::setSoftwareVersion(const std::string& softwareVersion)
{
_softwareVersion = softwareVersion;
}
void HTTPServerParams::setTimeout(const Poco::Timespan& timeout)
{
_timeout = timeout;
}
void HTTPServerParams::setKeepAlive(bool keepAlive)
{
_keepAlive = keepAlive;
}
void HTTPServerParams::setKeepAliveTimeout(const Poco::Timespan& timeout)
{
_keepAliveTimeout = timeout;
}
void HTTPServerParams::setMaxKeepAliveRequests(int maxKeepAliveRequests)
{
poco_assert (maxKeepAliveRequests >= 0);
_maxKeepAliveRequests = maxKeepAliveRequests;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,54 @@
//
// HTTPServerRequest.cpp
//
// $Id: //poco/1.4/Net/src/HTTPServerRequest.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerRequest
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPServerRequest.h"
namespace Poco {
namespace Net {
HTTPServerRequest::HTTPServerRequest()
{
}
HTTPServerRequest::~HTTPServerRequest()
{
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,106 @@
//
// HTTPServerRequestImpl.cpp
//
// $Id: //poco/1.4/Net/src/HTTPServerRequestImpl.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerRequestImpl
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPServerRequestImpl.h"
#include "Poco/Net/HTTPServerSession.h"
#include "Poco/Net/HTTPHeaderStream.h"
#include "Poco/Net/HTTPStream.h"
#include "Poco/Net/HTTPFixedLengthStream.h"
#include "Poco/Net/HTTPChunkedStream.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/String.h"
using Poco::icompare;
namespace Poco {
namespace Net {
const std::string HTTPServerRequestImpl::EXPECT("Expect");
HTTPServerRequestImpl::HTTPServerRequestImpl(HTTPServerResponse& response, HTTPServerSession& session, HTTPServerParams* pParams):
_response(response),
_session(session),
_pStream(0),
_pParams(pParams, true)
{
HTTPHeaderInputStream hs(session);
read(hs);
// Now that we know socket is still connected, obtain addresses
_clientAddress = session.clientAddress();
_serverAddress = session.serverAddress();
if (getChunkedTransferEncoding())
_pStream = new HTTPChunkedInputStream(session);
else if (getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
_pStream = new HTTPFixedLengthInputStream(session, getContentLength());
else if (getMethod() == HTTPRequest::HTTP_GET || getMethod() == HTTPRequest::HTTP_HEAD)
_pStream = new HTTPFixedLengthInputStream(session, 0);
else
_pStream = new HTTPInputStream(session);
}
HTTPServerRequestImpl::~HTTPServerRequestImpl()
{
delete _pStream;
}
StreamSocket& HTTPServerRequestImpl::socket()
{
return _session.socket();
}
StreamSocket HTTPServerRequestImpl::detachSocket()
{
return _session.detachSocket();
}
bool HTTPServerRequestImpl::expectContinue() const
{
const std::string& expect = get(EXPECT, EMPTY);
return !expect.empty() && icompare(expect, "100-continue") == 0;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,54 @@
//
// HTTPServerResponse.cpp
//
// $Id: //poco/1.4/Net/src/HTTPServerResponse.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerResponse
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPServerResponse.h"
namespace Poco {
namespace Net {
HTTPServerResponse::HTTPServerResponse()
{
}
HTTPServerResponse::~HTTPServerResponse()
{
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,181 @@
//
// HTTPServerResponseImpl.cpp
//
// $Id: //poco/1.4/Net/src/HTTPServerResponseImpl.cpp#2 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerResponseImpl
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPServerResponseImpl.h"
#include "Poco/Net/HTTPServerSession.h"
#include "Poco/Net/HTTPHeaderStream.h"
#include "Poco/Net/HTTPStream.h"
#include "Poco/Net/HTTPFixedLengthStream.h"
#include "Poco/Net/HTTPChunkedStream.h"
#include "Poco/File.h"
#include "Poco/Timestamp.h"
#include "Poco/NumberFormatter.h"
#include "Poco/StreamCopier.h"
#include "Poco/CountingStream.h"
#include "Poco/Exception.h"
#include "Poco/FileStream.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
using Poco::File;
using Poco::Timestamp;
using Poco::NumberFormatter;
using Poco::StreamCopier;
using Poco::OpenFileException;
using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
namespace Poco {
namespace Net {
HTTPServerResponseImpl::HTTPServerResponseImpl(HTTPServerSession& session):
_session(session),
_pStream(0)
{
}
HTTPServerResponseImpl::~HTTPServerResponseImpl()
{
delete _pStream;
}
void HTTPServerResponseImpl::sendContinue()
{
HTTPHeaderOutputStream hs(_session);
hs << getVersion() << " 100 Continue\r\n\r\n";
}
std::ostream& HTTPServerResponseImpl::send()
{
poco_assert (!_pStream);
if (getChunkedTransferEncoding())
{
HTTPHeaderOutputStream hs(_session);
write(hs);
_pStream = new HTTPChunkedOutputStream(_session);
}
else if (getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
{
Poco::CountingOutputStream cs;
write(cs);
_pStream = new HTTPFixedLengthOutputStream(_session, getContentLength() + cs.chars());
write(*_pStream);
}
else
{
_pStream = new HTTPOutputStream(_session);
setKeepAlive(false);
write(*_pStream);
}
return *_pStream;
}
void HTTPServerResponseImpl::sendFile(const std::string& path, const std::string& mediaType)
{
poco_assert (!_pStream);
File f(path);
Timestamp dateTime = f.getLastModified();
File::FileSize length = f.getSize();
set("Last-Modified", DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT));
#if defined(POCO_HAVE_INT64)
setContentLength64(length);
#else
setContentLength(static_cast<int>(length));
#endif
setContentType(mediaType);
setChunkedTransferEncoding(false);
Poco::FileInputStream istr(path);
if (istr.good())
{
_pStream = new HTTPHeaderOutputStream(_session);
write(*_pStream);
StreamCopier::copyStream(istr, *_pStream);
}
else throw OpenFileException(path);
}
void HTTPServerResponseImpl::sendBuffer(const void* pBuffer, std::size_t length)
{
poco_assert (!_pStream);
setContentLength(static_cast<int>(length));
setChunkedTransferEncoding(false);
_pStream = new HTTPHeaderOutputStream(_session);
write(*_pStream);
_pStream->write(static_cast<const char*>(pBuffer), static_cast<std::streamsize>(length));
}
void HTTPServerResponseImpl::redirect(const std::string& uri, HTTPStatus status)
{
poco_assert (!_pStream);
setContentLength(0);
setChunkedTransferEncoding(false);
setStatusAndReason(status);
set("Location", uri);
_pStream = new HTTPHeaderOutputStream(_session);
write(*_pStream);
}
void HTTPServerResponseImpl::requireAuthentication(const std::string& realm)
{
poco_assert (!_pStream);
setStatusAndReason(HTTPResponse::HTTP_UNAUTHORIZED);
std::string auth("Basic realm=\"");
auth.append(realm);
auth.append("\"");
set("WWW-Authenticate", auth);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,92 @@
//
// HTTPServerSession.cpp
//
// $Id: //poco/1.4/Net/src/HTTPServerSession.cpp#1 $
//
// Library: Net
// Package: HTTPServer
// Module: HTTPServerSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPServerSession.h"
namespace Poco {
namespace Net {
HTTPServerSession::HTTPServerSession(const StreamSocket& socket, HTTPServerParams::Ptr pParams):
HTTPSession(socket, pParams->getKeepAlive()),
_firstRequest(true),
_keepAliveTimeout(pParams->getKeepAliveTimeout()),
_maxKeepAliveRequests(pParams->getMaxKeepAliveRequests())
{
setTimeout(pParams->getTimeout());
this->socket().setReceiveTimeout(pParams->getTimeout());
}
HTTPServerSession::~HTTPServerSession()
{
}
bool HTTPServerSession::hasMoreRequests()
{
if (!socket().impl()->initialized()) return false;
if (_firstRequest)
{
_firstRequest = false;
--_maxKeepAliveRequests;
return socket().poll(getTimeout(), Socket::SELECT_READ);
}
else if (_maxKeepAliveRequests != 0 && getKeepAlive())
{
if (_maxKeepAliveRequests > 0)
--_maxKeepAliveRequests;
return buffered() > 0 || socket().poll(_keepAliveTimeout, Socket::SELECT_READ);
}
else return false;
}
SocketAddress HTTPServerSession::clientAddress()
{
return socket().peerAddress();
}
SocketAddress HTTPServerSession::serverAddress()
{
return socket().address();
}
} } // namespace Poco::Net

244
Net/src/HTTPSession.cpp Normal file
View File

@@ -0,0 +1,244 @@
//
// HTTPSession.cpp
//
// $Id: //poco/1.4/Net/src/HTTPSession.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPSession.h"
#include "Poco/Net/HTTPBufferAllocator.h"
#include "Poco/Net/NetException.h"
#include <cstring>
using Poco::TimeoutException;
namespace Poco {
namespace Net {
HTTPSession::HTTPSession():
_pBuffer(0),
_pCurrent(0),
_pEnd(0),
_keepAlive(false),
_timeout(HTTP_DEFAULT_TIMEOUT),
_pException(0)
{
}
HTTPSession::HTTPSession(const StreamSocket& socket):
_socket(socket),
_pBuffer(0),
_pCurrent(0),
_pEnd(0),
_keepAlive(false),
_timeout(HTTP_DEFAULT_TIMEOUT),
_pException(0)
{
}
HTTPSession::HTTPSession(const StreamSocket& socket, bool keepAlive):
_socket(socket),
_pBuffer(0),
_pCurrent(0),
_pEnd(0),
_keepAlive(keepAlive),
_timeout(HTTP_DEFAULT_TIMEOUT),
_pException(0)
{
}
HTTPSession::~HTTPSession()
{
if (_pBuffer) HTTPBufferAllocator::deallocate(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE);
try
{
close();
}
catch (...)
{
}
delete _pException;
}
void HTTPSession::setKeepAlive(bool keepAlive)
{
_keepAlive = keepAlive;
}
void HTTPSession::setTimeout(const Poco::Timespan& timeout)
{
_timeout = timeout;
}
int HTTPSession::get()
{
if (_pCurrent == _pEnd)
refill();
if (_pCurrent < _pEnd)
return *_pCurrent++;
else
return std::char_traits<char>::eof();
}
int HTTPSession::peek()
{
if (_pCurrent == _pEnd)
refill();
if (_pCurrent < _pEnd)
return *_pCurrent;
else
return std::char_traits<char>::eof();
}
int HTTPSession::read(char* buffer, std::streamsize length)
{
if (_pCurrent < _pEnd)
{
int n = (int) (_pEnd - _pCurrent);
if (n > length) n = (int) length;
std::memcpy(buffer, _pCurrent, n);
_pCurrent += n;
return n;
}
else return receive(buffer, (int) length);
}
int HTTPSession::write(const char* buffer, std::streamsize length)
{
try
{
return _socket.sendBytes(buffer, (int) length);
}
catch (Poco::Exception& exc)
{
setException(exc);
throw;
}
}
int HTTPSession::receive(char* buffer, int length)
{
try
{
return _socket.receiveBytes(buffer, length);
}
catch (Poco::Exception& exc)
{
setException(exc);
throw;
}
}
void HTTPSession::refill()
{
if (!_pBuffer)
{
_pBuffer = HTTPBufferAllocator::allocate(HTTPBufferAllocator::BUFFER_SIZE);
}
_pCurrent = _pEnd = _pBuffer;
int n = receive(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE);
_pEnd += n;
}
bool HTTPSession::connected() const
{
return _socket.impl()->initialized();
}
void HTTPSession::connect(const SocketAddress& address)
{
_socket.connect(address, _timeout);
_socket.setReceiveTimeout(_timeout);
_socket.setNoDelay(true);
}
void HTTPSession::abort()
{
_socket.shutdown();
close();
}
void HTTPSession::close()
{
_socket.close();
}
void HTTPSession::setException(const Poco::Exception& exc)
{
delete _pException;
_pException = exc.clone();
}
StreamSocket HTTPSession::detachSocket()
{
StreamSocket oldSocket(_socket);
StreamSocket newSocket;
_socket = newSocket;
return oldSocket;
}
void HTTPSession::attachSocket(const StreamSocket& socket)
{
_socket = socket;
}
void HTTPSession::attachSessionData(const Poco::Any& data)
{
_data = data;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,168 @@
//
// HTTPSessionFactory.cpp
//
// $Id: //poco/1.4/Net/src/HTTPSessionFactory.cpp#1 $
//
// Library: Net
// Package: HTTPClient
// Module: HTTPSessionFactory
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPSessionFactory.h"
#include "Poco/Net/HTTPSessionInstantiator.h"
#include "Poco/Exception.h"
using Poco::SingletonHolder;
using Poco::FastMutex;
using Poco::NotFoundException;
using Poco::ExistsException;
namespace Poco {
namespace Net {
HTTPSessionFactory::HTTPSessionFactory():
_proxyPort(0)
{
}
HTTPSessionFactory::HTTPSessionFactory(const std::string& proxyHost, Poco::UInt16 proxyPort):
_proxyHost(proxyHost),
_proxyPort(proxyPort)
{
}
HTTPSessionFactory::~HTTPSessionFactory()
{
for (Instantiators::iterator it = _instantiators.begin(); it != _instantiators.end(); ++it)
{
delete it->second.pIn;
}
}
void HTTPSessionFactory::registerProtocol(const std::string& protocol, HTTPSessionInstantiator* pSessionInstantiator)
{
poco_assert_dbg(pSessionInstantiator);
FastMutex::ScopedLock lock(_mutex);
std::pair<Instantiators::iterator, bool> tmp = _instantiators.insert(make_pair(protocol, InstantiatorInfo(pSessionInstantiator)));
if (!tmp.second)
{
++tmp.first->second.cnt;
delete pSessionInstantiator;
}
}
void HTTPSessionFactory::unregisterProtocol(const std::string& protocol)
{
FastMutex::ScopedLock lock(_mutex);
Instantiators::iterator it = _instantiators.find(protocol);
if (it != _instantiators.end())
{
if (it->second.cnt == 1)
{
delete it->second.pIn;
_instantiators.erase(it);
}
else --it->second.cnt;
}
else throw NotFoundException("No HTTPSessionInstantiator registered for", protocol);
}
bool HTTPSessionFactory::supportsProtocol(const std::string& protocol)
{
FastMutex::ScopedLock lock(_mutex);
Instantiators::iterator it = _instantiators.find(protocol);
return it != _instantiators.end();
}
HTTPClientSession* HTTPSessionFactory::createClientSession(const Poco::URI& uri)
{
FastMutex::ScopedLock lock(_mutex);
if (uri.isRelative()) throw Poco::UnknownURISchemeException("Relative URIs are not supported by HTTPSessionFactory.");
Instantiators::iterator it = _instantiators.find(uri.getScheme());
if (it != _instantiators.end())
{
it->second.pIn->setProxy(_proxyHost, _proxyPort);
it->second.pIn->setProxyCredentials(_proxyUsername, _proxyPassword);
return it->second.pIn->createClientSession(uri);
}
else throw Poco::UnknownURISchemeException(uri.getScheme());
}
void HTTPSessionFactory::setProxy(const std::string& host, Poco::UInt16 port)
{
FastMutex::ScopedLock lock(_mutex);
_proxyHost = host;
_proxyPort = port;
}
void HTTPSessionFactory::setProxyCredentials(const std::string& username, const std::string& password)
{
FastMutex::ScopedLock lock(_mutex);
_proxyUsername = username;
_proxyPassword = password;
}
namespace
{
static SingletonHolder<HTTPSessionFactory> singleton;
}
HTTPSessionFactory& HTTPSessionFactory::defaultFactory()
{
return *singleton.get();
}
HTTPSessionFactory::InstantiatorInfo::InstantiatorInfo(HTTPSessionInstantiator* pInst): pIn(pInst), cnt(1)
{
poco_check_ptr (pIn);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,96 @@
//
// HTTPSessionInstantiator.cpp
//
// $Id: //poco/1.4/Net/src/HTTPSessionInstantiator.cpp#1 $
//
// Library: Net
// Package: HTTPClient
// Module: HTTPSessionInstantiator
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPSessionInstantiator.h"
#include "Poco/Net/HTTPSessionFactory.h"
#include "Poco/Net/HTTPClientSession.h"
using Poco::URI;
namespace Poco {
namespace Net {
HTTPSessionInstantiator::HTTPSessionInstantiator():
_proxyPort(0)
{
}
HTTPSessionInstantiator::~HTTPSessionInstantiator()
{
}
HTTPClientSession* HTTPSessionInstantiator::createClientSession(const Poco::URI& uri)
{
poco_assert (uri.getScheme() == "http");
HTTPClientSession* pSession = new HTTPClientSession(uri.getHost(), uri.getPort());
pSession->setProxy(proxyHost(), proxyPort());
pSession->setProxyCredentials(proxyUsername(), proxyPassword());
return pSession;
}
void HTTPSessionInstantiator::registerInstantiator()
{
HTTPSessionFactory::defaultFactory().registerProtocol("http", new HTTPSessionInstantiator);
}
void HTTPSessionInstantiator::unregisterInstantiator()
{
HTTPSessionFactory::defaultFactory().unregisterProtocol("http");
}
void HTTPSessionInstantiator::setProxy(const std::string& host, Poco::UInt16 port)
{
_proxyHost = host;
_proxyPort = port;
}
void HTTPSessionInstantiator::setProxyCredentials(const std::string& username, const std::string& password)
{
_proxyUsername = username;
_proxyPassword = password;
}
} } // namespace Poco::Net

180
Net/src/HTTPStream.cpp Normal file
View File

@@ -0,0 +1,180 @@
//
// HTTPStream.cpp
//
// $Id: //poco/1.4/Net/src/HTTPStream.cpp#1 $
//
// Library: Net
// Package: HTTP
// Module: HTTPStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPStream.h"
#include "Poco/Net/HTTPSession.h"
namespace Poco {
namespace Net {
//
// HTTPStreamBuf
//
HTTPStreamBuf::HTTPStreamBuf(HTTPSession& session, openmode mode):
HTTPBasicStreamBuf(HTTPBufferAllocator::BUFFER_SIZE, mode),
_session(session),
_mode(mode)
{
}
HTTPStreamBuf::~HTTPStreamBuf()
{
}
void HTTPStreamBuf::close()
{
if (_mode & std::ios::out)
{
sync();
_session.socket().shutdownSend();
}
}
int HTTPStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
return _session.read(buffer, length);
}
int HTTPStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
return _session.write(buffer, length);
}
//
// HTTPIOS
//
HTTPIOS::HTTPIOS(HTTPSession& session, HTTPStreamBuf::openmode mode):
_buf(session, mode)
{
poco_ios_init(&_buf);
}
HTTPIOS::~HTTPIOS()
{
try
{
_buf.close();
}
catch (...)
{
}
}
HTTPStreamBuf* HTTPIOS::rdbuf()
{
return &_buf;
}
//
// HTTPInputStream
//
Poco::MemoryPool HTTPInputStream::_pool(sizeof(HTTPInputStream));
HTTPInputStream::HTTPInputStream(HTTPSession& session):
HTTPIOS(session, std::ios::in),
std::istream(&_buf)
{
}
HTTPInputStream::~HTTPInputStream()
{
}
void* HTTPInputStream::operator new(std::size_t size)
{
return _pool.get();
}
void HTTPInputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
//
// HTTPOutputStream
//
Poco::MemoryPool HTTPOutputStream::_pool(sizeof(HTTPOutputStream));
HTTPOutputStream::HTTPOutputStream(HTTPSession& session):
HTTPIOS(session, std::ios::out),
std::ostream(&_buf)
{
}
HTTPOutputStream::~HTTPOutputStream()
{
}
void* HTTPOutputStream::operator new(std::size_t size)
{
return _pool.get();
}
void HTTPOutputStream::operator delete(void* ptr)
{
_pool.release(ptr);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,183 @@
//
// HTTPStreamFactory.cpp
//
// $Id: //poco/1.4/Net/src/HTTPStreamFactory.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPStreamFactory
//
// Copyright (c) 2005-2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HTTPStreamFactory.h"
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPIOStream.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPCredentials.h"
#include "Poco/Net/NetException.h"
#include "Poco/URI.h"
#include "Poco/URIStreamOpener.h"
#include "Poco/UnbufferedStreamBuf.h"
#include "Poco/NullStream.h"
#include "Poco/StreamCopier.h"
using Poco::URIStreamFactory;
using Poco::URI;
using Poco::URIStreamOpener;
using Poco::UnbufferedStreamBuf;
namespace Poco {
namespace Net {
HTTPStreamFactory::HTTPStreamFactory():
_proxyPort(HTTPSession::HTTP_PORT)
{
}
HTTPStreamFactory::HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort):
_proxyHost(proxyHost),
_proxyPort(proxyPort)
{
}
HTTPStreamFactory::HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16 proxyPort, const std::string& proxyUsername, const std::string& proxyPassword):
_proxyHost(proxyHost),
_proxyPort(proxyPort),
_proxyUsername(proxyUsername),
_proxyPassword(proxyPassword)
{
}
HTTPStreamFactory::~HTTPStreamFactory()
{
}
std::istream* HTTPStreamFactory::open(const URI& uri)
{
poco_assert (uri.getScheme() == "http");
URI resolvedURI(uri);
URI proxyUri;
HTTPClientSession* pSession = 0;
HTTPResponse res;
bool retry = false;
bool authorize = false;
std::string username;
std::string password;
try
{
do
{
if (!pSession)
{
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
if (proxyUri.empty())
pSession->setProxy(_proxyHost, _proxyPort);
else
pSession->setProxy(proxyUri.getHost(), proxyUri.getPort());
pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
}
std::string path = resolvedURI.getPathAndQuery();
if (path.empty()) path = "/";
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
if (authorize)
{
HTTPCredentials::extractCredentials(uri, username, password);
HTTPCredentials cred(username, password);
cred.authenticate(req, res);
}
pSession->sendRequest(req);
std::istream& rs = pSession->receiveResponse(res);
bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY ||
res.getStatus() == HTTPResponse::HTTP_FOUND ||
res.getStatus() == HTTPResponse::HTTP_SEE_OTHER ||
res.getStatus() == HTTPResponse::HTTP_TEMPORARY_REDIRECT);
if (moved)
{
resolvedURI.resolve(res.get("Location"));
if (!username.empty())
{
resolvedURI.setUserInfo(username + ":" + password);
}
throw URIRedirection(resolvedURI.toString());
}
else if (res.getStatus() == HTTPResponse::HTTP_OK)
{
return new HTTPResponseStream(rs, pSession);
}
else if (res.getStatus() == HTTPResponse::HTTP_USEPROXY && !retry)
{
// The requested resource MUST be accessed through the proxy
// given by the Location field. The Location field gives the
// URI of the proxy. The recipient is expected to repeat this
// single request via the proxy. 305 responses MUST only be generated by origin servers.
// only use for one single request!
proxyUri.resolve(res.get("Location"));
delete pSession; pSession = 0;
retry = true; // only allow useproxy once
}
else if (res.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED && !authorize)
{
authorize = true;
retry = true;
Poco::NullOutputStream null;
Poco::StreamCopier::copyStream(rs, null);
}
else throw HTTPException(res.getReason(), uri.toString());
}
while (retry);
throw HTTPException("Too many redirects", uri.toString());
}
catch (...)
{
delete pSession;
throw;
}
}
void HTTPStreamFactory::registerFactory()
{
URIStreamOpener::defaultOpener().registerStreamFactory("http", new HTTPStreamFactory);
}
} } // namespace Poco::Net

157
Net/src/HostEntry.cpp Normal file
View File

@@ -0,0 +1,157 @@
//
// HostEntry.cpp
//
// $Id: //poco/1.4/Net/src/HostEntry.cpp#7 $
//
// Library: Net
// Package: NetCore
// Module: HostEntry
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/HostEntry.h"
#include "Poco/Exception.h"
#include <algorithm>
namespace Poco {
namespace Net {
HostEntry::HostEntry()
{
}
HostEntry::HostEntry(struct hostent* entry)
{
poco_check_ptr (entry);
_name = entry->h_name;
char** alias = entry->h_aliases;
if (alias)
{
while (*alias)
{
_aliases.push_back(std::string(*alias));
++alias;
}
}
char** address = entry->h_addr_list;
if (address)
{
while (*address)
{
_addresses.push_back(IPAddress(*address, entry->h_length));
++address;
}
}
}
#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
HostEntry::HostEntry(struct addrinfo* ainfo)
{
poco_check_ptr (ainfo);
for (struct addrinfo* ai = ainfo; ai; ai = ai->ai_next)
{
if (ai->ai_canonname)
{
_name.assign(ai->ai_canonname);
}
if (ai->ai_addrlen && ai->ai_addr)
{
switch (ai->ai_addr->sa_family)
{
case AF_INET:
_addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in*>(ai->ai_addr)->sin_addr, sizeof(in_addr)));
break;
#if defined(POCO_HAVE_IPv6)
case AF_INET6:
_addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_addr, sizeof(in6_addr), reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_scope_id));
break;
#endif
}
}
}
}
#endif // POCO_HAVE_IPv6
#if defined(POCO_VXWORKS)
HostEntry::HostEntry(const std::string& name, const IPAddress& addr):
_name(name)
{
_addresses.push_back(addr);
}
#endif // POCO_VXWORKS
HostEntry::HostEntry(const HostEntry& entry):
_name(entry._name),
_aliases(entry._aliases),
_addresses(entry._addresses)
{
}
HostEntry& HostEntry::operator = (const HostEntry& entry)
{
if (&entry != this)
{
_name = entry._name;
_aliases = entry._aliases;
_addresses = entry._addresses;
}
return *this;
}
void HostEntry::swap(HostEntry& hostEntry)
{
std::swap(_name, hostEntry._name);
std::swap(_aliases, hostEntry._aliases);
std::swap(_addresses, hostEntry._addresses);
}
HostEntry::~HostEntry()
{
}
} } // namespace Poco::Net

166
Net/src/ICMPClient.cpp Normal file
View File

@@ -0,0 +1,166 @@
//
// ICMPClient.cpp
//
// $Id: //poco/1.4/Net/src/ICMPClient.cpp#1 $
//
// Library: Net
// Package: ICMP
// Module: ICMPClient
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/ICMPClient.h"
#include "Poco/Net/ICMPSocket.h"
#include "Poco/Net/NetException.h"
#include "Poco/Channel.h"
#include "Poco/Message.h"
#include "Poco/Exception.h"
#include <sstream>
using Poco::Channel;
using Poco::Message;
using Poco::InvalidArgumentException;
using Poco::NotImplementedException;
using Poco::TimeoutException;
using Poco::Exception;
namespace Poco {
namespace Net {
ICMPClient::ICMPClient(IPAddress::Family family):
_family(family)
{
}
ICMPClient::~ICMPClient()
{
}
int ICMPClient::ping(const std::string& address, int repeat) const
{
if (repeat <= 0) return 0;
SocketAddress addr(address, 0);
return ping(addr, repeat);
}
int ICMPClient::ping(SocketAddress& address, int repeat) const
{
if (repeat <= 0) return 0;
ICMPSocket icmpSocket(_family);
SocketAddress returnAddress;
ICMPEventArgs eventArgs(address, repeat, icmpSocket.dataSize(), icmpSocket.ttl());
pingBegin.notify(this, eventArgs);
for (int i = 0; i < repeat; ++i)
{
icmpSocket.sendTo(address);
++eventArgs;
try
{
int t = icmpSocket.receiveFrom(returnAddress);
eventArgs.setReplyTime(i, t);
pingReply.notify(this, eventArgs);
}
catch (TimeoutException&)
{
std::ostringstream os;
os << address.host().toString() << ": Request timed out.";
eventArgs.setError(i, os.str());
pingError.notify(this, eventArgs);
continue;
}
catch (ICMPException& ex)
{
std::ostringstream os;
os << address.host().toString() << ": " << ex.what();
eventArgs.setError(i, os.str());
pingError.notify(this, eventArgs);
continue;
}
catch (Exception& ex)
{
std::ostringstream os;
os << ex.displayText();
eventArgs.setError(i, os.str());
pingError.notify(this, eventArgs);
continue;
}
}
pingEnd.notify(this, eventArgs);
return eventArgs.received();
}
int ICMPClient::pingIPv4(const std::string& address, int repeat)
{
if (repeat <= 0) return 0;
SocketAddress a(address, 0);
return ping(a, IPAddress::IPv4, repeat);
}
int ICMPClient::ping(SocketAddress& address, IPAddress::Family family, int repeat)
{
if (repeat <= 0) return 0;
ICMPSocket icmpSocket(family);
SocketAddress returnAddress;
int received = 0;
for (int i = 0; i < repeat; ++i)
{
icmpSocket.sendTo(address);
try
{
icmpSocket.receiveFrom(returnAddress);
++received;
}
catch (TimeoutException&)
{
}
catch (ICMPException&)
{
}
}
return received;
}
} } // namespace Poco::Net

190
Net/src/ICMPEventArgs.cpp Normal file
View File

@@ -0,0 +1,190 @@
//
// ICMPEventArgs.cpp
//
// $Id: //poco/1.4/Net/src/ICMPEventArgs.cpp#1 $
//
// Library: Net
// Package: ICMP
// Module: ICMPEventArgs
//
// Implementation of ICMPEventArgs
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/ICMPEventArgs.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/DNS.h"
#include "Poco/Exception.h"
#include "Poco/Net/NetException.h"
#include <numeric>
using Poco::IOException;
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
ICMPEventArgs::ICMPEventArgs(const SocketAddress& address, int repetitions, int dataSize, int ttl):
_address(address),
_sent(0),
_dataSize(dataSize),
_ttl(ttl),
_rtt(repetitions, 0),
_errors(repetitions)
{
}
ICMPEventArgs::~ICMPEventArgs()
{
}
std::string ICMPEventArgs::hostName() const
{
try
{
return DNS::resolve(_address.host().toString()).name();
}
catch (HostNotFoundException&)
{
}
catch (NoAddressFoundException&)
{
}
catch (DNSException&)
{
}
catch (IOException&)
{
}
return _address.host().toString();
}
std::string ICMPEventArgs::hostAddress() const
{
return _address.host().toString();
}
void ICMPEventArgs::setRepetitions(int repetitions)
{
_rtt.clear();
_rtt.resize(repetitions, 0);
_errors.assign(repetitions, "");
}
ICMPEventArgs& ICMPEventArgs::operator ++ ()
{
++_sent;
return *this;
}
ICMPEventArgs ICMPEventArgs::operator ++ (int)
{
ICMPEventArgs prev(*this);
operator ++ ();
return prev;
}
int ICMPEventArgs::received() const
{
int received = 0;
for (int i = 0; i < _rtt.size(); ++i)
{
if (_rtt[i]) ++received;
}
return received;
}
void ICMPEventArgs::setError(int index, const std::string& text)
{
if (index >= _errors.size())
throw InvalidArgumentException("Supplied index exceeds vector capacity.");
_errors[index] = text;
}
const std::string& ICMPEventArgs::error(int index) const
{
if (0 == _errors.size())
throw InvalidArgumentException("Supplied index exceeds vector capacity.");
if (-1 == index) index = _sent - 1;
return _errors[index];
}
void ICMPEventArgs::setReplyTime(int index, int time)
{
if (index >= _rtt.size())
throw InvalidArgumentException("Supplied index exceeds array capacity.");
if (0 == time) time = 1;
_rtt[index] = time;
}
int ICMPEventArgs::replyTime(int index) const
{
if (0 == _rtt.size())
throw InvalidArgumentException("Supplied index exceeds array capacity.");
if (-1 == index) index = _sent - 1;
return _rtt[index];
}
int ICMPEventArgs::avgRTT() const
{
if (0 == _rtt.size()) return 0;
return (int) (std::accumulate(_rtt.begin(), _rtt.end(), 0) / _rtt.size());
}
float ICMPEventArgs::percent() const
{
if (0 == _rtt.size()) return 0;
return ((float) received() / (float) _rtt.size()) * (float) 100.0;
}
} } // namespace Poco::Net

132
Net/src/ICMPPacket.cpp Normal file
View File

@@ -0,0 +1,132 @@
//
// ICMPPacket.cpp
//
// $Id: //poco/1.4/Net/src/ICMPPacket.cpp#2 $
//
// Library: Net
// Package: ICMP
// Module: ICMPPacket
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/ICMPPacket.h"
#include "Poco/Net/ICMPv4PacketImpl.h"
#include "Poco/Net/NetException.h"
#include "Poco/Timestamp.h"
#include "Poco/Timespan.h"
#include "Poco/NumberFormatter.h"
#include <sstream>
using Poco::InvalidArgumentException;
using Poco::NotImplementedException;
using Poco::Timestamp;
using Poco::Timespan;
using Poco::NumberFormatter;
using Poco::UInt8;
using Poco::UInt16;
using Poco::Int32;
namespace Poco {
namespace Net {
ICMPPacket::ICMPPacket(IPAddress::Family family, int dataSize):_pImpl(0)
{
if (family == IPAddress::IPv4)
_pImpl = new ICMPv4PacketImpl(dataSize);
#if defined(POCO_HAVE_IPv6)
else if (family == IPAddress::IPv6)
throw NotImplementedException("ICMPv6 packets not implemented.");
#endif
else throw InvalidArgumentException("Invalid or unsupported address family passed to ICMPPacket");
}
ICMPPacket::~ICMPPacket()
{
delete _pImpl;
}
void ICMPPacket::setDataSize(int dataSize)
{
_pImpl->setDataSize(dataSize);
}
int ICMPPacket::getDataSize() const
{
return _pImpl->getDataSize();
}
int ICMPPacket::packetSize() const
{
return _pImpl->packetSize();
}
int ICMPPacket::maxPacketSize() const
{
return _pImpl->maxPacketSize();
}
const Poco::UInt8* ICMPPacket::packet()
{
return _pImpl->packet();
}
struct timeval ICMPPacket::time(Poco::UInt8* buffer, int length) const
{
return _pImpl->time(buffer, length);
}
bool ICMPPacket::validReplyID(Poco::UInt8* buffer, int length) const
{
return _pImpl->validReplyID(buffer, length);
}
std::string ICMPPacket::errorDescription(Poco::UInt8* buffer, int length)
{
return _pImpl->errorDescription(buffer, length);
}
std::string ICMPPacket::typeDescription(int typeId)
{
return _pImpl->typeDescription(typeId);
}
} } // namespace Poco::Net

125
Net/src/ICMPPacketImpl.cpp Normal file
View File

@@ -0,0 +1,125 @@
//
// ICMPPacketImpl.cpp
//
// $Id: //poco/1.4/Net/src/ICMPPacketImpl.cpp#2 $
//
// Library: Net
// Package: ICMP
// Module: ICMPPacketImpl
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/ICMPPacketImpl.h"
#include "Poco/Net/NetException.h"
#include "Poco/Timestamp.h"
#include "Poco/Timespan.h"
#include "Poco/NumberFormatter.h"
#include <sstream>
using Poco::InvalidArgumentException;
using Poco::Timestamp;
using Poco::Timespan;
using Poco::NumberFormatter;
using Poco::UInt8;
using Poco::UInt16;
using Poco::Int32;
namespace Poco {
namespace Net {
const UInt16 ICMPPacketImpl::MAX_PACKET_SIZE = 4096;
const UInt16 ICMPPacketImpl::MAX_SEQ_VALUE = 65535;
ICMPPacketImpl::ICMPPacketImpl(int dataSize):
_seq(0),
_pPacket(new UInt8[MAX_PACKET_SIZE]),
_dataSize(dataSize)
{
if (_dataSize > MAX_PACKET_SIZE)
throw InvalidArgumentException("Packet size must be <= " + NumberFormatter::format(MAX_PACKET_SIZE));
}
ICMPPacketImpl::~ICMPPacketImpl()
{
delete [] _pPacket;
}
void ICMPPacketImpl::setDataSize(int dataSize)
{
_dataSize = dataSize;
initPacket();
}
int ICMPPacketImpl::getDataSize() const
{
return _dataSize;
}
const Poco::UInt8* ICMPPacketImpl::packet(bool init)
{
if (init) initPacket();
return _pPacket;
}
unsigned short ICMPPacketImpl::checksum(UInt16 *addr, Int32 len)
{
Int32 nleft = len;
UInt16* w = addr;
UInt16 answer;
Int32 sum = 0;
while (nleft > 1)
{
sum += *w++;
nleft -= sizeof(UInt16);
}
if (nleft == 1)
{
UInt16 u = 0;
*(UInt8*) (&u) = *(UInt8*) w;
sum += u;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return answer;
}
} } // namespace Poco::Net

101
Net/src/ICMPSocket.cpp Normal file
View File

@@ -0,0 +1,101 @@
//
// ICMPSocket.cpp
//
// $Id: //poco/1.4/Net/src/ICMPSocket.cpp#1 $
//
// Library: Net
// Package: ICMP
// Module: ICMPSocket
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/ICMPSocket.h"
#include "Poco/Net/ICMPSocketImpl.h"
#include "Poco/Exception.h"
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
ICMPSocket::ICMPSocket(IPAddress::Family family, int dataSize, int ttl, int timeout):
Socket(new ICMPSocketImpl(family, dataSize, ttl, timeout)),
_dataSize(dataSize),
_ttl(ttl),
_timeout(timeout)
{
}
ICMPSocket::ICMPSocket(const Socket& socket):
Socket(socket)
{
if (!dynamic_cast<ICMPSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
ICMPSocket::ICMPSocket(SocketImpl* pImpl):
Socket(pImpl)
{
if (!dynamic_cast<ICMPSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
ICMPSocket::~ICMPSocket()
{
}
ICMPSocket& ICMPSocket::operator = (const Socket& socket)
{
if (dynamic_cast<ICMPSocketImpl*>(socket.impl()))
Socket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
int ICMPSocket::sendTo(const SocketAddress& address, int flags)
{
return impl()->sendTo(0, 0, address, flags);
}
int ICMPSocket::receiveFrom(SocketAddress& address, int flags)
{
return impl()->receiveFrom(0, 0, address, flags);
}
} } // namespace Poco::Net

120
Net/src/ICMPSocketImpl.cpp Normal file
View File

@@ -0,0 +1,120 @@
//
// ICMPSocketImpl.cpp
//
// $Id: //poco/1.4/Net/src/ICMPSocketImpl.cpp#1 $
//
// Library: Net
// Package: ICMP
// Module: ICMPSocketImpl
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/ICMPSocketImpl.h"
#include "Poco/Net/NetException.h"
#include "Poco/Timespan.h"
#include "Poco/Timestamp.h"
#include "Poco/Exception.h"
using Poco::TimeoutException;
using Poco::Timespan;
using Poco::Exception;
namespace Poco {
namespace Net {
ICMPSocketImpl::ICMPSocketImpl(IPAddress::Family family, int dataSize, int ttl, int timeout):
RawSocketImpl(family, IPPROTO_ICMP),
_icmpPacket(family, dataSize),
_timeout(timeout)
{
setOption(IPPROTO_IP, IP_TTL, ttl);
setReceiveTimeout(Timespan(timeout));
}
ICMPSocketImpl::~ICMPSocketImpl()
{
}
int ICMPSocketImpl::sendTo(const void*, int, const SocketAddress& address, int flags)
{
int n = SocketImpl::sendTo(_icmpPacket.packet(), _icmpPacket.packetSize(), address, flags);
return n;
}
int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
{
int maxPacketSize = _icmpPacket.maxPacketSize();
unsigned char* buffer = new unsigned char[maxPacketSize];
try
{
Poco::Timestamp ts;
do
{
if (ts.isElapsed(_timeout))
{
// This guards against a possible DoS attack, where sending
// fake ping responses will cause an endless loop.
throw TimeoutException();
}
SocketImpl::receiveFrom(buffer, maxPacketSize, address, flags);
}
while (!_icmpPacket.validReplyID(buffer, maxPacketSize));
}
catch (TimeoutException&)
{
delete [] buffer;
throw;
}
catch (Exception&)
{
std::string err = _icmpPacket.errorDescription(buffer, maxPacketSize);
delete [] buffer;
if (!err.empty())
throw ICMPException(err);
else
throw;
}
struct timeval then = _icmpPacket.time(buffer, maxPacketSize);
struct timeval now = _icmpPacket.time();
int elapsed = (((now.tv_sec * 1000000) + now.tv_usec) - ((then.tv_sec * 1000000) + then.tv_usec))/1000;
delete[] buffer;
return elapsed;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,284 @@
//
// ICMPv4PacketImpl.cpp
//
// $Id: //poco/1.4/Net/src/ICMPv4PacketImpl.cpp#2 $
//
// Library: Net
// Package: ICMP
// Module: ICMPv4PacketImpl
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/ICMPv4PacketImpl.h"
#include "Poco/Net/NetException.h"
#include "Poco/Timestamp.h"
#include "Poco/Timespan.h"
#include "Poco/NumberFormatter.h"
#if !defined(POCO_VXWORKS)
#include "Poco/Process.h"
#endif
#include <sstream>
using Poco::InvalidArgumentException;
using Poco::Timestamp;
using Poco::Timespan;
using Poco::NumberFormatter;
using Poco::UInt8;
using Poco::UInt16;
using Poco::Int32;
namespace Poco {
namespace Net {
const UInt8 ICMPv4PacketImpl::DESTINATION_UNREACHABLE_TYPE = 3;
const Poco::UInt8 ICMPv4PacketImpl::SOURCE_QUENCH_TYPE = 4;
const Poco::UInt8 ICMPv4PacketImpl::REDIRECT_MESSAGE_TYPE = 5;
const UInt8 ICMPv4PacketImpl::TIME_EXCEEDED_TYPE = 11;
const Poco::UInt8 ICMPv4PacketImpl::PARAMETER_PROBLEM_TYPE = 12;
const std::string ICMPv4PacketImpl::MESSAGE_TYPE[] =
{
"Echo Reply",
"ICMP 1",
"ICMP 2",
"Dest Unreachable",
"Source Quench",
"Redirect",
"ICMP 6",
"ICMP 7",
"Echo",
"ICMP 9",
"ICMP 10",
"Time Exceeded",
"Parameter Problem",
"Timestamp",
"Timestamp Reply",
"Info Request",
"Info Reply",
"Unknown type"
};
const std::string ICMPv4PacketImpl::DESTINATION_UNREACHABLE_CODE[] =
{
"Net unreachable",
"Host unreachable",
"Protocol unreachable",
"Port unreachable",
"Fragmentation needed and DF set",
"Source route failed",
"Unknown code"
};
const std::string ICMPv4PacketImpl::REDIRECT_MESSAGE_CODE[] =
{
"Redirect datagrams for the network",
"Redirect datagrams for the host",
"Redirect datagrams for the type of service and network",
"Redirect datagrams for the type of service and host",
"Unknown code"
};
const std::string ICMPv4PacketImpl::TIME_EXCEEDED_CODE[] =
{
"Time to live exceeded in transit",
"Fragment reassembly time exceeded",
"Unknown code"
};
const std::string ICMPv4PacketImpl::PARAMETER_PROBLEM_CODE[] =
{
"Pointer indicates the error",
"Unknown code"
};
ICMPv4PacketImpl::ICMPv4PacketImpl(int dataSize):
ICMPPacketImpl(dataSize)
{
initPacket();
}
ICMPv4PacketImpl::~ICMPv4PacketImpl()
{
}
int ICMPv4PacketImpl::packetSize() const
{
return getDataSize() + sizeof(Header);
}
void ICMPv4PacketImpl::initPacket()
{
if (_seq >= MAX_SEQ_VALUE) resetSequence();
Header* icp = (Header*) packet(false);
icp->type = ECHO_REQUEST;
icp->code = 0;
icp->checksum = 0;
icp->seq = ++_seq;
#if defined(POCO_VXWORKS)
icp->id = 0;
#else
icp->id = static_cast<UInt16>(Poco::Process::id());
#endif
struct timeval* ptp = (struct timeval *) (icp + 1);
*ptp = time();
icp->checksum = checksum((UInt16*) icp, getDataSize() + sizeof(Header));
}
struct timeval ICMPv4PacketImpl::time(Poco::UInt8* buffer, int length) const
{
struct timeval tv;
if (0 == buffer || 0 == length)
{
Timespan value(Timestamp().epochMicroseconds());
tv.tv_sec = (long) value.totalSeconds();
tv.tv_usec = (long) value.useconds();
}
else
{
struct timeval* ptv = (struct timeval*) data(buffer, length);
if (ptv) tv = *ptv;
else throw InvalidArgumentException("Invalid packet.");
}
return tv;
}
ICMPv4PacketImpl::Header* ICMPv4PacketImpl::header(Poco::UInt8* buffer, int length) const
{
poco_check_ptr (buffer);
int offset = (buffer[0] & 0x0F) * 4;
if ((offset + sizeof(Header)) > length) return 0;
buffer += offset;
return (Header *) buffer;
}
Poco::UInt8* ICMPv4PacketImpl::data(Poco::UInt8* buffer, int length) const
{
return ((Poco::UInt8*) header(buffer, length)) + sizeof(Header);
}
bool ICMPv4PacketImpl::validReplyID(Poco::UInt8* buffer, int length) const
{
Header *icp = header(buffer, length);
#if defined(POCO_VXWORKS)
return icp && icp->id == 0;
#else
return icp && (static_cast<Poco::UInt16>(Process::id()) == icp->id);
#endif
}
std::string ICMPv4PacketImpl::errorDescription(unsigned char* buffer, int length)
{
Header *icp = header(buffer, length);
if (!icp) return "Invalid header.";
if (ECHO_REPLY == icp->type) return std::string(); // not an error
UInt8 pointer = 0;
if (PARAMETER_PROBLEM == icp->type)
{
UInt8 mask = 0x00FF;
pointer = icp->id & mask;
}
MessageType type = static_cast<MessageType>(icp->type);
int code = icp->code;
std::ostringstream err;
switch (type)
{
case DESTINATION_UNREACHABLE_TYPE:
if (code >= NET_UNREACHABLE && code < DESTINATION_UNREACHABLE_UNKNOWN)
err << DESTINATION_UNREACHABLE_CODE[code];
else
err << DESTINATION_UNREACHABLE_CODE[DESTINATION_UNREACHABLE_UNKNOWN];
break;
case SOURCE_QUENCH_TYPE:
err << "Source quench";
break;
case REDIRECT_MESSAGE_TYPE:
if (code >= REDIRECT_NETWORK && code < REDIRECT_MESSAGE_UNKNOWN)
err << REDIRECT_MESSAGE_CODE[code];
else
err << REDIRECT_MESSAGE_CODE[REDIRECT_MESSAGE_UNKNOWN];
break;
case TIME_EXCEEDED_TYPE:
if (code >= TIME_TO_LIVE || code < TIME_EXCEEDED_UNKNOWN)
err << TIME_EXCEEDED_CODE[code];
else
err << TIME_EXCEEDED_CODE[TIME_EXCEEDED_UNKNOWN];
break;
case PARAMETER_PROBLEM_TYPE:
if (POINTER_INDICATES_THE_ERROR != code)
code = PARAMETER_PROBLEM_UNKNOWN;
err << PARAMETER_PROBLEM_CODE[code] << ": error in octet #" << pointer;
break;
default:
err << "Unknown type.";
break;
}
return err.str();
}
std::string ICMPv4PacketImpl::typeDescription(int typeId)
{
poco_assert (typeId >= ECHO_REPLY && typeId < MESSAGE_TYPE_LENGTH);
return MESSAGE_TYPE[typeId];
}
} } // namespace Poco::Net

894
Net/src/IPAddress.cpp Normal file
View File

@@ -0,0 +1,894 @@
//
// IPAddress.cpp
//
// $Id: //poco/1.4/Net/src/IPAddress.cpp#5 $
//
// Library: Net
// Package: NetCore
// Module: IPAddress
//
// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/IPAddress.h"
#include "Poco/Net/NetException.h"
#include "Poco/RefCountedObject.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Types.h"
#include <algorithm>
#include <cstring>
using Poco::RefCountedObject;
using Poco::NumberFormatter;
using Poco::UInt8;
using Poco::UInt16;
using Poco::UInt32;
namespace Poco {
namespace Net {
//
// IPAddressImpl
//
class IPAddressImpl: public RefCountedObject
{
public:
virtual std::string toString() const = 0;
virtual poco_socklen_t length() const = 0;
virtual const void* addr() const = 0;
virtual IPAddress::Family family() const = 0;
virtual int af() const = 0;
virtual Poco::UInt32 scope() const = 0;
virtual bool isWildcard() const = 0;
virtual bool isBroadcast() const = 0;
virtual bool isLoopback() const = 0;
virtual bool isMulticast() const = 0;
virtual bool isLinkLocal() const = 0;
virtual bool isSiteLocal() const = 0;
virtual bool isIPv4Mapped() const = 0;
virtual bool isIPv4Compatible() const = 0;
virtual bool isWellKnownMC() const = 0;
virtual bool isNodeLocalMC() const = 0;
virtual bool isLinkLocalMC() const = 0;
virtual bool isSiteLocalMC() const = 0;
virtual bool isOrgLocalMC() const = 0;
virtual bool isGlobalMC() const = 0;
virtual void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet) = 0;
virtual IPAddressImpl* clone() const = 0;
protected:
IPAddressImpl()
{
#if defined(_WIN32)
Poco::Net::initializeNetwork();
#endif
}
virtual ~IPAddressImpl()
{
#if defined(_WIN32)
Poco::Net::uninitializeNetwork();
#endif
}
private:
IPAddressImpl(const IPAddressImpl&);
IPAddressImpl& operator = (const IPAddressImpl&);
};
class IPv4AddressImpl: public IPAddressImpl
{
public:
IPv4AddressImpl()
{
std::memset(&_addr, 0, sizeof(_addr));
}
IPv4AddressImpl(const void* addr)
{
std::memcpy(&_addr, addr, sizeof(_addr));
}
std::string toString() const
{
const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr);
std::string result;
result.reserve(16);
NumberFormatter::append(result, bytes[0]);
result.append(".");
NumberFormatter::append(result, bytes[1]);
result.append(".");
NumberFormatter::append(result, bytes[2]);
result.append(".");
NumberFormatter::append(result, bytes[3]);
return result;
}
poco_socklen_t length() const
{
return sizeof(_addr);
}
const void* addr() const
{
return &_addr;
}
IPAddress::Family family() const
{
return IPAddress::IPv4;
}
int af() const
{
return AF_INET;
}
Poco::UInt32 scope() const
{
return 0;
}
bool isWildcard() const
{
return _addr.s_addr == INADDR_ANY;
}
bool isBroadcast() const
{
return _addr.s_addr == INADDR_NONE;
}
bool isLoopback() const
{
return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.1 to 127.255.255.255
}
bool isMulticast() const
{
return (ntohl(_addr.s_addr) & 0xF0000000) == 0xE0000000; // 224.0.0.0/24 to 239.0.0.0/24
}
bool isLinkLocal() const
{
return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16
}
bool isSiteLocal() const
{
UInt32 addr = ntohl(_addr.s_addr);
return (addr & 0xFF000000) == 0x0A000000 || // 10.0.0.0/24
(addr & 0xFFFF0000) == 0xC0A80000 || // 192.68.0.0/16
(addr >= 0xAC100000 && addr <= 0xAC1FFFFF); // 172.16.0.0 to 172.31.255.255
}
bool isIPv4Compatible() const
{
return true;
}
bool isIPv4Mapped() const
{
return true;
}
bool isWellKnownMC() const
{
return (ntohl(_addr.s_addr) & 0xFFFFFF00) == 0xE0000000; // 224.0.0.0/8
}
bool isNodeLocalMC() const
{
return false;
}
bool isLinkLocalMC() const
{
return (ntohl(_addr.s_addr) & 0xFF000000) == 0xE0000000; // 244.0.0.0/24
}
bool isSiteLocalMC() const
{
return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFFF0000; // 239.255.0.0/16
}
bool isOrgLocalMC() const
{
return (ntohl(_addr.s_addr) & 0xFFFF0000) == 0xEFC00000; // 239.192.0.0/16
}
bool isGlobalMC() const
{
UInt32 addr = ntohl(_addr.s_addr);
return addr >= 0xE0000100 && addr <= 0xEE000000; // 224.0.1.0 to 238.255.255.255
}
static IPv4AddressImpl* parse(const std::string& addr)
{
if (addr.empty()) return 0;
#if defined(_WIN32)
struct in_addr ia;
ia.s_addr = inet_addr(addr.c_str());
if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
return 0;
else
return new IPv4AddressImpl(&ia);
#else
#if __GNUC__ < 3 || defined(POCO_VXWORKS)
struct in_addr ia;
ia.s_addr = inet_addr(const_cast<char*>(addr.c_str()));
if (ia.s_addr == INADDR_NONE && addr != "255.255.255.255")
return 0;
else
return new IPv4AddressImpl(&ia);
#else
struct in_addr ia;
if (inet_aton(addr.c_str(), &ia))
return new IPv4AddressImpl(&ia);
else
return 0;
#endif
#endif
}
void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet)
{
poco_assert (pMask->af() == AF_INET && pSet->af() == AF_INET);
_addr.s_addr &= static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr;
_addr.s_addr |= static_cast<const IPv4AddressImpl*>(pSet)->_addr.s_addr & ~static_cast<const IPv4AddressImpl*>(pMask)->_addr.s_addr;
}
IPAddressImpl* clone() const
{
return new IPv4AddressImpl(&_addr);
}
private:
struct in_addr _addr;
};
#if defined(POCO_HAVE_IPv6)
class IPv6AddressImpl: public IPAddressImpl
{
public:
IPv6AddressImpl():
_scope(0)
{
std::memset(&_addr, 0, sizeof(_addr));
}
IPv6AddressImpl(const void* addr):
_scope(0)
{
std::memcpy(&_addr, addr, sizeof(_addr));
}
IPv6AddressImpl(const void* addr, Poco::UInt32 scope):
_scope(scope)
{
std::memcpy(&_addr, addr, sizeof(_addr));
}
std::string toString() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
if (isIPv4Compatible() || isIPv4Mapped())
{
std::string result;
result.reserve(24);
if (words[5] == 0)
result.append("::");
else
result.append("::FFFF:");
const UInt8* bytes = reinterpret_cast<const UInt8*>(&_addr);
NumberFormatter::append(result, bytes[12]);
result.append(".");
NumberFormatter::append(result, bytes[13]);
result.append(".");
NumberFormatter::append(result, bytes[14]);
result.append(".");
NumberFormatter::append(result, bytes[15]);
return result;
}
else
{
std::string result;
result.reserve(64);
bool zeroSequence = false;
int i = 0;
while (i < 8)
{
if (!zeroSequence && words[i] == 0)
{
int zi = i;
while (zi < 8 && words[zi] == 0) ++zi;
if (zi > i + 1)
{
i = zi;
result.append(":");
zeroSequence = true;
}
}
if (i > 0) result.append(":");
if (i < 8) NumberFormatter::appendHex(result, ntohs(words[i++]));
}
if (_scope > 0)
{
result.append("%");
#if defined(_WIN32)
NumberFormatter::append(result, _scope);
#else
char buffer[IFNAMSIZ];
if (if_indextoname(_scope, buffer))
{
result.append(buffer);
}
else
{
NumberFormatter::append(result, _scope);
}
#endif
}
return result;
}
}
poco_socklen_t length() const
{
return sizeof(_addr);
}
const void* addr() const
{
return &_addr;
}
IPAddress::Family family() const
{
return IPAddress::IPv6;
}
int af() const
{
return AF_INET6;
}
Poco::UInt32 scope() const
{
return _scope;
}
bool isWildcard() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
words[4] == 0 && words[5] == 0 && words[6] == 0 && words[7] == 0;
}
bool isBroadcast() const
{
return false;
}
bool isLoopback() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
words[4] == 0 && words[5] == 0 && words[6] == 0 && ntohs(words[7]) == 0x0001;
}
bool isMulticast() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (ntohs(words[0]) & 0xFFE0) == 0xFF00;
}
bool isLinkLocal() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (ntohs(words[0]) & 0xFFE0) == 0xFE80;
}
bool isSiteLocal() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (ntohs(words[0]) & 0xFFE0) == 0xFEC0;
}
bool isIPv4Compatible() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && words[5] == 0;
}
bool isIPv4Mapped() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 && words[4] == 0 && ntohs(words[5]) == 0xFFFF;
}
bool isWellKnownMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (ntohs(words[0]) & 0xFFF0) == 0xFF00;
}
bool isNodeLocalMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (ntohs(words[0]) & 0xFFEF) == 0xFF01;
}
bool isLinkLocalMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (ntohs(words[0]) & 0xFFEF) == 0xFF02;
}
bool isSiteLocalMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (ntohs(words[0]) & 0xFFEF) == 0xFF05;
}
bool isOrgLocalMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (ntohs(words[0]) & 0xFFEF) == 0xFF08;
}
bool isGlobalMC() const
{
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
return (ntohs(words[0]) & 0xFFEF) == 0xFF0F;
}
static IPv6AddressImpl* parse(const std::string& addr)
{
if (addr.empty()) return 0;
#if defined(_WIN32)
struct addrinfo* pAI;
struct addrinfo hints;
std::memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
int rc = getaddrinfo(addr.c_str(), NULL, &hints, &pAI);
if (rc == 0)
{
IPv6AddressImpl* pResult = new IPv6AddressImpl(&reinterpret_cast<struct sockaddr_in6*>(pAI->ai_addr)->sin6_addr, static_cast<int>(reinterpret_cast<struct sockaddr_in6*>(pAI->ai_addr)->sin6_scope_id));
freeaddrinfo(pAI);
return pResult;
}
else return 0;
#else
struct in6_addr ia;
std::string::size_type pos = addr.find('%');
if (std::string::npos != pos)
{
std::string::size_type start = ('[' == addr[0]) ? 1 : 0;
std::string unscopedAddr(addr, start, pos - start);
std::string scope(addr, pos + 1, addr.size() - start - pos);
Poco::UInt32 scopeId(0);
if (!(scopeId = if_nametoindex(scope.c_str())))
return 0;
if (inet_pton(AF_INET6, unscopedAddr.c_str(), &ia) == 1)
return new IPv6AddressImpl(&ia, scopeId);
else
return 0;
}
else
{
if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1)
return new IPv6AddressImpl(&ia);
else
return 0;
}
#endif
}
void mask(const IPAddressImpl* pMask, const IPAddressImpl* pSet)
{
throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses");
}
IPAddressImpl* clone() const
{
return new IPv6AddressImpl(&_addr, _scope);
}
private:
struct in6_addr _addr;
Poco::UInt32 _scope;
};
#endif // POCO_HAVE_IPv6
//
// IPAddress
//
IPAddress::IPAddress(): _pImpl(new IPv4AddressImpl)
{
}
IPAddress::IPAddress(const IPAddress& addr): _pImpl(addr._pImpl)
{
_pImpl->duplicate();
}
IPAddress::IPAddress(Family family): _pImpl(0)
{
if (family == IPv4)
_pImpl = new IPv4AddressImpl();
#if defined(POCO_HAVE_IPv6)
else if (family == IPv6)
_pImpl = new IPv6AddressImpl();
#endif
else
throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
}
IPAddress::IPAddress(const std::string& addr)
{
_pImpl = IPv4AddressImpl::parse(addr);
#if defined(POCO_HAVE_IPv6)
if (!_pImpl)
_pImpl = IPv6AddressImpl::parse(addr);
#endif
if (!_pImpl) throw InvalidAddressException(addr);
}
IPAddress::IPAddress(const std::string& addr, Family family): _pImpl(0)
{
if (family == IPv4)
_pImpl = IPv4AddressImpl::parse(addr);
#if defined(POCO_HAVE_IPv6)
else if (family == IPv6)
_pImpl = IPv6AddressImpl::parse(addr);
#endif
else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to IPAddress()");
if (!_pImpl) throw InvalidAddressException(addr);
}
IPAddress::IPAddress(const void* addr, poco_socklen_t length)
{
if (length == sizeof(struct in_addr))
_pImpl = new IPv4AddressImpl(addr);
#if defined(POCO_HAVE_IPv6)
else if (length == sizeof(struct in6_addr))
_pImpl = new IPv6AddressImpl(addr);
#endif
else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()");
}
IPAddress::IPAddress(const void* addr, poco_socklen_t length, Poco::UInt32 scope)
{
if (length == sizeof(struct in_addr))
_pImpl = new IPv4AddressImpl(addr);
#if defined(POCO_HAVE_IPv6)
else if (length == sizeof(struct in6_addr))
_pImpl = new IPv6AddressImpl(addr, scope);
#endif
else throw Poco::InvalidArgumentException("Invalid address length passed to IPAddress()");
}
IPAddress::~IPAddress()
{
_pImpl->release();
}
IPAddress& IPAddress::operator = (const IPAddress& addr)
{
if (&addr != this)
{
_pImpl->release();
_pImpl = addr._pImpl;
_pImpl->duplicate();
}
return *this;
}
void IPAddress::swap(IPAddress& address)
{
std::swap(_pImpl, address._pImpl);
}
IPAddress::Family IPAddress::family() const
{
return _pImpl->family();
}
Poco::UInt32 IPAddress::scope() const
{
return _pImpl->scope();
}
std::string IPAddress::toString() const
{
return _pImpl->toString();
}
bool IPAddress::isWildcard() const
{
return _pImpl->isWildcard();
}
bool IPAddress::isBroadcast() const
{
return _pImpl->isBroadcast();
}
bool IPAddress::isLoopback() const
{
return _pImpl->isLoopback();
}
bool IPAddress::isMulticast() const
{
return _pImpl->isMulticast();
}
bool IPAddress::isUnicast() const
{
return !isWildcard() && !isBroadcast() && !isMulticast();
}
bool IPAddress::isLinkLocal() const
{
return _pImpl->isLinkLocal();
}
bool IPAddress::isSiteLocal() const
{
return _pImpl->isSiteLocal();
}
bool IPAddress::isIPv4Compatible() const
{
return _pImpl->isIPv4Compatible();
}
bool IPAddress::isIPv4Mapped() const
{
return _pImpl->isIPv4Mapped();
}
bool IPAddress::isWellKnownMC() const
{
return _pImpl->isWellKnownMC();
}
bool IPAddress::isNodeLocalMC() const
{
return _pImpl->isNodeLocalMC();
}
bool IPAddress::isLinkLocalMC() const
{
return _pImpl->isLinkLocalMC();
}
bool IPAddress::isSiteLocalMC() const
{
return _pImpl->isSiteLocalMC();
}
bool IPAddress::isOrgLocalMC() const
{
return _pImpl->isOrgLocalMC();
}
bool IPAddress::isGlobalMC() const
{
return _pImpl->isGlobalMC();
}
bool IPAddress::operator == (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return std::memcmp(addr(), a.addr(), l1) == 0;
else
return false;
}
bool IPAddress::operator != (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return std::memcmp(addr(), a.addr(), l1) != 0;
else
return true;
}
bool IPAddress::operator < (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return std::memcmp(addr(), a.addr(), l1) < 0;
else
return l1 < l2;
}
bool IPAddress::operator <= (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return std::memcmp(addr(), a.addr(), l1) <= 0;
else
return l1 < l2;
}
bool IPAddress::operator > (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return std::memcmp(addr(), a.addr(), l1) > 0;
else
return l1 > l2;
}
bool IPAddress::operator >= (const IPAddress& a) const
{
poco_socklen_t l1 = length();
poco_socklen_t l2 = a.length();
if (l1 == l2)
return std::memcmp(addr(), a.addr(), l1) >= 0;
else
return l1 > l2;
}
poco_socklen_t IPAddress::length() const
{
return _pImpl->length();
}
const void* IPAddress::addr() const
{
return _pImpl->addr();
}
int IPAddress::af() const
{
return _pImpl->af();
}
void IPAddress::init(IPAddressImpl* pImpl)
{
_pImpl->release();
_pImpl = pImpl;
}
IPAddress IPAddress::parse(const std::string& addr)
{
return IPAddress(addr);
}
bool IPAddress::tryParse(const std::string& addr, IPAddress& result)
{
IPAddressImpl* pImpl = IPv4AddressImpl::parse(addr);
#if defined(POCO_HAVE_IPv6)
if (!pImpl) pImpl = IPv6AddressImpl::parse(addr);
#endif
if (pImpl)
{
result.init(pImpl);
return true;
}
else return false;
}
void IPAddress::mask(const IPAddress& mask)
{
IPAddressImpl* pClone = _pImpl->clone();
_pImpl->release();
_pImpl = pClone;
IPAddress null;
_pImpl->mask(mask._pImpl, null._pImpl);
}
void IPAddress::mask(const IPAddress& mask, const IPAddress& set)
{
IPAddressImpl* pClone = _pImpl->clone();
_pImpl->release();
_pImpl = pClone;
_pImpl->mask(mask._pImpl, set._pImpl);
}
IPAddress IPAddress::wildcard(Family family)
{
return IPAddress(family);
}
IPAddress IPAddress::broadcast()
{
struct in_addr ia;
ia.s_addr = INADDR_NONE;
return IPAddress(&ia, sizeof(ia));
}
} } // namespace Poco::Net

577
Net/src/MailMessage.cpp Normal file
View File

@@ -0,0 +1,577 @@
//
// MailMessage.cpp
//
// $Id: //poco/1.4/Net/src/MailMessage.cpp#2 $
//
// Library: Net
// Package: Mail
// Module: MailMessage
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/MailMessage.h"
#include "Poco/Net/MediaType.h"
#include "Poco/Net/MultipartReader.h"
#include "Poco/Net/MultipartWriter.h"
#include "Poco/Net/PartSource.h"
#include "Poco/Net/PartHandler.h"
#include "Poco/Net/QuotedPrintableEncoder.h"
#include "Poco/Net/QuotedPrintableDecoder.h"
#include "Poco/Base64Encoder.h"
#include "Poco/Base64Decoder.h"
#include "Poco/StreamCopier.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeParser.h"
#include "Poco/String.h"
#include "Poco/StreamCopier.h"
#include "Poco/NumberFormatter.h"
#include <sstream>
using Poco::Base64Encoder;
using Poco::Base64Decoder;
using Poco::StreamCopier;
using Poco::DateTimeFormat;
using Poco::DateTimeFormatter;
using Poco::DateTimeParser;
using Poco::icompare;
namespace Poco {
namespace Net {
namespace
{
class StringPartHandler: public PartHandler
{
public:
StringPartHandler(std::string& content):
_str(content)
{
}
~StringPartHandler()
{
}
void handlePart(const MessageHeader& header, std::istream& stream)
{
Poco::StreamCopier::copyToString(stream, _str);
}
private:
std::string& _str;
};
}
const std::string MailMessage::HEADER_SUBJECT("Subject");
const std::string MailMessage::HEADER_FROM("From");
const std::string MailMessage::HEADER_TO("To");
const std::string MailMessage::HEADER_CC("CC");
const std::string MailMessage::HEADER_BCC("BCC");
const std::string MailMessage::HEADER_DATE("Date");
const std::string MailMessage::HEADER_CONTENT_TYPE("Content-Type");
const std::string MailMessage::HEADER_CONTENT_TRANSFER_ENCODING("Content-Transfer-Encoding");
const std::string MailMessage::HEADER_CONTENT_DISPOSITION("Content-Disposition");
const std::string MailMessage::HEADER_MIME_VERSION("Mime-Version");
const std::string MailMessage::EMPTY_HEADER;
const std::string MailMessage::TEXT_PLAIN("text/plain");
const std::string MailMessage::CTE_7BIT("7bit");
const std::string MailMessage::CTE_8BIT("8bit");
const std::string MailMessage::CTE_QUOTED_PRINTABLE("quoted-printable");
const std::string MailMessage::CTE_BASE64("base64");
MailMessage::MailMessage()
{
Poco::Timestamp now;
setDate(now);
setContentType("text/plain");
}
MailMessage::~MailMessage()
{
for (PartVec::iterator it = _parts.begin(); it != _parts.end(); ++it)
{
delete it->pSource;
}
}
void MailMessage::addRecipient(const MailRecipient& recipient)
{
_recipients.push_back(recipient);
}
void MailMessage::setSender(const std::string& sender)
{
set(HEADER_FROM, sender);
}
const std::string& MailMessage::getSender() const
{
if (has(HEADER_FROM))
return get(HEADER_FROM);
else
return EMPTY_HEADER;
}
void MailMessage::setSubject(const std::string& subject)
{
set(HEADER_SUBJECT, subject);
}
const std::string& MailMessage::getSubject() const
{
if (has(HEADER_SUBJECT))
return get(HEADER_SUBJECT);
else
return EMPTY_HEADER;
}
void MailMessage::setContent(const std::string& content, ContentTransferEncoding encoding)
{
_content = content;
_encoding = encoding;
set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(encoding));
}
void MailMessage::setContentType(const std::string& mediaType)
{
set(HEADER_CONTENT_TYPE, mediaType);
}
void MailMessage::setContentType(const MediaType& mediaType)
{
setContentType(mediaType.toString());
}
const std::string& MailMessage::getContentType() const
{
if (has(HEADER_CONTENT_TYPE))
return get(HEADER_CONTENT_TYPE);
else
return TEXT_PLAIN;
}
void MailMessage::setDate(const Poco::Timestamp& dateTime)
{
set(HEADER_DATE, DateTimeFormatter::format(dateTime, DateTimeFormat::RFC1123_FORMAT));
}
Poco::Timestamp MailMessage::getDate() const
{
const std::string& dateTime = get(HEADER_DATE);
int tzd;
return DateTimeParser::parse(dateTime, tzd).timestamp();
}
bool MailMessage::isMultipart() const
{
MediaType mediaType = getContentType();
return mediaType.matches("multipart");
}
void MailMessage::addPart(const std::string& name, PartSource* pSource, ContentDisposition disposition, ContentTransferEncoding encoding)
{
poco_check_ptr (pSource);
makeMultipart();
Part part;
part.name = name;
part.pSource = pSource;
part.disposition = disposition;
part.encoding = encoding;
_parts.push_back(part);
}
void MailMessage::addContent(PartSource* pSource, ContentTransferEncoding encoding)
{
addPart("", pSource, CONTENT_INLINE, encoding);
}
void MailMessage::addAttachment(const std::string& name, PartSource* pSource, ContentTransferEncoding encoding)
{
addPart(name, pSource, CONTENT_ATTACHMENT, encoding);
}
void MailMessage::read(std::istream& istr, PartHandler& handler)
{
readHeader(istr);
if (isMultipart())
{
readMultipart(istr, handler);
}
else
{
StringPartHandler handler(_content);
readPart(istr, *this, handler);
}
}
void MailMessage::read(std::istream& istr)
{
readHeader(istr);
StringPartHandler handler(_content);
readPart(istr, *this, handler);
}
void MailMessage::write(std::ostream& ostr) const
{
MessageHeader header(*this);
setRecipientHeaders(header);
if (isMultipart())
{
writeMultipart(header, ostr);
}
else
{
writeHeader(header, ostr);
std::istringstream istr(_content);
writeEncoded(istr, ostr, _encoding);
}
}
void MailMessage::makeMultipart()
{
if (!isMultipart())
{
MediaType mediaType("multipart", "mixed");
setContentType(mediaType);
}
}
void MailMessage::writeHeader(const MessageHeader& header, std::ostream& ostr) const
{
header.write(ostr);
ostr << "\r\n";
}
void MailMessage::writeMultipart(MessageHeader& header, std::ostream& ostr) const
{
std::string boundary(MultipartWriter::createBoundary());
MediaType mediaType(getContentType());
mediaType.setParameter("boundary", boundary);
header.set(HEADER_CONTENT_TYPE, mediaType.toString());
header.set(HEADER_MIME_VERSION, "1.0");
writeHeader(header, ostr);
MultipartWriter writer(ostr, boundary);
for (PartVec::const_iterator it = _parts.begin(); it != _parts.end(); ++it)
{
writePart(writer, *it);
}
writer.close();
}
void MailMessage::writePart(MultipartWriter& writer, const Part& part) const
{
MessageHeader partHeader(part.pSource->headers());
MediaType mediaType(part.pSource->mediaType());
if (!part.name.empty())
mediaType.setParameter("name", part.name);
partHeader.set(HEADER_CONTENT_TYPE, mediaType.toString());
partHeader.set(HEADER_CONTENT_TRANSFER_ENCODING, contentTransferEncodingToString(part.encoding));
std::string disposition;
if (part.disposition == CONTENT_ATTACHMENT)
{
disposition = "attachment";
const std::string& filename = part.pSource->filename();
if (!filename.empty())
{
disposition.append("; filename=");
quote(filename, disposition);
}
}
else disposition = "inline";
partHeader.set(HEADER_CONTENT_DISPOSITION, disposition);
writer.nextPart(partHeader);
writeEncoded(part.pSource->stream(), writer.stream(), part.encoding);
}
void MailMessage::writeEncoded(std::istream& istr, std::ostream& ostr, ContentTransferEncoding encoding) const
{
switch (encoding)
{
case ENCODING_7BIT:
case ENCODING_8BIT:
StreamCopier::copyStream(istr, ostr);
break;
case ENCODING_QUOTED_PRINTABLE:
{
QuotedPrintableEncoder encoder(ostr);
StreamCopier::copyStream(istr, encoder);
encoder.close();
}
break;
case ENCODING_BASE64:
{
Base64Encoder encoder(ostr);
StreamCopier::copyStream(istr, encoder);
encoder.close();
}
break;
}
}
void MailMessage::readHeader(std::istream& istr)
{
clear();
MessageHeader::read(istr);
istr.get(); // \r
istr.get(); // \n
}
void MailMessage::readMultipart(std::istream& istr, PartHandler& handler)
{
MediaType contentType(getContentType());
std::string boundary = contentType.getParameter("boundary");
MultipartReader reader(istr, boundary);
while (reader.hasNextPart())
{
MessageHeader partHeader;
reader.nextPart(partHeader);
readPart(reader.stream(), partHeader, handler);
}
}
void MailMessage::readPart(std::istream& istr, const MessageHeader& header, PartHandler& handler)
{
std::string encoding;
if (header.has(HEADER_CONTENT_TRANSFER_ENCODING))
{
encoding = header.get(HEADER_CONTENT_TRANSFER_ENCODING);
// get rid of a parameter if one is set
std::string::size_type pos = encoding.find(';');
if (pos != std::string::npos)
encoding.resize(pos);
}
if (icompare(encoding, CTE_QUOTED_PRINTABLE) == 0)
{
QuotedPrintableDecoder decoder(istr);
handlePart(decoder, header, handler);
}
else if (icompare(encoding, CTE_BASE64) == 0)
{
Base64Decoder decoder(istr);
handlePart(decoder, header, handler);
}
else
{
handlePart(istr, header, handler);
}
}
void MailMessage::handlePart(std::istream& istr, const MessageHeader& header, PartHandler& handler)
{
handler.handlePart(header, istr);
// Read remaining characters from stream in case
// the handler failed to read the complete stream.
while (istr.good()) istr.get();
}
void MailMessage::setRecipientHeaders(MessageHeader& headers) const
{
std::string to;
std::string cc;
std::string bcc;
for (Recipients::const_iterator it = _recipients.begin(); it != _recipients.end(); ++it)
{
switch (it->getType())
{
case MailRecipient::PRIMARY_RECIPIENT:
appendRecipient(*it, to);
break;
case MailRecipient::CC_RECIPIENT:
appendRecipient(*it, cc);
break;
case MailRecipient::BCC_RECIPIENT:
break;
}
}
if (!to.empty()) headers.set(HEADER_TO, to);
if (!cc.empty()) headers.set(HEADER_CC, cc);
}
const std::string& MailMessage::contentTransferEncodingToString(ContentTransferEncoding encoding)
{
switch (encoding)
{
case ENCODING_7BIT:
return CTE_7BIT;
case ENCODING_8BIT:
return CTE_8BIT;
case ENCODING_QUOTED_PRINTABLE:
return CTE_QUOTED_PRINTABLE;
case ENCODING_BASE64:
return CTE_BASE64;
default:
poco_bugcheck();
}
return CTE_7BIT;
}
int MailMessage::lineLength(const std::string& str)
{
int n = 0;
std::string::const_reverse_iterator it = str.rbegin();
std::string::const_reverse_iterator end = str.rend();
while (it != end && *it != '\n') { ++n; ++it; }
return n;
}
void MailMessage::appendRecipient(const MailRecipient& recipient, std::string& str)
{
if (!str.empty()) str.append(", ");
const std::string& realName = recipient.getRealName();
const std::string& address = recipient.getAddress();
std::string rec;
if (!realName.empty())
{
quote(realName, rec, true);
rec.append(" ");
}
rec.append("<");
rec.append(address);
rec.append(">");
if (lineLength(str) + rec.length() > 70) str.append("\r\n\t");
str.append(rec);
}
std::string MailMessage::encodeWord(const std::string& text, const std::string& charset)
{
bool containsNonASCII = false;
for (std::string::const_iterator it = text.begin(); it != text.end(); ++it)
{
if (static_cast<unsigned char>(*it) > 127)
{
containsNonASCII = true;
break;
}
}
if (!containsNonASCII) return text;
std::string encodedText;
std::string::size_type lineLength = 0;
for (std::string::const_iterator it = text.begin(); it != text.end(); ++it)
{
if (lineLength == 0)
{
encodedText += "=?";
encodedText += charset;
encodedText += "?q?";
lineLength += charset.length() + 5;
}
switch (*it)
{
case ' ':
encodedText += '_';
lineLength++;
break;
case '=':
case '?':
case '_':
case '(':
case ')':
case '[':
case ']':
case '<':
case '>':
case ',':
case ';':
case ':':
case '.':
case '@':
encodedText += '=';
NumberFormatter::appendHex(encodedText, static_cast<unsigned>(static_cast<unsigned char>(*it)), 2);
lineLength += 3;
break;
default:
if (*it > 32 && *it < 127)
{
encodedText += *it;
lineLength++;
}
else
{
encodedText += '=';
NumberFormatter::appendHex(encodedText, static_cast<unsigned>(static_cast<unsigned char>(*it)), 2);
lineLength += 3;
}
}
if ((lineLength >= 64 && (*it == ' ' || *it == '\t' || *it == '\r' || *it == '\n')) || lineLength >= 72)
{
encodedText += "?=\r\n ";
lineLength = 0;
}
}
if (lineLength > 0)
{
encodedText += "?=";
}
return encodedText;
}
} } // namespace Poco::Net

116
Net/src/MailRecipient.cpp Normal file
View File

@@ -0,0 +1,116 @@
//
// MailRecipient.cpp
//
// $Id: //poco/1.4/Net/src/MailRecipient.cpp#1 $
//
// Library: Net
// Package: Mail
// Module: MailRecipient
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/MailRecipient.h"
#include <algorithm>
namespace Poco {
namespace Net {
MailRecipient::MailRecipient():
_type(PRIMARY_RECIPIENT)
{
}
MailRecipient::MailRecipient(const MailRecipient& recipient):
_address(recipient._address),
_realName(recipient._realName),
_type(recipient._type)
{
}
MailRecipient::MailRecipient(RecipientType type, const std::string& address):
_address(address),
_type(type)
{
}
MailRecipient::MailRecipient(RecipientType type, const std::string& address, const std::string& realName):
_address(address),
_realName(realName),
_type(type)
{
}
MailRecipient::~MailRecipient()
{
}
MailRecipient& MailRecipient::operator = (const MailRecipient& recipient)
{
if (this != &recipient)
{
MailRecipient tmp(recipient);
swap(tmp);
}
return *this;
}
void MailRecipient::swap(MailRecipient& recipient)
{
std::swap(_type, recipient._type);
std::swap(_address, recipient._address);
std::swap(_realName, recipient._realName);
}
void MailRecipient::setType(RecipientType type)
{
_type = type;
}
void MailRecipient::setAddress(const std::string& address)
{
_address = address;
}
void MailRecipient::setRealName(const std::string& realName)
{
_realName = realName;
}
} } // namespace Poco::Net

241
Net/src/MailStream.cpp Normal file
View File

@@ -0,0 +1,241 @@
//
// MailStream.cpp
//
// $Id: //poco/1.4/Net/src/MailStream.cpp#1 $
//
// Library: Net
// Package: Mail
// Module: MailStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/MailStream.h"
namespace Poco {
namespace Net {
MailStreamBuf::MailStreamBuf(std::istream& istr):
_pIstr(&istr),
_pOstr(0),
_state(ST_CR_LF)
{
}
MailStreamBuf::MailStreamBuf(std::ostream& ostr):
_pIstr(0),
_pOstr(&ostr),
_state(ST_CR_LF)
{
}
MailStreamBuf::~MailStreamBuf()
{
}
void MailStreamBuf::close()
{
if (_pOstr && _state != ST_CR_LF_DOT_CR_LF)
{
if (!_buffer.empty())
_pOstr->write(_buffer.data(), (std::streamsize) _buffer.length());
if (_state != ST_CR_LF)
_pOstr->write("\r\n", 2);
_pOstr->write(".\r\n", 3);
_state = ST_CR_LF_DOT_CR_LF;
}
}
int MailStreamBuf::readFromDevice()
{
int c = std::char_traits<char>::eof();
if (!_buffer.empty())
{
c = _buffer[0];
_buffer.erase(0, 1);
}
else
{
c = readOne();
while (c != std::char_traits<char>::eof() && _state != ST_DATA && _state != ST_CR_LF_DOT_CR_LF)
c = readOne();
if (!_buffer.empty())
{
c = _buffer[0];
_buffer.erase(0, 1);
}
}
return c;
}
int MailStreamBuf::readOne()
{
int c = std::char_traits<char>::eof();
if (_state != ST_CR_LF_DOT_CR_LF)
{
c = _pIstr->get();
switch (c)
{
case '\r':
if (_state == ST_CR_LF_DOT)
_state = ST_CR_LF_DOT_CR;
else
_state = ST_CR;
break;
case '\n':
if (_state == ST_CR)
_state = ST_CR_LF;
else if (_state == ST_CR_LF_DOT_CR)
_state = ST_CR_LF_DOT_CR_LF;
else
_state = ST_DATA;
break;
case '.':
if (_state == ST_CR_LF)
_state = ST_CR_LF_DOT;
else if (_state == ST_CR_LF_DOT)
_state = ST_CR_LF_DOT_DOT;
else
_state = ST_DATA;
break;
default:
_state = ST_DATA;
}
if (_state == ST_CR_LF_DOT_DOT)
_state = ST_DATA;
else if (_state == ST_CR_LF_DOT_CR_LF)
_buffer.resize(_buffer.size() - 2);
else if (c != std::char_traits<char>::eof())
_buffer += (char) c;
}
return c;
}
int MailStreamBuf::writeToDevice(char c)
{
switch (c)
{
case '\r':
_state = ST_CR;
break;
case '\n':
if (_state == ST_CR)
_state = ST_CR_LF;
else
_state = ST_DATA;
break;
case '.':
if (_state == ST_CR_LF)
_state = ST_CR_LF_DOT;
else
_state = ST_DATA;
break;
default:
_state = ST_DATA;
}
if (_state == ST_DATA)
{
if (!_buffer.empty())
{
_pOstr->write(_buffer.data(), (std::streamsize) _buffer.length());
_buffer.clear();
}
_pOstr->put(c);
}
else if (_state == ST_CR_LF_DOT)
{
_pOstr->write("\r\n..", 4);
_state = ST_DATA;
_buffer.clear();
}
else _buffer += c;
return charToInt(c);
}
MailIOS::MailIOS(std::istream& istr): _buf(istr)
{
poco_ios_init(&_buf);
}
MailIOS::MailIOS(std::ostream& ostr): _buf(ostr)
{
poco_ios_init(&_buf);
}
MailIOS::~MailIOS()
{
}
void MailIOS::close()
{
_buf.close();
}
MailStreamBuf* MailIOS::rdbuf()
{
return &_buf;
}
MailInputStream::MailInputStream(std::istream& istr):
MailIOS(istr),
std::istream(&_buf)
{
}
MailInputStream::~MailInputStream()
{
}
MailOutputStream::MailOutputStream(std::ostream& ostr):
MailIOS(ostr),
std::ostream(&_buf)
{
}
MailOutputStream::~MailOutputStream()
{
}
} } // namespace Poco::Net

213
Net/src/MediaType.cpp Normal file
View File

@@ -0,0 +1,213 @@
//
// MediaType.cpp
//
// $Id: //poco/1.4/Net/src/MediaType.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: MediaType
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/MediaType.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/String.h"
#include "Poco/Ascii.h"
#include <algorithm>
using Poco::icompare;
namespace Poco {
namespace Net {
MediaType::MediaType(const std::string& mediaType)
{
parse(mediaType);
}
MediaType::MediaType(const std::string& type, const std::string& subType):
_type(type),
_subType(subType)
{
}
MediaType::MediaType(const MediaType& mediaType):
_type(mediaType._type),
_subType(mediaType._subType),
_parameters(mediaType._parameters)
{
}
MediaType::~MediaType()
{
}
MediaType& MediaType::operator = (const MediaType& mediaType)
{
if (&mediaType != this)
{
_type = mediaType._type;
_subType = mediaType._subType;
_parameters = mediaType._parameters;
}
return *this;
}
MediaType& MediaType::operator = (const std::string& mediaType)
{
parse(mediaType);
return *this;
}
void MediaType::swap(MediaType& mediaType)
{
std::swap(_type, mediaType._type);
std::swap(_subType, mediaType._subType);
_parameters.swap(mediaType._parameters);
}
void MediaType::setType(const std::string& type)
{
_type = type;
}
void MediaType::setSubType(const std::string& subType)
{
_subType = subType;
}
void MediaType::setParameter(const std::string& name, const std::string& value)
{
_parameters.set(name, value);
}
const std::string& MediaType::getParameter(const std::string& name) const
{
return _parameters.get(name);
}
bool MediaType::hasParameter(const std::string& name) const
{
return _parameters.has(name);
}
void MediaType::removeParameter(const std::string& name)
{
_parameters.erase(name);
}
std::string MediaType::toString() const
{
std::string result;
result.append(_type);
result.append("/");
result.append(_subType);
for (NameValueCollection::ConstIterator it = _parameters.begin(); it != _parameters.end(); ++it)
{
result.append("; ");
result.append(it->first);
result.append("=");
MessageHeader::quote(it->second, result);
}
return result;
}
bool MediaType::matches(const MediaType& mediaType) const
{
return matches(mediaType._type, mediaType._subType);
}
bool MediaType::matches(const std::string& type, const std::string& subType) const
{
return icompare(_type, type) == 0 && icompare(_subType, subType) == 0;
}
bool MediaType::matches(const std::string& type) const
{
return icompare(_type, type) == 0;
}
bool MediaType::matchesRange(const MediaType& mediaType) const
{
return matchesRange(mediaType._type, mediaType._subType);
}
bool MediaType::matchesRange(const std::string& type, const std::string& subType) const
{
if (_type == "*" || type == "*" || icompare(_type, type) == 0)
{
return _subType == "*" || subType == "*" || icompare(_subType, subType) == 0;
}
else return false;
}
bool MediaType::matchesRange(const std::string& type) const
{
return _type == "*" || type == "*" || matches(type);
}
void MediaType::parse(const std::string& mediaType)
{
_type.clear();
_subType.clear();
_parameters.clear();
std::string::const_iterator it = mediaType.begin();
std::string::const_iterator end = mediaType.end();
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
while (it != end && *it != '/') _type += *it++;
if (it != end) ++it;
while (it != end && *it != ';' && !Poco::Ascii::isSpace(*it)) _subType += *it++;
while (it != end && *it != ';') ++it;
MessageHeader::splitParameters(it, end, _parameters);
}
} } // namespace Poco::Net

263
Net/src/MessageHeader.cpp Normal file
View File

@@ -0,0 +1,263 @@
//
// MessageHeader.cpp
//
// $Id: //poco/1.4/Net/src/MessageHeader.cpp#4 $
//
// Library: Net
// Package: Messages
// Module: MessageHeader
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/NetException.h"
#include "Poco/String.h"
#include "Poco/Ascii.h"
namespace Poco {
namespace Net {
MessageHeader::MessageHeader():
_fieldLimit(DFL_FIELD_LIMIT)
{
}
MessageHeader::MessageHeader(const MessageHeader& messageHeader):
NameValueCollection(messageHeader),
_fieldLimit(DFL_FIELD_LIMIT)
{
}
MessageHeader::~MessageHeader()
{
}
MessageHeader& MessageHeader::operator = (const MessageHeader& messageHeader)
{
NameValueCollection::operator = (messageHeader);
return *this;
}
void MessageHeader::write(std::ostream& ostr) const
{
NameValueCollection::ConstIterator it = begin();
while (it != end())
{
ostr << it->first << ": " << it->second << "\r\n";
++it;
}
}
void MessageHeader::read(std::istream& istr)
{
static const int eof = std::char_traits<char>::eof();
std::streambuf& buf = *istr.rdbuf();
std::string name;
std::string value;
name.reserve(32);
value.reserve(64);
int ch = buf.sbumpc();
int fields = 0;
while (ch != eof && ch != '\r' && ch != '\n')
{
if (_fieldLimit > 0 && fields == _fieldLimit)
throw MessageException("Too many header fields");
name.clear();
value.clear();
while (ch != eof && ch != ':' && ch != '\n' && name.length() < MAX_NAME_LENGTH) { name += ch; ch = buf.sbumpc(); }
if (ch == '\n') { ch = buf.sbumpc(); continue; } // ignore invalid header lines
if (ch != ':') throw MessageException("Field name too long/no colon found");
if (ch != eof) ch = buf.sbumpc(); // ':'
while (ch != eof && Poco::Ascii::isSpace(ch) && ch != '\r' && ch != '\n') ch = buf.sbumpc();
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += ch; ch = buf.sbumpc(); }
if (ch == '\r') ch = buf.sbumpc();
if (ch == '\n')
ch = buf.sbumpc();
else if (ch != eof)
throw MessageException("Field value too long/no CRLF found");
while (ch == ' ' || ch == '\t') // folding
{
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += ch; ch = buf.sbumpc(); }
if (ch == '\r') ch = buf.sbumpc();
if (ch == '\n')
ch = buf.sbumpc();
else if (ch != eof)
throw MessageException("Folded field value too long/no CRLF found");
}
Poco::trimRightInPlace(value);
add(name, value);
++fields;
}
istr.putback(ch);
}
int MessageHeader::getFieldLimit() const
{
return _fieldLimit;
}
void MessageHeader::setFieldLimit(int limit)
{
poco_assert (limit >= 0);
_fieldLimit = limit;
}
void MessageHeader::splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty)
{
elements.clear();
std::string::const_iterator it = s.begin();
std::string::const_iterator end = s.end();
std::string elem;
elem.reserve(64);
while (it != end)
{
if (*it == '"')
{
elem += *it++;
while (it != end && *it != '"')
{
if (*it == '\\')
{
++it;
if (it != end) elem += *it++;
}
else elem += *it++;
}
if (it != end) elem += *it++;
}
else if (*it == '\\')
{
++it;
if (it != end) elem += *it++;
}
else if (*it == ',')
{
Poco::trimInPlace(elem);
if (!ignoreEmpty || !elem.empty())
elements.push_back(elem);
elem.clear();
++it;
}
else elem += *it++;
}
if (!elem.empty())
{
Poco::trimInPlace(elem);
if (!ignoreEmpty || !elem.empty())
elements.push_back(elem);
}
}
void MessageHeader::splitParameters(const std::string& s, std::string& value, NameValueCollection& parameters)
{
value.clear();
parameters.clear();
std::string::const_iterator it = s.begin();
std::string::const_iterator end = s.end();
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
while (it != end && *it != ';') value += *it++;
Poco::trimRightInPlace(value);
if (it != end) ++it;
splitParameters(it, end, parameters);
}
void MessageHeader::splitParameters(const std::string::const_iterator& begin, const std::string::const_iterator& end, NameValueCollection& parameters)
{
std::string pname;
std::string pvalue;
pname.reserve(32);
pvalue.reserve(64);
std::string::const_iterator it = begin;
while (it != end)
{
pname.clear();
pvalue.clear();
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
while (it != end && *it != '=' && *it != ';') pname += *it++;
Poco::trimRightInPlace(pname);
if (it != end && *it != ';') ++it;
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
while (it != end && *it != ';')
{
if (*it == '"')
{
++it;
while (it != end && *it != '"')
{
if (*it == '\\')
{
++it;
if (it != end) pvalue += *it++;
}
else pvalue += *it++;
}
if (it != end) ++it;
}
else if (*it == '\\')
{
++it;
if (it != end) pvalue += *it++;
}
else pvalue += *it++;
}
Poco::trimRightInPlace(pvalue);
if (!pname.empty()) parameters.add(pname, pvalue);
if (it != end) ++it;
}
}
void MessageHeader::quote(const std::string& value, std::string& result, bool allowSpace)
{
bool mustQuote = false;
for (std::string::const_iterator it = value.begin(); !mustQuote && it != value.end(); ++it)
{
if (!Poco::Ascii::isAlphaNumeric(*it) && *it != '.' && *it != '_' && *it != '-' && !(Poco::Ascii::isSpace(*it) && allowSpace))
mustQuote = true;
}
if (mustQuote) result += '"';
result.append(value);
if (mustQuote) result += '"';
}
} } // namespace Poco::Net

263
Net/src/MulticastSocket.cpp Normal file
View File

@@ -0,0 +1,263 @@
//
// MulticastSocket.cpp
//
// $Id: //poco/1.4/Net/src/MulticastSocket.cpp#1 $
//
// Library: Net
// Package: Sockets
// Module: MulticastSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/MulticastSocket.h"
#include "Poco/Net/NetException.h"
#include <cstring>
#if defined(hpux) && defined(_XOPEN_SOURCE_EXTENDED) && defined(POCO_HPUX_IP_MREQ_HACK)
// netinet/in.h does not define struct ip_mreq if
// _XOPEN_SOURCE_EXTENDED is #define'd in HP-UX 11.x
// versions prior to 11.30. Compile with -DPOCO_HPUX_IP_MREQ_HACK
// if you experience problems.
struct ip_mreq
{
struct in_addr imr_multiaddr;
struct in_addr imr_interface;
};
#endif
// some Unix variants don't have IPV6_ADD_MEMBERSHIP/IPV6_DROP_MEMBERSHIP
#if defined(IPV6_JOIN_GROUP) && !defined(IPV6_ADD_MEMBERSHIP)
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
#endif
namespace Poco {
namespace Net {
MulticastSocket::MulticastSocket()
{
}
MulticastSocket::MulticastSocket(IPAddress::Family family): DatagramSocket(family)
{
}
MulticastSocket::MulticastSocket(const SocketAddress& address, bool reuseAddress): DatagramSocket(address, reuseAddress)
{
}
MulticastSocket::MulticastSocket(const Socket& socket): DatagramSocket(socket)
{
}
MulticastSocket::~MulticastSocket()
{
}
MulticastSocket& MulticastSocket::operator = (const Socket& socket)
{
DatagramSocket::operator = (socket);
return *this;
}
void MulticastSocket::setInterface(const NetworkInterface& interfc)
{
if (!interfc.supportsIPv6())
{
impl()->setOption(IPPROTO_IP, IP_MULTICAST_IF, interfc.address());
}
else
{
#if defined(POCO_HAVE_IPv6)
impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, interfc.index());
#endif
}
}
NetworkInterface MulticastSocket::getInterface() const
{
try
{
IPAddress addr;
impl()->getOption(IPPROTO_IP, IP_MULTICAST_IF, addr);
return NetworkInterface::forAddress(addr);
}
catch (Poco::Exception&)
{
#if defined(POCO_HAVE_IPv6)
int ix;
impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, ix);
return NetworkInterface::forIndex(ix);
#else
throw;
#endif
}
}
void MulticastSocket::setLoopback(bool flag)
{
if (address().af() == AF_INET)
{
unsigned char uflag = flag ? 1 : 0;
impl()->setOption(IPPROTO_IP, IP_MULTICAST_LOOP, uflag);
}
else
{
#if defined(POCO_HAVE_IPv6)
unsigned uflag = flag ? 1 : 0;
impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, uflag);
#endif
}
}
bool MulticastSocket::getLoopback() const
{
bool flag = false;
if (address().af() == AF_INET)
{
unsigned char uflag;
impl()->getOption(IPPROTO_IP, IP_MULTICAST_LOOP, uflag);
flag = uflag != 0;
}
else
{
#if defined(POCO_HAVE_IPv6)
unsigned uflag;
impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_LOOP, uflag);
flag = uflag != 0;
#endif
}
return flag;
}
void MulticastSocket::setTimeToLive(unsigned value)
{
if (address().af() == AF_INET)
{
unsigned char ttl = (unsigned char) value;
impl()->setOption(IPPROTO_IP, IP_MULTICAST_TTL, ttl);
}
else
{
#if defined(POCO_HAVE_IPv6)
impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, value);
#endif
}
}
unsigned MulticastSocket::getTimeToLive() const
{
unsigned ttl(0);
if (address().af() == AF_INET)
{
unsigned char cttl;
impl()->getOption(IPPROTO_IP, IP_MULTICAST_TTL, cttl);
ttl = cttl;
}
else
{
#if defined(POCO_HAVE_IPv6)
impl()->getOption(IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl);
#endif
}
return ttl;
}
void MulticastSocket::joinGroup(const IPAddress& groupAddress)
{
NetworkInterface intf;
joinGroup(groupAddress, intf);
}
void MulticastSocket::joinGroup(const IPAddress& groupAddress, const NetworkInterface& interfc)
{
if (groupAddress.af() == AF_INET)
{
struct ip_mreq mr;
std::memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length());
std::memcpy(&mr.imr_interface, interfc.address().addr(), interfc.address().length());
impl()->setRawOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr));
}
else
{
#if defined(POCO_HAVE_IPv6)
struct ipv6_mreq mr;
std::memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length());
mr.ipv6mr_interface = interfc.index();
impl()->setRawOption(IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(mr));
#endif
}
}
void MulticastSocket::leaveGroup(const IPAddress& groupAddress)
{
NetworkInterface intf;
leaveGroup(groupAddress, intf);
}
void MulticastSocket::leaveGroup(const IPAddress& groupAddress, const NetworkInterface& interfc)
{
if (groupAddress.af() == AF_INET)
{
struct ip_mreq mr;
std::memcpy(&mr.imr_multiaddr, groupAddress.addr(), groupAddress.length());
std::memcpy(&mr.imr_interface, interfc.address().addr(), interfc.address().length());
impl()->setRawOption(IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr));
}
else
{
#if defined(POCO_HAVE_IPv6)
struct ipv6_mreq mr;
std::memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length());
mr.ipv6mr_interface = interfc.index();
impl()->setRawOption(IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mr, sizeof(mr));
#endif
}
}
} } // namespace Poco::Net

320
Net/src/MultipartReader.cpp Normal file
View File

@@ -0,0 +1,320 @@
//
// MultipartReader.cpp
//
// $Id: //poco/1.4/Net/src/MultipartReader.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: MultipartReader
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/MultipartReader.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/Net/NetException.h"
#include "Poco/Ascii.h"
using Poco::BufferedStreamBuf;
namespace Poco {
namespace Net {
//
// MultipartStreamBuf
//
MultipartStreamBuf::MultipartStreamBuf(std::istream& istr, const std::string& boundary):
BufferedStreamBuf(STREAM_BUFFER_SIZE, std::ios::in),
_istr(istr),
_boundary(boundary),
_lastPart(false)
{
poco_assert (!boundary.empty() && boundary.length() < STREAM_BUFFER_SIZE - 6);
}
MultipartStreamBuf::~MultipartStreamBuf()
{
}
int MultipartStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
poco_assert_dbg (length >= _boundary.length() + 6);
static const int eof = std::char_traits<char>::eof();
std::streambuf& buf = *_istr.rdbuf();
int n = 0;
int ch = buf.sbumpc();
if (ch == eof) return -1;
*buffer++ = (char) ch; ++n;
if (ch == '\n' || (ch == '\r' && buf.sgetc() == '\n'))
{
if (ch == '\r')
{
ch = buf.sbumpc(); // '\n'
*buffer++ = (char) ch; ++n;
}
ch = buf.sgetc();
if (ch == '\r' || ch == '\n') return n;
*buffer++ = (char) buf.sbumpc(); ++n;
if (ch == '-' && buf.sgetc() == '-')
{
ch = buf.sbumpc(); // '-'
*buffer++ = (char) ch; ++n;
std::string::const_iterator it = _boundary.begin();
std::string::const_iterator end = _boundary.end();
ch = buf.sbumpc();
*buffer++ = (char) ch; ++n;
while (it != end && ch == *it)
{
++it;
ch = buf.sbumpc();
*buffer++ = (char) ch; ++n;
}
if (it == end)
{
if (ch == '\n' || (ch == '\r' && buf.sgetc() == '\n'))
{
if (ch == '\r')
{
ch = buf.sbumpc(); // '\n'
}
return 0;
}
else if (ch == '-' && buf.sgetc() == '-')
{
ch = buf.sbumpc(); // '-'
_lastPart = true;
return 0;
}
}
}
}
ch = buf.sgetc();
while (ch != eof && ch != '\r' && ch != '\n' && n < length)
{
*buffer++ = (char) buf.sbumpc(); ++n;
ch = buf.sgetc();
}
return n;
}
bool MultipartStreamBuf::lastPart() const
{
return _lastPart;
}
//
// MultipartIOS
//
MultipartIOS::MultipartIOS(std::istream& istr, const std::string& boundary):
_buf(istr, boundary)
{
poco_ios_init(&_buf);
}
MultipartIOS::~MultipartIOS()
{
_buf.sync();
}
MultipartStreamBuf* MultipartIOS::rdbuf()
{
return &_buf;
}
bool MultipartIOS::lastPart() const
{
return _buf.lastPart();
}
//
// MultipartInputStream
//
MultipartInputStream::MultipartInputStream(std::istream& istr, const std::string& boundary):
MultipartIOS(istr, boundary),
std::istream(&_buf)
{
}
MultipartInputStream::~MultipartInputStream()
{
}
//
// MultipartReader
//
MultipartReader::MultipartReader(std::istream& istr):
_istr(istr),
_pMPI(0)
{
}
MultipartReader::MultipartReader(std::istream& istr, const std::string& boundary):
_istr(istr),
_boundary(boundary),
_pMPI(0)
{
}
MultipartReader::~MultipartReader()
{
delete _pMPI;
}
void MultipartReader::nextPart(MessageHeader& messageHeader)
{
if (!_pMPI)
{
if (_boundary.empty())
guessBoundary();
else
findFirstBoundary();
}
else if (_pMPI->lastPart())
{
throw MultipartException("No more parts available");
}
parseHeader(messageHeader);
delete _pMPI;
_pMPI = new MultipartInputStream(_istr, _boundary);
}
bool MultipartReader::hasNextPart()
{
return (!_pMPI || !_pMPI->lastPart()) && _istr.good();
}
std::istream& MultipartReader::stream() const
{
poco_check_ptr (_pMPI);
return *_pMPI;
}
const std::string& MultipartReader::boundary() const
{
return _boundary;
}
void MultipartReader::findFirstBoundary()
{
std::string expect("--");
expect.append(_boundary);
std::string line;
line.reserve(expect.length());
bool ok = true;
do
{
ok = readLine(line, expect.length());
}
while (ok && line != expect);
if (!ok) throw MultipartException("No boundary line found");
}
void MultipartReader::guessBoundary()
{
static const int eof = std::char_traits<char>::eof();
int ch = _istr.get();
while (Poco::Ascii::isSpace(ch))
ch = _istr.get();
if (ch == '-' && _istr.peek() == '-')
{
_istr.get();
ch = _istr.peek();
while (ch != eof && ch != '\r' && ch != '\n')
{
_boundary += (char) _istr.get();
ch = _istr.peek();
}
if (ch == '\r' || ch == '\n')
ch = _istr.get();
if (_istr.peek() == '\n')
_istr.get();
}
else throw MultipartException("No boundary line found");
}
void MultipartReader::parseHeader(MessageHeader& messageHeader)
{
messageHeader.clear();
messageHeader.read(_istr);
int ch = _istr.get();
if (ch == '\r' && _istr.peek() == '\n') ch = _istr.get();
}
bool MultipartReader::readLine(std::string& line, std::string::size_type n)
{
static const int eof = std::char_traits<char>::eof();
line.clear();
int ch = _istr.peek();
while (ch != eof && ch != '\r' && ch != '\n')
{
ch = (char) _istr.get();
if (line.length() < n) line += ch;
ch = _istr.peek();
}
if (ch != eof) _istr.get();
if (ch == '\r' && _istr.peek() == '\n') _istr.get();
return ch != eof;
}
} } // namespace Poco::Net

108
Net/src/MultipartWriter.cpp Normal file
View File

@@ -0,0 +1,108 @@
//
// MultipartWriter.cpp
//
// $Id: //poco/1.4/Net/src/MultipartWriter.cpp#1 $
//
// Library: Net
// Package: Messages
// Module: MultipartWriter
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/MultipartWriter.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/Random.h"
#include "Poco/NumberFormatter.h"
using Poco::Random;
using Poco::NumberFormatter;
namespace Poco {
namespace Net {
MultipartWriter::MultipartWriter(std::ostream& ostr):
_ostr(ostr),
_boundary(createBoundary()),
_firstPart(true)
{
}
MultipartWriter::MultipartWriter(std::ostream& ostr, const std::string& boundary):
_ostr(ostr),
_boundary(boundary),
_firstPart(true)
{
if (_boundary.empty())
_boundary = createBoundary();
}
MultipartWriter::~MultipartWriter()
{
}
void MultipartWriter::nextPart(const MessageHeader& header)
{
if (_firstPart)
_firstPart = false;
else
_ostr << "\r\n";
_ostr << "--" << _boundary << "\r\n";
header.write(_ostr);
_ostr << "\r\n";
}
void MultipartWriter::close()
{
_ostr << "\r\n--" << _boundary << "--\r\n";
}
const std::string& MultipartWriter::boundary() const
{
return _boundary;
}
std::string MultipartWriter::createBoundary()
{
std::string boundary("MIME_boundary_");
Random rnd;
NumberFormatter::appendHex(boundary, rnd.next(), 8);
NumberFormatter::appendHex(boundary, rnd.next(), 8);
return boundary;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,175 @@
//
// NameValueCollection.cpp
//
// $Id: //poco/1.4/Net/src/NameValueCollection.cpp#1 $
//
// Library: Net
// Package: Messages
// Module: NameValueCollection
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/NameValueCollection.h"
#include "Poco/Exception.h"
#include <algorithm>
using Poco::NotFoundException;
namespace Poco {
namespace Net {
NameValueCollection::NameValueCollection()
{
}
NameValueCollection::NameValueCollection(const NameValueCollection& nvc):
_map(nvc._map)
{
}
NameValueCollection::~NameValueCollection()
{
}
NameValueCollection& NameValueCollection::operator = (const NameValueCollection& nvc)
{
if (&nvc != this)
{
_map = nvc._map;
}
return *this;
}
void NameValueCollection::swap(NameValueCollection& nvc)
{
std::swap(_map, nvc._map);
}
const std::string& NameValueCollection::operator [] (const std::string& name) const
{
ConstIterator it = _map.find(name);
if (it != _map.end())
return it->second;
else
throw NotFoundException(name);
}
void NameValueCollection::set(const std::string& name, const std::string& value)
{
Iterator it = _map.find(name);
if (it != _map.end())
it->second = value;
else
_map.insert(HeaderMap::value_type(name, value));
}
void NameValueCollection::add(const std::string& name, const std::string& value)
{
_map.insert(HeaderMap::value_type(name, value));
}
const std::string& NameValueCollection::get(const std::string& name) const
{
ConstIterator it = _map.find(name);
if (it != _map.end())
return it->second;
else
throw NotFoundException(name);
}
const std::string& NameValueCollection::get(const std::string& name, const std::string& defaultValue) const
{
ConstIterator it = _map.find(name);
if (it != _map.end())
return it->second;
else
return defaultValue;
}
bool NameValueCollection::has(const std::string& name) const
{
return _map.find(name) != _map.end();
}
NameValueCollection::ConstIterator NameValueCollection::find(const std::string& name) const
{
return _map.find(name);
}
NameValueCollection::ConstIterator NameValueCollection::begin() const
{
return _map.begin();
}
NameValueCollection::ConstIterator NameValueCollection::end() const
{
return _map.end();
}
bool NameValueCollection::empty() const
{
return _map.empty();
}
int NameValueCollection::size() const
{
return (int) _map.size();
}
void NameValueCollection::erase(const std::string& name)
{
_map.erase(name);
}
void NameValueCollection::clear()
{
_map.clear();
}
} } // namespace Poco::Net

73
Net/src/NetException.cpp Normal file
View File

@@ -0,0 +1,73 @@
//
// NetException.cpp
//
// $Id: //poco/1.4/Net/src/NetException.cpp#4 $
//
// Library: Net
// Package: NetCore
// Module: NetException
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/NetException.h"
#include <typeinfo>
using Poco::IOException;
namespace Poco {
namespace Net {
POCO_IMPLEMENT_EXCEPTION(NetException, IOException, "Net Exception")
POCO_IMPLEMENT_EXCEPTION(InvalidAddressException, NetException, "Invalid address")
POCO_IMPLEMENT_EXCEPTION(InvalidSocketException, NetException, "Invalid socket")
POCO_IMPLEMENT_EXCEPTION(ServiceNotFoundException, NetException, "Service not found")
POCO_IMPLEMENT_EXCEPTION(ConnectionAbortedException, NetException, "Software caused connection abort")
POCO_IMPLEMENT_EXCEPTION(ConnectionResetException, NetException, "Connection reset by peer")
POCO_IMPLEMENT_EXCEPTION(ConnectionRefusedException, NetException, "Connection refused")
POCO_IMPLEMENT_EXCEPTION(DNSException, NetException, "DNS error")
POCO_IMPLEMENT_EXCEPTION(HostNotFoundException, DNSException, "Host not found")
POCO_IMPLEMENT_EXCEPTION(NoAddressFoundException, DNSException, "No address found")
POCO_IMPLEMENT_EXCEPTION(InterfaceNotFoundException, NetException, "Interface not found")
POCO_IMPLEMENT_EXCEPTION(NoMessageException, NetException, "No message received")
POCO_IMPLEMENT_EXCEPTION(MessageException, NetException, "Malformed message")
POCO_IMPLEMENT_EXCEPTION(MultipartException, MessageException, "Malformed multipart message")
POCO_IMPLEMENT_EXCEPTION(HTTPException, NetException, "HTTP Exception")
POCO_IMPLEMENT_EXCEPTION(NotAuthenticatedException, HTTPException, "No authentication information found")
POCO_IMPLEMENT_EXCEPTION(UnsupportedRedirectException, HTTPException, "Unsupported HTTP redirect (protocol change)")
POCO_IMPLEMENT_EXCEPTION(FTPException, NetException, "FTP Exception")
POCO_IMPLEMENT_EXCEPTION(SMTPException, NetException, "SMTP Exception")
POCO_IMPLEMENT_EXCEPTION(POP3Exception, NetException, "POP3 Exception")
POCO_IMPLEMENT_EXCEPTION(ICMPException, NetException, "ICMP Exception")
POCO_IMPLEMENT_EXCEPTION(HTMLFormException, NetException, "HTML Form Exception")
POCO_IMPLEMENT_EXCEPTION(WebSocketException, NetException, "WebSocket Exception")
} } // namespace Poco::Net

View File

@@ -0,0 +1,889 @@
//
// NetworkInterface.cpp
//
// $Id: //poco/1.4/Net/src/NetworkInterface.cpp#9 $
//
// Library: Net
// Package: Sockets
// Module: NetworkInterface
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute ,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/NetworkInterface.h"
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/NetException.h"
#include "Poco/NumberFormatter.h"
#include "Poco/RefCountedObject.h"
#if defined(_WIN32) && defined(POCO_WIN32_UTF8)
#include "Poco/UnicodeConverter.h"
#endif
#include <cstring>
using Poco::NumberFormatter;
using Poco::FastMutex;
namespace Poco {
namespace Net {
//
// NetworkInterfaceImpl
//
class NetworkInterfaceImpl: public Poco::RefCountedObject
{
public:
NetworkInterfaceImpl();
NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const IPAddress& address, int index = -1);
NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, int index = -1);
int index() const;
const std::string& name() const;
const std::string& displayName() const;
const IPAddress& address() const;
const IPAddress& subnetMask() const;
const IPAddress& broadcastAddress() const;
protected:
~NetworkInterfaceImpl();
private:
std::string _name;
std::string _displayName;
IPAddress _address;
IPAddress _subnetMask;
IPAddress _broadcastAddress;
int _index;
};
NetworkInterfaceImpl::NetworkInterfaceImpl():
_index(-1)
{
}
NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const IPAddress& address, int index):
_name(name),
_displayName(displayName),
_address(address),
_index(index)
{
#if !defined(_WIN32) && !defined(POCO_VXWORKS)
if (index == -1) // IPv4
{
struct ifreq ifr;
std::strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ);
DatagramSocket ds(IPAddress::IPv4);
ds.impl()->ioctl(SIOCGIFNETMASK, &ifr);
if (ifr.ifr_addr.sa_family == AF_INET)
_subnetMask = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr));
if (!address.isLoopback())
{
try
{
// Not every interface (e.g. loopback) has a broadcast address
ds.impl()->ioctl(SIOCGIFBRDADDR, &ifr);
if (ifr.ifr_addr.sa_family == AF_INET)
_broadcastAddress = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr));
}
catch (...)
{
}
}
}
#endif
}
NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, int index):
_name(name),
_displayName(displayName),
_address(address),
_subnetMask(subnetMask),
_broadcastAddress(broadcastAddress),
_index(index)
{
}
NetworkInterfaceImpl::~NetworkInterfaceImpl()
{
}
inline int NetworkInterfaceImpl::index() const
{
return _index;
}
inline const std::string& NetworkInterfaceImpl::name() const
{
return _name;
}
inline const std::string& NetworkInterfaceImpl::displayName() const
{
return _displayName;
}
inline const IPAddress& NetworkInterfaceImpl::address() const
{
return _address;
}
inline const IPAddress& NetworkInterfaceImpl::subnetMask() const
{
return _subnetMask;
}
inline const IPAddress& NetworkInterfaceImpl::broadcastAddress() const
{
return _broadcastAddress;
}
//
// NetworkInterface
//
FastMutex NetworkInterface::_mutex;
NetworkInterface::NetworkInterface():
_pImpl(new NetworkInterfaceImpl)
{
}
NetworkInterface::NetworkInterface(const NetworkInterface& interfc):
_pImpl(interfc._pImpl)
{
_pImpl->duplicate();
}
NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const IPAddress& address, int index):
_pImpl(new NetworkInterfaceImpl(name, displayName, address, index))
{
}
NetworkInterface::NetworkInterface(const std::string& name, const std::string& displayName, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, int index):
_pImpl(new NetworkInterfaceImpl(name, displayName, address, subnetMask, broadcastAddress, index))
{
}
NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, int index):
_pImpl(new NetworkInterfaceImpl(name, name, address, index))
{
}
NetworkInterface::NetworkInterface(const std::string& name, const IPAddress& address, const IPAddress& subnetMask, const IPAddress& broadcastAddress, int index):
_pImpl(new NetworkInterfaceImpl(name, name, address, subnetMask, broadcastAddress, index))
{
}
NetworkInterface::~NetworkInterface()
{
_pImpl->release();
}
NetworkInterface& NetworkInterface::operator = (const NetworkInterface& interfc)
{
NetworkInterface tmp(interfc);
swap(tmp);
return *this;
}
void NetworkInterface::swap(NetworkInterface& other)
{
using std::swap;
swap(_pImpl, other._pImpl);
}
int NetworkInterface::index() const
{
return _pImpl->index();
}
const std::string& NetworkInterface::name() const
{
return _pImpl->name();
}
const std::string& NetworkInterface::displayName() const
{
return _pImpl->displayName();
}
const IPAddress& NetworkInterface::address() const
{
return _pImpl->address();
}
const IPAddress& NetworkInterface::subnetMask() const
{
return _pImpl->subnetMask();
}
const IPAddress& NetworkInterface::broadcastAddress() const
{
return _pImpl->broadcastAddress();
}
bool NetworkInterface::supportsIPv4() const
{
return _pImpl->index() == -1;
}
bool NetworkInterface::supportsIPv6() const
{
return _pImpl->index() != -1;
}
NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->name() == name && ((requireIPv6 && it->supportsIPv6()) || !requireIPv6))
return *it;
}
throw InterfaceNotFoundException(name);
}
NetworkInterface NetworkInterface::forName(const std::string& name, IPVersion ipVersion)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->name() == name)
{
if (ipVersion == IPv4_ONLY && it->supportsIPv4())
return *it;
else if (ipVersion == IPv6_ONLY && it->supportsIPv6())
return *it;
else if (ipVersion == IPv4_OR_IPv6)
return *it;
}
}
throw InterfaceNotFoundException(name);
}
NetworkInterface NetworkInterface::forAddress(const IPAddress& addr)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->address() == addr)
return *it;
}
throw InterfaceNotFoundException(addr.toString());
}
NetworkInterface NetworkInterface::forIndex(int i)
{
if (i != 0)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->index() == i)
return *it;
}
throw InterfaceNotFoundException("#" + NumberFormatter::format(i));
}
else return NetworkInterface();
}
} } // namespace Poco::Net
//
// platform-specific code below
//
#if defined(POCO_OS_FAMILY_WINDOWS)
//
// Windows
//
#include <iphlpapi.h>
namespace Poco {
namespace Net {
#if defined(POCO_HAVE_IPv6)
IPAddress subnetMaskForInterface(const std::string& name, bool isLoopback)
{
if (isLoopback)
{
return IPAddress::parse("255.0.0.0");
}
else
{
std::string subKey("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces\\");
subKey += name;
std::wstring usubKey;
Poco::UnicodeConverter::toUTF16(subKey, usubKey);
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, usubKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
return IPAddress();
wchar_t unetmask[16];
DWORD size = sizeof(unetmask);
if (RegQueryValueExW(hKey, L"DhcpSubnetMask", NULL, NULL, (LPBYTE) &unetmask, &size) != ERROR_SUCCESS)
{
if (RegQueryValueExW(hKey, L"SubnetMask", NULL, NULL, (LPBYTE) &unetmask, &size) != ERROR_SUCCESS)
{
RegCloseKey(hKey);
return IPAddress();
}
}
RegCloseKey(hKey);
std::string netmask;
Poco::UnicodeConverter::toUTF8(unetmask, netmask);
return IPAddress::parse(netmask);
}
}
#endif // POCO_HAVE_IPv6
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
DWORD rc;
#if defined(POCO_HAVE_IPv6)
// On Windows XP/Server 2003 and later we use GetAdaptersAddresses.
PIP_ADAPTER_ADDRESSES pAdapterAddresses;
PIP_ADAPTER_ADDRESSES pAddress = 0;
ULONG addrLen = sizeof(IP_ADAPTER_ADDRESSES);
pAdapterAddresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(new char[addrLen]);
// Make an initial call to GetAdaptersAddresses to get
// the necessary size into addrLen
rc = GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &addrLen);
if (rc == ERROR_BUFFER_OVERFLOW)
{
delete [] reinterpret_cast<char*>(pAdapterAddresses);
pAdapterAddresses = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(new char[addrLen]);
}
else if (rc != ERROR_SUCCESS)
{
throw NetException("cannot get network adapter list");
}
try
{
if (GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &addrLen) == NO_ERROR)
{
pAddress = pAdapterAddresses;
while (pAddress)
{
if (pAddress->OperStatus == IfOperStatusUp)
{
PIP_ADAPTER_UNICAST_ADDRESS pUniAddr = pAddress->FirstUnicastAddress;
while (pUniAddr)
{
std::string name(pAddress->AdapterName);
std::string displayName;
#ifdef POCO_WIN32_UTF8
Poco::UnicodeConverter::toUTF8(pAddress->FriendlyName, displayName);
#else
char displayNameBuffer[1024];
int rc = WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR, pAddress->FriendlyName, -1, displayNameBuffer, sizeof(displayNameBuffer), NULL, NULL);
if (rc) displayName = displayNameBuffer;
#endif
IPAddress address;
IPAddress subnetMask;
IPAddress broadcastAddress;
switch (pUniAddr->Address.lpSockaddr->sa_family)
{
case AF_INET:
address = IPAddress(&reinterpret_cast<struct sockaddr_in*>(pUniAddr->Address.lpSockaddr)->sin_addr, sizeof(in_addr));
subnetMask = subnetMaskForInterface(name, address.isLoopback());
if (!address.isLoopback())
{
broadcastAddress = address;
broadcastAddress.mask(subnetMask, IPAddress::broadcast());
}
result.push_back(NetworkInterface(name, displayName, address, subnetMask, broadcastAddress));
break;
case AF_INET6:
address = IPAddress(&reinterpret_cast<struct sockaddr_in6*>(pUniAddr->Address.lpSockaddr)->sin6_addr, sizeof(in6_addr), reinterpret_cast<struct sockaddr_in6*>(pUniAddr->Address.lpSockaddr)->sin6_scope_id);
result.push_back(NetworkInterface(name, displayName, address, pAddress->Ipv6IfIndex));
break;
}
pUniAddr = pUniAddr->Next;
}
}
pAddress = pAddress->Next;
}
}
else throw NetException("cannot get network adapter list");
}
catch (Poco::Exception&)
{
delete [] reinterpret_cast<char*>(pAdapterAddresses);
throw;
}
delete [] reinterpret_cast<char*>(pAdapterAddresses);
return result;
#endif // POCO_HAVE_IPv6
// Add IPv4 loopback interface (not returned by GetAdaptersInfo)
result.push_back(NetworkInterface("Loopback", "Loopback Interface", IPAddress("127.0.0.1"), IPAddress("255.0.0.0"), IPAddress(), -1));
// On Windows 2000 we use GetAdaptersInfo.
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pInfo = 0;
ULONG infoLen = sizeof(IP_ADAPTER_INFO);
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[infoLen]);
// Make an initial call to GetAdaptersInfo to get
// the necessary size into infoLen
rc = GetAdaptersInfo(pAdapterInfo, &infoLen);
if (rc == ERROR_BUFFER_OVERFLOW)
{
delete [] reinterpret_cast<char*>(pAdapterInfo);
pAdapterInfo = reinterpret_cast<IP_ADAPTER_INFO*>(new char[infoLen]);
}
else if (rc != ERROR_SUCCESS)
{
throw NetException("cannot get network adapter list");
}
try
{
if (GetAdaptersInfo(pAdapterInfo, &infoLen) == NO_ERROR)
{
pInfo = pAdapterInfo;
while (pInfo)
{
IPAddress address(std::string(pInfo->IpAddressList.IpAddress.String));
if (!address.isWildcard()) // only return interfaces that have an address assigned.
{
IPAddress subnetMask(std::string(pInfo->IpAddressList.IpMask.String));
IPAddress broadcastAddress(address);
broadcastAddress.mask(subnetMask, IPAddress::broadcast());
std::string name(pInfo->AdapterName);
std::string displayName(pInfo->Description);
result.push_back(NetworkInterface(name, displayName, address, subnetMask, broadcastAddress));
}
pInfo = pInfo->Next;
}
}
else throw NetException("cannot get network adapter list");
}
catch (Poco::Exception&)
{
delete [] reinterpret_cast<char*>(pAdapterInfo);
throw;
}
delete [] reinterpret_cast<char*>(pAdapterInfo);
return result;
}
} } // namespace Poco::Net
#elif defined(POCO_VXWORKS)
//
// VxWorks
//
namespace Poco {
namespace Net {
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
int ifIndex = 1;
char ifName[32];
char ifAddr[INET_ADDR_LEN];
for (;;)
{
if (ifIndexToIfName(ifIndex, ifName) == OK)
{
std::string name(ifName);
IPAddress addr;
IPAddress mask;
IPAddress bcst;
if (ifAddrGet(ifName, ifAddr) == OK)
{
addr = IPAddress(std::string(ifAddr));
}
int ifMask;
if (ifMaskGet(ifName, &ifMask) == OK)
{
mask = IPAddress(&ifMask, sizeof(ifMask));
}
if (ifBroadcastGet(ifName, ifAddr) == OK)
{
bcst = IPAddress(std::string(ifAddr));
}
result.push_back(NetworkInterface(name, name, addr, mask, bcst));
ifIndex++;
}
else break;
}
return result;
}
} } // namespace Poco::Net
#elif defined(POCO_OS_FAMILY_BSD) || POCO_OS == POCO_OS_QNX
//
// BSD variants
//
#include <sys/types.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <net/if_dl.h>
namespace Poco {
namespace Net {
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
struct ifaddrs* ifaphead;
int rc = getifaddrs(&ifaphead);
if (rc) throw NetException("cannot get network adapter list");
for (struct ifaddrs* ifap = ifaphead; ifap; ifap = ifap->ifa_next)
{
if (ifap->ifa_addr)
{
if (ifap->ifa_addr->sa_family == AF_INET)
{
std::string name(ifap->ifa_name);
IPAddress addr(&reinterpret_cast<struct sockaddr_in*>(ifap->ifa_addr)->sin_addr, sizeof(struct in_addr));
IPAddress subnetMask(&reinterpret_cast<struct sockaddr_in*>(ifap->ifa_netmask)->sin_addr, sizeof(struct in_addr));
IPAddress broadcastAddr;
if (ifap->ifa_flags & IFF_BROADCAST)
broadcastAddr = IPAddress(&reinterpret_cast<struct sockaddr_in*>(ifap->ifa_dstaddr)->sin_addr, sizeof(struct in_addr));
result.push_back(NetworkInterface(name, name, addr, subnetMask, broadcastAddr));
}
#if defined(POCO_HAVE_IPv6)
else if (ifap->ifa_addr->sa_family == AF_INET6)
{
Poco::UInt32 ifIndex = if_nametoindex(ifap->ifa_name);
IPAddress addr(&reinterpret_cast<struct sockaddr_in6*>(ifap->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
std::string name(ifap->ifa_name);
result.push_back(NetworkInterface(name, name, addr, ifIndex));
}
#endif
}
}
freeifaddrs(ifaphead);
return result;
}
} } // namespace Poco::Net
#elif POCO_OS == POCO_OS_LINUX
//
// Linux
//
#if defined(POCO_HAVE_IPv6)
#include <sys/types.h>
#include <ifaddrs.h>
namespace Poco {
namespace Net {
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
NetworkInterfaceList result;
struct ifaddrs* ifaces = 0;
struct ifaddrs* currIface = 0;
if (getifaddrs(&ifaces) < 0)
throw NetException("cannot get network adapter list");
try
{
for (currIface = ifaces; currIface != 0; currIface = currIface->ifa_next)
{
IPAddress addr;
bool haveAddr = false;
int ifIndex(-1);
switch (currIface->ifa_addr->sa_family)
{
case AF_INET6:
ifIndex = if_nametoindex(currIface->ifa_name);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(currIface->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
haveAddr = true;
break;
case AF_INET:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(currIface->ifa_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break;
default:
break;
}
if (haveAddr)
{
std::string name(currIface->ifa_name);
result.push_back(NetworkInterface(name, name, addr, ifIndex));
}
}
}
catch (...)
{
}
if (ifaces) freeifaddrs(ifaces);
return result;
}
} } // namespace Poco::Net
#else // !POCO_HAVE_IPv6
namespace Poco {
namespace Net {
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
DatagramSocket socket;
// the following code is loosely based
// on W. Richard Stevens, UNIX Network Programming, pp 434ff.
int lastlen = 0;
int len = 100*sizeof(struct ifreq);
char* buf = 0;
try
{
struct ifconf ifc;
for (;;)
{
buf = new char[len];
ifc.ifc_len = len;
ifc.ifc_buf = buf;
if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0)
{
if (errno != EINVAL || lastlen != 0)
throw NetException("cannot get network adapter list");
}
else
{
if (ifc.ifc_len == lastlen)
break;
lastlen = ifc.ifc_len;
}
len += 10*sizeof(struct ifreq);
delete [] buf;
}
for (const char* ptr = buf; ptr < buf + ifc.ifc_len;)
{
const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr);
IPAddress addr;
bool haveAddr = false;
switch (ifr->ifr_addr.sa_family)
{
case AF_INET:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break;
default:
break;
}
if (haveAddr)
{
int index = -1;
std::string name(ifr->ifr_name);
result.push_back(NetworkInterface(name, name, addr, index));
}
ptr += sizeof(struct ifreq);
}
}
catch (...)
{
delete [] buf;
throw;
}
delete [] buf;
return result;
}
} } // namespace Poco::Net
#endif // POCO_HAVE_IPv6
#else
//
// Non-BSD Unix variants
//
namespace Poco {
namespace Net {
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
DatagramSocket socket;
// the following code is loosely based
// on W. Richard Stevens, UNIX Network Programming, pp 434ff.
int lastlen = 0;
int len = 100*sizeof(struct ifreq);
char* buf = 0;
try
{
struct ifconf ifc;
for (;;)
{
buf = new char[len];
ifc.ifc_len = len;
ifc.ifc_buf = buf;
if (::ioctl(socket.impl()->sockfd(), SIOCGIFCONF, &ifc) < 0)
{
if (errno != EINVAL || lastlen != 0)
throw NetException("cannot get network adapter list");
}
else
{
if (ifc.ifc_len == lastlen)
break;
lastlen = ifc.ifc_len;
}
len += 10*sizeof(struct ifreq);
delete [] buf;
}
for (const char* ptr = buf; ptr < buf + ifc.ifc_len;)
{
const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr);
#if defined(POCO_HAVE_SALEN)
len = ifr->ifr_addr.sa_len;
if (sizeof(struct sockaddr) > len) len = sizeof(struct sockaddr);
#else
len = sizeof(struct sockaddr);
#endif
IPAddress addr;
bool haveAddr = false;
int ifIndex(-1);
switch (ifr->ifr_addr.sa_family)
{
#if defined(POCO_HAVE_IPv6)
case AF_INET6:
ifIndex = if_nametoindex(ifr->ifr_name);
if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
haveAddr = true;
break;
#endif
case AF_INET:
if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break;
default:
break;
}
if (haveAddr)
{
std::string name(ifr->ifr_name);
result.push_back(NetworkInterface(name, name, addr, ifIndex));
}
len += sizeof(ifr->ifr_name);
ptr += len;
}
}
catch (...)
{
delete [] buf;
throw;
}
delete [] buf;
return result;
}
} } // namespace Poco::Net
#endif

View File

@@ -0,0 +1,68 @@
//
// NullPartHandler.cpp
//
// $Id: //poco/1.4/Net/src/NullPartHandler.cpp#1 $
//
// Library: Net
// Package: Messages
// Module: NullPartHandler
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/NullPartHandler.h"
#include "Poco/Net/MessageHeader.h"
#include "Poco/NullStream.h"
#include "Poco/StreamCopier.h"
using Poco::NullOutputStream;
using Poco::StreamCopier;
namespace Poco {
namespace Net {
NullPartHandler::NullPartHandler()
{
}
NullPartHandler::~NullPartHandler()
{
}
void NullPartHandler::handlePart(const MessageHeader& header, std::istream& stream)
{
NullOutputStream ostr;
StreamCopier::copyStream(stream, ostr);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,302 @@
//
// POP3ClientSession.cpp
//
// $Id: //poco/1.4/Net/src/POP3ClientSession.cpp#1 $
//
// Library: Net
// Package: Mail
// Module: POP3ClientSession
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/POP3ClientSession.h"
#include "Poco/Net/MailMessage.h"
#include "Poco/Net/MailStream.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/NetException.h"
#include "Poco/StreamCopier.h"
#include "Poco/NumberFormatter.h"
#include "Poco/UnbufferedStreamBuf.h"
#include "Poco/Ascii.h"
#include <istream>
using Poco::NumberFormatter;
using Poco::StreamCopier;
namespace Poco {
namespace Net {
class DialogStreamBuf: public Poco::UnbufferedStreamBuf
{
public:
DialogStreamBuf(DialogSocket& socket):
_socket(socket)
{
}
~DialogStreamBuf()
{
}
private:
int readFromDevice()
{
return _socket.get();
}
DialogSocket& _socket;
};
class DialogIOS: public virtual std::ios
{
public:
DialogIOS(DialogSocket& socket):
_buf(socket)
{
poco_ios_init(&_buf);
}
~DialogIOS()
{
}
DialogStreamBuf* rdbuf()
{
return &_buf;
}
protected:
DialogStreamBuf _buf;
};
class DialogInputStream: public DialogIOS, public std::istream
{
public:
DialogInputStream(DialogSocket& socket):
DialogIOS(socket),
std::istream(&_buf)
{
}
~DialogInputStream()
{
}
};
POP3ClientSession::POP3ClientSession(const StreamSocket& socket):
_socket(socket),
_isOpen(true)
{
}
POP3ClientSession::POP3ClientSession(const std::string& host, Poco::UInt16 port):
_socket(SocketAddress(host, port)),
_isOpen(true)
{
}
POP3ClientSession::~POP3ClientSession()
{
try
{
close();
}
catch (...)
{
}
}
void POP3ClientSession::setTimeout(const Poco::Timespan& timeout)
{
_socket.setReceiveTimeout(timeout);
}
Poco::Timespan POP3ClientSession::getTimeout() const
{
return _socket.getReceiveTimeout();
}
void POP3ClientSession::login(const std::string& username, const std::string& password)
{
std::string response;
_socket.receiveMessage(response);
if (!isPositive(response)) throw POP3Exception("The POP3 service is unavailable", response);
sendCommand("USER", username, response);
if (!isPositive(response)) throw POP3Exception("Login rejected for user", response);
sendCommand("PASS", password, response);
if (!isPositive(response)) throw POP3Exception("Password rejected for user", response);
}
void POP3ClientSession::close()
{
if (_isOpen)
{
std::string response;
sendCommand("QUIT", response);
_socket.close();
_isOpen = false;
}
}
int POP3ClientSession::messageCount()
{
std::string response;
sendCommand("STAT", response);
if (!isPositive(response)) throw POP3Exception("Cannot determine message count", response);
std::string::const_iterator it = response.begin();
std::string::const_iterator end = response.end();
int count = 0;
while (it != end && !Poco::Ascii::isSpace(*it)) ++it;
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
while (it != end && Poco::Ascii::isDigit(*it)) count = count*10 + *it++ - '0';
return count;
}
void POP3ClientSession::listMessages(MessageInfoVec& messages)
{
messages.clear();
std::string response;
sendCommand("LIST", response);
if (!isPositive(response)) throw POP3Exception("Cannot get message list", response);
_socket.receiveMessage(response);
while (response != ".")
{
MessageInfo info = {0, 0};
std::string::const_iterator it = response.begin();
std::string::const_iterator end = response.end();
while (it != end && Poco::Ascii::isDigit(*it)) info.id = info.id*10 + *it++ - '0';
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
while (it != end && Poco::Ascii::isDigit(*it)) info.size = info.size*10 + *it++ - '0';
messages.push_back(info);
_socket.receiveMessage(response);
}
}
void POP3ClientSession::retrieveMessage(int id, MailMessage& message)
{
std::string response;
sendCommand("RETR", NumberFormatter::format(id), response);
if (!isPositive(response)) throw POP3Exception("Cannot get message list", response);
DialogInputStream sis(_socket);
MailInputStream mis(sis);
message.read(mis);
while (mis.good()) mis.get(); // read any remaining junk
}
void POP3ClientSession::retrieveMessage(int id, MailMessage& message, PartHandler& handler)
{
std::string response;
sendCommand("RETR", NumberFormatter::format(id), response);
if (!isPositive(response)) throw POP3Exception("Cannot get message list", response);
DialogInputStream sis(_socket);
MailInputStream mis(sis);
message.read(mis, handler);
while (mis.good()) mis.get(); // read any remaining junk
}
void POP3ClientSession::retrieveMessage(int id, std::ostream& ostr)
{
std::string response;
sendCommand("RETR", NumberFormatter::format(id), response);
if (!isPositive(response)) throw POP3Exception("Cannot get message list", response);
DialogInputStream sis(_socket);
MailInputStream mis(sis);
StreamCopier::copyStream(mis, ostr);
}
void POP3ClientSession::retrieveHeader(int id, MessageHeader& header)
{
std::string response;
sendCommand("TOP", NumberFormatter::format(id), "0", response);
if (!isPositive(response)) throw POP3Exception("Cannot get message list", response);
DialogInputStream sis(_socket);
MailInputStream mis(sis);
header.read(mis);
// skip stuff following header
mis.get(); // \r
mis.get(); // \n
}
void POP3ClientSession::deleteMessage(int id)
{
std::string response;
sendCommand("DELE", NumberFormatter::format(id), response);
if (!isPositive(response)) throw POP3Exception("Cannot mark message for deletion", response);
}
bool POP3ClientSession::sendCommand(const std::string& command, std::string& response)
{
_socket.sendMessage(command);
_socket.receiveMessage(response);
return isPositive(response);
}
bool POP3ClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response)
{
_socket.sendMessage(command, arg);
_socket.receiveMessage(response);
return isPositive(response);
}
bool POP3ClientSession::sendCommand(const std::string& command, const std::string& arg1, const std::string& arg2, std::string& response)
{
_socket.sendMessage(command, arg1, arg2);
_socket.receiveMessage(response);
return isPositive(response);
}
bool POP3ClientSession::isPositive(const std::string& response)
{
return response.length() > 0 && response[0] == '+';
}
} } // namespace Poco::Net

54
Net/src/PartHandler.cpp Normal file
View File

@@ -0,0 +1,54 @@
//
// PartHandler.cpp
//
// $Id: //poco/1.4/Net/src/PartHandler.cpp#1 $
//
// Library: Net
// Package: Messages
// Module: PartHandler
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/PartHandler.h"
namespace Poco {
namespace Net {
PartHandler::PartHandler()
{
}
PartHandler::~PartHandler()
{
}
} } // namespace Poco::Net

73
Net/src/PartSource.cpp Normal file
View File

@@ -0,0 +1,73 @@
//
// PartSource.cpp
//
// $Id: //poco/1.4/Net/src/PartSource.cpp#1 $
//
// Library: Net
// Package: Messages
// Module: PartSource
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/PartSource.h"
namespace Poco {
namespace Net {
PartSource::PartSource():
_mediaType("application/octet-stream")
{
}
PartSource::PartSource(const std::string& mediaType):
_mediaType(mediaType)
{
}
PartSource::~PartSource()
{
}
namespace
{
static const std::string EMPTY;
}
const std::string& PartSource::filename()
{
return EMPTY;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,124 @@
//
// QuotedPrintableDecoder.cpp
//
// $Id: //poco/1.4/Net/src/QuotedPrintableDecoder.cpp#2 $
//
// Library: Net
// Package: Messages
// Module: QuotedPrintableDecoder
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/QuotedPrintableDecoder.h"
#include "Poco/NumberParser.h"
#include "Poco/Exception.h"
#include "Poco/Ascii.h"
using Poco::UnbufferedStreamBuf;
using Poco::NumberParser;
using Poco::DataFormatException;
namespace Poco {
namespace Net {
QuotedPrintableDecoderBuf::QuotedPrintableDecoderBuf(std::istream& istr):
_buf(*istr.rdbuf())
{
}
QuotedPrintableDecoderBuf::~QuotedPrintableDecoderBuf()
{
}
int QuotedPrintableDecoderBuf::readFromDevice()
{
int ch = _buf.sbumpc();
while (ch == '=')
{
ch = _buf.sbumpc();
if (ch == '\r')
{
ch = _buf.sbumpc(); // read \n
}
else if (Poco::Ascii::isHexDigit(ch))
{
std::string hex;
hex += (char) ch;
ch = _buf.sbumpc();
if (Poco::Ascii::isHexDigit(ch))
{
hex += (char) ch;
return NumberParser::parseHex(hex);
}
throw DataFormatException("Incomplete hex number in quoted-printable encoded stream");
}
else if (ch != '\n')
{
throw DataFormatException("Invalid occurrence of '=' in quoted-printable encoded stream");
}
ch = _buf.sbumpc();
}
return ch;
}
QuotedPrintableDecoderIOS::QuotedPrintableDecoderIOS(std::istream& istr): _buf(istr)
{
poco_ios_init(&_buf);
}
QuotedPrintableDecoderIOS::~QuotedPrintableDecoderIOS()
{
}
QuotedPrintableDecoderBuf* QuotedPrintableDecoderIOS::rdbuf()
{
return &_buf;
}
QuotedPrintableDecoder::QuotedPrintableDecoder(std::istream& istr):
QuotedPrintableDecoderIOS(istr),
std::istream(&_buf)
{
}
QuotedPrintableDecoder::~QuotedPrintableDecoder()
{
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,172 @@
//
// QuotedPrintableEncoder.cpp
//
// $Id: //poco/1.4/Net/src/QuotedPrintableEncoder.cpp#1 $
//
// Library: Net
// Package: Messages
// Module: QuotedPrintableEncoder
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/QuotedPrintableEncoder.h"
#include "Poco/NumberFormatter.h"
using Poco::UnbufferedStreamBuf;
using Poco::NumberFormatter;
namespace Poco {
namespace Net {
QuotedPrintableEncoderBuf::QuotedPrintableEncoderBuf(std::ostream& ostr):
_pending(-1),
_lineLength(0),
_ostr(ostr)
{
}
QuotedPrintableEncoderBuf::~QuotedPrintableEncoderBuf()
{
try
{
close();
}
catch (...)
{
}
}
int QuotedPrintableEncoderBuf::writeToDevice(char c)
{
if (_pending != -1)
{
if (_pending == '\r' && c == '\n')
writeRaw((char) _pending);
else if (c == '\r' || c == '\n')
writeEncoded((char) _pending);
else
writeRaw((char) _pending);
_pending = -1;
}
if (c == '\t' || c == ' ')
{
_pending = charToInt(c);
return _pending;
}
else if (c == '\r' || c == '\n' || (c > 32 && c < 127 && c != '='))
{
writeRaw(c);
}
else
{
writeEncoded(c);
}
return charToInt(c);
}
void QuotedPrintableEncoderBuf::writeEncoded(char c)
{
if (_lineLength >= 73)
{
_ostr << "=\r\n";
_lineLength = 3;
}
else _lineLength += 3;
_ostr << '=' << NumberFormatter::formatHex((unsigned) charToInt(c), 2);
}
void QuotedPrintableEncoderBuf::writeRaw(char c)
{
if (c == '\r' || c == '\n')
{
_ostr.put(c);
_lineLength = 0;
}
else if (_lineLength < 75)
{
_ostr.put(c);
++_lineLength;
}
else
{
_ostr << "=\r\n" << c;
_lineLength = 1;
}
}
int QuotedPrintableEncoderBuf::close()
{
sync();
return _ostr ? 0 : -1;
}
QuotedPrintableEncoderIOS::QuotedPrintableEncoderIOS(std::ostream& ostr): _buf(ostr)
{
poco_ios_init(&_buf);
}
QuotedPrintableEncoderIOS::~QuotedPrintableEncoderIOS()
{
}
int QuotedPrintableEncoderIOS::close()
{
return _buf.close();
}
QuotedPrintableEncoderBuf* QuotedPrintableEncoderIOS::rdbuf()
{
return &_buf;
}
QuotedPrintableEncoder::QuotedPrintableEncoder(std::ostream& ostr):
QuotedPrintableEncoderIOS(ostr),
std::ostream(&_buf)
{
}
QuotedPrintableEncoder::~QuotedPrintableEncoder()
{
}
} } // namespace Poco::Net

133
Net/src/RawSocket.cpp Normal file
View File

@@ -0,0 +1,133 @@
//
// RawSocket.cpp
//
// $Id: //poco/1.4/Net/src/RawSocket.cpp#1 $
//
// Library: Net
// Package: Sockets
// Module: RawSocket
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/RawSocket.h"
#include "Poco/Net/RawSocketImpl.h"
#include "Poco/Exception.h"
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
RawSocket::RawSocket():
Socket(new RawSocketImpl)
{
}
RawSocket::RawSocket(IPAddress::Family family, int proto):
Socket(new RawSocketImpl(family, proto))
{
}
RawSocket::RawSocket(const SocketAddress& address, bool reuseAddress):
Socket(new RawSocketImpl)
{
bind(address, reuseAddress);
}
RawSocket::RawSocket(const Socket& socket): Socket(socket)
{
if (!dynamic_cast<RawSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
RawSocket::RawSocket(SocketImpl* pImpl): Socket(pImpl)
{
if (!dynamic_cast<RawSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
RawSocket::~RawSocket()
{
}
RawSocket& RawSocket::operator = (const Socket& socket)
{
if (dynamic_cast<RawSocketImpl*>(socket.impl()))
Socket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
void RawSocket::connect(const SocketAddress& address)
{
impl()->connect(address);
}
void RawSocket::bind(const SocketAddress& address, bool reuseAddress)
{
impl()->bind(address, reuseAddress);
}
int RawSocket::sendBytes(const void* buffer, int length, int flags)
{
return impl()->sendBytes(buffer, length, flags);
}
int RawSocket::receiveBytes(void* buffer, int length, int flags)
{
return impl()->receiveBytes(buffer, length, flags);
}
int RawSocket::sendTo(const void* buffer, int length, const SocketAddress& address, int flags)
{
return impl()->sendTo(buffer, length, address, flags);
}
int RawSocket::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
{
return impl()->receiveFrom(buffer, length, address, flags);
}
} } // namespace Poco::Net

91
Net/src/RawSocketImpl.cpp Normal file
View File

@@ -0,0 +1,91 @@
//
// RawSocketImpl.cpp
//
// $Id: //poco/1.4/Net/src/RawSocketImpl.cpp#1 $
//
// Library: Net
// Package: Sockets
// Module: RawSocketImpl
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/RawSocketImpl.h"
#include "Poco/Net/NetException.h"
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
RawSocketImpl::RawSocketImpl()
{
init(AF_INET);
}
RawSocketImpl::RawSocketImpl(IPAddress::Family family, int proto)
{
if (family == IPAddress::IPv4)
init2(AF_INET, proto);
#if defined(POCO_HAVE_IPv6)
else if (family == IPAddress::IPv6)
init2(AF_INET6, proto);
#endif
else throw InvalidArgumentException("Invalid or unsupported address family passed to RawSocketImpl");
}
RawSocketImpl::RawSocketImpl(poco_socket_t sockfd):
SocketImpl(sockfd)
{
}
RawSocketImpl::~RawSocketImpl()
{
}
void RawSocketImpl::init(int af)
{
init2(af, IPPROTO_RAW);
}
void RawSocketImpl::init2(int af, int proto)
{
initSocket(af, SOCK_RAW, proto);
setOption(IPPROTO_IP, IP_HDRINCL, 0);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,355 @@
//
// RemoteSyslogChannel.cpp
//
// $Id: //poco/1.4/Net/src/RemoteSyslogChannel.cpp#2 $
//
// Library: Net
// Package: Logging
// Module: RemoteSyslogChannel
//
// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/RemoteSyslogChannel.h"
#include "Poco/Message.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/DNS.h"
#include "Poco/LoggingFactory.h"
#include "Poco/Instantiator.h"
#include "Poco/String.h"
namespace Poco {
namespace Net {
const std::string RemoteSyslogChannel::BSD_TIMEFORMAT("%b %f %H:%M:%S");
const std::string RemoteSyslogChannel::SYSLOG_TIMEFORMAT("%Y-%m-%dT%H:%M:%S.%i%z");
const std::string RemoteSyslogChannel::PROP_NAME("name");
const std::string RemoteSyslogChannel::PROP_FACILITY("facility");
const std::string RemoteSyslogChannel::PROP_FORMAT("format");
const std::string RemoteSyslogChannel::PROP_LOGHOST("loghost");
const std::string RemoteSyslogChannel::PROP_HOST("host");
RemoteSyslogChannel::RemoteSyslogChannel():
_logHost("localhost"),
_name("-"),
_facility(SYSLOG_USER),
_bsdFormat(false),
_open(false)
{
}
RemoteSyslogChannel::RemoteSyslogChannel(const std::string& address, const std::string& name, int facility, bool bsdFormat):
_logHost(address),
_name(name),
_facility(facility),
_bsdFormat(bsdFormat),
_open(false)
{
if (_name.empty()) _name = "-";
}
RemoteSyslogChannel::~RemoteSyslogChannel()
{
close();
}
void RemoteSyslogChannel::open()
{
if (_open) return;
if (_logHost.find(':') != std::string::npos)
_socketAddress = SocketAddress(_logHost);
else
_socketAddress = SocketAddress(_logHost, SYSLOG_PORT);
if (_host.empty())
{
try
{
_host = DNS::thisHost().name();
}
catch (Poco::Exception&)
{
_host = _socket.address().host().toString();
}
}
}
void RemoteSyslogChannel::close()
{
if (_open)
{
_socket.close();
_open = false;
}
}
void RemoteSyslogChannel::log(const Message& msg)
{
Poco::FastMutex::ScopedLock lock(_mutex);
if (!_open) open();
std::string m;
m.reserve(1024);
m += '<';
Poco::NumberFormatter::append(m, getPrio(msg) + _facility);
m += '>';
if (_bsdFormat)
{
Poco::DateTimeFormatter::append(m, msg.getTime(), BSD_TIMEFORMAT);
m += ' ';
m += _host;
}
else
{
m += "1 "; // version
Poco::DateTimeFormatter::append(m, msg.getTime(), SYSLOG_TIMEFORMAT);
m += ' ';
m += _host;
m += ' ';
m += _name;
m += ' ';
Poco::NumberFormatter::append(m, msg.getPid());
m += ' ';
m += msg.getSource();
}
m += ' ';
m += msg.getText();
_socket.sendTo(m.data(), static_cast<int>(m.size()), _socketAddress);
}
void RemoteSyslogChannel::setProperty(const std::string& name, const std::string& value)
{
if (name == PROP_NAME)
{
_name = value;
if (_name.empty()) _name = "-";
}
else if (name == PROP_FACILITY)
{
std::string facility;
if (Poco::icompare(value, 4, "LOG_") == 0)
facility = Poco::toUpper(value.substr(4));
else if (Poco::icompare(value, 4, "SYSLOG_") == 0)
facility = Poco::toUpper(value.substr(7));
else
facility = Poco::toUpper(value);
if (facility == "KERN")
_facility = SYSLOG_KERN;
else if (facility == "USER")
_facility = SYSLOG_USER;
else if (facility == "MAIL")
_facility = SYSLOG_MAIL;
else if (facility == "DAEMON")
_facility = SYSLOG_DAEMON;
else if (facility == "AUTH")
_facility = SYSLOG_AUTH;
else if (facility == "AUTHPRIV")
_facility = SYSLOG_AUTHPRIV;
else if (facility == "SYSLOG")
_facility = SYSLOG_SYSLOG;
else if (facility == "LPR")
_facility = SYSLOG_LPR;
else if (facility == "NEWS")
_facility = SYSLOG_NEWS;
else if (facility == "UUCP")
_facility = SYSLOG_UUCP;
else if (facility == "CRON")
_facility = SYSLOG_CRON;
else if (facility == "FTP")
_facility = SYSLOG_FTP;
else if (facility == "NTP")
_facility = SYSLOG_NTP;
else if (facility == "LOGAUDIT")
_facility = SYSLOG_LOGAUDIT;
else if (facility == "LOGALERT")
_facility = SYSLOG_LOGALERT;
else if (facility == "CLOCK")
_facility = SYSLOG_CLOCK;
else if (facility == "LOCAL0")
_facility = SYSLOG_LOCAL0;
else if (facility == "LOCAL1")
_facility = SYSLOG_LOCAL1;
else if (facility == "LOCAL2")
_facility = SYSLOG_LOCAL2;
else if (facility == "LOCAL3")
_facility = SYSLOG_LOCAL3;
else if (facility == "LOCAL4")
_facility = SYSLOG_LOCAL4;
else if (facility == "LOCAL5")
_facility = SYSLOG_LOCAL5;
else if (facility == "LOCAL6")
_facility = SYSLOG_LOCAL6;
else if (facility == "LOCAL7")
_facility = SYSLOG_LOCAL7;
}
else if (name == PROP_LOGHOST)
{
_logHost = value;
}
else if (name == PROP_HOST)
{
_host = value;
}
else if (name == PROP_FORMAT)
{
_bsdFormat = (value == "bsd" || value == "rfc3164");
}
else
{
Channel::setProperty(name, value);
}
}
std::string RemoteSyslogChannel::getProperty(const std::string& name) const
{
if (name == PROP_NAME)
{
if (_name != "-")
return _name;
else
return "";
}
else if (name == PROP_FACILITY)
{
if (_facility == SYSLOG_KERN)
return "KERN";
else if (_facility == SYSLOG_USER)
return "USER";
else if (_facility == SYSLOG_MAIL)
return "MAIL";
else if (_facility == SYSLOG_DAEMON)
return "DAEMON";
else if (_facility == SYSLOG_AUTH)
return "AUTH";
else if (_facility == SYSLOG_AUTHPRIV)
return "AUTHPRIV";
else if (_facility == SYSLOG_SYSLOG)
return "SYSLOG";
else if (_facility == SYSLOG_LPR)
return "LPR";
else if (_facility == SYSLOG_NEWS)
return "NEWS";
else if (_facility == SYSLOG_UUCP)
return "UUCP";
else if (_facility == SYSLOG_CRON)
return "CRON";
else if (_facility == SYSLOG_FTP)
return "FTP";
else if (_facility == SYSLOG_NTP)
return "NTP";
else if (_facility == SYSLOG_LOGAUDIT)
return "LOGAUDIT";
else if (_facility == SYSLOG_LOGALERT)
return "LOGALERT";
else if (_facility == SYSLOG_CLOCK)
return "CLOCK";
else if (_facility == SYSLOG_LOCAL0)
return "LOCAL0";
else if (_facility == SYSLOG_LOCAL1)
return "LOCAL1";
else if (_facility == SYSLOG_LOCAL2)
return "LOCAL2";
else if (_facility == SYSLOG_LOCAL3)
return "LOCAL3";
else if (_facility == SYSLOG_LOCAL4)
return "LOCAL4";
else if (_facility == SYSLOG_LOCAL5)
return "LOCAL5";
else if (_facility == SYSLOG_LOCAL6)
return "LOCAL6";
else if (_facility == SYSLOG_LOCAL7)
return "LOCAL7";
else
return "";
}
else if (name == PROP_LOGHOST)
{
return _logHost;
}
else if (name == PROP_HOST)
{
return _host;
}
else if (name == PROP_FORMAT)
{
return _bsdFormat ? "rfc3164" : "rfc5424";
}
else
{
return Channel::getProperty(name);
}
}
int RemoteSyslogChannel::getPrio(const Message& msg)
{
switch (msg.getPriority())
{
case Message::PRIO_TRACE:
case Message::PRIO_DEBUG:
return SYSLOG_DEBUG;
case Message::PRIO_INFORMATION:
return SYSLOG_INFORMATIONAL;
case Message::PRIO_NOTICE:
return SYSLOG_NOTICE;
case Message::PRIO_WARNING:
return SYSLOG_WARNING;
case Message::PRIO_ERROR:
return SYSLOG_ERROR;
case Message::PRIO_CRITICAL:
return SYSLOG_CRITICAL;
case Message::PRIO_FATAL:
return SYSLOG_ALERT;
default:
return 0;
}
}
void RemoteSyslogChannel::registerChannel()
{
Poco::LoggingFactory::defaultFactory().registerChannelClass("RemoteSyslogChannel", new Poco::Instantiator<RemoteSyslogChannel, Poco::Channel>);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,579 @@
//
// RemoteSyslogListener.cpp
//
// $Id: //poco/1.4/Net/src/RemoteSyslogListener.cpp#4 $
//
// Library: Net
// Package: Logging
// Module: RemoteSyslogListener
//
// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/RemoteSyslogListener.h"
#include "Poco/Net/RemoteSyslogChannel.h"
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Runnable.h"
#include "Poco/Notification.h"
#include "Poco/AutoPtr.h"
#include "Poco/NumberParser.h"
#include "Poco/NumberFormatter.h"
#include "Poco/DateTimeParser.h"
#include "Poco/Message.h"
#include "Poco/LoggingFactory.h"
#include "Poco/Buffer.h"
#include "Poco/Ascii.h"
#include <cstddef>
namespace Poco {
namespace Net {
//
// MessageNotification
//
class MessageNotification: public Poco::Notification
{
public:
MessageNotification(const char* buffer, std::size_t length, const Poco::Net::SocketAddress& sourceAddress):
_message(buffer, length),
_sourceAddress(sourceAddress)
{
}
MessageNotification(const std::string& message, const Poco::Net::SocketAddress& sourceAddress):
_message(message),
_sourceAddress(sourceAddress)
{
}
~MessageNotification()
{
}
const std::string& message() const
{
return _message;
}
const Poco::Net::SocketAddress& sourceAddress() const
{
return _sourceAddress;
}
private:
std::string _message;
Poco::Net::SocketAddress _sourceAddress;
};
//
// RemoteUDPListener
//
class RemoteUDPListener: public Poco::Runnable
{
public:
enum
{
WAITTIME_MILLISEC = 1000,
BUFFER_SIZE = 65536
};
RemoteUDPListener(Poco::NotificationQueue& queue, Poco::UInt16 port);
~RemoteUDPListener();
void run();
void safeStop();
private:
Poco::NotificationQueue& _queue;
DatagramSocket _socket;
bool _stopped;
};
RemoteUDPListener::RemoteUDPListener(Poco::NotificationQueue& queue, Poco::UInt16 port):
_queue(queue),
_socket(Poco::Net::SocketAddress(Poco::Net::IPAddress(), port)),
_stopped(false)
{
}
RemoteUDPListener::~RemoteUDPListener()
{
}
void RemoteUDPListener::run()
{
Poco::Buffer<char> buffer(BUFFER_SIZE);
Poco::Timespan waitTime(WAITTIME_MILLISEC* 1000);
while (!_stopped)
{
try
{
if (_socket.poll(waitTime, Socket::SELECT_READ))
{
Poco::Net::SocketAddress sourceAddress;
int n = _socket.receiveFrom(buffer.begin(), BUFFER_SIZE, sourceAddress);
if (n > 0)
{
_queue.enqueueNotification(new MessageNotification(buffer.begin(), n, sourceAddress));
}
}
}
catch (...)
{
// lazy exception catching
}
}
}
void RemoteUDPListener::safeStop()
{
_stopped = true;
}
//
// SyslogParser
//
class SyslogParser: public Poco::Runnable
{
public:
static const std::string NILVALUE;
enum
{
WAITTIME_MILLISEC = 1000
};
SyslogParser(Poco::NotificationQueue& queue, RemoteSyslogListener* pListener);
~SyslogParser();
void parse(const std::string& line, Poco::Message& message);
void run();
void safeStop();
static Poco::Message::Priority convert(RemoteSyslogChannel::Severity severity);
private:
void parsePrio(const std::string& line, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac);
void parseNew(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos, Poco::Message& message);
void parseBSD(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos, Poco::Message& message);
static std::string parseUntilSpace(const std::string& line, std::size_t& pos);
/// Parses until it encounters the next space char, returns the string from pos, excluding space
/// pos will point past the space char
private:
Poco::NotificationQueue& _queue;
bool _stopped;
RemoteSyslogListener* _pListener;
};
const std::string SyslogParser::NILVALUE("-");
SyslogParser::SyslogParser(Poco::NotificationQueue& queue, RemoteSyslogListener* pListener):
_queue(queue),
_stopped(false),
_pListener(pListener)
{
poco_check_ptr (_pListener);
}
SyslogParser::~SyslogParser()
{
}
void SyslogParser::run()
{
while (!_stopped)
{
try
{
Poco::AutoPtr<Poco::Notification> pNf(_queue.waitDequeueNotification(WAITTIME_MILLISEC));
if (pNf)
{
Poco::AutoPtr<MessageNotification> pMsgNf = pNf.cast<MessageNotification>();
Poco::Message message;
parse(pMsgNf->message(), message);
message["addr"] =pMsgNf->sourceAddress().host().toString();
_pListener->log(message);
}
}
catch (Poco::Exception&)
{
// parsing exception, what should we do?
}
catch (...)
{
}
}
}
void SyslogParser::safeStop()
{
_stopped = true;
}
void SyslogParser::parse(const std::string& line, Poco::Message& message)
{
// <int> -> int: lower 3 bits severity, upper bits: facility
std::size_t pos = 0;
RemoteSyslogChannel::Severity severity;
RemoteSyslogChannel::Facility fac;
parsePrio(line, pos, severity, fac);
// the next field decide if we parse an old BSD message or a new syslog message
// BSD: expects a month value in string form: Jan, Feb...
// SYSLOG expects a version number: 1
if (Poco::Ascii::isDigit(line[pos]))
{
parseNew(line, severity, fac, pos, message);
}
else
{
parseBSD(line, severity, fac, pos, message);
}
poco_assert (pos == line.size());
}
void SyslogParser::parsePrio(const std::string& line, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac)
{
poco_assert (pos < line.size());
poco_assert (line[pos] == '<');
++pos;
std::size_t start = pos;
while (pos < line.size() && Poco::Ascii::isDigit(line[pos]))
++pos;
poco_assert (line[pos] == '>');
poco_assert (pos - start > 0);
std::string valStr = line.substr(start, pos - start);
++pos; // skip the >
int val = Poco::NumberParser::parse(valStr);
poco_assert (val >= 0 && val <= (RemoteSyslogChannel::SYSLOG_LOCAL7 + RemoteSyslogChannel::SYSLOG_DEBUG));
Poco::UInt16 pri = static_cast<Poco::UInt16>(val);
// now get the lowest 3 bits
severity = static_cast<RemoteSyslogChannel::Severity>(pri & 0x0007u);
fac = static_cast<RemoteSyslogChannel::Facility>(pri & 0xfff8u);
}
void SyslogParser::parseNew(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos, Poco::Message& message)
{
Poco::Message::Priority prio = convert(severity);
// rest of the unparsed header is:
// VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID
std::string versionStr(parseUntilSpace(line, pos));
std::string timeStr(parseUntilSpace(line, pos)); // can be the nilvalue!
std::string hostName(parseUntilSpace(line, pos));
std::string appName(parseUntilSpace(line, pos));
std::string procId(parseUntilSpace(line, pos));
std::string msgId(parseUntilSpace(line, pos));
std::string messageText(line.substr(pos));
pos = line.size();
Poco::DateTime date;
int tzd = 0;
bool hasDate = Poco::DateTimeParser::tryParse(RemoteSyslogChannel::SYSLOG_TIMEFORMAT, timeStr, date, tzd);
Poco::Message logEntry(msgId, messageText, prio);
logEntry["host"] = hostName;
logEntry["app"] = appName;
if (hasDate)
logEntry.setTime(date.timestamp());
int lval(0);
Poco::NumberParser::tryParse(procId, lval);
logEntry.setPid(lval);
message.swap(logEntry);
}
void SyslogParser::parseBSD(const std::string& line, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos, Poco::Message& message)
{
Poco::Message::Priority prio = convert(severity);
// rest of the unparsed header is:
// "%b %f %H:%M:%S" SP hostname|ipaddress
// detect three spaces
int spaceCnt = 0;
std::size_t start = pos;
while (spaceCnt < 3 && pos < line.size())
{
if (line[pos] == ' ')
{
spaceCnt++;
if (spaceCnt == 1)
{
// size must be 3 chars for month
if (pos - start != 3)
{
// probably a shortened time value, or the hostname
// assume hostName
Poco::Message logEntry(line.substr(start, pos-start), line.substr(pos+1), prio);
message.swap(logEntry);
return;
}
}
else if (spaceCnt == 2)
{
// a day value!
if (!(Poco::Ascii::isDigit(line[pos-1]) && (Poco::Ascii::isDigit(line[pos-2]) || Poco::Ascii::isSpace(line[pos-2]))))
{
// assume the next field is a hostname
spaceCnt = 3;
}
}
if (pos + 1 < line.size() && line[pos+1] == ' ')
{
// we have two spaces when the day value is smaller than 10!
++pos; // skip one
}
}
++pos;
}
std::string timeStr(line.substr(start, pos-start-1));
int tzd(0);
Poco::DateTime date;
int year = date.year(); // year is not included, use the current one
bool hasDate = Poco::DateTimeParser::tryParse(RemoteSyslogChannel::BSD_TIMEFORMAT, timeStr, date, tzd);
if (hasDate)
{
int m = date.month();
int d = date.day();
int h = date.hour();
int min = date.minute();
int sec = date.second();
date = Poco::DateTime(year, m, d, h, min, sec);
}
// next entry is host SP
std::string hostName(parseUntilSpace(line, pos));
// TAG: at most 32 alphanumeric chars, ANY non alphannumeric indicates start of message content
// ignore: treat everything as content
std::string messageText(line.substr(pos));
pos = line.size();
Poco::Message logEntry(hostName, messageText, prio);
logEntry.setTime(date.timestamp());
message.swap(logEntry);
}
std::string SyslogParser::parseUntilSpace(const std::string& line, std::size_t& pos)
{
std::size_t start = pos;
while (pos < line.size() && !Poco::Ascii::isSpace(line[pos]))
++pos;
// skip space
++pos;
return line.substr(start, pos-start-1);
}
Poco::Message::Priority SyslogParser::convert(RemoteSyslogChannel::Severity severity)
{
switch (severity)
{
case RemoteSyslogChannel::SYSLOG_EMERGENCY:
return Poco::Message::PRIO_FATAL;
case RemoteSyslogChannel::SYSLOG_ALERT:
return Poco::Message::PRIO_FATAL;
case RemoteSyslogChannel::SYSLOG_CRITICAL:
return Poco::Message::PRIO_CRITICAL;
case RemoteSyslogChannel::SYSLOG_ERROR:
return Poco::Message::PRIO_ERROR;
case RemoteSyslogChannel::SYSLOG_WARNING:
return Poco::Message::PRIO_WARNING;
case RemoteSyslogChannel::SYSLOG_NOTICE:
return Poco::Message::PRIO_NOTICE;
case RemoteSyslogChannel::SYSLOG_INFORMATIONAL:
return Poco::Message::PRIO_INFORMATION;
case RemoteSyslogChannel::SYSLOG_DEBUG:
return Poco::Message::PRIO_DEBUG;
}
throw Poco::LogicException("Illegal severity value in message");
}
//
// RemoteSyslogListener
//
const std::string RemoteSyslogListener::PROP_PORT("port");
const std::string RemoteSyslogListener::PROP_THREADS("threads");
RemoteSyslogListener::RemoteSyslogListener():
_pListener(0),
_pParser(0),
_port(RemoteSyslogChannel::SYSLOG_PORT),
_threads(1)
{
}
RemoteSyslogListener::RemoteSyslogListener(Poco::UInt16 port):
_pListener(0),
_pParser(0),
_port(port),
_threads(1)
{
}
RemoteSyslogListener::RemoteSyslogListener(Poco::UInt16 port, int threads):
_pListener(0),
_pParser(0),
_port(port),
_threads(threads)
{
}
RemoteSyslogListener::~RemoteSyslogListener()
{
}
void RemoteSyslogListener::processMessage(const std::string& messageText)
{
Poco::Message message;
_pParser->parse(messageText, message);
log(message);
}
void RemoteSyslogListener::enqueueMessage(const std::string& messageText, const Poco::Net::SocketAddress& senderAddress)
{
_queue.enqueueNotification(new MessageNotification(messageText, senderAddress));
}
void RemoteSyslogListener::setProperty(const std::string& name, const std::string& value)
{
if (name == PROP_PORT)
{
int val = Poco::NumberParser::parse(value);
if (val >= 0 && val < 65536)
_port = static_cast<Poco::UInt16>(val);
else
throw Poco::InvalidArgumentException("Not a valid port number", value);
}
else if (name == PROP_THREADS)
{
int val = Poco::NumberParser::parse(value);
if (val > 0 && val < 16)
_threads = val;
else
throw Poco::InvalidArgumentException("Invalid number of threads", value);
}
else
{
SplitterChannel::setProperty(name, value);
}
}
std::string RemoteSyslogListener::getProperty(const std::string& name) const
{
if (name == PROP_PORT)
return Poco::NumberFormatter::format(_port);
else if (name == PROP_THREADS)
return Poco::NumberFormatter::format(_threads);
else
return SplitterChannel::getProperty(name);
}
void RemoteSyslogListener::open()
{
SplitterChannel::open();
_pParser = new SyslogParser(_queue, this);
if (_port > 0)
{
_pListener = new RemoteUDPListener(_queue, _port);
}
for (int i = 0; i < _threads; i++)
{
_threadPool.start(*_pParser);
}
if (_pListener)
{
_threadPool.start(*_pListener);
}
}
void RemoteSyslogListener::close()
{
if (_pListener)
{
_pListener->safeStop();
}
if (_pParser)
{
_pParser->safeStop();
}
_queue.clear();
_threadPool.joinAll();
delete _pListener;
delete _pParser;
_pListener = 0;
_pParser = 0;
SplitterChannel::close();
}
void RemoteSyslogListener::registerChannel()
{
Poco::LoggingFactory::defaultFactory().registerChannelClass("RemoteSyslogListener", new Poco::Instantiator<RemoteSyslogListener, Poco::Channel>);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,373 @@
//
// SMTPClientSession.cpp
//
// $Id: //poco/1.4/Net/src/SMTPClientSession.cpp#1 $
//
// Library: Net
// Package: Mail
// Module: SMTPClientSession
//
// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SMTPClientSession.h"
#include "Poco/Net/MailMessage.h"
#include "Poco/Net/MailRecipient.h"
#include "Poco/Net/MailStream.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/SocketStream.h"
#include "Poco/Net/NetException.h"
#include "Poco/Environment.h"
#include "Poco/Net/NetworkInterface.h"
#include "Poco/HMACEngine.h"
#include "Poco/MD5Engine.h"
#include "Poco/SHA1Engine.h"
#include "Poco/DigestStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/Base64Encoder.h"
#include "Poco/Base64Decoder.h"
#include "Poco/String.h"
#include <sstream>
#include <fstream>
#include <iostream>
using Poco::DigestEngine;
using Poco::HMACEngine;
using Poco::MD5Engine;
using Poco::SHA1Engine;
using Poco::DigestOutputStream;
using Poco::StreamCopier;
using Poco::Base64Encoder;
using Poco::Base64Decoder;
using Poco::Environment;
namespace Poco {
namespace Net {
SMTPClientSession::SMTPClientSession(const StreamSocket& socket):
_socket(socket),
_isOpen(false)
{
}
SMTPClientSession::SMTPClientSession(const std::string& host, Poco::UInt16 port):
_socket(SocketAddress(host, port)),
_isOpen(false)
{
}
SMTPClientSession::~SMTPClientSession()
{
try
{
close();
}
catch (...)
{
}
}
void SMTPClientSession::setTimeout(const Poco::Timespan& timeout)
{
_socket.setReceiveTimeout(timeout);
}
Poco::Timespan SMTPClientSession::getTimeout() const
{
return _socket.getReceiveTimeout();
}
void SMTPClientSession::login(const std::string& hostname, std::string& response)
{
open();
int status = sendCommand("EHLO", hostname, response);
if (isPermanentNegative(status))
status = sendCommand("HELO", hostname, response);
if (!isPositiveCompletion(status)) throw SMTPException("Login failed", response, status);
}
void SMTPClientSession::login(const std::string& hostname)
{
std::string response;
login(hostname, response);
}
void SMTPClientSession::login()
{
login(Environment::nodeName());
}
void SMTPClientSession::loginUsingCRAMMD5(const std::string& username, const std::string& password)
{
HMACEngine<MD5Engine> hmac(password);
loginUsingCRAM(username, "CRAM-MD5", hmac);
}
void SMTPClientSession::loginUsingCRAMSHA1(const std::string& username, const std::string& password)
{
HMACEngine<SHA1Engine> hmac(password);
loginUsingCRAM(username, "CRAM-SHA1", hmac);
}
void SMTPClientSession::loginUsingCRAM(const std::string& username, const std::string& method, Poco::DigestEngine& hmac)
{
int status = 0;
std::string response;
status = sendCommand(std::string("AUTH ") + method, response);
if (!isPositiveIntermediate(status)) throw SMTPException(std::string("Cannot authenticate using ") + method, response, status);
std::string challengeBase64 = response.substr(4);
std::istringstream istr(challengeBase64);
Base64Decoder decoder(istr);
std::string challenge;
StreamCopier::copyToString(decoder, challenge);
hmac.update(challenge);
const DigestEngine::Digest& digest = hmac.digest();
std::string digestString(DigestEngine::digestToHex(digest));
std::string challengeResponse = username + " " + digestString;
std::ostringstream challengeResponseBase64;
Base64Encoder encoder(challengeResponseBase64);
encoder << challengeResponse;
encoder.close();
status = sendCommand(challengeResponseBase64.str(), response);
if (!isPositiveCompletion(status)) throw SMTPException(std::string("Login using ") + method + " failed", response, status);
}
void SMTPClientSession::loginUsingLogin(const std::string& username, const std::string& password)
{
int status = 0;
std::string response;
status = sendCommand("AUTH LOGIN", response);
if (!isPositiveIntermediate(status)) throw SMTPException("Cannot authenticate using LOGIN", response, status);
std::ostringstream usernameBase64;
Base64Encoder usernameEncoder(usernameBase64);
usernameEncoder << username;
usernameEncoder.close();
std::ostringstream passwordBase64;
Base64Encoder passwordEncoder(passwordBase64);
passwordEncoder << password;
passwordEncoder.close();
//Server request for username/password not defined could be either
//S: login:
//C: user_login
//S: password:
//C: user_password
//or
//S: password:
//C: user_password
//S: login:
//C: user_login
std::string decodedResponse;
std::istringstream responseStream(response.substr(4));
Base64Decoder responseDecoder(responseStream);
StreamCopier::copyToString(responseDecoder, decodedResponse);
if (Poco::icompare(decodedResponse, 0, 8, "username") == 0) // username first (md5("Username:"))
{
status = sendCommand(usernameBase64.str(), response);
if (!isPositiveIntermediate(status)) throw SMTPException("Login using LOGIN username failed", response, status);
status = sendCommand(passwordBase64.str(), response);
if (!isPositiveCompletion(status)) throw SMTPException("Login using LOGIN password failed", response, status);
}
else if (Poco::icompare(decodedResponse, 0, 8, "password") == 0) // password first (md5("Password:"))
{
status = sendCommand(passwordBase64.str(), response);
if (!isPositiveIntermediate(status)) throw SMTPException("Login using LOGIN password failed", response, status);
status = sendCommand(usernameBase64.str(), response);
if (!isPositiveCompletion(status)) throw SMTPException("Login using LOGIN username failed", response, status);
}
}
void SMTPClientSession::loginUsingPlain(const std::string& username, const std::string& password)
{
int status = 0;
std::string response;
std::ostringstream credentialsBase64;
Base64Encoder credentialsEncoder(credentialsBase64);
credentialsEncoder << username << '\0' << password;
credentialsEncoder.close();
status = sendCommand("AUTH PLAIN", credentialsBase64.str(), response);
if (!isPositiveCompletion(status)) throw SMTPException("Login using PLAIN failed", response, status);
}
void SMTPClientSession::login(LoginMethod loginMethod, const std::string& username, const std::string& password)
{
login(Environment::nodeName(), loginMethod, username, password);
}
void SMTPClientSession::login(const std::string& hostname, LoginMethod loginMethod, const std::string& username, const std::string& password)
{
std::string response;
login(hostname, response);
if (loginMethod == AUTH_CRAM_MD5)
{
if (response.find("CRAM-MD5", 0) != std::string::npos)
{
loginUsingCRAMMD5(username, password);
}
else throw SMTPException("The mail service does not support CRAM-MD5 authentication", response);
}
else if (loginMethod == AUTH_CRAM_SHA1)
{
if (response.find("CRAM-SHA1", 0) != std::string::npos)
{
loginUsingCRAMSHA1(username, password);
}
else throw SMTPException("The mail service does not support CRAM-SHA1 authentication", response);
}
else if (loginMethod == AUTH_LOGIN)
{
if (response.find("LOGIN", 0) != std::string::npos)
{
loginUsingLogin(username, password);
}
else throw SMTPException("The mail service does not support LOGIN authentication", response);
}
else if (loginMethod == AUTH_PLAIN)
{
if (response.find("PLAIN", 0) != std::string::npos)
{
loginUsingPlain(username, password);
}
else throw SMTPException("The mail service does not support PLAIN authentication", response);
}
else if (loginMethod != AUTH_NONE)
{
throw SMTPException("The autentication method is not supported");
}
}
void SMTPClientSession::open()
{
if (!_isOpen)
{
std::string response;
int status = _socket.receiveStatusMessage(response);
if (!isPositiveCompletion(status)) throw SMTPException("The mail service is unavailable", response, status);
_isOpen = true;
}
}
void SMTPClientSession::close()
{
if (_isOpen)
{
std::string response;
sendCommand("QUIT", response);
_socket.close();
_isOpen = false;
}
}
void SMTPClientSession::sendMessage(const MailMessage& message)
{
std::string response;
int status = 0;
const std::string& fromField = message.getSender();
std::string::size_type emailPos = fromField.find('<');
if (emailPos == std::string::npos)
{
std::string sender("<");
sender.append(fromField);
sender.append(">");
status = sendCommand("MAIL FROM:", sender, response);
}
else
{
status = sendCommand("MAIL FROM:", fromField.substr(emailPos, fromField.size() - emailPos), response);
}
if (!isPositiveCompletion(status)) throw SMTPException("Cannot send message", response, status);
for (MailMessage::Recipients::const_iterator it = message.recipients().begin(); it != message.recipients().end(); ++it)
{
std::string recipient("<");
recipient.append(it->getAddress());
recipient.append(">");
int status = sendCommand("RCPT TO:", recipient, response);
if (!isPositiveCompletion(status)) throw SMTPException(std::string("Recipient rejected: ") + recipient, response, status);
}
status = sendCommand("DATA", response);
if (!isPositiveIntermediate(status)) throw SMTPException("Cannot send message data", response, status);
SocketOutputStream socketStream(_socket);
MailOutputStream mailStream(socketStream);
message.write(mailStream);
mailStream.close();
socketStream.flush();
status = _socket.receiveStatusMessage(response);
if (!isPositiveCompletion(status)) throw SMTPException("The server rejected the message", response, status);
}
int SMTPClientSession::sendCommand(const std::string& command, std::string& response)
{
_socket.sendMessage(command);
return _socket.receiveStatusMessage(response);
}
int SMTPClientSession::sendCommand(const std::string& command, const std::string& arg, std::string& response)
{
_socket.sendMessage(command, arg);
return _socket.receiveStatusMessage(response);
}
} } // namespace Poco::Net

144
Net/src/ServerSocket.cpp Normal file
View File

@@ -0,0 +1,144 @@
//
// ServerSocket.cpp
//
// $Id: //poco/1.4/Net/src/ServerSocket.cpp#2 $
//
// Library: Net
// Package: Sockets
// Module: ServerSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/ServerSocketImpl.h"
#include "Poco/Exception.h"
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
ServerSocket::ServerSocket(): Socket(new ServerSocketImpl)
{
}
ServerSocket::ServerSocket(const Socket& socket): Socket(socket)
{
if (!dynamic_cast<ServerSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
ServerSocket::ServerSocket(const SocketAddress& address, int backlog): Socket(new ServerSocketImpl)
{
impl()->bind(address, true);
impl()->listen(backlog);
}
ServerSocket::ServerSocket(Poco::UInt16 port, int backlog): Socket(new ServerSocketImpl)
{
IPAddress wildcardAddr;
SocketAddress address(wildcardAddr, port);
impl()->bind(address, true);
impl()->listen(backlog);
}
ServerSocket::ServerSocket(SocketImpl* pImpl, bool ignore): Socket(pImpl)
{
}
ServerSocket::~ServerSocket()
{
}
ServerSocket& ServerSocket::operator = (const Socket& socket)
{
if (dynamic_cast<ServerSocketImpl*>(socket.impl()))
Socket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
void ServerSocket::bind(const SocketAddress& address, bool reuseAddress)
{
impl()->bind(address, reuseAddress);
}
void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress)
{
IPAddress wildcardAddr;
SocketAddress address(wildcardAddr, port);
impl()->bind(address, reuseAddress);
}
void ServerSocket::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only)
{
impl()->bind6(address, reuseAddress, ipV6Only);
}
void ServerSocket::bind6(Poco::UInt16 port, bool reuseAddress, bool ipV6Only)
{
IPAddress wildcardAddr;
SocketAddress address(wildcardAddr, port);
impl()->bind6(address, reuseAddress, ipV6Only);
}
void ServerSocket::listen(int backlog)
{
impl()->listen(backlog);
}
StreamSocket ServerSocket::acceptConnection(SocketAddress& clientAddr)
{
return StreamSocket(impl()->acceptConnection(clientAddr));
}
StreamSocket ServerSocket::acceptConnection()
{
SocketAddress clientAddr;
return StreamSocket(impl()->acceptConnection(clientAddr));
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,54 @@
//
// ServerSocketImpl.cpp
//
// $Id: //poco/1.4/Net/src/ServerSocketImpl.cpp#1 $
//
// Library: Net
// Package: Sockets
// Module: ServerSocketImpl
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/ServerSocketImpl.h"
namespace Poco {
namespace Net {
ServerSocketImpl::ServerSocketImpl()
{
}
ServerSocketImpl::~ServerSocketImpl()
{
}
} } // namespace Poco::Net

340
Net/src/Socket.cpp Normal file
View File

@@ -0,0 +1,340 @@
//
// Socket.cpp
//
// $Id: //poco/1.4/Net/src/Socket.cpp#3 $
//
// Library: Net
// Package: Sockets
// Module: Socket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/Socket.h"
#include "Poco/Net/StreamSocketImpl.h"
#include "Poco/Timestamp.h"
#include <algorithm>
#include <string.h> // FD_SET needs memset on some platforms, so we can't use <cstring>
#if defined(POCO_HAVE_FD_EPOLL)
#include <sys/epoll.h>
#endif
namespace Poco {
namespace Net {
Socket::Socket():
_pImpl(new StreamSocketImpl)
{
}
Socket::Socket(SocketImpl* pImpl):
_pImpl(pImpl)
{
poco_check_ptr (_pImpl);
}
Socket::Socket(const Socket& socket):
_pImpl(socket._pImpl)
{
poco_check_ptr (_pImpl);
_pImpl->duplicate();
}
Socket& Socket::operator = (const Socket& socket)
{
if (&socket != this)
{
if (_pImpl) _pImpl->release();
_pImpl = socket._pImpl;
if (_pImpl) _pImpl->duplicate();
}
return *this;
}
Socket::~Socket()
{
_pImpl->release();
}
int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exceptList, const Poco::Timespan& timeout)
{
#if defined(POCO_HAVE_FD_EPOLL)
int epollSize = readList.size() + writeList.size() + exceptList.size();
if (epollSize == 0) return 0;
int epollfd = -1;
{
struct epoll_event eventsIn[epollSize];
memset(eventsIn, 0, sizeof(eventsIn));
struct epoll_event* eventLast = eventsIn;
for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it)
{
poco_socket_t sockfd = it->sockfd();
if (sockfd != POCO_INVALID_SOCKET)
{
struct epoll_event* e = eventsIn;
for (; e != eventLast; ++e)
{
if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd)
break;
}
if (e == eventLast)
{
e->data.ptr = &(*it);
++eventLast;
}
e->events |= EPOLLIN;
}
}
for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it)
{
poco_socket_t sockfd = it->sockfd();
if (sockfd != POCO_INVALID_SOCKET)
{
struct epoll_event* e = eventsIn;
for (; e != eventLast; ++e)
{
if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd)
break;
}
if (e == eventLast)
{
e->data.ptr = &(*it);
++eventLast;
}
e->events |= EPOLLOUT;
}
}
for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it)
{
poco_socket_t sockfd = it->sockfd();
if (sockfd != POCO_INVALID_SOCKET)
{
struct epoll_event* e = eventsIn;
for (; e != eventLast; ++e)
{
if (reinterpret_cast<Socket*>(e->data.ptr)->sockfd() == sockfd)
break;
}
if (e == eventLast)
{
e->data.ptr = &(*it);
++eventLast;
}
e->events |= EPOLLERR;
}
}
epollSize = eventLast - eventsIn;
epollfd = epoll_create(epollSize);
if (epollfd < 0)
{
char buf[1024];
strerror_r(errno, buf, sizeof(buf));
SocketImpl::error(std::string("Can't create epoll queue: ") + buf);
}
for (struct epoll_event* e = eventsIn; e != eventLast; ++e)
{
poco_socket_t sockfd = reinterpret_cast<Socket*>(e->data.ptr)->sockfd();
if (sockfd != POCO_INVALID_SOCKET)
{
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, e) < 0)
{
char buf[1024];
strerror_r(errno, buf, sizeof(buf));
::close(epollfd);
SocketImpl::error(std::string("Can't insert socket to epoll queue: ") + buf);
}
}
}
}
struct epoll_event eventsOut[epollSize];
memset(eventsOut, 0, sizeof(eventsOut));
Poco::Timespan remainingTime(timeout);
int rc;
do
{
Poco::Timestamp start;
rc = epoll_wait(epollfd, eventsOut, epollSize, remainingTime.totalMilliseconds());
if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
{
Poco::Timestamp end;
Poco::Timespan waited = end - start;
if (waited < remainingTime)
remainingTime -= waited;
else
remainingTime = 0;
}
}
while (rc < 0 && SocketImpl::lastError() == POCO_EINTR);
::close(epollfd);
if (rc < 0) SocketImpl::error();
SocketList readyReadList;
SocketList readyWriteList;
SocketList readyExceptList;
for (int n = 0; n < rc; ++n)
{
if (eventsOut[n].events & EPOLLERR)
readyExceptList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr));
if (eventsOut[n].events & EPOLLIN)
readyReadList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr));
if (eventsOut[n].events & EPOLLOUT)
readyWriteList.push_back(*reinterpret_cast<Socket*>(eventsOut[n].data.ptr));
}
std::swap(readList, readyReadList);
std::swap(writeList, readyWriteList);
std::swap(exceptList, readyExceptList);
return readList.size() + writeList.size() + exceptList.size();
#else
fd_set fdRead;
fd_set fdWrite;
fd_set fdExcept;
int nfd = 0;
FD_ZERO(&fdRead);
for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it)
{
poco_socket_t fd = it->sockfd();
if (fd != POCO_INVALID_SOCKET)
{
if (int(fd) > nfd)
nfd = int(fd);
FD_SET(fd, &fdRead);
}
}
FD_ZERO(&fdWrite);
for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it)
{
poco_socket_t fd = it->sockfd();
if (fd != POCO_INVALID_SOCKET)
{
if (int(fd) > nfd)
nfd = int(fd);
FD_SET(fd, &fdWrite);
}
}
FD_ZERO(&fdExcept);
for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it)
{
poco_socket_t fd = it->sockfd();
if (fd != POCO_INVALID_SOCKET)
{
if (int(fd) > nfd)
nfd = int(fd);
FD_SET(fd, &fdExcept);
}
}
if (nfd == 0) return 0;
Poco::Timespan remainingTime(timeout);
int rc;
do
{
struct timeval tv;
tv.tv_sec = (long) remainingTime.totalSeconds();
tv.tv_usec = (long) remainingTime.useconds();
Poco::Timestamp start;
rc = ::select(nfd + 1, &fdRead, &fdWrite, &fdExcept, &tv);
if (rc < 0 && SocketImpl::lastError() == POCO_EINTR)
{
Poco::Timestamp end;
Poco::Timespan waited = end - start;
if (waited < remainingTime)
remainingTime -= waited;
else
remainingTime = 0;
}
}
while (rc < 0 && SocketImpl::lastError() == POCO_EINTR);
if (rc < 0) SocketImpl::error();
SocketList readyReadList;
for (SocketList::const_iterator it = readList.begin(); it != readList.end(); ++it)
{
poco_socket_t fd = it->sockfd();
if (fd != POCO_INVALID_SOCKET)
{
if (FD_ISSET(fd, &fdRead))
readyReadList.push_back(*it);
}
}
std::swap(readList, readyReadList);
SocketList readyWriteList;
for (SocketList::const_iterator it = writeList.begin(); it != writeList.end(); ++it)
{
poco_socket_t fd = it->sockfd();
if (fd != POCO_INVALID_SOCKET)
{
if (FD_ISSET(fd, &fdWrite))
readyWriteList.push_back(*it);
}
}
std::swap(writeList, readyWriteList);
SocketList readyExceptList;
for (SocketList::const_iterator it = exceptList.begin(); it != exceptList.end(); ++it)
{
poco_socket_t fd = it->sockfd();
if (fd != POCO_INVALID_SOCKET)
{
if (FD_ISSET(fd, &fdExcept))
readyExceptList.push_back(*it);
}
}
std::swap(exceptList, readyExceptList);
return rc;
#endif // POCO_HAVE_FD_EPOLL
}
bool Socket::supportsIPv6()
{
#if defined(POCO_HAVE_IPv6)
return true;
#else
return false;
#endif
}
} } // namespace Poco::Net

422
Net/src/SocketAddress.cpp Normal file
View File

@@ -0,0 +1,422 @@
//
// SocketAddress.cpp
//
// $Id: //poco/1.4/Net/src/SocketAddress.cpp#5 $
//
// Library: Net
// Package: NetCore
// Module: SocketAddress
//
// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/IPAddress.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/DNS.h"
#include "Poco/RefCountedObject.h"
#include "Poco/NumberParser.h"
#include "Poco/NumberFormatter.h"
#include <algorithm>
#include <cstring>
using Poco::RefCountedObject;
using Poco::NumberParser;
using Poco::NumberFormatter;
using Poco::UInt16;
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
struct AFLT
{
bool operator () (const IPAddress& a1, const IPAddress& a2)
{
return a1.af() < a2.af();
}
};
//
// SocketAddressImpl
//
class SocketAddressImpl: public RefCountedObject
{
public:
virtual IPAddress host() const = 0;
virtual UInt16 port() const = 0;
virtual poco_socklen_t length() const = 0;
virtual const struct sockaddr* addr() const = 0;
virtual int af() const = 0;
protected:
SocketAddressImpl()
{
#if defined(_WIN32)
Poco::Net::initializeNetwork();
#endif
}
virtual ~SocketAddressImpl()
{
#if defined(_WIN32)
Poco::Net::uninitializeNetwork();
#endif
}
private:
SocketAddressImpl(const SocketAddressImpl&);
SocketAddressImpl& operator = (const SocketAddressImpl&);
};
class IPv4SocketAddressImpl: public SocketAddressImpl
{
public:
IPv4SocketAddressImpl()
{
std::memset(&_addr, 0, sizeof(_addr));
_addr.sin_family = AF_INET;
poco_set_sin_len(&_addr);
}
IPv4SocketAddressImpl(const struct sockaddr_in* addr)
{
std::memcpy(&_addr, addr, sizeof(_addr));
}
IPv4SocketAddressImpl(const void* addr, UInt16 port)
{
std::memset(&_addr, 0, sizeof(_addr));
_addr.sin_family = AF_INET;
std::memcpy(&_addr.sin_addr, addr, sizeof(_addr.sin_addr));
_addr.sin_port = port;
}
IPAddress host() const
{
return IPAddress(&_addr.sin_addr, sizeof(_addr.sin_addr));
}
UInt16 port() const
{
return _addr.sin_port;
}
poco_socklen_t length() const
{
return sizeof(_addr);
}
const struct sockaddr* addr() const
{
return reinterpret_cast<const struct sockaddr*>(&_addr);
}
int af() const
{
return _addr.sin_family;
}
private:
struct sockaddr_in _addr;
};
#if defined(POCO_HAVE_IPv6)
class IPv6SocketAddressImpl: public SocketAddressImpl
{
public:
IPv6SocketAddressImpl(const struct sockaddr_in6* addr)
{
std::memcpy(&_addr, addr, sizeof(_addr));
}
IPv6SocketAddressImpl(const void* addr, UInt16 port)
{
std::memset(&_addr, 0, sizeof(_addr));
_addr.sin6_family = AF_INET6;
poco_set_sin6_len(&_addr);
std::memcpy(&_addr.sin6_addr, addr, sizeof(_addr.sin6_addr));
_addr.sin6_port = port;
}
IPv6SocketAddressImpl(const void* addr, UInt16 port, UInt32 scope)
{
std::memset(&_addr, 0, sizeof(_addr));
_addr.sin6_family = AF_INET6;
poco_set_sin6_len(&_addr);
std::memcpy(&_addr.sin6_addr, addr, sizeof(_addr.sin6_addr));
_addr.sin6_port = port;
_addr.sin6_scope_id = scope;
}
IPAddress host() const
{
return IPAddress(&_addr.sin6_addr, sizeof(_addr.sin6_addr), _addr.sin6_scope_id);
}
UInt16 port() const
{
return _addr.sin6_port;
}
poco_socklen_t length() const
{
return sizeof(_addr);
}
const struct sockaddr* addr() const
{
return reinterpret_cast<const struct sockaddr*>(&_addr);
}
int af() const
{
return _addr.sin6_family;
}
private:
struct sockaddr_in6 _addr;
};
#endif // POCO_HAVE_IPv6
//
// SocketAddress
//
SocketAddress::SocketAddress()
{
_pImpl = new IPv4SocketAddressImpl;
}
SocketAddress::SocketAddress(const IPAddress& addr, Poco::UInt16 port)
{
init(addr, port);
}
SocketAddress::SocketAddress(const std::string& addr, Poco::UInt16 port)
{
init(addr, port);
}
SocketAddress::SocketAddress(const std::string& addr, const std::string& port)
{
init(addr, resolveService(port));
}
SocketAddress::SocketAddress(const std::string& hostAndPort)
{
poco_assert (!hostAndPort.empty());
std::string host;
std::string port;
std::string::const_iterator it = hostAndPort.begin();
std::string::const_iterator end = hostAndPort.end();
if (*it == '[')
{
++it;
while (it != end && *it != ']') host += *it++;
if (it == end) throw InvalidArgumentException("Malformed IPv6 address");
++it;
}
else
{
while (it != end && *it != ':') host += *it++;
}
if (it != end && *it == ':')
{
++it;
while (it != end) port += *it++;
}
else throw InvalidArgumentException("Missing port number");
init(host, resolveService(port));
}
SocketAddress::SocketAddress(const SocketAddress& addr)
{
_pImpl = addr._pImpl;
_pImpl->duplicate();
}
SocketAddress::SocketAddress(const struct sockaddr* addr, poco_socklen_t length)
{
if (length == sizeof(struct sockaddr_in))
_pImpl = new IPv4SocketAddressImpl(reinterpret_cast<const struct sockaddr_in*>(addr));
#if defined(POCO_HAVE_IPv6)
else if (length == sizeof(struct sockaddr_in6))
_pImpl = new IPv6SocketAddressImpl(reinterpret_cast<const struct sockaddr_in6*>(addr));
#endif
else throw Poco::InvalidArgumentException("Invalid address length passed to SocketAddress()");
}
SocketAddress::~SocketAddress()
{
_pImpl->release();
}
SocketAddress& SocketAddress::operator = (const SocketAddress& addr)
{
if (&addr != this)
{
_pImpl->release();
_pImpl = addr._pImpl;
_pImpl->duplicate();
}
return *this;
}
void SocketAddress::swap(SocketAddress& addr)
{
std::swap(_pImpl, addr._pImpl);
}
IPAddress SocketAddress::host() const
{
return _pImpl->host();
}
Poco::UInt16 SocketAddress::port() const
{
return ntohs(_pImpl->port());
}
poco_socklen_t SocketAddress::length() const
{
return _pImpl->length();
}
const struct sockaddr* SocketAddress::addr() const
{
return _pImpl->addr();
}
int SocketAddress::af() const
{
return _pImpl->af();
}
std::string SocketAddress::toString() const
{
std::string result;
if (host().family() == IPAddress::IPv6)
result.append("[");
result.append(host().toString());
if (host().family() == IPAddress::IPv6)
result.append("]");
result.append(":");
NumberFormatter::append(result, port());
return result;
}
void SocketAddress::init(const IPAddress& host, Poco::UInt16 port)
{
if (host.family() == IPAddress::IPv4)
_pImpl = new IPv4SocketAddressImpl(host.addr(), htons(port));
#if defined(POCO_HAVE_IPv6)
else if (host.family() == IPAddress::IPv6)
_pImpl = new IPv6SocketAddressImpl(host.addr(), htons(port), host.scope());
#endif
else throw Poco::NotImplementedException("unsupported IP address family");
}
void SocketAddress::init(const std::string& host, Poco::UInt16 port)
{
IPAddress ip;
if (IPAddress::tryParse(host, ip))
{
init(ip, port);
}
else
{
HostEntry he = DNS::hostByName(host);
HostEntry::AddressList addresses = he.addresses();
if (addresses.size() > 0)
{
#if defined(POCO_HAVE_IPv6)
// if we get both IPv4 and IPv6 addresses, prefer IPv4
std::sort(addresses.begin(), addresses.end(), AFLT());
#endif
init(addresses[0], port);
}
else throw HostNotFoundException("No address found for host", host);
}
}
Poco::UInt16 SocketAddress::resolveService(const std::string& service)
{
unsigned port;
if (NumberParser::tryParseUnsigned(service, port) && port <= 0xFFFF)
{
return (UInt16) port;
}
else
{
#if defined(POCO_VXWORKS)
throw ServiceNotFoundException(service);
#else
struct servent* se = getservbyname(service.c_str(), NULL);
if (se)
return ntohs(se->s_port);
else
throw ServiceNotFoundException(service);
#endif
}
}
} } // namespace Poco::Net

1017
Net/src/SocketImpl.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,127 @@
//
// SocketNotification.cpp
//
// $Id: //poco/1.4/Net/src/SocketNotification.cpp#1 $
//
// Library: Net
// Package: Reactor
// Module: SocketNotification
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SocketNotification.h"
namespace Poco {
namespace Net {
SocketNotification::SocketNotification(SocketReactor* pReactor):
_pReactor(pReactor)
{
}
SocketNotification::~SocketNotification()
{
}
void SocketNotification::setSocket(const Socket& socket)
{
_socket = socket;
}
ReadableNotification::ReadableNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
ReadableNotification::~ReadableNotification()
{
}
WritableNotification::WritableNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
WritableNotification::~WritableNotification()
{
}
ErrorNotification::ErrorNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
ErrorNotification::~ErrorNotification()
{
}
TimeoutNotification::TimeoutNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
TimeoutNotification::~TimeoutNotification()
{
}
IdleNotification::IdleNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
IdleNotification::~IdleNotification()
{
}
ShutdownNotification::ShutdownNotification(SocketReactor* pReactor):
SocketNotification(pReactor)
{
}
ShutdownNotification::~ShutdownNotification()
{
}
} } // namespace Poco::Net

111
Net/src/SocketNotifier.cpp Normal file
View File

@@ -0,0 +1,111 @@
//
// SocketNotifier.cpp
//
// $Id: //poco/1.4/Net/src/SocketNotifier.cpp#1 $
//
// Library: Net
// Package: Reactor
// Module: SocketNotifier
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SocketNotifier.h"
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/SocketNotification.h"
namespace Poco {
namespace Net {
SocketNotifier::SocketNotifier(const Socket& socket):
_socket(socket)
{
}
SocketNotifier::~SocketNotifier()
{
}
void SocketNotifier::addObserver(SocketReactor* pReactor, const Poco::AbstractObserver& observer)
{
_nc.addObserver(observer);
if (observer.accepts(pReactor->_pReadableNotification))
_events.insert(pReactor->_pReadableNotification.get());
else if (observer.accepts(pReactor->_pWritableNotification))
_events.insert(pReactor->_pWritableNotification.get());
else if (observer.accepts(pReactor->_pErrorNotification))
_events.insert(pReactor->_pErrorNotification.get());
else if (observer.accepts(pReactor->_pTimeoutNotification))
_events.insert(pReactor->_pTimeoutNotification.get());
}
void SocketNotifier::removeObserver(SocketReactor* pReactor, const Poco::AbstractObserver& observer)
{
_nc.removeObserver(observer);
EventSet::iterator it = _events.end();
if (observer.accepts(pReactor->_pReadableNotification))
it = _events.find(pReactor->_pReadableNotification.get());
else if (observer.accepts(pReactor->_pWritableNotification))
it = _events.find(pReactor->_pWritableNotification.get());
else if (observer.accepts(pReactor->_pErrorNotification))
it = _events.find(pReactor->_pErrorNotification.get());
else if (observer.accepts(pReactor->_pTimeoutNotification))
it = _events.find(pReactor->_pTimeoutNotification.get());
if (it != _events.end())
_events.erase(it);
}
namespace
{
static Socket nullSocket;
}
void SocketNotifier::dispatch(SocketNotification* pNotification)
{
pNotification->setSocket(_socket);
pNotification->duplicate();
try
{
_nc.postNotification(pNotification);
}
catch (...)
{
pNotification->setSocket(nullSocket);
throw;
}
pNotification->setSocket(nullSocket);
}
} } // namespace Poco::Net

288
Net/src/SocketReactor.cpp Normal file
View File

@@ -0,0 +1,288 @@
//
// SocketReactor.cpp
//
// $Id: //poco/1.4/Net/src/SocketReactor.cpp#1 $
//
// Library: Net
// Package: Reactor
// Module: SocketReactor
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SocketReactor.h"
#include "Poco/Net/SocketNotification.h"
#include "Poco/Net/SocketNotifier.h"
#include "Poco/ErrorHandler.h"
#include "Poco/Thread.h"
#include "Poco/Exception.h"
using Poco::FastMutex;
using Poco::Exception;
using Poco::ErrorHandler;
namespace Poco {
namespace Net {
SocketReactor::SocketReactor():
_stop(false),
_timeout(DEFAULT_TIMEOUT),
_pReadableNotification(new ReadableNotification(this)),
_pWritableNotification(new WritableNotification(this)),
_pErrorNotification(new ErrorNotification(this)),
_pTimeoutNotification(new TimeoutNotification(this)),
_pIdleNotification(new IdleNotification(this)),
_pShutdownNotification(new ShutdownNotification(this))
{
}
SocketReactor::SocketReactor(const Poco::Timespan& timeout):
_stop(false),
_timeout(timeout),
_pReadableNotification(new ReadableNotification(this)),
_pWritableNotification(new WritableNotification(this)),
_pErrorNotification(new ErrorNotification(this)),
_pTimeoutNotification(new TimeoutNotification(this)),
_pIdleNotification(new IdleNotification(this)),
_pShutdownNotification(new ShutdownNotification(this))
{
}
SocketReactor::~SocketReactor()
{
}
void SocketReactor::run()
{
Socket::SocketList readable;
Socket::SocketList writable;
Socket::SocketList except;
while (!_stop)
{
try
{
readable.clear();
writable.clear();
except.clear();
int nSockets = 0;
{
FastMutex::ScopedLock lock(_mutex);
for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it)
{
if (it->second->accepts(_pReadableNotification))
{
readable.push_back(it->first);
nSockets++;
}
if (it->second->accepts(_pWritableNotification))
{
writable.push_back(it->first);
nSockets++;
}
if (it->second->accepts(_pErrorNotification))
{
except.push_back(it->first);
nSockets++;
}
}
}
if (nSockets == 0)
{
onIdle();
}
else if (Socket::select(readable, writable, except, _timeout))
{
onBusy();
for (Socket::SocketList::iterator it = readable.begin(); it != readable.end(); ++it)
dispatch(*it, _pReadableNotification);
for (Socket::SocketList::iterator it = writable.begin(); it != writable.end(); ++it)
dispatch(*it, _pWritableNotification);
for (Socket::SocketList::iterator it = except.begin(); it != except.end(); ++it)
dispatch(*it, _pErrorNotification);
}
else onTimeout();
}
catch (Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
}
onShutdown();
}
void SocketReactor::stop()
{
_stop = true;
}
void SocketReactor::setTimeout(const Poco::Timespan& timeout)
{
_timeout = timeout;
}
const Poco::Timespan& SocketReactor::getTimeout() const
{
return _timeout;
}
void SocketReactor::addEventHandler(const Socket& socket, const Poco::AbstractObserver& observer)
{
NotifierPtr pNotifier;
{
FastMutex::ScopedLock lock(_mutex);
EventHandlerMap::iterator it = _handlers.find(socket);
if (it == _handlers.end())
{
pNotifier = new SocketNotifier(socket);
_handlers[socket] = pNotifier;
}
else pNotifier = it->second;
}
pNotifier->addObserver(this, observer);
}
void SocketReactor::removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer)
{
NotifierPtr pNotifier;
{
FastMutex::ScopedLock lock(_mutex);
EventHandlerMap::iterator it = _handlers.find(socket);
if (it != _handlers.end())
{
pNotifier = it->second;
if (pNotifier->countObservers() == 1)
{
_handlers.erase(it);
}
}
}
if (pNotifier)
{
pNotifier->removeObserver(this, observer);
}
}
void SocketReactor::onTimeout()
{
dispatch(_pTimeoutNotification);
}
void SocketReactor::onIdle()
{
dispatch(_pIdleNotification);
}
void SocketReactor::onShutdown()
{
dispatch(_pShutdownNotification);
}
void SocketReactor::onBusy()
{
}
void SocketReactor::dispatch(const Socket& socket, SocketNotification* pNotification)
{
NotifierPtr pNotifier;
{
FastMutex::ScopedLock lock(_mutex);
EventHandlerMap::iterator it = _handlers.find(socket);
if (it != _handlers.end())
pNotifier = it->second;
else
return;
}
dispatch(pNotifier, pNotification);
}
void SocketReactor::dispatch(SocketNotification* pNotification)
{
std::vector<NotifierPtr> delegates;
delegates.reserve(_handlers.size());
{
FastMutex::ScopedLock lock(_mutex);
for (EventHandlerMap::iterator it = _handlers.begin(); it != _handlers.end(); ++it)
delegates.push_back(it->second);
}
for (std::vector<NotifierPtr>::iterator it = delegates.begin(); it != delegates.end(); ++it)
{
dispatch(*it, pNotification);
}
}
void SocketReactor::dispatch(NotifierPtr& pNotifier, SocketNotification* pNotification)
{
try
{
pNotifier->dispatch(pNotification);
}
catch (Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
}
} } // namespace Poco::Net

178
Net/src/SocketStream.cpp Normal file
View File

@@ -0,0 +1,178 @@
//
// SocketStream.cpp
//
// $Id: //poco/1.4/Net/src/SocketStream.cpp#1 $
//
// Library: Net
// Package: Sockets
// Module: SocketStream
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/SocketStream.h"
#include "Poco/Net/StreamSocketImpl.h"
#include "Poco/Exception.h"
using Poco::BufferedBidirectionalStreamBuf;
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
//
// SocketStreamBuf
//
SocketStreamBuf::SocketStreamBuf(const Socket& socket):
BufferedBidirectionalStreamBuf(STREAM_BUFFER_SIZE, std::ios::in | std::ios::out),
_pImpl(dynamic_cast<StreamSocketImpl*>(socket.impl()))
{
if (_pImpl)
_pImpl->duplicate();
else
throw InvalidArgumentException("Invalid or null SocketImpl passed to SocketStreamBuf");
}
SocketStreamBuf::~SocketStreamBuf()
{
_pImpl->release();
}
int SocketStreamBuf::readFromDevice(char* buffer, std::streamsize length)
{
return _pImpl->receiveBytes(buffer, (int) length);
}
int SocketStreamBuf::writeToDevice(const char* buffer, std::streamsize length)
{
return _pImpl->sendBytes(buffer, (int) length);
}
//
// SocketIOS
//
SocketIOS::SocketIOS(const Socket& socket):
_buf(socket)
{
poco_ios_init(&_buf);
}
SocketIOS::~SocketIOS()
{
try
{
_buf.sync();
}
catch (...)
{
}
}
SocketStreamBuf* SocketIOS::rdbuf()
{
return &_buf;
}
void SocketIOS::close()
{
_buf.sync();
_buf.socketImpl()->close();
}
StreamSocket SocketIOS::socket() const
{
return StreamSocket(_buf.socketImpl());
}
//
// SocketOutputStream
//
SocketOutputStream::SocketOutputStream(const Socket& socket):
SocketIOS(socket),
std::ostream(&_buf)
{
}
SocketOutputStream::~SocketOutputStream()
{
}
//
// SocketInputStream
//
SocketInputStream::SocketInputStream(const Socket& socket):
SocketIOS(socket),
std::istream(&_buf)
{
}
SocketInputStream::~SocketInputStream()
{
}
//
// SocketStream
//
SocketStream::SocketStream(const Socket& socket):
SocketIOS(socket),
std::iostream(&_buf)
{
}
SocketStream::~SocketStream()
{
}
} } // namespace Poco::Net

148
Net/src/StreamSocket.cpp Normal file
View File

@@ -0,0 +1,148 @@
//
// StreamSocket.cpp
//
// $Id: //poco/1.4/Net/src/StreamSocket.cpp#1 $
//
// Library: Net
// Package: Sockets
// Module: StreamSocket
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/StreamSocketImpl.h"
#include "Poco/Exception.h"
using Poco::InvalidArgumentException;
namespace Poco {
namespace Net {
StreamSocket::StreamSocket(): Socket(new StreamSocketImpl)
{
}
StreamSocket::StreamSocket(const SocketAddress& address): Socket(new StreamSocketImpl)
{
connect(address);
}
StreamSocket::StreamSocket(IPAddress::Family family): Socket(new StreamSocketImpl(family))
{
}
StreamSocket::StreamSocket(const Socket& socket): Socket(socket)
{
if (!dynamic_cast<StreamSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
StreamSocket::StreamSocket(SocketImpl* pImpl): Socket(pImpl)
{
if (!dynamic_cast<StreamSocketImpl*>(impl()))
throw InvalidArgumentException("Cannot assign incompatible socket");
}
StreamSocket::~StreamSocket()
{
}
StreamSocket& StreamSocket::operator = (const Socket& socket)
{
if (dynamic_cast<StreamSocketImpl*>(socket.impl()))
Socket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
void StreamSocket::connect(const SocketAddress& address)
{
impl()->connect(address);
}
void StreamSocket::connect(const SocketAddress& address, const Poco::Timespan& timeout)
{
impl()->connect(address, timeout);
}
void StreamSocket::connectNB(const SocketAddress& address)
{
impl()->connectNB(address);
}
void StreamSocket::shutdownReceive()
{
impl()->shutdownReceive();
}
void StreamSocket::shutdownSend()
{
impl()->shutdownSend();
}
void StreamSocket::shutdown()
{
impl()->shutdown();
}
int StreamSocket::sendBytes(const void* buffer, int length, int flags)
{
return impl()->sendBytes(buffer, length, flags);
}
int StreamSocket::receiveBytes(void* buffer, int length, int flags)
{
return impl()->receiveBytes(buffer, length, flags);
}
void StreamSocket::sendUrgent(unsigned char data)
{
impl()->sendUrgent(data);
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,95 @@
//
// StreamSocketImpl.cpp
//
// $Id: //poco/1.4/Net/src/StreamSocketImpl.cpp#1 $
//
// Library: Net
// Package: Sockets
// Module: StreamSocketImpl
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/StreamSocketImpl.h"
#include "Poco/Exception.h"
#include "Poco/Thread.h"
namespace Poco {
namespace Net {
StreamSocketImpl::StreamSocketImpl()
{
}
StreamSocketImpl::StreamSocketImpl(IPAddress::Family family)
{
if (family == IPAddress::IPv4)
init(AF_INET);
#if defined(POCO_HAVE_IPv6)
else if (family == IPAddress::IPv6)
init(AF_INET6);
#endif
else throw Poco::InvalidArgumentException("Invalid or unsupported address family passed to StreamSocketImpl");
}
StreamSocketImpl::StreamSocketImpl(poco_socket_t sockfd): SocketImpl(sockfd)
{
}
StreamSocketImpl::~StreamSocketImpl()
{
}
int StreamSocketImpl::sendBytes(const void* buffer, int length, int flags)
{
const char* p = reinterpret_cast<const char*>(buffer);
int remaining = length;
int sent = 0;
bool blocking = getBlocking();
while (remaining > 0)
{
int n = SocketImpl::sendBytes(p, remaining, flags);
poco_assert_dbg (n >= 0);
p += n;
sent += n;
remaining -= n;
if (blocking && remaining > 0)
Poco::Thread::yield();
else
break;
}
return sent;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,83 @@
//
// StringPartSource.cpp
//
// $Id: //poco/1.4/Net/src/StringPartSource.cpp#1 $
//
// Library: Net
// Package: Messages
// Module: StringPartSource
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/StringPartSource.h"
namespace Poco {
namespace Net {
StringPartSource::StringPartSource(const std::string& str):
PartSource("text/plain"),
_istr(str)
{
}
StringPartSource::StringPartSource(const std::string& str, const std::string& mediaType):
PartSource(mediaType),
_istr(str)
{
}
StringPartSource::StringPartSource(const std::string& str, const std::string& mediaType, const std::string& filename):
PartSource(mediaType),
_istr(str),
_filename(filename)
{
}
StringPartSource::~StringPartSource()
{
}
std::istream& StringPartSource::stream()
{
return _istr;
}
const std::string& StringPartSource::filename()
{
return _filename;
}
} } // namespace Poco::Net

179
Net/src/TCPServer.cpp Normal file
View File

@@ -0,0 +1,179 @@
//
// TCPServer.cpp
//
// $Id: //poco/1.4/Net/src/TCPServer.cpp#1 $
//
// Library: Net
// Package: TCPServer
// Module: TCPServer
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/TCPServer.h"
#include "Poco/Net/TCPServerDispatcher.h"
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Timespan.h"
#include "Poco/Exception.h"
#include "Poco/ErrorHandler.h"
using Poco::ErrorHandler;
namespace Poco {
namespace Net {
TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, const ServerSocket& socket, TCPServerParams::Ptr pParams):
_socket(socket),
_pDispatcher(new TCPServerDispatcher(pFactory, Poco::ThreadPool::defaultPool(), pParams)),
_thread(threadName(socket)),
_stopped(true)
{
}
TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, TCPServerParams::Ptr pParams):
_socket(socket),
_pDispatcher(new TCPServerDispatcher(pFactory, threadPool, pParams)),
_thread(threadName(socket)),
_stopped(true)
{
}
TCPServer::~TCPServer()
{
stop();
_pDispatcher->release();
}
const TCPServerParams& TCPServer::params() const
{
return _pDispatcher->params();
}
void TCPServer::start()
{
poco_assert (_stopped);
_stopped = false;
_thread.start(*this);
}
void TCPServer::stop()
{
if (!_stopped)
{
_stopped = true;
_thread.join();
_pDispatcher->stop();
}
}
void TCPServer::run()
{
while (!_stopped)
{
Poco::Timespan timeout(250000);
if (_socket.poll(timeout, Socket::SELECT_READ))
{
try
{
StreamSocket ss = _socket.acceptConnection();
// enabe nodelay per default: OSX really needs that
ss.setNoDelay(true);
_pDispatcher->enqueue(ss);
}
catch (Poco::Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
}
}
}
int TCPServer::currentThreads() const
{
return _pDispatcher->currentThreads();
}
int TCPServer::totalConnections() const
{
return _pDispatcher->totalConnections();
}
int TCPServer::currentConnections() const
{
return _pDispatcher->currentConnections();
}
int TCPServer::maxConcurrentConnections() const
{
return _pDispatcher->maxConcurrentConnections();
}
int TCPServer::queuedConnections() const
{
return _pDispatcher->queuedConnections();
}
int TCPServer::refusedConnections() const
{
return _pDispatcher->refusedConnections();
}
std::string TCPServer::threadName(const ServerSocket& socket)
{
std::string name("TCPServer: ");
name.append(socket.address().toString());
return name;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,82 @@
//
// TCPServerConnection.cpp
//
// $Id: //poco/1.4/Net/src/TCPServerConnection.cpp#1 $
//
// Library: Net
// Package: TCPServer
// Module: TCPServerConnection
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Exception.h"
#include "Poco/ErrorHandler.h"
using Poco::Exception;
using Poco::ErrorHandler;
namespace Poco {
namespace Net {
TCPServerConnection::TCPServerConnection(const StreamSocket& socket):
_socket(socket)
{
}
TCPServerConnection::~TCPServerConnection()
{
}
void TCPServerConnection::start()
{
try
{
run();
}
catch (Exception& exc)
{
ErrorHandler::handle(exc);
}
catch (std::exception& exc)
{
ErrorHandler::handle(exc);
}
catch (...)
{
ErrorHandler::handle();
}
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,54 @@
//
// TCPServerConnectionFactory.cpp
//
// $Id: //poco/1.4/Net/src/TCPServerConnectionFactory.cpp#1 $
//
// Library: Net
// Package: TCPServer
// Module: TCPServerConnectionFactory
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/TCPServerConnectionFactory.h"
namespace Poco {
namespace Net {
TCPServerConnectionFactory::TCPServerConnectionFactory()
{
}
TCPServerConnectionFactory::~TCPServerConnectionFactory()
{
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,258 @@
//
// TCPServerDispatcher.cpp
//
// $Id: //poco/1.4/Net/src/TCPServerDispatcher.cpp#1 $
//
// Library: Net
// Package: TCPServer
// Module: TCPServerDispatcher
//
// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/TCPServerDispatcher.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Notification.h"
#include "Poco/AutoPtr.h"
#include <memory>
using Poco::Notification;
using Poco::FastMutex;
using Poco::AutoPtr;
namespace Poco {
namespace Net {
class TCPConnectionNotification: public Notification
{
public:
TCPConnectionNotification(const StreamSocket& socket):
_socket(socket)
{
}
~TCPConnectionNotification()
{
}
const StreamSocket& socket() const
{
return _socket;
}
private:
StreamSocket _socket;
};
TCPServerDispatcher::TCPServerDispatcher(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, TCPServerParams::Ptr pParams):
_rc(1),
_pParams(pParams),
_currentThreads(0),
_totalConnections(0),
_currentConnections(0),
_maxConcurrentConnections(0),
_refusedConnections(0),
_stopped(false),
_pConnectionFactory(pFactory),
_threadPool(threadPool)
{
poco_check_ptr (pFactory);
if (!_pParams)
_pParams = new TCPServerParams;
if (_pParams->getMaxThreads() == 0)
_pParams->setMaxThreads(threadPool.capacity());
}
TCPServerDispatcher::~TCPServerDispatcher()
{
}
void TCPServerDispatcher::duplicate()
{
_mutex.lock();
++_rc;
_mutex.unlock();
}
void TCPServerDispatcher::release()
{
_mutex.lock();
int rc = --_rc;
_mutex.unlock();
if (rc == 0) delete this;
}
void TCPServerDispatcher::run()
{
AutoPtr<TCPServerDispatcher> guard(this, true); // ensure object stays alive
int idleTime = (int) _pParams->getThreadIdleTime().totalMilliseconds();
for (;;)
{
AutoPtr<Notification> pNf = _queue.waitDequeueNotification(idleTime);
if (pNf)
{
TCPConnectionNotification* pCNf = dynamic_cast<TCPConnectionNotification*>(pNf.get());
if (pCNf)
{
std::auto_ptr<TCPServerConnection> pConnection(_pConnectionFactory->createConnection(pCNf->socket()));
poco_check_ptr(pConnection.get());
beginConnection();
pConnection->start();
endConnection();
}
}
FastMutex::ScopedLock lock(_mutex);
if (_stopped || (_currentThreads > 1 && _queue.empty()))
{
--_currentThreads;
break;
}
}
}
namespace
{
static const std::string threadName("TCPServerConnection");
}
void TCPServerDispatcher::enqueue(const StreamSocket& socket)
{
FastMutex::ScopedLock lock(_mutex);
if (_queue.size() < _pParams->getMaxQueued())
{
_queue.enqueueNotification(new TCPConnectionNotification(socket));
if (!_queue.hasIdleThreads() && _currentThreads < _pParams->getMaxThreads())
{
try
{
_threadPool.startWithPriority(_pParams->getThreadPriority(), *this, threadName);
++_currentThreads;
}
catch (Poco::Exception&)
{
// no problem here, connection is already queued
// and a new thread might be available later.
}
}
}
else
{
++_refusedConnections;
}
}
void TCPServerDispatcher::stop()
{
_stopped = true;
_queue.clear();
_queue.wakeUpAll();
}
int TCPServerDispatcher::currentThreads() const
{
FastMutex::ScopedLock lock(_mutex);
return _currentThreads;
}
int TCPServerDispatcher::totalConnections() const
{
FastMutex::ScopedLock lock(_mutex);
return _totalConnections;
}
int TCPServerDispatcher::currentConnections() const
{
FastMutex::ScopedLock lock(_mutex);
return _currentConnections;
}
int TCPServerDispatcher::maxConcurrentConnections() const
{
FastMutex::ScopedLock lock(_mutex);
return _maxConcurrentConnections;
}
int TCPServerDispatcher::queuedConnections() const
{
return _queue.size();
}
int TCPServerDispatcher::refusedConnections() const
{
FastMutex::ScopedLock lock(_mutex);
return _refusedConnections;
}
void TCPServerDispatcher::beginConnection()
{
FastMutex::ScopedLock lock(_mutex);
++_totalConnections;
++_currentConnections;
if (_currentConnections > _maxConcurrentConnections)
_maxConcurrentConnections = _currentConnections;
}
void TCPServerDispatcher::endConnection()
{
FastMutex::ScopedLock lock(_mutex);
--_currentConnections;
}
} } // namespace Poco::Net

View File

@@ -0,0 +1,86 @@
//
// TCPServerParams.cpp
//
// $Id: //poco/1.4/Net/src/TCPServerParams.cpp#1 $
//
// Library: Net
// Package: TCPServer
// Module: TCPServerParams
//
// Copyright (c) 2005-2007, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/TCPServerParams.h"
namespace Poco {
namespace Net {
TCPServerParams::TCPServerParams():
_threadIdleTime(10000000),
_maxThreads(0),
_maxQueued(64),
_threadPriority(Poco::Thread::PRIO_NORMAL)
{
}
TCPServerParams::~TCPServerParams()
{
}
void TCPServerParams::setThreadIdleTime(const Poco::Timespan& milliseconds)
{
_threadIdleTime = milliseconds;
}
void TCPServerParams::setMaxThreads(int count)
{
poco_assert (count > 0);
_maxThreads = count;
}
void TCPServerParams::setMaxQueued(int count)
{
poco_assert (count > 0);
_maxQueued = count;
}
void TCPServerParams::setThreadPriority(Poco::Thread::Priority prio)
{
_threadPriority = prio;
}
} } // namespace Poco::Net

244
Net/src/WebSocket.cpp Normal file
View File

@@ -0,0 +1,244 @@
//
// WebSocket.cpp
//
// $Id: //poco/1.4/Net/src/WebSocket.cpp#4 $
//
// Library: Net
// Package: WebSocket
// Module: WebSocket
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/WebSocket.h"
#include "Poco/Net/WebSocketImpl.h"
#include "Poco/Net/HTTPServerRequestImpl.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/NetException.h"
#include "Poco/Buffer.h"
#include "Poco/MemoryStream.h"
#include "Poco/NullStream.h"
#include "Poco/BinaryWriter.h"
#include "Poco/SHA1Engine.h"
#include "Poco/Base64Encoder.h"
#include "Poco/String.h"
#include "Poco/Random.h"
#include "Poco/StreamCopier.h"
#include <sstream>
namespace Poco {
namespace Net {
const std::string WebSocket::WEBSOCKET_GUID("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
const std::string WebSocket::WEBSOCKET_VERSION("13");
HTTPCredentials WebSocket::_defaultCreds;
WebSocket::WebSocket(HTTPServerRequest& request, HTTPServerResponse& response):
StreamSocket(accept(request, response))
{
}
WebSocket::WebSocket(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response):
StreamSocket(connect(cs, request, response, _defaultCreds))
{
}
WebSocket::WebSocket(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response, HTTPCredentials& credentials):
StreamSocket(connect(cs, request, response, credentials))
{
}
WebSocket::~WebSocket()
{
}
WebSocket& WebSocket::operator = (const Socket& socket)
{
if (dynamic_cast<WebSocketImpl*>(socket.impl()))
Socket::operator = (socket);
else
throw InvalidArgumentException("Cannot assign incompatible socket");
return *this;
}
void WebSocket::shutdown()
{
shutdown(WS_NORMAL_CLOSE);
}
void WebSocket::shutdown(Poco::UInt16 statusCode, const std::string& statusMessage)
{
Poco::Buffer<char> buffer(statusMessage.size() + 2);
Poco::MemoryOutputStream ostr(buffer.begin(), buffer.size());
Poco::BinaryWriter writer(ostr, Poco::BinaryWriter::NETWORK_BYTE_ORDER);
writer << statusCode;
writer.writeRaw(statusMessage);
sendFrame(buffer.begin(), static_cast<int>(ostr.charsWritten()), FRAME_FLAG_FIN | FRAME_OP_CLOSE);
}
int WebSocket::sendFrame(const void* buffer, int length, int flags)
{
return static_cast<WebSocketImpl*>(impl())->sendBytes(buffer, length, flags);
}
int WebSocket::receiveFrame(void* buffer, int length, int& flags)
{
int n = static_cast<WebSocketImpl*>(impl())->receiveBytes(buffer, length, 0);
flags = static_cast<WebSocketImpl*>(impl())->frameFlags();
return n;
}
WebSocket::Mode WebSocket::mode() const
{
return static_cast<WebSocketImpl*>(impl())->mustMaskPayload() ? WS_CLIENT : WS_SERVER;
}
WebSocketImpl* WebSocket::accept(HTTPServerRequest& request, HTTPServerResponse& response)
{
if (icompare(request.get("Connection", ""), "Upgrade") == 0 &&
icompare(request.get("Upgrade", ""), "websocket") == 0)
{
std::string version = request.get("Sec-WebSocket-Version", "");
if (version.empty()) throw WebSocketException("Missing Sec-WebSocket-Version in handshake request", WS_ERR_HANDSHAKE_NO_VERSION);
if (version != WEBSOCKET_VERSION) throw WebSocketException("Unsupported WebSocket version requested", version, WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION);
std::string key = request.get("Sec-WebSocket-Key", "");
Poco::trimInPlace(key);
if (key.empty()) throw WebSocketException("Missing Sec-WebSocket-Key in handshake request", WS_ERR_HANDSHAKE_NO_KEY);
response.setStatusAndReason(HTTPResponse::HTTP_SWITCHING_PROTOCOLS);
response.set("Upgrade", "websocket");
response.set("Connection", "Upgrade");
response.set("Sec-WebSocket-Accept", computeAccept(key));
response.setContentLength(0);
response.send().flush();
return new WebSocketImpl(static_cast<StreamSocketImpl*>(static_cast<HTTPServerRequestImpl&>(request).detachSocket().impl()), false);
}
else throw WebSocketException("No WebSocket handshake", WS_ERR_NO_HANDSHAKE);
}
WebSocketImpl* WebSocket::connect(HTTPClientSession& cs, HTTPRequest& request, HTTPResponse& response, HTTPCredentials& credentials)
{
if (!cs.getProxyHost().empty() && !cs.secure())
{
cs.proxyTunnel();
}
std::string key = createKey();
request.set("Connection", "Upgrade");
request.set("Upgrade", "websocket");
request.set("Sec-WebSocket-Version", WEBSOCKET_VERSION);
request.set("Sec-WebSocket-Key", key);
request.setChunkedTransferEncoding(false);
cs.setKeepAlive(true);
cs.sendRequest(request);
std::istream& istr = cs.receiveResponse(response);
if (response.getStatus() == HTTPResponse::HTTP_SWITCHING_PROTOCOLS)
{
return completeHandshake(cs, response, key);
}
else if (response.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED)
{
Poco::NullOutputStream null;
Poco::StreamCopier::copyStream(istr, null);
credentials.authenticate(request, response);
if (!cs.getProxyHost().empty() && !cs.secure())
{
cs.reset();
cs.proxyTunnel();
}
cs.sendRequest(request);
cs.receiveResponse(response);
if (response.getStatus() == HTTPResponse::HTTP_SWITCHING_PROTOCOLS)
{
return completeHandshake(cs, response, key);
}
else if (response.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED)
{
throw WebSocketException("Not authorized", WS_ERR_UNAUTHORIZED);
}
}
throw WebSocketException("Cannot upgrade to WebSocket connection", response.getReason(), WS_ERR_NO_HANDSHAKE);
}
WebSocketImpl* WebSocket::completeHandshake(HTTPClientSession& cs, HTTPResponse& response, const std::string& key)
{
std::string connection = response.get("Connection", "");
if (Poco::icompare(connection, "Upgrade") != 0)
throw WebSocketException("No Connection: Upgrade header in handshake response", WS_ERR_NO_HANDSHAKE);
std::string upgrade = response.get("Upgrade", "");
if (Poco::icompare(upgrade, "websocket") != 0)
throw WebSocketException("No Upgrade: websocket header in handshake response", WS_ERR_NO_HANDSHAKE);
std::string accept = response.get("Sec-WebSocket-Accept", "");
if (accept != computeAccept(key))
throw WebSocketException("Invalid or missing Sec-WebSocket-Accept header in handshake response", WS_ERR_NO_HANDSHAKE);
return new WebSocketImpl(static_cast<StreamSocketImpl*>(cs.socket().impl()), true);
}
std::string WebSocket::createKey()
{
Poco::Random rnd;
std::ostringstream ostr;
Poco::Base64Encoder base64(ostr);
Poco::BinaryWriter writer(base64);
writer << rnd.next() << rnd.next() << rnd.next() << rnd.next();
base64.close();
return ostr.str();
}
std::string WebSocket::computeAccept(const std::string& key)
{
std::string accept(key);
accept += WEBSOCKET_GUID;
Poco::SHA1Engine sha1;
sha1.update(accept);
Poco::DigestEngine::Digest d = sha1.digest();
std::ostringstream ostr;
Poco::Base64Encoder base64(ostr);
base64.write(reinterpret_cast<const char*>(&d[0]), d.size());
base64.close();
return ostr.str();
}
} } // namespace Poco::Net

279
Net/src/WebSocketImpl.cpp Normal file
View File

@@ -0,0 +1,279 @@
//
// WebSocketImpl.cpp
//
// $Id: //poco/1.4/Net/src/WebSocketImpl.cpp#2 $
//
// Library: Net
// Package: WebSocket
// Module: WebSocketImpl
//
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#include "Poco/Net/WebSocketImpl.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/WebSocket.h"
#include "Poco/Buffer.h"
#include "Poco/BinaryWriter.h"
#include "Poco/BinaryReader.h"
#include "Poco/MemoryStream.h"
#include "Poco/Format.h"
#include <cstring>
namespace Poco {
namespace Net {
WebSocketImpl::WebSocketImpl(StreamSocketImpl* pStreamSocketImpl, bool mustMaskPayload):
StreamSocketImpl(pStreamSocketImpl->sockfd()),
_pStreamSocketImpl(pStreamSocketImpl),
_frameFlags(0),
_mustMaskPayload(mustMaskPayload)
{
poco_check_ptr(pStreamSocketImpl);
_pStreamSocketImpl->duplicate();
}
WebSocketImpl::~WebSocketImpl()
{
_pStreamSocketImpl->release();
reset();
}
int WebSocketImpl::sendBytes(const void* buffer, int length, int flags)
{
Poco::Buffer<char> frame(length + MAX_HEADER_LENGTH);
Poco::MemoryOutputStream ostr(frame.begin(), frame.size());
Poco::BinaryWriter writer(ostr, Poco::BinaryWriter::NETWORK_BYTE_ORDER);
writer << static_cast<Poco::UInt8>(flags);
Poco::UInt8 lengthByte(0);
if (_mustMaskPayload)
{
lengthByte |= FRAME_FLAG_MASK;
}
if (length < 126)
{
lengthByte |= static_cast<Poco::UInt8>(length);
writer << lengthByte;
}
else if (length < 65536)
{
lengthByte |= 126;
writer << lengthByte << static_cast<Poco::UInt16>(length);
}
else
{
lengthByte |= 127;
writer << lengthByte << static_cast<Poco::UInt64>(length);
}
if (_mustMaskPayload)
{
const Poco::UInt32 mask = _rnd.next();
const char* m = reinterpret_cast<const char*>(&mask);
const char* b = reinterpret_cast<const char*>(buffer);
writer.writeRaw(m, 4);
char* p = frame.begin() + ostr.charsWritten();
for (int i = 0; i < length; i++)
{
p[i] = b[i] ^ m[i % 4];
}
}
else
{
std::memcpy(frame.begin() + ostr.charsWritten(), buffer, length);
}
_pStreamSocketImpl->sendBytes(frame.begin(), length + static_cast<int>(ostr.charsWritten()));
return length;
}
int WebSocketImpl::receiveBytes(void* buffer, int length, int)
{
char header[MAX_HEADER_LENGTH];
int n = _pStreamSocketImpl->receiveBytes(header, MAX_HEADER_LENGTH);
if (n > 0)
{
Poco::MemoryInputStream istr(header, n);
Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER);
Poco::UInt8 flags;
Poco::UInt8 lengthByte;
char mask[4];
reader >> flags >> lengthByte;
_frameFlags = flags;
int payloadLength = 0;
int payloadOffset = 2;
if ((lengthByte & 0x7f) == 127)
{
Poco::UInt64 l;
reader >> l;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %Lu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
payloadOffset += 8;
}
else if ((lengthByte & 0x7f) == 126)
{
Poco::UInt16 l;
reader >> l;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %hu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
payloadOffset += 2;
}
else
{
Poco::UInt8 l = lengthByte & 0x7f;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %u", unsigned(l)), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
}
if (lengthByte & FRAME_FLAG_MASK)
{
reader.readRaw(mask, 4);
payloadOffset += 4;
}
int received = 0;
if (payloadOffset < n)
{
std::memcpy(buffer, header + payloadOffset, n - payloadOffset);
received = n - payloadOffset;
}
while (received < payloadLength)
{
n = _pStreamSocketImpl->receiveBytes(reinterpret_cast<char*>(buffer) + received, payloadLength - received);
if (n > 0)
received += n;
else
throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
}
if (lengthByte & FRAME_FLAG_MASK)
{
char* p = reinterpret_cast<char*>(buffer);
for (int i = 0; i < received; i++)
{
p[i] ^= mask[i % 4];
}
}
return received;
}
return n;
}
SocketImpl* WebSocketImpl::acceptConnection(SocketAddress& clientAddr)
{
throw Poco::InvalidAccessException("Cannot acceptConnection() on a WebSocketImpl");
}
void WebSocketImpl::connect(const SocketAddress& address)
{
throw Poco::InvalidAccessException("Cannot connect() a WebSocketImpl");
}
void WebSocketImpl::connect(const SocketAddress& address, const Poco::Timespan& timeout)
{
throw Poco::InvalidAccessException("Cannot connect() a WebSocketImpl");
}
void WebSocketImpl::connectNB(const SocketAddress& address, const Poco::Timespan& timeout)
{
throw Poco::InvalidAccessException("Cannot connectNB() a WebSocketImpl");
}
void WebSocketImpl::bind(const SocketAddress& address, bool reuseAddress)
{
throw Poco::InvalidAccessException("Cannot bind() a WebSocketImpl");
}
void WebSocketImpl::bind6(const SocketAddress& address, bool reuseAddress, bool ipV6Only)
{
throw Poco::InvalidAccessException("Cannot bind6() a WebSocketImpl");
}
void WebSocketImpl::listen(int backlog)
{
throw Poco::InvalidAccessException("Cannot listen() on a WebSocketImpl");
}
void WebSocketImpl::close()
{
_pStreamSocketImpl->close();
reset();
}
void WebSocketImpl::shutdownReceive()
{
_pStreamSocketImpl->shutdownReceive();
}
void WebSocketImpl::shutdownSend()
{
_pStreamSocketImpl->shutdownSend();
}
void WebSocketImpl::shutdown()
{
_pStreamSocketImpl->shutdown();
}
int WebSocketImpl::sendTo(const void* buffer, int length, const SocketAddress& address, int flags)
{
throw Poco::InvalidAccessException("Cannot sendTo() on a WebSocketImpl");
}
int WebSocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
{
throw Poco::InvalidAccessException("Cannot receiveFrom() on a WebSocketImpl");
}
void WebSocketImpl::sendUrgent(unsigned char data)
{
throw Poco::InvalidAccessException("Cannot sendUrgent() on a WebSocketImpl");
}
bool WebSocketImpl::secure() const
{
return _pStreamSocketImpl->secure();
}
} } // namespace Poco::Net