mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 16:48:06 +02:00
Net: near complete merge to 1.4.2
This commit is contained in:
237
Net/src/DNS.cpp
237
Net/src/DNS.cpp
@@ -39,6 +39,8 @@
|
||||
#include "Poco/Net/SocketAddress.h"
|
||||
#include "Poco/Environment.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/AtomicCounter.h"
|
||||
#include <cstring>
|
||||
|
||||
|
||||
using Poco::FastMutex;
|
||||
@@ -47,13 +49,9 @@ using Poco::NumberFormatter;
|
||||
using Poco::IOException;
|
||||
|
||||
|
||||
//
|
||||
// Automatic initialization of Windows networking
|
||||
//
|
||||
#if defined(_WIN32) && !defined(POCO_NET_NO_AUTOMATIC_WSASTARTUP)
|
||||
namespace
|
||||
{
|
||||
class NetworkInitializer
|
||||
class NetworkInitializer
|
||||
{
|
||||
public:
|
||||
NetworkInitializer()
|
||||
@@ -63,105 +61,110 @@ namespace
|
||||
|
||||
~NetworkInitializer()
|
||||
{
|
||||
Poco::Net::uninitializeNetwork();
|
||||
}
|
||||
};
|
||||
|
||||
static NetworkInitializer networkInitializer;
|
||||
Poco::Net::uninitializeNetwork();
|
||||
}
|
||||
};
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
DNS::DNSCache DNS::_cache;
|
||||
Poco::FastMutex DNS::_mutex;
|
||||
|
||||
|
||||
HostEntry DNS::hostByName(const std::string& hostname)
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
DNSCache::const_iterator it = _cache.find(hostname);
|
||||
if (it != _cache.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(_WIN32) && defined(POCO_HAVE_IPv6)
|
||||
struct addrinfo* pAI;
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
if (getaddrinfo(hostname.c_str(), NULL, &hints, &pAI) == 0)
|
||||
{
|
||||
std::pair<DNSCache::iterator, bool> res = _cache.insert(std::pair<std::string, HostEntry>(hostname, HostEntry(pAI)));
|
||||
freeaddrinfo(pAI);
|
||||
return res.first->second;
|
||||
}
|
||||
NetworkInitializer networkInitializer;
|
||||
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
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)
|
||||
{
|
||||
std::pair<DNSCache::iterator, bool> res = _cache.insert(std::pair<std::string, HostEntry>(hostname, HostEntry(he)));
|
||||
return res.first->second;
|
||||
}
|
||||
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
|
||||
error(lastError(), hostname); // will throw an appropriate exception
|
||||
throw NetException(); // to silence compiler
|
||||
}
|
||||
|
||||
|
||||
HostEntry DNS::hostByAddress(const IPAddress& address)
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
NetworkInitializer networkInitializer;
|
||||
|
||||
#if defined(_WIN32) && defined(POCO_HAVE_IPv6)
|
||||
SocketAddress sa(address, 0);
|
||||
static char fqname[1024];
|
||||
if (getnameinfo(sa.addr(), sa.length(), fqname, sizeof(fqname), NULL, 0, 0) == 0)
|
||||
{
|
||||
DNSCache::const_iterator it = _cache.find(std::string(fqname));
|
||||
if (it != _cache.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct addrinfo* pAI;
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
if (getaddrinfo(fqname, NULL, &hints, &pAI) == 0)
|
||||
{
|
||||
std::pair<DNSCache::iterator, bool> res = _cache.insert(std::pair<std::string, HostEntry>(std::string(fqname), HostEntry(pAI)));
|
||||
freeaddrinfo(pAI);
|
||||
return res.first->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
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)
|
||||
{
|
||||
std::pair<DNSCache::iterator, bool> res = _cache.insert(std::pair<std::string, HostEntry>(std::string(he->h_name), HostEntry(he)));
|
||||
return res.first->second;
|
||||
}
|
||||
struct hostent* he = gethostbyaddr(reinterpret_cast<const char*>(address.addr()), address.length(), address.af());
|
||||
if (he)
|
||||
{
|
||||
return HostEntry(he);
|
||||
}
|
||||
#endif
|
||||
error(lastError(), address.toString()); // will throw an appropriate exception
|
||||
int err = lastError();
|
||||
error(err, address.toString()); // will throw an appropriate exception
|
||||
throw NetException(); // to silence compiler
|
||||
}
|
||||
|
||||
|
||||
HostEntry DNS::resolve(const std::string& address)
|
||||
{
|
||||
IPAddress ip;
|
||||
if (IPAddress::tryParse(address, ip))
|
||||
return hostByAddress(ip);
|
||||
NetworkInitializer networkInitializer;
|
||||
|
||||
IPAddress ip;
|
||||
if (IPAddress::tryParse(address, ip))
|
||||
return hostByAddress(ip);
|
||||
else
|
||||
return hostByName(address);
|
||||
}
|
||||
@@ -169,9 +172,11 @@ HostEntry DNS::resolve(const std::string& address)
|
||||
|
||||
IPAddress DNS::resolveOne(const std::string& address)
|
||||
{
|
||||
HostEntry entry = resolve(address);
|
||||
if (!entry.addresses().empty())
|
||||
return entry.addresses()[0];
|
||||
NetworkInitializer networkInitializer;
|
||||
|
||||
const HostEntry& entry = resolve(address);
|
||||
if (!entry.addresses().empty())
|
||||
return entry.addresses()[0];
|
||||
else
|
||||
throw NoAddressFoundException(address);
|
||||
}
|
||||
@@ -179,23 +184,22 @@ IPAddress DNS::resolveOne(const std::string& address)
|
||||
|
||||
HostEntry DNS::thisHost()
|
||||
{
|
||||
return hostByName(hostName());
|
||||
return hostByName(hostName());
|
||||
}
|
||||
|
||||
|
||||
void DNS::flushCache()
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
_cache.clear();
|
||||
}
|
||||
|
||||
|
||||
std::string DNS::hostName()
|
||||
{
|
||||
char buffer[256];
|
||||
int rc = gethostname(buffer, sizeof(buffer));
|
||||
if (rc == 0)
|
||||
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");
|
||||
@@ -206,6 +210,8 @@ int DNS::lastError()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return GetLastError();
|
||||
#elif defined(POCO_VXWORKS)
|
||||
return errno;
|
||||
#else
|
||||
return h_errno;
|
||||
#endif
|
||||
@@ -234,20 +240,63 @@ void DNS::error(int code, const std::string& arg)
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
WORD version = MAKEWORD(2, 2);
|
||||
WSADATA data;
|
||||
WSAStartup(version, &data);
|
||||
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)
|
||||
WSACleanup();
|
||||
if (--initializeCount == 0)
|
||||
{
|
||||
WSACleanup();
|
||||
}
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
|
@@ -35,8 +35,8 @@
|
||||
|
||||
|
||||
#include "Poco/Net/DialogSocket.h"
|
||||
#include "Poco/Ascii.h"
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -81,6 +81,17 @@ DialogSocket::~DialogSocket()
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -256,7 +267,7 @@ int DialogSocket::receiveStatusLine(std::string& line)
|
||||
int ch = get();
|
||||
if (ch != EOF_CHAR) line += (char) ch;
|
||||
int n = 0;
|
||||
while (std::isdigit(ch) && n < 3)
|
||||
while (Poco::Ascii::isDigit(ch) && n < 3)
|
||||
{
|
||||
status *= 10;
|
||||
status += ch - '0';
|
||||
@@ -275,4 +286,15 @@ int DialogSocket::receiveStatusLine(std::string& line)
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@@ -68,6 +68,17 @@ FilePartSource::FilePartSource(const std::string& path, const std::string& media
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
|
@@ -48,7 +48,6 @@
|
||||
#include "Poco/URI.h"
|
||||
#include "Poco/String.h"
|
||||
#include <sstream>
|
||||
#include <cctype>
|
||||
|
||||
|
||||
using Poco::NullInputStream;
|
||||
@@ -125,7 +124,7 @@ void HTMLForm::addPart(const std::string& name, PartSource* pSource)
|
||||
void HTMLForm::load(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler)
|
||||
{
|
||||
clear();
|
||||
if (request.getMethod() == HTTPRequest::HTTP_POST)
|
||||
if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT)
|
||||
{
|
||||
std::string mediaType;
|
||||
NameValueCollection params;
|
||||
@@ -176,7 +175,7 @@ void HTMLForm::read(std::istream& istr, PartHandler& handler)
|
||||
|
||||
void HTMLForm::prepareSubmit(HTTPRequest& request)
|
||||
{
|
||||
if (request.getMethod() == HTTPRequest::HTTP_POST)
|
||||
if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT)
|
||||
{
|
||||
if (_encoding == ENCODING_URL)
|
||||
{
|
||||
@@ -320,9 +319,9 @@ void HTMLForm::writeUrl(std::ostream& ostr)
|
||||
{
|
||||
if (it != begin()) ostr << "&";
|
||||
std::string name;
|
||||
URI::encode(it->first, "=&+", name);
|
||||
URI::encode(it->first, "=&+;", name);
|
||||
std::string value;
|
||||
URI::encode(it->second, "=&+", value);
|
||||
URI::encode(it->second, "=&+;", value);
|
||||
ostr << name << "=" << value;
|
||||
}
|
||||
}
|
||||
@@ -343,8 +342,8 @@ void HTMLForm::writeMultipart(std::ostream& ostr)
|
||||
}
|
||||
for (PartVec::iterator ita = _parts.begin(); ita != _parts.end(); ++ita)
|
||||
{
|
||||
MessageHeader header;
|
||||
std::string disp("file; name=\"");
|
||||
MessageHeader header(ita->pSource->headers());
|
||||
std::string disp("form-data; name=\"");
|
||||
disp.append(ita->name);
|
||||
disp.append("\"");
|
||||
std::string filename = ita->pSource->filename();
|
||||
|
@@ -116,6 +116,7 @@ void HTTPBasicCredentials::authenticate(HTTPRequest& request)
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
Base64Encoder encoder(ostr);
|
||||
encoder.rdbuf()->setLineLength(0);
|
||||
encoder << _username << ":" << _password;
|
||||
encoder.close();
|
||||
request.setCredentials(SCHEME, ostr.str());
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// HTTPChunkedStream.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPChunkedStream.cpp#17 $
|
||||
// $Id: //poco/1.4/Net/src/HTTPChunkedStream.cpp#1 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTP
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "Poco/Net/HTTPSession.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/NumberParser.h"
|
||||
#include <cctype>
|
||||
#include "Poco/Ascii.h"
|
||||
|
||||
|
||||
using Poco::NumberFormatter;
|
||||
@@ -85,9 +85,9 @@ int HTTPChunkedStreamBuf::readFromDevice(char* buffer, std::streamsize length)
|
||||
if (_chunk == 0)
|
||||
{
|
||||
int ch = _session.get();
|
||||
while (std::isspace(ch)) ch = _session.get();
|
||||
while (Poco::Ascii::isSpace(ch)) ch = _session.get();
|
||||
std::string chunkLen;
|
||||
while (std::isxdigit(ch)) { chunkLen += (char) ch; ch = _session.get(); }
|
||||
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))
|
||||
|
@@ -44,6 +44,8 @@
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/CountingStream.h"
|
||||
#include "Poco/Base64Encoder.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
using Poco::NumberFormatter;
|
||||
@@ -163,6 +165,25 @@ void HTTPClientSession::setProxyPort(Poco::UInt16 port)
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
@@ -180,43 +201,54 @@ std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
|
||||
close();
|
||||
_mustReconnect = false;
|
||||
}
|
||||
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());
|
||||
_reconnect = keepAlive;
|
||||
_expectResponseBody = request.getMethod() != HTTPRequest::HTTP_HEAD;
|
||||
if (request.getChunkedTransferEncoding())
|
||||
try
|
||||
{
|
||||
HTTPHeaderOutputStream hos(*this);
|
||||
request.write(hos);
|
||||
_pRequestStream = new HTTPChunkedOutputStream(*this);
|
||||
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;
|
||||
}
|
||||
else if (request.getContentLength() != HTTPMessage::UNKNOWN_CONTENT_LENGTH)
|
||||
catch (Exception&)
|
||||
{
|
||||
Poco::CountingOutputStream cs;
|
||||
request.write(cs);
|
||||
_pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength() + cs.chars());
|
||||
request.write(*_pRequestStream);
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -235,11 +267,17 @@ std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
|
||||
}
|
||||
catch (MessageException&)
|
||||
{
|
||||
close();
|
||||
if (networkException())
|
||||
networkException()->rethrow();
|
||||
else
|
||||
throw;
|
||||
}
|
||||
catch (Exception&)
|
||||
{
|
||||
close();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
while (response.getStatus() == HTTPResponse::HTTP_CONTINUE);
|
||||
|
||||
@@ -258,6 +296,18 @@ std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
|
||||
}
|
||||
|
||||
|
||||
void HTTPClientSession::reset()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
bool HTTPClientSession::secure() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int HTTPClientSession::write(const char* buffer, std::streamsize length)
|
||||
{
|
||||
try
|
||||
@@ -322,7 +372,7 @@ void HTTPClientSession::deleteRequestStream()
|
||||
|
||||
void HTTPClientSession::setResponseStream(std::istream* pRespStream)
|
||||
{
|
||||
poco_assert( !_pResponseStream);
|
||||
poco_assert (!_pResponseStream);
|
||||
_pResponseStream = pRespStream;
|
||||
}
|
||||
|
||||
@@ -345,4 +395,24 @@ bool HTTPClientSession::mustReconnect() const
|
||||
}
|
||||
|
||||
|
||||
void HTTPClientSession::proxyAuthenticate(HTTPRequest& request)
|
||||
{
|
||||
proxyAuthenticateImpl(request);
|
||||
}
|
||||
|
||||
|
||||
void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request)
|
||||
{
|
||||
if (!_proxyUsername.empty())
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << "Basic ";
|
||||
Base64Encoder encoder(ostr);
|
||||
encoder << _proxyUsername << ":" << _proxyPassword;
|
||||
encoder.close();
|
||||
request.set("Proxy-Authorization", ostr.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// HTTPCookie.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPCookie.cpp#9 $
|
||||
// $Id: //poco/1.4/Net/src/HTTPCookie.cpp#1 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTP
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/NumberParser.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/URI.h"
|
||||
|
||||
|
||||
using Poco::Timestamp;
|
||||
@@ -315,4 +316,26 @@ std::string HTTPCookie::toString() const
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@@ -88,22 +88,26 @@ void HTTPMessage::setVersion(const std::string& version)
|
||||
}
|
||||
|
||||
|
||||
void HTTPMessage::setContentLength(int length)
|
||||
void HTTPMessage::setContentLength(std::streamsize length)
|
||||
{
|
||||
if (length != UNKNOWN_CONTENT_LENGTH)
|
||||
set(CONTENT_LENGTH, NumberFormatter::format(length));
|
||||
if (length != UNKNOWN_CONTENT_LENGTH)
|
||||
set(CONTENT_LENGTH, NumberFormatter::format(length));
|
||||
else
|
||||
erase(CONTENT_LENGTH);
|
||||
}
|
||||
|
||||
|
||||
int HTTPMessage::getContentLength() const
|
||||
|
||||
std::streamsize HTTPMessage::getContentLength() const
|
||||
{
|
||||
const std::string& contentLength = get(CONTENT_LENGTH, EMPTY);
|
||||
if (!contentLength.empty())
|
||||
return NumberParser::parse(contentLength);
|
||||
else
|
||||
return UNKNOWN_CONTENT_LENGTH;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +175,7 @@ bool HTTPMessage::getKeepAlive() const
|
||||
{
|
||||
const std::string& connection = get(CONNECTION, EMPTY);
|
||||
if (!connection.empty())
|
||||
return icompare(connection, CONNECTION_KEEP_ALIVE) == 0;
|
||||
return icompare(connection, CONNECTION_CLOSE) != 0;
|
||||
else
|
||||
return getVersion() == HTTP_1_1;
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// HTTPRequest.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPRequest.cpp#14 $
|
||||
// $Id: //poco/1.4/Net/src/HTTPRequest.cpp#1 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: HTTP
|
||||
@@ -35,11 +35,10 @@
|
||||
|
||||
|
||||
#include "Poco/Net/HTTPRequest.h"
|
||||
#include "Poco/Net/HTTPSession.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Net/NameValueCollection.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include <cctype>
|
||||
#include "Poco/Ascii.h"
|
||||
|
||||
|
||||
using Poco::NumberFormatter;
|
||||
@@ -118,7 +117,7 @@ void HTTPRequest::setHost(const std::string& host)
|
||||
void HTTPRequest::setHost(const std::string& host, Poco::UInt16 port)
|
||||
{
|
||||
std::string value(host);
|
||||
if (port != HTTPSession::HTTP_PORT)
|
||||
if (port != 80 && port != 443)
|
||||
{
|
||||
value.append(":");
|
||||
NumberFormatter::append(value, port);
|
||||
@@ -175,9 +174,9 @@ void HTTPRequest::getCredentials(std::string& scheme, std::string& authInfo) con
|
||||
const std::string& auth = get(AUTHORIZATION);
|
||||
std::string::const_iterator it = auth.begin();
|
||||
std::string::const_iterator end = auth.end();
|
||||
while (it != end && std::isspace(*it)) ++it;
|
||||
while (it != end && !std::isspace(*it)) scheme += *it++;
|
||||
while (it != end && std::isspace(*it)) ++it;
|
||||
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();
|
||||
@@ -213,16 +212,16 @@ void HTTPRequest::read(std::istream& istr)
|
||||
version.reserve(16);
|
||||
int ch = istr.get();
|
||||
if (ch == eof) throw NoMessageException();
|
||||
while (std::isspace(ch)) ch = istr.get();
|
||||
while (Poco::Ascii::isSpace(ch)) ch = istr.get();
|
||||
if (ch == eof) throw MessageException("No HTTP request header");
|
||||
while (!std::isspace(ch) && ch != eof && method.length() < MAX_METHOD_LENGTH) { method += (char) ch; ch = istr.get(); }
|
||||
if (!std::isspace(ch)) throw MessageException("HTTP request method invalid or too long");
|
||||
while (std::isspace(ch)) ch = istr.get();
|
||||
while (!std::isspace(ch) && ch != eof && uri.length() < MAX_URI_LENGTH) { uri += (char) ch; ch = istr.get(); }
|
||||
if (!std::isspace(ch)) throw MessageException("HTTP request URI invalid or too long");
|
||||
while (std::isspace(ch)) ch = istr.get();
|
||||
while (!std::isspace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); }
|
||||
if (!std::isspace(ch)) throw MessageException("Invalid HTTP version string");
|
||||
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();
|
||||
|
@@ -42,7 +42,7 @@
|
||||
#include "Poco/DateTimeFormatter.h"
|
||||
#include "Poco/DateTimeFormat.h"
|
||||
#include "Poco/DateTimeParser.h"
|
||||
#include <cctype>
|
||||
#include "Poco/Ascii.h"
|
||||
|
||||
|
||||
using Poco::DateTime;
|
||||
@@ -228,16 +228,16 @@ void HTTPResponse::read(std::istream& istr)
|
||||
|
||||
int ch = istr.get();
|
||||
if (ch == eof) throw NoMessageException();
|
||||
while (std::isspace(ch)) ch = istr.get();
|
||||
while (Poco::Ascii::isSpace(ch)) ch = istr.get();
|
||||
if (ch == eof) throw MessageException("No HTTP response header");
|
||||
while (!std::isspace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); }
|
||||
if (!std::isspace(ch)) throw MessageException("Invalid HTTP version string");
|
||||
while (std::isspace(ch)) ch = istr.get();
|
||||
while (!std::isspace(ch) && ch != eof && status.length() < MAX_STATUS_LENGTH) { status += (char) ch; ch = istr.get(); }
|
||||
if (!std::isspace(ch)) throw MessageException("Invalid HTTP status code");
|
||||
while (std::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 (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 (!std::isspace(ch)) throw MessageException("HTTP reason string too long");
|
||||
if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP reason string too long");
|
||||
if (ch == '\r') ch = istr.get();
|
||||
|
||||
HTTPMessage::read(istr);
|
||||
|
@@ -1,93 +1,106 @@
|
||||
//
|
||||
// HTTPServerRequestImpl.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPServerRequestImpl.cpp#4 $
|
||||
//
|
||||
// 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),
|
||||
_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;
|
||||
}
|
||||
|
||||
|
||||
bool HTTPServerRequestImpl::expectContinue() const
|
||||
{
|
||||
const std::string& expect = get(EXPECT, EMPTY);
|
||||
return !expect.empty() && icompare(expect, "100-continue") == 0;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
//
|
||||
// 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
|
||||
|
@@ -1,174 +1,177 @@
|
||||
//
|
||||
// HTTPServerResponseImpl.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/HTTPServerResponseImpl.cpp#7 $
|
||||
//
|
||||
// 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));
|
||||
setContentLength(static_cast<int>(length));
|
||||
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)
|
||||
{
|
||||
poco_assert (!_pStream);
|
||||
|
||||
setStatusAndReason(HTTPResponse::HTTP_FOUND);
|
||||
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
|
||||
//
|
||||
// HTTPServerResponseImpl.cpp
|
||||
//
|
||||
// $Id: //poco/1.4/Net/src/HTTPServerResponseImpl.cpp#1 $
|
||||
//
|
||||
// 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));
|
||||
setContentLength(static_cast<int>(length));
|
||||
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
|
||||
|
@@ -59,6 +59,8 @@ HTTPServerSession::~HTTPServerSession()
|
||||
|
||||
bool HTTPServerSession::hasMoreRequests()
|
||||
{
|
||||
if (!socket().impl()->initialized()) return false;
|
||||
|
||||
if (_firstRequest)
|
||||
{
|
||||
_firstRequest = false;
|
||||
|
@@ -84,9 +84,15 @@ HTTPSession::HTTPSession(const StreamSocket& socket, bool keepAlive):
|
||||
|
||||
HTTPSession::~HTTPSession()
|
||||
{
|
||||
if (_pBuffer) HTTPBufferAllocator::deallocate(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE);
|
||||
close();
|
||||
delete _pException;
|
||||
if (_pBuffer) HTTPBufferAllocator::deallocate(_pBuffer, HTTPBufferAllocator::BUFFER_SIZE);
|
||||
try
|
||||
{
|
||||
close();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
delete _pException;
|
||||
}
|
||||
|
||||
|
||||
@@ -229,4 +235,10 @@ void HTTPSession::attachSocket(const StreamSocket& socket)
|
||||
}
|
||||
|
||||
|
||||
void HTTPSession::attachSessionData(const Poco::Any& data)
|
||||
{
|
||||
_data = data;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
@@ -119,12 +119,13 @@ HTTPClientSession* HTTPSessionFactory::createClientSession(const Poco::URI& uri)
|
||||
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);
|
||||
return it->second.pIn->createClientSession(uri);
|
||||
}
|
||||
else throw Poco::UnknownURISchemeException(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());
|
||||
}
|
||||
|
||||
|
||||
@@ -137,10 +138,24 @@ void HTTPSessionFactory::setProxy(const std::string& host, Poco::UInt16 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()
|
||||
{
|
||||
static SingletonHolder<HTTPSessionFactory> singleton;
|
||||
return *singleton.get();
|
||||
return *singleton.get();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -62,6 +62,7 @@ HTTPClientSession* HTTPSessionInstantiator::createClientSession(const Poco::URI&
|
||||
poco_assert (uri.getScheme() == "http");
|
||||
HTTPClientSession* pSession = new HTTPClientSession(uri.getHost(), uri.getPort());
|
||||
pSession->setProxy(proxyHost(), proxyPort());
|
||||
pSession->setProxyCredentials(proxyUsername(), proxyPassword());
|
||||
return pSession;
|
||||
}
|
||||
|
||||
@@ -85,4 +86,11 @@ void HTTPSessionInstantiator::setProxy(const std::string& host, Poco::UInt16 por
|
||||
}
|
||||
|
||||
|
||||
void HTTPSessionInstantiator::setProxyCredentials(const std::string& username, const std::string& password)
|
||||
{
|
||||
_proxyUsername = username;
|
||||
_proxyPassword = password;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
@@ -68,6 +68,15 @@ HTTPStreamFactory::HTTPStreamFactory(const std::string& proxyHost, Poco::UInt16
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
}
|
||||
@@ -92,7 +101,8 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
|
||||
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);
|
||||
@@ -114,14 +124,14 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
|
||||
}
|
||||
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.
|
||||
// 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
|
||||
retry = true; // only allow useproxy once
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -43,17 +43,12 @@ namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
//
|
||||
// HostEntryImpl
|
||||
//
|
||||
|
||||
|
||||
HostEntryImpl::HostEntryImpl()
|
||||
HostEntry::HostEntry()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HostEntryImpl::HostEntryImpl(struct hostent* entry)
|
||||
HostEntry::HostEntry(struct hostent* entry)
|
||||
{
|
||||
poco_check_ptr (entry);
|
||||
|
||||
@@ -79,10 +74,10 @@ HostEntryImpl::HostEntryImpl(struct hostent* entry)
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(POCO_HAVE_IPv6)
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
|
||||
|
||||
HostEntryImpl::HostEntryImpl(struct addrinfo* ainfo)
|
||||
HostEntry::HostEntry(struct addrinfo* ainfo)
|
||||
{
|
||||
poco_check_ptr (ainfo);
|
||||
|
||||
@@ -97,48 +92,59 @@ HostEntryImpl::HostEntryImpl(struct addrinfo* ainfo)
|
||||
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;
|
||||
case AF_INET6:
|
||||
_addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_addr, sizeof(in6_addr)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
_addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in*>(ai->ai_addr)->sin_addr, sizeof(in_addr)));
|
||||
break;
|
||||
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
|
||||
|
||||
|
||||
HostEntryImpl::~HostEntryImpl()
|
||||
#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::HostEntry():
|
||||
_pImpl(new HostEntryImpl)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HostEntry::HostEntry(struct hostent* entry):
|
||||
_pImpl(new HostEntryImpl(entry))
|
||||
HostEntry& HostEntry::operator = (const HostEntry& entry)
|
||||
{
|
||||
if (&entry != this)
|
||||
{
|
||||
_name = entry._name;
|
||||
_aliases = entry._aliases;
|
||||
_addresses = entry._addresses;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
#if defined(_WIN32) && defined(POCO_HAVE_IPv6)
|
||||
HostEntry::HostEntry(struct addrinfo* info):
|
||||
_pImpl(new HostEntryImpl(info))
|
||||
void HostEntry::swap(HostEntry& hostEntry)
|
||||
{
|
||||
std::swap(_name, hostEntry._name);
|
||||
std::swap(_aliases, hostEntry._aliases);
|
||||
std::swap(_addresses, hostEntry._addresses);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
HostEntry::~HostEntry()
|
||||
@@ -146,18 +152,4 @@ HostEntry::~HostEntry()
|
||||
}
|
||||
|
||||
|
||||
HostEntry::HostEntry(const HostEntry& entry):
|
||||
_pImpl(entry._pImpl)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
HostEntry& HostEntry::operator = (const HostEntry& entry)
|
||||
{
|
||||
HostEntry tmp(entry);
|
||||
tmp.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include "Poco/Net/DNS.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include <numeric>
|
||||
|
||||
|
||||
using Poco::IOException;
|
||||
@@ -56,7 +57,7 @@ ICMPEventArgs::ICMPEventArgs(const SocketAddress& address, int repetitions, int
|
||||
_sent(0),
|
||||
_dataSize(dataSize),
|
||||
_ttl(ttl),
|
||||
_rtt(0, repetitions),
|
||||
_rtt(repetitions, 0),
|
||||
_errors(repetitions)
|
||||
{
|
||||
}
|
||||
@@ -97,8 +98,8 @@ std::string ICMPEventArgs::hostAddress() const
|
||||
|
||||
void ICMPEventArgs::setRepetitions(int repetitions)
|
||||
{
|
||||
_rtt.apply(&ICMPEventArgs::zeroVal);
|
||||
if (_rtt.size() != repetitions) _rtt.resize(repetitions, 0);
|
||||
_rtt.clear();
|
||||
_rtt.resize(repetitions, 0);
|
||||
_errors.assign(repetitions, "");
|
||||
}
|
||||
|
||||
@@ -174,7 +175,7 @@ int ICMPEventArgs::avgRTT() const
|
||||
{
|
||||
if (0 == _rtt.size()) return 0;
|
||||
|
||||
return (int) (_rtt.sum() / _rtt.size());
|
||||
return (int) (std::accumulate(_rtt.begin(), _rtt.end(), 0) / _rtt.size());
|
||||
}
|
||||
|
||||
|
||||
@@ -186,10 +187,4 @@ float ICMPEventArgs::percent() const
|
||||
}
|
||||
|
||||
|
||||
int ICMPEventArgs::zeroVal(int n)
|
||||
{
|
||||
return n*0;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace Poco::Net
|
||||
|
@@ -39,7 +39,6 @@
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/Timespan.h"
|
||||
#include "Poco/Process.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include <sstream>
|
||||
|
||||
@@ -48,7 +47,6 @@ using Poco::InvalidArgumentException;
|
||||
using Poco::NotImplementedException;
|
||||
using Poco::Timestamp;
|
||||
using Poco::Timespan;
|
||||
using Poco::Process;
|
||||
using Poco::NumberFormatter;
|
||||
using Poco::UInt8;
|
||||
using Poco::UInt16;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// ICMPPacketImpl.cpp
|
||||
//
|
||||
// $Id: //poco/svn/Net/src/ICMPPacketImpl.cpp#2 $
|
||||
// $Id: //poco/1.4/Net/src/ICMPPacketImpl.cpp#2 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: ICMP
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/Timespan.h"
|
||||
#include "Poco/Process.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include <sstream>
|
||||
|
||||
@@ -46,7 +45,6 @@
|
||||
using Poco::InvalidArgumentException;
|
||||
using Poco::Timestamp;
|
||||
using Poco::Timespan;
|
||||
using Poco::Process;
|
||||
using Poco::NumberFormatter;
|
||||
using Poco::UInt8;
|
||||
using Poco::UInt16;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// ICMPSocketImpl.cpp
|
||||
//
|
||||
// $Id: //poco/svn/Net/src/ICMPSocketImpl.cpp#2 $
|
||||
// $Id: //poco/1.4/Net/src/ICMPSocketImpl.cpp#1 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: ICMP
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "Poco/Net/ICMPSocketImpl.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Timespan.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/Exception.h"
|
||||
|
||||
|
||||
@@ -51,7 +52,8 @@ namespace Net {
|
||||
|
||||
ICMPSocketImpl::ICMPSocketImpl(IPAddress::Family family, int dataSize, int ttl, int timeout):
|
||||
RawSocketImpl(family, IPPROTO_ICMP),
|
||||
_icmpPacket(family, dataSize)
|
||||
_icmpPacket(family, dataSize),
|
||||
_timeout(timeout)
|
||||
{
|
||||
setOption(IPPROTO_IP, IP_TTL, ttl);
|
||||
setReceiveTimeout(Timespan(timeout));
|
||||
@@ -77,21 +79,28 @@ int ICMPSocketImpl::receiveFrom(void*, int, SocketAddress& address, int flags)
|
||||
|
||||
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));
|
||||
while (!_icmpPacket.validReplyID(buffer, maxPacketSize));
|
||||
}
|
||||
catch (TimeoutException&)
|
||||
{
|
||||
delete[] buffer;
|
||||
delete [] buffer;
|
||||
throw;
|
||||
}
|
||||
catch (Exception&)
|
||||
{
|
||||
std::string err = _icmpPacket.errorDescription(buffer, maxPacketSize);
|
||||
delete[] buffer;
|
||||
delete [] buffer;
|
||||
if (!err.empty())
|
||||
throw ICMPException(err);
|
||||
else
|
||||
|
@@ -38,8 +38,10 @@
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/Timestamp.h"
|
||||
#include "Poco/Timespan.h"
|
||||
#include "Poco/Process.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#if !defined(POCO_VXWORKS)
|
||||
#include "Poco/Process.h"
|
||||
#endif
|
||||
#include <sstream>
|
||||
|
||||
|
||||
@@ -57,11 +59,11 @@ namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
const UInt8 ICMPv4PacketImpl::DESTINATION_UNREACHABLE_TYPE = 3;
|
||||
const UInt8 ICMPv4PacketImpl::SOURCE_QUENCH_TYPE = 4;
|
||||
const UInt8 ICMPv4PacketImpl::REDIRECT_MESSAGE_TYPE = 5;
|
||||
const UInt8 ICMPv4PacketImpl::TIME_EXCEEDED_TYPE = 11;
|
||||
const UInt8 ICMPv4PacketImpl::PARAMETER_PROBLEM_TYPE = 12;
|
||||
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[] =
|
||||
@@ -125,10 +127,10 @@ const std::string ICMPv4PacketImpl::PARAMETER_PROBLEM_CODE[] =
|
||||
|
||||
|
||||
ICMPv4PacketImpl::ICMPv4PacketImpl(int dataSize):
|
||||
ICMPPacketImpl(dataSize),
|
||||
_seq(0)
|
||||
ICMPPacketImpl(dataSize),
|
||||
_seq(0)
|
||||
{
|
||||
initPacket();
|
||||
initPacket();
|
||||
}
|
||||
|
||||
|
||||
@@ -152,8 +154,12 @@ void ICMPv4PacketImpl::initPacket()
|
||||
icp->code = 0;
|
||||
icp->checksum = 0;
|
||||
icp->seq = ++_seq;
|
||||
icp->id = static_cast<UInt16>(Process::id());
|
||||
|
||||
#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();
|
||||
|
||||
@@ -202,7 +208,11 @@ Poco::UInt8* ICMPv4PacketImpl::data(Poco::UInt8* buffer, int length) const
|
||||
bool ICMPv4PacketImpl::validReplyID(Poco::UInt8* buffer, int length) const
|
||||
{
|
||||
Header *icp = header(buffer, length);
|
||||
return icp && (Process::id() == icp->id);
|
||||
#if defined(POCO_VXWORKS)
|
||||
return icp && icp->id == 0;
|
||||
#else
|
||||
return icp && (static_cast<Poco::UInt16>(Process::id()) == icp->id);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
// Package: NetCore
|
||||
// Module: IPAddress
|
||||
//
|
||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||
// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
@@ -64,12 +64,13 @@ 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 bool isWildcard() const = 0;
|
||||
virtual bool isBroadcast() const = 0;
|
||||
virtual bool isLoopback() 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;
|
||||
@@ -85,13 +86,19 @@ public:
|
||||
virtual IPAddressImpl* clone() const = 0;
|
||||
|
||||
protected:
|
||||
IPAddressImpl()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~IPAddressImpl()
|
||||
{
|
||||
}
|
||||
IPAddressImpl()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
Poco::Net::initializeNetwork();
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual ~IPAddressImpl()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
Poco::Net::uninitializeNetwork();
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
IPAddressImpl(const IPAddressImpl&);
|
||||
@@ -144,12 +151,17 @@ public:
|
||||
|
||||
int af() const
|
||||
{
|
||||
return AF_INET;
|
||||
}
|
||||
|
||||
bool isWildcard() const
|
||||
{
|
||||
return _addr.s_addr == INADDR_ANY;
|
||||
return AF_INET;
|
||||
}
|
||||
|
||||
Poco::UInt32 scope() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool isWildcard() const
|
||||
{
|
||||
return _addr.s_addr == INADDR_ANY;
|
||||
}
|
||||
|
||||
bool isBroadcast() const
|
||||
@@ -159,7 +171,7 @@ public:
|
||||
|
||||
bool isLoopback() const
|
||||
{
|
||||
return ntohl(_addr.s_addr) == 0x7F000001; // 127.0.0.1
|
||||
return (ntohl(_addr.s_addr) & 0xFF000000) == 0x7F000000; // 127.0.0.1 to 127.255.255.255
|
||||
}
|
||||
|
||||
bool isMulticast() const
|
||||
@@ -232,9 +244,9 @@ public:
|
||||
else
|
||||
return new IPv4AddressImpl(&ia);
|
||||
#else
|
||||
#if __GNUC__ < 3
|
||||
#if __GNUC__ < 3 || defined(POCO_VXWORKS)
|
||||
struct in_addr ia;
|
||||
ia.s_addr = inet_addr(addr.c_str());
|
||||
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
|
||||
@@ -273,15 +285,23 @@ private:
|
||||
class IPv6AddressImpl: public IPAddressImpl
|
||||
{
|
||||
public:
|
||||
IPv6AddressImpl()
|
||||
{
|
||||
std::memset(&_addr, 0, sizeof(_addr));
|
||||
}
|
||||
IPv6AddressImpl():
|
||||
_scope(0)
|
||||
{
|
||||
std::memset(&_addr, 0, sizeof(_addr));
|
||||
}
|
||||
|
||||
IPv6AddressImpl(const void* addr)
|
||||
{
|
||||
std::memcpy(&_addr, addr, 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
|
||||
{
|
||||
@@ -304,13 +324,13 @@ public:
|
||||
NumberFormatter::append(result, bytes[15]);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(46);
|
||||
bool zeroSequence = false;
|
||||
int i = 0;
|
||||
while (i < 8)
|
||||
else
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(64);
|
||||
bool zeroSequence = false;
|
||||
int i = 0;
|
||||
while (i < 8)
|
||||
{
|
||||
if (!zeroSequence && words[i] == 0)
|
||||
{
|
||||
@@ -323,12 +343,29 @@ public:
|
||||
zeroSequence = true;
|
||||
}
|
||||
}
|
||||
if (i > 0) result.append(":");
|
||||
if (i < 8) NumberFormatter::appendHex(result, ntohs(words[i++]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
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
|
||||
{
|
||||
@@ -347,12 +384,17 @@ public:
|
||||
|
||||
int af() const
|
||||
{
|
||||
return AF_INET6;
|
||||
}
|
||||
return AF_INET6;
|
||||
}
|
||||
|
||||
Poco::UInt32 scope() const
|
||||
{
|
||||
return _scope;
|
||||
}
|
||||
|
||||
bool isWildcard() const
|
||||
{
|
||||
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
|
||||
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;
|
||||
}
|
||||
@@ -363,79 +405,79 @@ public:
|
||||
}
|
||||
|
||||
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 && words[7] == 1;
|
||||
}
|
||||
|
||||
bool isMulticast() const
|
||||
{
|
||||
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
|
||||
return (words[0] & 0xFFE0) == 0xFF00;
|
||||
}
|
||||
|
||||
bool isLinkLocal() const
|
||||
{
|
||||
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
|
||||
return (words[0] & 0xFFE0) == 0xFE80;
|
||||
}
|
||||
|
||||
bool isSiteLocal() const
|
||||
{
|
||||
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
|
||||
return (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 && 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 && words[5] == 0xFFFF;
|
||||
}
|
||||
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 (words[0] & 0xFFF0) == 0xFF00;
|
||||
}
|
||||
|
||||
bool isNodeLocalMC() const
|
||||
{
|
||||
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
|
||||
return (words[0] & 0xFFEF) == 0xFF01;
|
||||
}
|
||||
|
||||
bool isLinkLocalMC() const
|
||||
{
|
||||
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
|
||||
return (words[0] & 0xFFEF) == 0xFF02;
|
||||
}
|
||||
|
||||
bool isSiteLocalMC() const
|
||||
{
|
||||
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
|
||||
return (words[0] & 0xFFEF) == 0xFF05;
|
||||
}
|
||||
|
||||
bool isOrgLocalMC() const
|
||||
{
|
||||
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
|
||||
return (words[0] & 0xFFEF) == 0xFF08;
|
||||
}
|
||||
|
||||
bool isGlobalMC() const
|
||||
{
|
||||
const UInt16* words = reinterpret_cast<const UInt16*>(&_addr);
|
||||
return (words[0] & 0xFFEF) == 0xFF0F;
|
||||
}
|
||||
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)
|
||||
static IPv6AddressImpl* parse(const std::string& addr)
|
||||
{
|
||||
if (addr.empty()) return 0;
|
||||
#if defined(_WIN32)
|
||||
@@ -443,20 +485,37 @@ public:
|
||||
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);
|
||||
freeaddrinfo(pAI);
|
||||
return pResult;
|
||||
}
|
||||
else return 0;
|
||||
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;
|
||||
if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1)
|
||||
return new IPv6AddressImpl(&ia);
|
||||
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
|
||||
return 0;
|
||||
{
|
||||
if (inet_pton(AF_INET6, addr.c_str(), &ia) == 1)
|
||||
return new IPv6AddressImpl(&ia);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -465,13 +524,14 @@ public:
|
||||
throw Poco::NotImplementedException("mask() is only supported for IPv4 addresses");
|
||||
}
|
||||
|
||||
IPAddressImpl* clone() const
|
||||
{
|
||||
return new IPv6AddressImpl(&_addr);
|
||||
}
|
||||
IPAddressImpl* clone() const
|
||||
{
|
||||
return new IPv6AddressImpl(&_addr, _scope);
|
||||
}
|
||||
|
||||
private:
|
||||
struct in6_addr _addr;
|
||||
struct in6_addr _addr;
|
||||
Poco::UInt32 _scope;
|
||||
};
|
||||
|
||||
|
||||
@@ -543,9 +603,21 @@ IPAddress::IPAddress(const void* addr, poco_socklen_t length)
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
_pImpl->release();
|
||||
}
|
||||
|
||||
|
||||
@@ -572,10 +644,16 @@ IPAddress::Family IPAddress::family() const
|
||||
return _pImpl->family();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Poco::UInt32 IPAddress::scope() const
|
||||
{
|
||||
return _pImpl->scope();
|
||||
}
|
||||
|
||||
|
||||
std::string IPAddress::toString() const
|
||||
{
|
||||
return _pImpl->toString();
|
||||
return _pImpl->toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -799,4 +877,18 @@ void IPAddress::mask(const IPAddress& mask, const IPAddress& set)
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@@ -49,8 +49,9 @@
|
||||
#include "Poco/DateTimeFormatter.h"
|
||||
#include "Poco/DateTimeParser.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include <sstream>
|
||||
#include <cctype>
|
||||
|
||||
|
||||
using Poco::Base64Encoder;
|
||||
@@ -82,12 +83,7 @@ namespace
|
||||
|
||||
void handlePart(const MessageHeader& header, std::istream& stream)
|
||||
{
|
||||
int ch = stream.get();
|
||||
while (ch >= 0)
|
||||
{
|
||||
_str += (char) ch;
|
||||
ch = stream.get();
|
||||
}
|
||||
Poco::StreamCopier::copyToString(stream, _str);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -320,7 +316,7 @@ void MailMessage::writeMultipart(MessageHeader& header, std::ostream& ostr) cons
|
||||
|
||||
void MailMessage::writePart(MultipartWriter& writer, const Part& part) const
|
||||
{
|
||||
MessageHeader partHeader;
|
||||
MessageHeader partHeader(part.pSource->headers());
|
||||
MediaType mediaType(part.pSource->mediaType());
|
||||
if (!part.name.empty())
|
||||
mediaType.setParameter("name", part.name);
|
||||
@@ -356,12 +352,14 @@ void MailMessage::writeEncoded(std::istream& istr, std::ostream& ostr, ContentTr
|
||||
{
|
||||
QuotedPrintableEncoder encoder(ostr);
|
||||
StreamCopier::copyStream(istr, encoder);
|
||||
encoder.close();
|
||||
}
|
||||
break;
|
||||
case ENCODING_BASE64:
|
||||
{
|
||||
Base64Encoder encoder(ostr);
|
||||
StreamCopier::copyStream(istr, encoder);
|
||||
encoder.close();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -458,7 +456,7 @@ const std::string& MailMessage::contentTransferEncodingToString(ContentTransferE
|
||||
switch (encoding)
|
||||
{
|
||||
case ENCODING_7BIT:
|
||||
return CTE_8BIT;
|
||||
return CTE_7BIT;
|
||||
case ENCODING_8BIT:
|
||||
return CTE_8BIT;
|
||||
case ENCODING_QUOTED_PRINTABLE:
|
||||
@@ -501,4 +499,79 @@ void MailMessage::appendRecipient(const MailRecipient& recipient, std::string& s
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@@ -37,8 +37,8 @@
|
||||
#include "Poco/Net/MediaType.h"
|
||||
#include "Poco/Net/MessageHeader.h"
|
||||
#include "Poco/String.h"
|
||||
#include "Poco/Ascii.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
|
||||
|
||||
using Poco::icompare;
|
||||
@@ -172,6 +172,28 @@ bool MediaType::matches(const std::string& type) const
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
@@ -179,10 +201,10 @@ void MediaType::parse(const std::string& mediaType)
|
||||
_parameters.clear();
|
||||
std::string::const_iterator it = mediaType.begin();
|
||||
std::string::const_iterator end = mediaType.end();
|
||||
while (it != end && std::isspace(*it)) ++it;
|
||||
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
|
||||
while (it != end && *it != '/') _type += *it++;
|
||||
if (it != end) ++it;
|
||||
while (it != end && *it != ';' && !std::isspace(*it)) _subType += *it++;
|
||||
while (it != end && *it != ';' && !Poco::Ascii::isSpace(*it)) _subType += *it++;
|
||||
while (it != end && *it != ';') ++it;
|
||||
MessageHeader::splitParameters(it, end, _parameters);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessageHeader.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/MessageHeader.cpp#13 $
|
||||
// $Id: //poco/1.4/Net/src/MessageHeader.cpp#3 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Messages
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "Poco/Net/MessageHeader.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include "Poco/String.h"
|
||||
#include <cctype>
|
||||
#include "Poco/Ascii.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -81,35 +81,38 @@ void MessageHeader::write(std::ostream& ostr) const
|
||||
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 = istr.get();
|
||||
int ch = buf.sbumpc();
|
||||
while (ch != eof && ch != '\r' && ch != '\n')
|
||||
{
|
||||
name.clear();
|
||||
value.clear();
|
||||
while (ch != eof && ch != ':' && ch != '\n' && name.length() < MAX_NAME_LENGTH) { name += ch; ch = istr.get(); }
|
||||
if (ch == '\n') { ch = istr.get(); continue; } // ignore invalid header lines
|
||||
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 = istr.get(); // ':'
|
||||
while (std::isspace(ch)) ch = istr.get();
|
||||
while (ch != eof && ch != '\r' && ch != '\n' && value.length() < MAX_VALUE_LENGTH) { value += ch; ch = istr.get(); }
|
||||
if (ch == '\r') ch = istr.get();
|
||||
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 = istr.get();
|
||||
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 = istr.get(); }
|
||||
if (ch == '\r') ch = istr.get();
|
||||
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 = istr.get();
|
||||
ch = buf.sbumpc();
|
||||
else if (ch != eof)
|
||||
throw MessageException("Folded field value too long/no CRLF found");
|
||||
}
|
||||
Poco::trimRightInPlace(value);
|
||||
add(name, value);
|
||||
}
|
||||
istr.putback(ch);
|
||||
@@ -169,7 +172,7 @@ void MessageHeader::splitParameters(const std::string& s, std::string& value, Na
|
||||
parameters.clear();
|
||||
std::string::const_iterator it = s.begin();
|
||||
std::string::const_iterator end = s.end();
|
||||
while (it != end && std::isspace(*it)) ++it;
|
||||
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
|
||||
while (it != end && *it != ';') value += *it++;
|
||||
Poco::trimRightInPlace(value);
|
||||
if (it != end) ++it;
|
||||
@@ -188,11 +191,11 @@ void MessageHeader::splitParameters(const std::string::const_iterator& begin, co
|
||||
{
|
||||
pname.clear();
|
||||
pvalue.clear();
|
||||
while (it != end && std::isspace(*it)) ++it;
|
||||
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 && std::isspace(*it)) ++it;
|
||||
while (it != end && Poco::Ascii::isSpace(*it)) ++it;
|
||||
while (it != end && *it != ';')
|
||||
{
|
||||
if (*it == '"')
|
||||
@@ -228,7 +231,7 @@ void MessageHeader::quote(const std::string& value, std::string& result, bool al
|
||||
bool mustQuote = false;
|
||||
for (std::string::const_iterator it = value.begin(); !mustQuote && it != value.end(); ++it)
|
||||
{
|
||||
if (!std::isalnum(*it) && *it != '.' && *it != '_' && *it != '-' && !(std::isspace(*it) && allowSpace))
|
||||
if (!Poco::Ascii::isAlphaNumeric(*it) && *it != '.' && *it != '_' && *it != '-' && !(Poco::Ascii::isSpace(*it) && allowSpace))
|
||||
mustQuote = true;
|
||||
}
|
||||
if (mustQuote) result += '"';
|
||||
|
@@ -99,16 +99,16 @@ MulticastSocket& MulticastSocket::operator = (const Socket& socket)
|
||||
}
|
||||
|
||||
|
||||
void MulticastSocket::setInterface(const NetworkInterface& interface)
|
||||
void MulticastSocket::setInterface(const NetworkInterface& interfc)
|
||||
{
|
||||
if (!interface.supportsIPv6())
|
||||
if (!interfc.supportsIPv6())
|
||||
{
|
||||
impl()->setOption(IPPROTO_IP, IP_MULTICAST_IF, interface.address());
|
||||
impl()->setOption(IPPROTO_IP, IP_MULTICAST_IF, interfc.address());
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, interface.index());
|
||||
impl()->setOption(IPPROTO_IPV6, IPV6_MULTICAST_IF, interfc.index());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -215,13 +215,13 @@ void MulticastSocket::joinGroup(const IPAddress& groupAddress)
|
||||
}
|
||||
|
||||
|
||||
void MulticastSocket::joinGroup(const IPAddress& groupAddress, const NetworkInterface& interface)
|
||||
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, interface.address().addr(), interface.address().length());
|
||||
std::memcpy(&mr.imr_interface, interfc.address().addr(), interfc.address().length());
|
||||
impl()->setRawOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr, sizeof(mr));
|
||||
}
|
||||
else
|
||||
@@ -229,7 +229,7 @@ void MulticastSocket::joinGroup(const IPAddress& groupAddress, const NetworkInte
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
struct ipv6_mreq mr;
|
||||
std::memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length());
|
||||
mr.ipv6mr_interface = interface.index();
|
||||
mr.ipv6mr_interface = interfc.index();
|
||||
impl()->setRawOption(IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, sizeof(mr));
|
||||
#endif
|
||||
}
|
||||
@@ -243,13 +243,13 @@ void MulticastSocket::leaveGroup(const IPAddress& groupAddress)
|
||||
}
|
||||
|
||||
|
||||
void MulticastSocket::leaveGroup(const IPAddress& groupAddress, const NetworkInterface& interface)
|
||||
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, interface.address().addr(), interface.address().length());
|
||||
std::memcpy(&mr.imr_interface, interfc.address().addr(), interfc.address().length());
|
||||
impl()->setRawOption(IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr, sizeof(mr));
|
||||
}
|
||||
else
|
||||
@@ -257,7 +257,7 @@ void MulticastSocket::leaveGroup(const IPAddress& groupAddress, const NetworkInt
|
||||
#if defined(POCO_HAVE_IPv6)
|
||||
struct ipv6_mreq mr;
|
||||
std::memcpy(&mr.ipv6mr_multiaddr, groupAddress.addr(), groupAddress.length());
|
||||
mr.ipv6mr_interface = interface.index();
|
||||
mr.ipv6mr_interface = interfc.index();
|
||||
impl()->setRawOption(IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mr, sizeof(mr));
|
||||
#endif
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// MultipartReader.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/MultipartReader.cpp#13 $
|
||||
// $Id: //poco/1.4/Net/src/MultipartReader.cpp#2 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Messages
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "Poco/Net/MultipartReader.h"
|
||||
#include "Poco/Net/MessageHeader.h"
|
||||
#include "Poco/Net/NetException.h"
|
||||
#include <cctype>
|
||||
#include "Poco/Ascii.h"
|
||||
|
||||
|
||||
using Poco::BufferedStreamBuf;
|
||||
@@ -72,58 +72,60 @@ 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 = _istr.get();
|
||||
int ch = buf.sbumpc();
|
||||
if (ch == eof) return -1;
|
||||
*buffer++ = (char) ch; ++n;
|
||||
if (ch == '\n' || (ch == '\r' && _istr.peek() == '\n'))
|
||||
if (ch == '\n' || (ch == '\r' && buf.sgetc() == '\n'))
|
||||
{
|
||||
if (ch == '\r')
|
||||
{
|
||||
ch = _istr.get(); // '\n'
|
||||
ch = buf.sbumpc(); // '\n'
|
||||
*buffer++ = (char) ch; ++n;
|
||||
}
|
||||
ch = _istr.peek();
|
||||
ch = buf.sgetc();
|
||||
if (ch == '\r' || ch == '\n') return n;
|
||||
*buffer++ = (char) _istr.get(); ++n;
|
||||
if (ch == '-' && _istr.peek() == '-')
|
||||
*buffer++ = (char) buf.sbumpc(); ++n;
|
||||
if (ch == '-' && buf.sgetc() == '-')
|
||||
{
|
||||
ch = _istr.get(); // '-'
|
||||
ch = buf.sbumpc(); // '-'
|
||||
*buffer++ = (char) ch; ++n;
|
||||
std::string::const_iterator it = _boundary.begin();
|
||||
std::string::const_iterator end = _boundary.end();
|
||||
ch = _istr.get();
|
||||
ch = buf.sbumpc();
|
||||
*buffer++ = (char) ch; ++n;
|
||||
while (it != end && ch == *it)
|
||||
{
|
||||
++it;
|
||||
ch = _istr.get();
|
||||
ch = buf.sbumpc();
|
||||
*buffer++ = (char) ch; ++n;
|
||||
}
|
||||
if (it == end)
|
||||
{
|
||||
if (ch == '\n' || (ch == '\r' && _istr.peek() == '\n'))
|
||||
if (ch == '\n' || (ch == '\r' && buf.sgetc() == '\n'))
|
||||
{
|
||||
if (ch == '\r')
|
||||
{
|
||||
ch = _istr.get(); // '\n'
|
||||
ch = buf.sbumpc(); // '\n'
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (ch == '-' && _istr.peek() == '-')
|
||||
else if (ch == '-' && buf.sgetc() == '-')
|
||||
{
|
||||
ch = _istr.get(); // '-'
|
||||
ch = buf.sbumpc(); // '-'
|
||||
_lastPart = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ch = _istr.peek();
|
||||
ch = buf.sgetc();
|
||||
while (ch != eof && ch != '\r' && ch != '\n' && n < length)
|
||||
{
|
||||
*buffer++ = (char) _istr.get(); ++n;
|
||||
ch = _istr.peek();
|
||||
*buffer++ = (char) buf.sbumpc(); ++n;
|
||||
ch = buf.sgetc();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@@ -268,7 +270,7 @@ void MultipartReader::guessBoundary()
|
||||
{
|
||||
static const int eof = std::char_traits<char>::eof();
|
||||
int ch = _istr.get();
|
||||
while (std::isspace(ch))
|
||||
while (Poco::Ascii::isSpace(ch))
|
||||
ch = _istr.get();
|
||||
if (ch == '-' && _istr.peek() == '-')
|
||||
{
|
||||
|
@@ -47,6 +47,7 @@ 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")
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// NetworkInterface.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/NetworkInterface.cpp#24 $
|
||||
// $Id: //poco/1.4/Net/src/NetworkInterface.cpp#3 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Sockets
|
||||
@@ -12,7 +12,7 @@
|
||||
//
|
||||
// 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,
|
||||
// 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:
|
||||
@@ -97,7 +97,7 @@ NetworkInterfaceImpl::NetworkInterfaceImpl(const std::string& name, const std::s
|
||||
_address(address),
|
||||
_index(index)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
#if !defined(_WIN32) && !defined(POCO_VXWORKS)
|
||||
if (index == -1) // IPv4
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
@@ -42,8 +42,8 @@
|
||||
#include "Poco/StreamCopier.h"
|
||||
#include "Poco/NumberFormatter.h"
|
||||
#include "Poco/UnbufferedStreamBuf.h"
|
||||
#include "Poco/Ascii.h"
|
||||
#include <istream>
|
||||
#include <cctype>
|
||||
|
||||
|
||||
using Poco::NumberFormatter;
|
||||
@@ -156,7 +156,7 @@ void POP3ClientSession::login(const std::string& username, const std::string& pa
|
||||
{
|
||||
std::string response;
|
||||
_socket.receiveMessage(response);
|
||||
if (!isPositive(response)) throw SMTPException("The POP3 service is unavailable", 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);
|
||||
@@ -184,9 +184,9 @@ int POP3ClientSession::messageCount()
|
||||
std::string::const_iterator it = response.begin();
|
||||
std::string::const_iterator end = response.end();
|
||||
int count = 0;
|
||||
while (it != end && !std::isspace(*it)) ++it;
|
||||
while (it != end && std::isspace(*it)) ++it;
|
||||
while (it != end && std::isdigit(*it)) count = count*10 + *it++ - '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;
|
||||
}
|
||||
|
||||
@@ -203,9 +203,9 @@ void POP3ClientSession::listMessages(MessageInfoVec& messages)
|
||||
MessageInfo info = {0, 0};
|
||||
std::string::const_iterator it = response.begin();
|
||||
std::string::const_iterator end = response.end();
|
||||
while (it != end && std::isdigit(*it)) info.id = info.id*10 + *it++ - '0';
|
||||
while (it != end && std::isspace(*it)) ++it;
|
||||
while (it != end && std::isdigit(*it)) info.size = info.size*10 + *it++ - '0';
|
||||
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);
|
||||
}
|
||||
|
@@ -58,10 +58,15 @@ PartSource::~PartSource()
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static const std::string EMPTY;
|
||||
}
|
||||
|
||||
|
||||
const std::string& PartSource::filename()
|
||||
{
|
||||
static const std::string empty;
|
||||
return empty;
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
//
|
||||
// QuotedPrintableDecoder.cpp
|
||||
//
|
||||
// $Id: //poco/svn/Net/src/QuotedPrintableDecoder.cpp#2 $
|
||||
// $Id: //poco/1.4/Net/src/QuotedPrintableDecoder.cpp#2 $
|
||||
//
|
||||
// Library: Net
|
||||
// Package: Messages
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "Poco/Net/QuotedPrintableDecoder.h"
|
||||
#include "Poco/NumberParser.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include <cctype>
|
||||
#include "Poco/Ascii.h"
|
||||
|
||||
|
||||
using Poco::UnbufferedStreamBuf;
|
||||
@@ -50,7 +50,7 @@ namespace Net {
|
||||
|
||||
|
||||
QuotedPrintableDecoderBuf::QuotedPrintableDecoderBuf(std::istream& istr):
|
||||
_istr(istr)
|
||||
_buf(*istr.rdbuf())
|
||||
{
|
||||
}
|
||||
|
||||
@@ -62,20 +62,20 @@ QuotedPrintableDecoderBuf::~QuotedPrintableDecoderBuf()
|
||||
|
||||
int QuotedPrintableDecoderBuf::readFromDevice()
|
||||
{
|
||||
int ch = _istr.get();
|
||||
int ch = _buf.sbumpc();
|
||||
while (ch == '=')
|
||||
{
|
||||
ch = _istr.get();
|
||||
ch = _buf.sbumpc();
|
||||
if (ch == '\r')
|
||||
{
|
||||
ch = _istr.get(); // read \n
|
||||
ch = _buf.sbumpc(); // read \n
|
||||
}
|
||||
else if (std::isxdigit(ch))
|
||||
else if (Poco::Ascii::isHexDigit(ch))
|
||||
{
|
||||
std::string hex;
|
||||
hex += (char) ch;
|
||||
ch = _istr.get();
|
||||
if (std::isxdigit(ch))
|
||||
ch = _buf.sbumpc();
|
||||
if (Poco::Ascii::isHexDigit(ch))
|
||||
{
|
||||
hex += (char) ch;
|
||||
return NumberParser::parseHex(hex);
|
||||
@@ -86,7 +86,7 @@ int QuotedPrintableDecoderBuf::readFromDevice()
|
||||
{
|
||||
throw DataFormatException("Invalid occurrence of '=' in quoted-printable encoded stream");
|
||||
}
|
||||
ch = _istr.get();
|
||||
ch = _buf.sbumpc();
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
@@ -1,355 +1,355 @@
|
||||
//
|
||||
// RemoteSyslogChannel.cpp
|
||||
//
|
||||
// $Id: //poco/Main/Net/src/RemoteSyslogChannel.cpp#4 $
|
||||
//
|
||||
// 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;
|
||||
|
||||
SocketAddress sa;
|
||||
if (_logHost.find(':') != std::string::npos)
|
||||
sa = SocketAddress(_logHost);
|
||||
else
|
||||
sa = SocketAddress(_logHost, SYSLOG_PORT);
|
||||
|
||||
_socket.connect(sa);
|
||||
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)
|
||||
{
|
||||
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.sendBytes(m.data(), (int) m.size());
|
||||
}
|
||||
|
||||
|
||||
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");
|
||||
}
|
||||
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 ? "bsd" : "new";
|
||||
}
|
||||
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
|
||||
//
|
||||
// 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
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#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"
|
||||
@@ -46,7 +47,7 @@
|
||||
#include "Poco/Message.h"
|
||||
#include "Poco/LoggingFactory.h"
|
||||
#include "Poco/Buffer.h"
|
||||
#include <cctype>
|
||||
#include "Poco/Ascii.h"
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
@@ -62,22 +63,35 @@ namespace Net {
|
||||
class MessageNotification: public Poco::Notification
|
||||
{
|
||||
public:
|
||||
MessageNotification(const std::string& msg)
|
||||
MessageNotification(const char* buffer, std::size_t length, const Poco::Net::SocketAddress& sourceAddress):
|
||||
_message(buffer, length),
|
||||
_sourceAddress(sourceAddress)
|
||||
{
|
||||
_msg = msg;
|
||||
}
|
||||
|
||||
|
||||
MessageNotification(const std::string& message, const Poco::Net::SocketAddress& sourceAddress):
|
||||
_message(message),
|
||||
_sourceAddress(sourceAddress)
|
||||
{
|
||||
}
|
||||
|
||||
~MessageNotification()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string& message() const
|
||||
{
|
||||
return _msg;
|
||||
return _message;
|
||||
}
|
||||
|
||||
const Poco::Net::SocketAddress& sourceAddress() const
|
||||
{
|
||||
return _sourceAddress;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _msg;
|
||||
std::string _message;
|
||||
Poco::Net::SocketAddress _sourceAddress;
|
||||
};
|
||||
|
||||
|
||||
@@ -111,7 +125,7 @@ private:
|
||||
RemoteUDPListener::RemoteUDPListener(Poco::NotificationQueue& queue, Poco::UInt16 port):
|
||||
_queue(queue),
|
||||
_socket(Poco::Net::SocketAddress(Poco::Net::IPAddress(), port)),
|
||||
_stopped(true)
|
||||
_stopped(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -123,10 +137,7 @@ RemoteUDPListener::~RemoteUDPListener()
|
||||
|
||||
void RemoteUDPListener::run()
|
||||
{
|
||||
poco_assert (_stopped);
|
||||
|
||||
Poco::Buffer<char> buffer(BUFFER_SIZE);
|
||||
_stopped = false;
|
||||
Poco::Timespan waitTime(WAITTIME_MILLISEC* 1000);
|
||||
while (!_stopped)
|
||||
{
|
||||
@@ -134,10 +145,11 @@ void RemoteUDPListener::run()
|
||||
{
|
||||
if (_socket.poll(waitTime, Socket::SELECT_READ))
|
||||
{
|
||||
int byteCnt = _socket.receiveBytes(buffer.begin(), BUFFER_SIZE);
|
||||
if (byteCnt > 0)
|
||||
Poco::Net::SocketAddress sourceAddress;
|
||||
int n = _socket.receiveFrom(buffer.begin(), BUFFER_SIZE, sourceAddress);
|
||||
if (n > 0)
|
||||
{
|
||||
_queue.enqueueNotification(new MessageNotification(std::string(buffer.begin(), byteCnt)));
|
||||
_queue.enqueueNotification(new MessageNotification(buffer.begin(), n, sourceAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,18 +185,18 @@ public:
|
||||
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 parse(const std::string& msg);
|
||||
void parsePrio(const std::string& msg, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac);
|
||||
void parseNew(const std::string& msg, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos);
|
||||
void parseBSD(const std::string& msg, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos);
|
||||
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& msg, std::size_t& pos);
|
||||
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
|
||||
|
||||
@@ -200,7 +212,7 @@ const std::string SyslogParser::NILVALUE("-");
|
||||
|
||||
SyslogParser::SyslogParser(Poco::NotificationQueue& queue, RemoteSyslogListener* pListener):
|
||||
_queue(queue),
|
||||
_stopped(true),
|
||||
_stopped(false),
|
||||
_pListener(pListener)
|
||||
{
|
||||
poco_check_ptr (_pListener);
|
||||
@@ -214,8 +226,6 @@ SyslogParser::~SyslogParser()
|
||||
|
||||
void SyslogParser::run()
|
||||
{
|
||||
poco_assert (_stopped);
|
||||
_stopped = false;
|
||||
while (!_stopped)
|
||||
{
|
||||
try
|
||||
@@ -224,7 +234,10 @@ void SyslogParser::run()
|
||||
if (pNf)
|
||||
{
|
||||
Poco::AutoPtr<MessageNotification> pMsgNf = pNf.cast<MessageNotification>();
|
||||
parse(pMsgNf->message());
|
||||
Poco::Message message;
|
||||
parse(pMsgNf->message(), message);
|
||||
message["addr"] =pMsgNf->sourceAddress().host().toString();
|
||||
_pListener->log(message);
|
||||
}
|
||||
}
|
||||
catch (Poco::Exception&)
|
||||
@@ -244,43 +257,43 @@ void SyslogParser::safeStop()
|
||||
}
|
||||
|
||||
|
||||
void SyslogParser::parse(const std::string& msg)
|
||||
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(msg, pos, severity, 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 (std::isdigit(msg[pos]))
|
||||
if (Poco::Ascii::isDigit(line[pos]))
|
||||
{
|
||||
parseNew(msg, severity, fac, pos);
|
||||
parseNew(line, severity, fac, pos, message);
|
||||
}
|
||||
else
|
||||
{
|
||||
parseBSD(msg, severity, fac, pos);
|
||||
parseBSD(line, severity, fac, pos, message);
|
||||
}
|
||||
poco_assert (pos == msg.size());
|
||||
poco_assert (pos == line.size());
|
||||
}
|
||||
|
||||
|
||||
void SyslogParser::parsePrio(const std::string& msg, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac)
|
||||
void SyslogParser::parsePrio(const std::string& line, std::size_t& pos, RemoteSyslogChannel::Severity& severity, RemoteSyslogChannel::Facility& fac)
|
||||
{
|
||||
poco_assert (pos < msg.size());
|
||||
poco_assert (msg[pos] == '<');
|
||||
poco_assert (pos < line.size());
|
||||
poco_assert (line[pos] == '<');
|
||||
++pos;
|
||||
std::size_t start = pos;
|
||||
|
||||
while (pos < msg.size() && std::isdigit(msg[pos]))
|
||||
while (pos < line.size() && Poco::Ascii::isDigit(line[pos]))
|
||||
++pos;
|
||||
|
||||
poco_assert (msg[pos] == '>');
|
||||
poco_assert (line[pos] == '>');
|
||||
poco_assert (pos - start > 0);
|
||||
std::string valStr = msg.substr(start, pos - start);
|
||||
std::string valStr = line.substr(start, pos - start);
|
||||
++pos; // skip the >
|
||||
|
||||
int val = Poco::NumberParser::parse(valStr);
|
||||
@@ -293,23 +306,23 @@ void SyslogParser::parsePrio(const std::string& msg, std::size_t& pos, RemoteSys
|
||||
}
|
||||
|
||||
|
||||
void SyslogParser::parseNew(const std::string& msg, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos)
|
||||
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(msg, pos));
|
||||
std::string timeStr(parseUntilSpace(msg, pos)); // can be the nilvalue!
|
||||
std::string hostName(parseUntilSpace(msg, pos));
|
||||
std::string appName(parseUntilSpace(msg, pos));
|
||||
std::string procId(parseUntilSpace(msg, pos));
|
||||
std::string msgId(parseUntilSpace(msg, pos));
|
||||
std::string message(msg.substr(pos));
|
||||
pos = msg.size();
|
||||
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, message, prio);
|
||||
Poco::Message logEntry(msgId, messageText, prio);
|
||||
logEntry["host"] = hostName;
|
||||
logEntry["app"] = appName;
|
||||
|
||||
@@ -318,11 +331,11 @@ void SyslogParser::parseNew(const std::string& msg, RemoteSyslogChannel::Severit
|
||||
int lval(0);
|
||||
Poco::NumberParser::tryParse(procId, lval);
|
||||
logEntry.setPid(lval);
|
||||
_pListener->log(logEntry);
|
||||
message.swap(logEntry);
|
||||
}
|
||||
|
||||
|
||||
void SyslogParser::parseBSD(const std::string& msg, RemoteSyslogChannel::Severity severity, RemoteSyslogChannel::Facility fac, std::size_t& pos)
|
||||
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:
|
||||
@@ -330,9 +343,9 @@ void SyslogParser::parseBSD(const std::string& msg, RemoteSyslogChannel::Severit
|
||||
// detect three spaces
|
||||
int spaceCnt = 0;
|
||||
std::size_t start = pos;
|
||||
while (spaceCnt < 3 && pos < msg.size())
|
||||
while (spaceCnt < 3 && pos < line.size())
|
||||
{
|
||||
if (msg[pos] == ' ')
|
||||
if (line[pos] == ' ')
|
||||
{
|
||||
spaceCnt++;
|
||||
if (spaceCnt == 1)
|
||||
@@ -342,21 +355,21 @@ void SyslogParser::parseBSD(const std::string& msg, RemoteSyslogChannel::Severit
|
||||
{
|
||||
// probably a shortened time value, or the hostname
|
||||
// assume hostName
|
||||
Poco::Message logEntry(msg.substr(start, pos-start), msg.substr(pos+1), prio);
|
||||
_pListener->log(logEntry);
|
||||
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 (!(std::isdigit(msg[pos-1]) && (std::isdigit(msg[pos-2]) || std::isspace(msg[pos-2]))))
|
||||
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 < msg.size() && msg[pos+1] == ' ')
|
||||
if (pos + 1 < line.size() && line[pos+1] == ' ')
|
||||
{
|
||||
// we have two spaces when the day value is smaller than 10!
|
||||
++pos; // skip one
|
||||
@@ -364,7 +377,7 @@ void SyslogParser::parseBSD(const std::string& msg, RemoteSyslogChannel::Severit
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
std::string timeStr(msg.substr(start, pos-start-1));
|
||||
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
|
||||
@@ -379,26 +392,26 @@ void SyslogParser::parseBSD(const std::string& msg, RemoteSyslogChannel::Severit
|
||||
date = Poco::DateTime(year, m, d, h, min, sec);
|
||||
}
|
||||
// next entry is host SP
|
||||
std::string hostName(parseUntilSpace(msg, pos));
|
||||
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 message(msg.substr(pos));
|
||||
pos = msg.size();
|
||||
Poco::Message logEntry(hostName, message, prio);
|
||||
std::string messageText(line.substr(pos));
|
||||
pos = line.size();
|
||||
Poco::Message logEntry(hostName, messageText, prio);
|
||||
logEntry.setTime(date.timestamp());
|
||||
_pListener->log(logEntry);
|
||||
message.swap(logEntry);
|
||||
}
|
||||
|
||||
|
||||
std::string SyslogParser::parseUntilSpace(const std::string& msg, std::size_t& pos)
|
||||
std::string SyslogParser::parseUntilSpace(const std::string& line, std::size_t& pos)
|
||||
{
|
||||
std::size_t start = pos;
|
||||
while (pos < msg.size() && !std::isspace(msg[pos]))
|
||||
while (pos < line.size() && !Poco::Ascii::isSpace(line[pos]))
|
||||
++pos;
|
||||
// skip space
|
||||
++pos;
|
||||
return msg.substr(start, pos-start-1);
|
||||
return line.substr(start, pos-start-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -433,15 +446,14 @@ Poco::Message::Priority SyslogParser::convert(RemoteSyslogChannel::Severity seve
|
||||
|
||||
|
||||
const std::string RemoteSyslogListener::PROP_PORT("port");
|
||||
const std::string RemoteSyslogListener::PROP_THREADS("threads");
|
||||
|
||||
|
||||
RemoteSyslogListener::RemoteSyslogListener():
|
||||
_pListener(0),
|
||||
_pParser(0),
|
||||
_listener(),
|
||||
_parser(),
|
||||
_queue(),
|
||||
_port(RemoteSyslogChannel::SYSLOG_PORT)
|
||||
_port(RemoteSyslogChannel::SYSLOG_PORT),
|
||||
_threads(1)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -449,10 +461,17 @@ RemoteSyslogListener::RemoteSyslogListener():
|
||||
RemoteSyslogListener::RemoteSyslogListener(Poco::UInt16 port):
|
||||
_pListener(0),
|
||||
_pParser(0),
|
||||
_listener(),
|
||||
_parser(),
|
||||
_queue(),
|
||||
_port(port)
|
||||
_port(port),
|
||||
_threads(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RemoteSyslogListener::RemoteSyslogListener(Poco::UInt16 port, int threads):
|
||||
_pListener(0),
|
||||
_pParser(0),
|
||||
_port(port),
|
||||
_threads(threads)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -462,16 +481,38 @@ 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)
|
||||
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);
|
||||
@@ -483,6 +524,8 @@ 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);
|
||||
}
|
||||
@@ -492,26 +535,37 @@ void RemoteSyslogListener::open()
|
||||
{
|
||||
SplitterChannel::open();
|
||||
_pParser = new SyslogParser(_queue, this);
|
||||
_pListener = new RemoteUDPListener(_queue, _port);
|
||||
_parser.start(*_pParser);
|
||||
_listener.start(*_pListener);
|
||||
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 && _pParser)
|
||||
if (_pListener)
|
||||
{
|
||||
_pListener->safeStop();
|
||||
_pParser->safeStop();
|
||||
_queue.clear();
|
||||
_listener.join();
|
||||
_parser.join();
|
||||
delete _pListener;
|
||||
delete _pParser;
|
||||
_pListener = 0;
|
||||
_pParser = 0;
|
||||
}
|
||||
if (_pParser)
|
||||
{
|
||||
_pParser->safeStop();
|
||||
}
|
||||
_queue.clear();
|
||||
_threadPool.joinAll();
|
||||
delete _pListener;
|
||||
delete _pParser;
|
||||
_pListener = 0;
|
||||
_pParser = 0;
|
||||
SplitterChannel::close();
|
||||
}
|
||||
|
||||
|
@@ -45,10 +45,12 @@
|
||||
#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>
|
||||
@@ -57,6 +59,7 @@
|
||||
using Poco::DigestEngine;
|
||||
using Poco::HMACEngine;
|
||||
using Poco::MD5Engine;
|
||||
using Poco::SHA1Engine;
|
||||
using Poco::DigestOutputStream;
|
||||
using Poco::StreamCopier;
|
||||
using Poco::Base64Encoder;
|
||||
@@ -112,7 +115,7 @@ void SMTPClientSession::login(const std::string& hostname, std::string& response
|
||||
int status = sendCommand("EHLO", hostname, response);
|
||||
if (isPermanentNegative(status))
|
||||
status = sendCommand("HELO", hostname, response);
|
||||
if (!isPositiveCompletion(status)) throw SMTPException("Login failed", response);
|
||||
if (!isPositiveCompletion(status)) throw SMTPException("Login failed", response, status);
|
||||
}
|
||||
|
||||
|
||||
@@ -129,21 +132,34 @@ void SMTPClientSession::login()
|
||||
}
|
||||
|
||||
|
||||
void SMTPClientSession::loginUsingCRAM_MD5(const std::string& username, const std::string& password)
|
||||
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("AUTH CRAM-MD5", response);
|
||||
if (!isPositiveIntermediate(status)) throw SMTPException("Cannot authenticate CRAM-MD5", 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;
|
||||
decoder >> challenge;
|
||||
StreamCopier::copyToString(decoder, challenge);
|
||||
|
||||
HMACEngine<MD5Engine> hmac(password);
|
||||
hmac.update(challenge);
|
||||
|
||||
const DigestEngine::Digest& digest = hmac.digest();
|
||||
@@ -157,7 +173,7 @@ void SMTPClientSession::loginUsingCRAM_MD5(const std::string& username, const st
|
||||
encoder.close();
|
||||
|
||||
status = sendCommand(challengeResponseBase64.str(), response);
|
||||
if (!isPositiveCompletion(status)) throw SMTPException("Login using CRAM-MD5 failed", response);
|
||||
if (!isPositiveCompletion(status)) throw SMTPException(std::string("Login using ") + method + " failed", response, status);
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +183,7 @@ void SMTPClientSession::loginUsingLogin(const std::string& username, const std::
|
||||
std::string response;
|
||||
|
||||
status = sendCommand("AUTH LOGIN", response);
|
||||
if (!isPositiveIntermediate(status)) throw SMTPException("Cannot authenticate LOGIN", response);
|
||||
if (!isPositiveIntermediate(status)) throw SMTPException("Cannot authenticate using LOGIN", response, status);
|
||||
|
||||
std::ostringstream usernameBase64;
|
||||
Base64Encoder usernameEncoder(usernameBase64);
|
||||
@@ -189,39 +205,72 @@ void SMTPClientSession::loginUsingLogin(const std::string& username, const std::
|
||||
//C: user_password
|
||||
//S: login:
|
||||
//C: user_login
|
||||
if (response == "334 VXNlcm5hbWU6") // username first (md5("Username:"))
|
||||
|
||||
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 user name failed", 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);
|
||||
if (!isPositiveCompletion(status)) throw SMTPException("Login using LOGIN password failed", response, status);
|
||||
}
|
||||
else if (response == "334 UGFzc3dvcmQ6") // password first (md5("Password:"))
|
||||
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);
|
||||
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 user name failed", 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(Environment::nodeName(), response);
|
||||
login(hostname, response);
|
||||
|
||||
if (loginMethod == AUTH_CRAM_MD5)
|
||||
{
|
||||
if (response.find("CRAM-MD5", 0) != std::string::npos)
|
||||
{
|
||||
loginUsingCRAM_MD5(username, password);
|
||||
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)
|
||||
@@ -230,6 +279,14 @@ void SMTPClientSession::login(LoginMethod loginMethod, const std::string& userna
|
||||
}
|
||||
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");
|
||||
@@ -243,7 +300,7 @@ void SMTPClientSession::open()
|
||||
{
|
||||
std::string response;
|
||||
int status = _socket.receiveStatusMessage(response);
|
||||
if (!isPositiveCompletion(status)) throw SMTPException("The mail service is unavailable", response);
|
||||
if (!isPositiveCompletion(status)) throw SMTPException("The mail service is unavailable", response, status);
|
||||
_isOpen = true;
|
||||
}
|
||||
}
|
||||
@@ -278,24 +335,24 @@ void SMTPClientSession::sendMessage(const MailMessage& message)
|
||||
{
|
||||
status = sendCommand("MAIL FROM:", fromField.substr(emailPos, fromField.size() - emailPos), response);
|
||||
}
|
||||
if (!isPositiveCompletion(status)) throw SMTPException("Cannot send message", 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);
|
||||
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);
|
||||
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);
|
||||
if (!isPositiveCompletion(status)) throw SMTPException("The server rejected the message", response, status);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -107,10 +107,24 @@ void ServerSocket::bind(Poco::UInt16 port, bool reuseAddress)
|
||||
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);
|
||||
impl()->listen(backlog);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
// Package: NetCore
|
||||
// Module: SocketAddress
|
||||
//
|
||||
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
||||
// Copyright (c) 2005-2011, Applied Informatics Software Engineering GmbH.
|
||||
// and Contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person or organization
|
||||
@@ -56,6 +56,15 @@ namespace Poco {
|
||||
namespace Net {
|
||||
|
||||
|
||||
struct AFLT
|
||||
{
|
||||
bool operator () (const IPAddress& a1, const IPAddress& a2)
|
||||
{
|
||||
return a1.af() < a2.af();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// SocketAddressImpl
|
||||
//
|
||||
@@ -71,14 +80,20 @@ public:
|
||||
virtual int af() const = 0;
|
||||
|
||||
protected:
|
||||
SocketAddressImpl()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~SocketAddressImpl()
|
||||
{
|
||||
}
|
||||
|
||||
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&);
|
||||
@@ -155,15 +170,25 @@ public:
|
||||
_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_port = port;
|
||||
}
|
||||
|
||||
IPAddress host() const
|
||||
{
|
||||
return IPAddress(&_addr.sin6_addr, sizeof(_addr.sin6_addr));
|
||||
}
|
||||
|
||||
UInt16 port() const
|
||||
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;
|
||||
}
|
||||
@@ -339,29 +364,36 @@ std::string SocketAddress::toString() const
|
||||
void SocketAddress::init(const IPAddress& host, Poco::UInt16 port)
|
||||
{
|
||||
if (host.family() == IPAddress::IPv4)
|
||||
_pImpl = new IPv4SocketAddressImpl(host.addr(), htons(port));
|
||||
_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));
|
||||
else if (host.family() == IPAddress::IPv6)
|
||||
_pImpl = new IPv6SocketAddressImpl(host.addr(), htons(port), host.scope());
|
||||
#endif
|
||||
else throw Poco::NotImplementedException("unsupported IP address family");
|
||||
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);
|
||||
if (he.addresses().size() > 0)
|
||||
init(he.addresses()[0], port);
|
||||
else throw HostNotFoundException("No address found for host", host);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -374,11 +406,15 @@ Poco::UInt16 SocketAddress::resolveService(const std::string& service)
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -85,10 +85,14 @@ void SocketNotifier::removeObserver(SocketReactor* pReactor, const Poco::Abstrac
|
||||
}
|
||||
|
||||
|
||||
void SocketNotifier::dispatch(SocketNotification* pNotification)
|
||||
namespace
|
||||
{
|
||||
static Socket nullSocket;
|
||||
}
|
||||
|
||||
|
||||
void SocketNotifier::dispatch(SocketNotification* pNotification)
|
||||
{
|
||||
pNotification->setSocket(_socket);
|
||||
pNotification->duplicate();
|
||||
try
|
||||
|
@@ -123,6 +123,8 @@ void SocketReactor::run()
|
||||
}
|
||||
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)
|
||||
@@ -169,31 +171,41 @@ const Poco::Timespan& SocketReactor::getTimeout() const
|
||||
|
||||
void SocketReactor::addEventHandler(const Socket& socket, const Poco::AbstractObserver& observer)
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
NotifierPtr pNotifier;
|
||||
EventHandlerMap::iterator it = _handlers.find(socket);
|
||||
if (it == _handlers.end())
|
||||
{
|
||||
pNotifier = new SocketNotifier(socket);
|
||||
_handlers[socket] = 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;
|
||||
}
|
||||
else pNotifier = it->second;
|
||||
pNotifier->addObserver(this, observer);
|
||||
}
|
||||
|
||||
|
||||
void SocketReactor::removeEventHandler(const Socket& socket, const Poco::AbstractObserver& observer)
|
||||
{
|
||||
FastMutex::ScopedLock lock(_mutex);
|
||||
|
||||
EventHandlerMap::iterator it = _handlers.find(socket);
|
||||
if (it != _handlers.end())
|
||||
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)
|
||||
{
|
||||
NotifierPtr pNotifier = it->second;
|
||||
pNotifier->removeObserver(this, observer);
|
||||
if (!pNotifier->hasObservers())
|
||||
_handlers.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,6 +228,11 @@ void SocketReactor::onShutdown()
|
||||
}
|
||||
|
||||
|
||||
void SocketReactor::onBusy()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SocketReactor::dispatch(const Socket& socket, SocketNotification* pNotification)
|
||||
{
|
||||
NotifierPtr pNotifier;
|
||||
|
@@ -36,6 +36,7 @@
|
||||
|
||||
#include "Poco/Net/StreamSocketImpl.h"
|
||||
#include "Poco/Exception.h"
|
||||
#include "Poco/Thread.h"
|
||||
|
||||
|
||||
namespace Poco {
|
||||
@@ -73,14 +74,21 @@ 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);
|
||||
if (n <= 0) return n;
|
||||
poco_assert_dbg (n >= 0);
|
||||
p += n;
|
||||
sent += n;
|
||||
remaining -= n;
|
||||
if (blocking && remaining > 0)
|
||||
Poco::Thread::yield();
|
||||
else
|
||||
break;
|
||||
}
|
||||
return length;
|
||||
return sent;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -147,6 +147,12 @@ void TCPServerDispatcher::run()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static const std::string threadName("TCPServerConnection");
|
||||
}
|
||||
|
||||
|
||||
void TCPServerDispatcher::enqueue(const StreamSocket& socket)
|
||||
{
|
||||
@@ -159,7 +165,6 @@ void TCPServerDispatcher::enqueue(const StreamSocket& socket)
|
||||
{
|
||||
try
|
||||
{
|
||||
static const std::string threadName("TCPServerConnection");
|
||||
_threadPool.startWithPriority(_pParams->getThreadPriority(), *this, threadName);
|
||||
++_currentThreads;
|
||||
}
|
||||
|
Reference in New Issue
Block a user