backport changes from 1.4.3 branch

This commit is contained in:
Marian Krivos
2012-01-07 11:06:14 +00:00
parent cc90b38ae5
commit 6268aa3865
69 changed files with 10381 additions and 5761 deletions

View File

@@ -51,7 +51,7 @@ using Poco::IOException;
namespace
{
class NetworkInitializer
class NetworkInitializer
{
public:
NetworkInitializer()
@@ -61,9 +61,9 @@ namespace
~NetworkInitializer()
{
Poco::Net::uninitializeNetwork();
}
};
Poco::Net::uninitializeNetwork();
}
};
}
@@ -75,37 +75,37 @@ HostEntry DNS::hostByName(const std::string& hostname)
{
NetworkInitializer networkInitializer;
#if defined(POCO_HAVE_IPv6)
#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
struct addrinfo* pAI;
struct addrinfo hints;
std::memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
int rc = getaddrinfo(hostname.c_str(), NULL, &hints, &pAI);
if (rc == 0)
{
HostEntry result(pAI);
freeaddrinfo(pAI);
return result;
}
else
{
aierror(rc, hostname);
}
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)));
}
int addr = hostGetByName(const_cast<char*>(hostname.c_str()));
if (addr != ERROR)
{
return HostEntry(hostname, IPAddress(&addr, sizeof(addr)));
}
#else
struct hostent* he = gethostbyname(hostname.c_str());
if (he)
{
return HostEntry(he);
}
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
}
@@ -113,46 +113,46 @@ HostEntry DNS::hostByAddress(const IPAddress& address)
{
NetworkInitializer networkInitializer;
#if defined(POCO_HAVE_IPv6)
#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
SocketAddress sa(address, 0);
static char fqname[1024];
int rc = getnameinfo(sa.addr(), sa.length(), fqname, sizeof(fqname), NULL, 0, NI_NAMEREQD);
if (rc == 0)
{
struct addrinfo* pAI;
struct addrinfo hints;
std::memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
rc = getaddrinfo(fqname, NULL, &hints, &pAI);
if (rc == 0)
{
HostEntry result(pAI);
freeaddrinfo(pAI);
return result;
}
else
{
aierror(rc, address.toString());
}
}
else
{
aierror(rc, address.toString());
}
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);
}
char name[MAXHOSTNAMELEN + 1];
if (hostGetByAddr(*reinterpret_cast<const int*>(address.addr()), name) == OK)
{
return HostEntry(std::string(name), address);
}
#else
struct hostent* he = gethostbyaddr(reinterpret_cast<const char*>(address.addr()), address.length(), address.af());
if (he)
{
return HostEntry(he);
}
struct hostent* he = gethostbyaddr(reinterpret_cast<const char*>(address.addr()), address.length(), address.af());
if (he)
{
return HostEntry(he);
}
#endif
int err = lastError();
int err = lastError();
error(err, address.toString()); // will throw an appropriate exception
throw NetException(); // to silence compiler
}
@@ -160,11 +160,11 @@ HostEntry DNS::hostByAddress(const IPAddress& address)
HostEntry DNS::resolve(const std::string& address)
{
NetworkInitializer networkInitializer;
NetworkInitializer networkInitializer;
IPAddress ip;
if (IPAddress::tryParse(address, ip))
return hostByAddress(ip);
IPAddress ip;
if (IPAddress::tryParse(address, ip))
return hostByAddress(ip);
else
return hostByName(address);
}
@@ -172,11 +172,11 @@ HostEntry DNS::resolve(const std::string& address)
IPAddress DNS::resolveOne(const std::string& address)
{
NetworkInitializer networkInitializer;
NetworkInitializer networkInitializer;
const HostEntry& entry = resolve(address);
if (!entry.addresses().empty())
return entry.addresses()[0];
const HostEntry& entry = resolve(address);
if (!entry.addresses().empty())
return entry.addresses()[0];
else
throw NoAddressFoundException(address);
}
@@ -184,7 +184,7 @@ IPAddress DNS::resolveOne(const std::string& address)
HostEntry DNS::thisHost()
{
return hostByName(hostName());
return hostByName(hostName());
}
@@ -195,11 +195,11 @@ void DNS::flushCache()
std::string DNS::hostName()
{
NetworkInitializer networkInitializer;
NetworkInitializer networkInitializer;
char buffer[256];
int rc = gethostname(buffer, sizeof(buffer));
if (rc == 0)
char buffer[256];
int rc = gethostname(buffer, sizeof(buffer));
if (rc == 0)
return std::string(buffer);
else
throw NetException("Cannot get host name");
@@ -243,30 +243,30 @@ 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);
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);
case EAI_NODATA:
throw NoAddressFoundException(arg);
#endif
case EAI_NONAME:
throw HostNotFoundException(arg);
case EAI_NONAME:
throw HostNotFoundException(arg);
#if defined(EAI_SYSTEM)
case EAI_SYSTEM:
error(lastError(), arg);
break;
case EAI_SYSTEM:
error(lastError(), arg);
break;
#endif
#if defined(_WIN32)
case WSANO_DATA: // may happen on XP
throw HostNotFoundException(arg);
case WSANO_DATA: // may happen on XP
throw HostNotFoundException(arg);
#endif
default:
throw DNSException("EAI", NumberFormatter::format(code));
}
default:
throw DNSException("EAI", NumberFormatter::format(code));
}
#endif // POCO_HAVE_IPv6
}
@@ -279,24 +279,24 @@ static Poco::AtomicCounter initializeCount;
void initializeNetwork()
{
#if defined(_WIN32)
if (++initializeCount == 1)
{
WORD version = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(version, &data) != 0)
throw NetException("Failed to initialize network subsystem");
}
if (++initializeCount == 1)
{
WORD version = MAKEWORD(2, 2);
WSADATA data;
if (WSAStartup(version, &data) != 0)
throw NetException("Failed to initialize network subsystem");
}
#endif // _WIN32
}
void uninitializeNetwork()
{
#if defined(_WIN32)
if (--initializeCount == 0)
{
WSACleanup();
}
if (--initializeCount == 0)
{
WSACleanup();
}
#endif // _WIN32
}

View File

@@ -63,12 +63,22 @@ DialogSocket::DialogSocket(const SocketAddress& address):
DialogSocket::DialogSocket(const Socket& socket):
StreamSocket(socket),
_pBuffer(0),
_pNext(0),
_pEnd(0)
StreamSocket(socket),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
allocBuffer();
}
DialogSocket::DialogSocket(const DialogSocket& socket):
StreamSocket(socket),
_pBuffer(0),
_pNext(0),
_pEnd(0)
{
allocBuffer();
}

View File

@@ -41,10 +41,10 @@
#include "Poco/Net/MultipartWriter.h"
#include "Poco/Net/MultipartReader.h"
#include "Poco/Net/NullPartHandler.h"
#include "Poco/Net/NetException.h"
#include "Poco/NullStream.h"
#include "Poco/CountingStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/Exception.h"
#include "Poco/URI.h"
#include "Poco/String.h"
#include <sstream>
@@ -66,32 +66,37 @@ const std::string HTMLForm::ENCODING_MULTIPART = "multipart/form-data";
HTMLForm::HTMLForm():
_encoding(ENCODING_URL)
_fieldLimit(DFL_FIELD_LIMIT),
_encoding(ENCODING_URL)
{
}
HTMLForm::HTMLForm(const std::string& encoding):
_encoding(encoding)
_fieldLimit(DFL_FIELD_LIMIT),
_encoding(encoding)
{
}
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler)
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody, PartHandler& handler):
_fieldLimit(DFL_FIELD_LIMIT)
{
load(request, requestBody, handler);
load(request, requestBody, handler);
}
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody)
HTMLForm::HTMLForm(const HTTPRequest& request, std::istream& requestBody):
_fieldLimit(DFL_FIELD_LIMIT)
{
load(request, requestBody);
load(request, requestBody);
}
HTMLForm::HTMLForm(const HTTPRequest& request)
HTMLForm::HTMLForm(const HTTPRequest& request):
_fieldLimit(DFL_FIELD_LIMIT)
{
load(request);
load(request);
}
@@ -173,9 +178,22 @@ void HTMLForm::read(std::istream& istr, PartHandler& handler)
}
void HTMLForm::read(std::istream& istr)
{
readUrl(istr);
}
void HTMLForm::read(const std::string& queryString)
{
std::istringstream istr(queryString);
readUrl(istr);
}
void HTMLForm::prepareSubmit(HTTPRequest& request)
{
if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT)
if (request.getMethod() == HTTPRequest::HTTP_POST || request.getMethod() == HTTPRequest::HTTP_PUT)
{
if (_encoding == ENCODING_URL)
{
@@ -241,14 +259,17 @@ void HTMLForm::write(std::ostream& ostr)
void HTMLForm::readUrl(std::istream& istr)
{
static const int eof = std::char_traits<char>::eof();
static const int eof = std::char_traits<char>::eof();
int ch = istr.get();
while (ch != eof)
{
std::string name;
std::string value;
while (ch != eof && ch != '=' && ch != '&')
int fields = 0;
int ch = istr.get();
while (ch != eof)
{
if (_fieldLimit > 0 && fields == _fieldLimit)
throw HTMLFormException("Too many form fields");
std::string name;
std::string value;
while (ch != eof && ch != '=' && ch != '&')
{
if (ch == '+') ch = ' ';
name += (char) ch;
@@ -266,24 +287,28 @@ void HTMLForm::readUrl(std::istream& istr)
}
std::string decodedName;
std::string decodedValue;
URI::decode(name, decodedName);
URI::decode(value, decodedValue);
add(decodedName, decodedValue);
if (ch == '&') ch = istr.get();
}
URI::decode(name, decodedName);
URI::decode(value, decodedValue);
add(decodedName, decodedValue);
++fields;
if (ch == '&') ch = istr.get();
}
}
void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler)
{
static const int eof = std::char_traits<char>::eof();
static const int eof = std::char_traits<char>::eof();
MultipartReader reader(istr, _boundary);
while (reader.hasNextPart())
{
MessageHeader header;
reader.nextPart(header);
std::string disp;
int fields = 0;
MultipartReader reader(istr, _boundary);
while (reader.hasNextPart())
{
if (_fieldLimit > 0 && fields == _fieldLimit)
throw HTMLFormException("Too many form fields");
MessageHeader header;
reader.nextPart(header);
std::string disp;
NameValueCollection params;
if (header.has("Content-Disposition"))
{
@@ -306,10 +331,11 @@ void HTMLForm::readMultipart(std::istream& istr, PartHandler& handler)
{
value += (char) ch;
ch = istr.get();
}
add(name, value);
}
}
}
add(name, value);
}
++fields;
}
}
@@ -363,4 +389,12 @@ void HTMLForm::writeMultipart(std::ostream& ostr)
}
void HTMLForm::setFieldLimit(int limit)
{
poco_assert (limit >= 0);
_fieldLimit = limit;
}
} } // namespace Poco::Net

View File

@@ -69,29 +69,20 @@ HTTPBasicCredentials::HTTPBasicCredentials(const std::string& username, const st
HTTPBasicCredentials::HTTPBasicCredentials(const HTTPRequest& request)
{
static const int eof = std::char_traits<char>::eof();
std::string scheme;
std::string authInfo;
request.getCredentials(scheme, authInfo);
if (icompare(scheme, SCHEME) == 0)
{
parseAuthInfo(authInfo);
}
else throw NotAuthenticatedException("Basic authentication expected");
}
std::string scheme;
std::string info;
request.getCredentials(scheme, info);
if (icompare(scheme, SCHEME) == 0)
{
std::istringstream istr(info);
Base64Decoder decoder(istr);
int ch = decoder.get();
while (ch != eof && ch != ':')
{
_username += (char) ch;
ch = decoder.get();
}
if (ch == ':') ch = decoder.get();
while (ch != eof)
{
_password += (char) ch;
ch = decoder.get();
}
}
else throw NotAuthenticatedException("Basic authentication expected");
HTTPBasicCredentials::HTTPBasicCredentials(const std::string& authInfo)
{
parseAuthInfo(authInfo);
}
@@ -123,4 +114,25 @@ void HTTPBasicCredentials::authenticate(HTTPRequest& request)
}
void HTTPBasicCredentials::parseAuthInfo(const std::string& authInfo)
{
static const int eof = std::char_traits<char>::eof();
std::istringstream istr(authInfo);
Base64Decoder decoder(istr);
int ch = decoder.get();
while (ch != eof && ch != ':')
{
_username += (char) ch;
ch = decoder.get();
}
if (ch == ':') ch = decoder.get();
while (ch != eof)
{
_password += (char) ch;
ch = decoder.get();
}
}
} } // namespace Poco::Net

View File

@@ -90,30 +90,52 @@ void HTTPMessage::setVersion(const std::string& version)
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);
}
std::streamsize HTTPMessage::getContentLength() const
{
const std::string& contentLength = get(CONTENT_LENGTH, EMPTY);
if (!contentLength.empty())
{
if (sizeof(std::streamsize) == sizeof(Poco::Int64))
return static_cast<std::streamsize>(NumberParser::parse64(contentLength));
else
return static_cast<std::streamsize>(NumberParser::parse(contentLength));
}
else return UNKNOWN_CONTENT_LENGTH;
}
#if defined(POCO_HAVE_INT64)
void HTTPMessage::setContentLength64(Poco::Int64 length)
{
if (length != UNKNOWN_CONTENT_LENGTH)
set(CONTENT_LENGTH, NumberFormatter::format(length));
else
erase(CONTENT_LENGTH);
}
Poco::Int64 HTTPMessage::getContentLength64() const
{
const std::string& contentLength = get(CONTENT_LENGTH, EMPTY);
if (!contentLength.empty())
{
if (sizeof(std::streamsize) == sizeof(Poco::Int64))
return static_cast<std::streamsize>(NumberParser::parse64(contentLength));
else
return static_cast<std::streamsize>(NumberParser::parse(contentLength));
return NumberParser::parse64(contentLength);
}
else return UNKNOWN_CONTENT_LENGTH;
}
#endif // defined(POCO_HAVE_INT64)
void HTTPMessage::setTransferEncoding(const std::string& transferEncoding)
{
if (icompare(transferEncoding, IDENTITY_TRANSFER_ENCODING) == 0)
if (icompare(transferEncoding, IDENTITY_TRANSFER_ENCODING) == 0)
erase(TRANSFER_ENCODING);
else
set(TRANSFER_ENCODING, transferEncoding);

View File

@@ -39,6 +39,7 @@
#include "Poco/Net/NameValueCollection.h"
#include "Poco/NumberFormatter.h"
#include "Poco/Ascii.h"
#include "Poco/String.h"
using Poco::NumberFormatter;
@@ -150,11 +151,11 @@ void HTTPRequest::setCookies(const NameValueCollection& cookies)
void HTTPRequest::getCookies(NameValueCollection& cookies) const
{
NameValueCollection::ConstIterator it = find(COOKIE);
while (it != end() && it->first == COOKIE)
{
splitParameters(it->second.begin(), it->second.end(), cookies);
++it;
NameValueCollection::ConstIterator it = find(COOKIE);
while (it != end() && Poco::icompare(it->first, COOKIE) == 0)
{
splitParameters(it->second.begin(), it->second.end(), cookies);
++it;
}
}

View File

@@ -43,6 +43,7 @@
#include "Poco/DateTimeFormat.h"
#include "Poco/DateTimeParser.h"
#include "Poco/Ascii.h"
#include "Poco/String.h"
using Poco::DateTime;
@@ -198,12 +199,12 @@ void HTTPResponse::addCookie(const HTTPCookie& cookie)
void HTTPResponse::getCookies(std::vector<HTTPCookie>& cookies) const
{
cookies.clear();
NameValueCollection::ConstIterator it = find(SET_COOKIE);
while (it != end() && it->first == SET_COOKIE)
{
NameValueCollection nvc;
splitParameters(it->second.begin(), it->second.end(), nvc);
cookies.clear();
NameValueCollection::ConstIterator it = find(SET_COOKIE);
while (it != end() && Poco::icompare(it->first, SET_COOKIE) == 0)
{
NameValueCollection nvc;
splitParameters(it->second.begin(), it->second.end(), nvc);
cookies.push_back(HTTPCookie(nvc));
++it;
}

View File

@@ -116,12 +116,16 @@ void HTTPServerResponseImpl::sendFile(const std::string& path, const std::string
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);
Timestamp dateTime = f.getLastModified();
File::FileSize length = f.getSize();
set("Last-Modified", DateTimeFormatter::format(dateTime, DateTimeFormat::HTTP_FORMAT));
#if defined(POCO_HAVE_INT64)
setContentLength64(length);
#else
setContentLength(static_cast<int>(length));
#endif
setContentType(mediaType);
setChunkedTransferEncoding(false);
Poco::FileInputStream istr(path);
if (istr.good())

View File

@@ -1,13 +1,13 @@
//
// HTTPStreamFactory.cpp
//
// $Id: //poco/svn/Net/src/HTTPStreamFactory.cpp#3 $
// $Id: //poco/1.4/Net/src/HTTPStreamFactory.cpp#2 $
//
// Library: Net
// Package: HTTP
// Module: HTTPStreamFactory
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// Copyright (c) 2005-2012, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
@@ -39,10 +39,13 @@
#include "Poco/Net/HTTPIOStream.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPCredentials.h"
#include "Poco/Net/NetException.h"
#include "Poco/URI.h"
#include "Poco/URIStreamOpener.h"
#include "Poco/UnbufferedStreamBuf.h"
#include "Poco/NullStream.h"
#include "Poco/StreamCopier.h"
using Poco::URIStreamFactory;
@@ -86,39 +89,57 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
{
poco_assert (uri.getScheme() == "http");
URI resolvedURI(uri);
URI proxyUri;
HTTPClientSession* pSession = 0;
bool retry = false;
URI resolvedURI(uri);
URI proxyUri;
HTTPClientSession* pSession = 0;
HTTPResponse res;
bool retry = false;
bool authorize = false;
std::string username;
std::string password;
try
{
do
{
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
if (proxyUri.empty())
pSession->setProxy(_proxyHost, _proxyPort);
else
pSession->setProxy(proxyUri.getHost(), proxyUri.getPort());
pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
std::string path = resolvedURI.getPathAndQuery();
if (path.empty()) path = "/";
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
pSession->sendRequest(req);
HTTPResponse res;
std::istream& rs = pSession->receiveResponse(res);
bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY ||
res.getStatus() == HTTPResponse::HTTP_FOUND ||
try
{
do
{
if (!pSession)
{
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
if (proxyUri.empty())
pSession->setProxy(_proxyHost, _proxyPort);
else
pSession->setProxy(proxyUri.getHost(), proxyUri.getPort());
pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
}
std::string path = resolvedURI.getPathAndQuery();
if (path.empty()) path = "/";
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
if (authorize)
{
HTTPCredentials::extractCredentials(uri, username, password);
HTTPCredentials cred(username, password);
cred.authenticate(req, res);
}
pSession->sendRequest(req);
std::istream& rs = pSession->receiveResponse(res);
bool moved = (res.getStatus() == HTTPResponse::HTTP_MOVED_PERMANENTLY ||
res.getStatus() == HTTPResponse::HTTP_FOUND ||
res.getStatus() == HTTPResponse::HTTP_SEE_OTHER ||
res.getStatus() == HTTPResponse::HTTP_TEMPORARY_REDIRECT);
if (moved)
{
resolvedURI.resolve(res.get("Location"));
throw URIRedirection(resolvedURI.toString());
}
else if (res.getStatus() == HTTPResponse::HTTP_OK)
if (moved)
{
resolvedURI.resolve(res.get("Location"));
if (!username.empty())
{
resolvedURI.setUserInfo(username + ":" + password);
}
throw URIRedirection(resolvedURI.toString());
}
else if (res.getStatus() == HTTPResponse::HTTP_OK)
{
return new HTTPResponseStream(rs, pSession);
}
@@ -130,16 +151,20 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
// single request via the proxy. 305 responses MUST only be generated by origin servers.
// only use for one single request!
proxyUri.resolve(res.get("Location"));
delete pSession; pSession = 0;
retry = true; // only allow useproxy once
}
else
{
throw HTTPException(res.getReason(), uri.toString());
}
}
while(retry);
throw HTTPException("Too many redirects", uri.toString());
delete pSession; pSession = 0;
retry = true; // only allow useproxy once
}
else if (res.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED && !authorize)
{
authorize = true;
retry = true;
Poco::NullOutputStream null;
Poco::StreamCopier::copyStream(rs, null);
}
else throw HTTPException(res.getReason(), uri.toString());
}
while (retry);
throw HTTPException("Too many redirects", uri.toString());
}
catch (...)
{

View File

@@ -74,7 +74,7 @@ HostEntry::HostEntry(struct hostent* entry)
}
#if defined(POCO_HAVE_IPv6)
#if defined(POCO_HAVE_IPv6) || defined(POCO_HAVE_ADDRINFO)
HostEntry::HostEntry(struct addrinfo* ainfo)
@@ -91,15 +91,17 @@ HostEntry::HostEntry(struct addrinfo* ainfo)
{
switch (ai->ai_addr->sa_family)
{
case AF_INET:
case AF_INET:
_addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in*>(ai->ai_addr)->sin_addr, sizeof(in_addr)));
break;
#if defined(POCO_HAVE_IPv6)
case AF_INET6:
_addresses.push_back(IPAddress(&reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_addr, sizeof(in6_addr), reinterpret_cast<struct sockaddr_in6*>(ai->ai_addr)->sin6_scope_id));
break;
#endif
}
}
}
}
}
@@ -110,9 +112,9 @@ HostEntry::HostEntry(struct addrinfo* ainfo)
HostEntry::HostEntry(const std::string& name, const IPAddress& addr):
_name(name)
_name(name)
{
_addresses.push_back(addr);
_addresses.push_back(addr);
}

View File

@@ -1,7 +1,7 @@
//
// MessageHeader.cpp
//
// $Id: //poco/1.4/Net/src/MessageHeader.cpp#3 $
// $Id: //poco/1.4/Net/src/MessageHeader.cpp#4 $
//
// Library: Net
// Package: Messages
@@ -44,13 +44,15 @@ namespace Poco {
namespace Net {
MessageHeader::MessageHeader()
MessageHeader::MessageHeader():
_fieldLimit(DFL_FIELD_LIMIT)
{
}
MessageHeader::MessageHeader(const MessageHeader& messageHeader):
NameValueCollection(messageHeader)
NameValueCollection(messageHeader),
_fieldLimit(DFL_FIELD_LIMIT)
{
}
@@ -85,14 +87,17 @@ void MessageHeader::read(std::istream& istr)
std::string name;
std::string value;
name.reserve(32);
value.reserve(64);
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 = buf.sbumpc(); }
name.reserve(32);
value.reserve(64);
int ch = buf.sbumpc();
int fields = 0;
while (ch != eof && ch != '\r' && ch != '\n')
{
if (_fieldLimit > 0 && fields == _fieldLimit)
throw MessageException("Too many header fields");
name.clear();
value.clear();
while (ch != eof && ch != ':' && ch != '\n' && name.length() < MAX_NAME_LENGTH) { name += ch; ch = buf.sbumpc(); }
if (ch == '\n') { ch = buf.sbumpc(); continue; } // ignore invalid header lines
if (ch != ':') throw MessageException("Field name too long/no colon found");
if (ch != eof) ch = buf.sbumpc(); // ':'
@@ -111,17 +116,32 @@ void MessageHeader::read(std::istream& istr)
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);
}
Poco::trimRightInPlace(value);
add(name, value);
++fields;
}
istr.putback(ch);
}
int MessageHeader::getFieldLimit() const
{
return _fieldLimit;
}
void MessageHeader::setFieldLimit(int limit)
{
poco_assert (limit >= 0);
_fieldLimit = limit;
}
void MessageHeader::splitElements(const std::string& s, std::vector<std::string>& elements, bool ignoreEmpty)
{
elements.clear();
elements.clear();
std::string::const_iterator it = s.begin();
std::string::const_iterator end = s.end();
std::string elem;

View File

@@ -66,6 +66,7 @@ POCO_IMPLEMENT_EXCEPTION(FTPException, NetException, "FTP Exception")
POCO_IMPLEMENT_EXCEPTION(SMTPException, NetException, "SMTP Exception")
POCO_IMPLEMENT_EXCEPTION(POP3Exception, NetException, "POP3 Exception")
POCO_IMPLEMENT_EXCEPTION(ICMPException, NetException, "ICMP Exception")
POCO_IMPLEMENT_EXCEPTION(HTMLFormException, NetException, "HTML Form Exception")
} } // namespace Poco::Net

View File

@@ -1,7 +1,7 @@
//
// NetworkInterface.cpp
//
// $Id: //poco/1.4/Net/src/NetworkInterface.cpp#3 $
// $Id: //poco/1.4/Net/src/NetworkInterface.cpp#9 $
//
// Library: Net
// Package: Sockets
@@ -292,42 +292,35 @@ bool NetworkInterface::supportsIPv6() const
NetworkInterface NetworkInterface::forName(const std::string& name, bool requireIPv6)
{
#if defined(_WIN32)
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->name() == name && ((requireIPv6 && it->supportsIPv6()) || !requireIPv6))
return *it;
}
throw InterfaceNotFoundException(name);
#else
FastMutex::ScopedLock lock(_mutex);
struct ifreq ifr;
std::strncpy(ifr.ifr_name, name.c_str(), IFNAMSIZ);
DatagramSocket ds(requireIPv6 ? IPAddress::IPv6 : IPAddress::IPv4);
ds.impl()->ioctl(SIOCGIFADDR, &ifr);
IPAddress addr;
#if defined(POCO_HAVE_IPv6)
if (ifr.ifr_addr.sa_family == AF_INET)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr));
else if (ifr.ifr_addr.sa_family == AF_INET6)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr.ifr_addr)->sin6_addr, sizeof(struct in6_addr));
else
throw InterfaceNotFoundException(addr.toString(), "interface has no IP address");
int index = if_nametoindex(name.c_str());
#else
if (ifr.ifr_addr.sa_family == AF_INET)
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr.ifr_addr)->sin_addr, sizeof(struct in_addr));
else
throw InterfaceNotFoundException(addr.toString(), "interface has no IP address");
int index = 0;
#endif
return NetworkInterface(name, name, addr, index);
#endif
return *it;
}
throw InterfaceNotFoundException(name);
}
NetworkInterface NetworkInterface::forName(const std::string& name, IPVersion ipVersion)
{
NetworkInterfaceList ifs = list();
for (NetworkInterfaceList::const_iterator it = ifs.begin(); it != ifs.end(); ++it)
{
if (it->name() == name)
{
if (ipVersion == IPv4_ONLY && it->supportsIPv4())
return *it;
else if (ipVersion == IPv6_ONLY && it->supportsIPv6())
return *it;
else if (ipVersion == IPv4_OR_IPv6)
return *it;
}
}
throw InterfaceNotFoundException(name);
}
NetworkInterface NetworkInterface::forAddress(const IPAddress& addr)
{
NetworkInterfaceList ifs = list();
@@ -374,10 +367,45 @@ NetworkInterface NetworkInterface::forIndex(int i)
namespace Poco {
namespace Net {
#if defined(POCO_HAVE_IPv6)
IPAddress subnetMaskForInterface(const std::string& name, bool isLoopback)
{
if (isLoopback)
{
return IPAddress::parse("255.0.0.0");
}
else
{
std::string subKey("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces\\");
subKey += name;
std::wstring usubKey;
Poco::UnicodeConverter::toUTF16(subKey, usubKey);
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, usubKey.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
return IPAddress();
wchar_t unetmask[16];
DWORD size = sizeof(unetmask);
if (RegQueryValueExW(hKey, L"DhcpSubnetMask", NULL, NULL, (LPBYTE) &unetmask, &size) != ERROR_SUCCESS)
{
if (RegQueryValueExW(hKey, L"SubnetMask", NULL, NULL, (LPBYTE) &unetmask, &size) != ERROR_SUCCESS)
{
RegCloseKey(hKey);
return IPAddress();
}
}
RegCloseKey(hKey);
std::string netmask;
Poco::UnicodeConverter::toUTF8(unetmask, netmask);
return IPAddress::parse(netmask);
}
}
#endif // POCO_HAVE_IPv6
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
DWORD rc;
@@ -403,48 +431,62 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
if (GetAdaptersAddresses(AF_UNSPEC, 0, 0, pAdapterAddresses, &addrLen) == NO_ERROR)
{
pAddress = pAdapterAddresses;
while (pAddress)
{
if (pAddress->FirstUnicastAddress)
{
IPAddress addr;
switch (pAddress->FirstUnicastAddress->Address.lpSockaddr->sa_family)
{
case AF_INET:
addr = IPAddress(&reinterpret_cast<struct sockaddr_in*>(pAddress->FirstUnicastAddress->Address.lpSockaddr)->sin_addr, sizeof(in_addr));
break;
case AF_INET6:
addr = IPAddress(&reinterpret_cast<struct sockaddr_in6*>(pAddress->FirstUnicastAddress->Address.lpSockaddr)->sin6_addr, sizeof(in6_addr));
break;
}
std::string name(pAddress->AdapterName);
std::string displayName;
pAddress = pAdapterAddresses;
while (pAddress)
{
if (pAddress->OperStatus == IfOperStatusUp)
{
PIP_ADAPTER_UNICAST_ADDRESS pUniAddr = pAddress->FirstUnicastAddress;
while (pUniAddr)
{
std::string name(pAddress->AdapterName);
std::string displayName;
#ifdef POCO_WIN32_UTF8
Poco::UnicodeConverter::toUTF8(pAddress->Description, displayName);
Poco::UnicodeConverter::toUTF8(pAddress->FriendlyName, displayName);
#else
char displayNameBuffer[1024];
int rc = WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR, pAddress->Description, -1, displayNameBuffer, sizeof(displayNameBuffer), NULL, NULL);
if (rc) displayName = displayNameBuffer;
char displayNameBuffer[1024];
int rc = WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR, pAddress->FriendlyName, -1, displayNameBuffer, sizeof(displayNameBuffer), NULL, NULL);
if (rc) displayName = displayNameBuffer;
#endif
result.push_back(NetworkInterface(name, displayName, addr, pAddress->Ipv6IfIndex));
pAddress = pAddress->Next;
}
}
}
else throw NetException("cannot get network adapter list");
}
catch (Poco::Exception&)
IPAddress address;
IPAddress subnetMask;
IPAddress broadcastAddress;
switch (pUniAddr->Address.lpSockaddr->sa_family)
{
case AF_INET:
address = IPAddress(&reinterpret_cast<struct sockaddr_in*>(pUniAddr->Address.lpSockaddr)->sin_addr, sizeof(in_addr));
subnetMask = subnetMaskForInterface(name, address.isLoopback());
if (!address.isLoopback())
{
broadcastAddress = address;
broadcastAddress.mask(subnetMask, IPAddress::broadcast());
}
result.push_back(NetworkInterface(name, displayName, address, subnetMask, broadcastAddress));
break;
case AF_INET6:
address = IPAddress(&reinterpret_cast<struct sockaddr_in6*>(pUniAddr->Address.lpSockaddr)->sin6_addr, sizeof(in6_addr), reinterpret_cast<struct sockaddr_in6*>(pUniAddr->Address.lpSockaddr)->sin6_scope_id);
result.push_back(NetworkInterface(name, displayName, address, pAddress->Ipv6IfIndex));
break;
}
pUniAddr = pUniAddr->Next;
}
}
pAddress = pAddress->Next;
}
}
else throw NetException("cannot get network adapter list");
}
catch (Poco::Exception&)
{
delete [] reinterpret_cast<char*>(pAdapterAddresses);
throw;
}
delete [] reinterpret_cast<char*>(pAdapterAddresses);
return result;
#endif
}
delete [] reinterpret_cast<char*>(pAdapterAddresses);
return result;
#endif // POCO_HAVE_IPv6
// Add IPv4 loopback interface (not returned by GetAdaptersInfo)
result.push_back(NetworkInterface("Loopback", "Loopback Interface", IPAddress("127.0.0.1"), IPAddress("255.0.0.0"), IPAddress(), -1));
// Add IPv4 loopback interface (not returned by GetAdaptersInfo)
result.push_back(NetworkInterface("Loopback", "Loopback Interface", IPAddress("127.0.0.1"), IPAddress("255.0.0.0"), IPAddress(), -1));
// On Windows 2000 we use GetAdaptersInfo.
PIP_ADAPTER_INFO pAdapterInfo;
PIP_ADAPTER_INFO pInfo = 0;
@@ -471,13 +513,13 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
IPAddress address(std::string(pInfo->IpAddressList.IpAddress.String));
if (!address.isWildcard()) // only return interfaces that have an address assigned.
{
IPAddress subnetMask(std::string(pInfo->IpAddressList.IpMask.String));
IPAddress broadcastAddress(address);
broadcastAddress.mask(subnetMask, IPAddress("255.255.255.255"));
std::string name(pInfo->AdapterName);
std::string displayName(pInfo->Description);
result.push_back(NetworkInterface(name, displayName, address, subnetMask, broadcastAddress));
{
IPAddress subnetMask(std::string(pInfo->IpAddressList.IpMask.String));
IPAddress broadcastAddress(address);
broadcastAddress.mask(subnetMask, IPAddress::broadcast());
std::string name(pInfo->AdapterName);
std::string displayName(pInfo->Description);
result.push_back(NetworkInterface(name, displayName, address, subnetMask, broadcastAddress));
}
pInfo = pInfo->Next;
}
@@ -498,6 +540,59 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
} } // namespace Poco::Net
#elif defined(POCO_VXWORKS)
//
// VxWorks
//
namespace Poco {
namespace Net {
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
FastMutex::ScopedLock lock(_mutex);
NetworkInterfaceList result;
int ifIndex = 1;
char ifName[32];
char ifAddr[INET_ADDR_LEN];
for (;;)
{
if (ifIndexToIfName(ifIndex, ifName) == OK)
{
std::string name(ifName);
IPAddress addr;
IPAddress mask;
IPAddress bcst;
if (ifAddrGet(ifName, ifAddr) == OK)
{
addr = IPAddress(std::string(ifAddr));
}
int ifMask;
if (ifMaskGet(ifName, &ifMask) == OK)
{
mask = IPAddress(&ifMask, sizeof(ifMask));
}
if (ifBroadcastGet(ifName, ifAddr) == OK)
{
bcst = IPAddress(std::string(ifAddr));
}
result.push_back(NetworkInterface(name, name, addr, mask, bcst));
ifIndex++;
}
else break;
}
return result;
}
} } // namespace Poco::Net
#elif defined(POCO_OS_FAMILY_BSD) || POCO_OS == POCO_OS_QNX
//
// BSD variants
@@ -536,14 +631,15 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
result.push_back(NetworkInterface(name, name, addr, subnetMask, broadcastAddr));
}
#if defined(POCO_HAVE_IPv6)
else if (ifap->ifa_addr->sa_family == AF_INET6)
{
IPAddress addr(&reinterpret_cast<struct sockaddr_in6*>(ifap->ifa_addr)->sin6_addr, sizeof(struct in6_addr));
std::string name(ifap->ifa_name);
result.push_back(NetworkInterface(name, name, addr, if_nametoindex(ifap->ifa_name)));
}
else if (ifap->ifa_addr->sa_family == AF_INET6)
{
Poco::UInt32 ifIndex = if_nametoindex(ifap->ifa_name);
IPAddress addr(&reinterpret_cast<struct sockaddr_in6*>(ifap->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
std::string name(ifap->ifa_name);
result.push_back(NetworkInterface(name, name, addr, ifIndex));
}
#endif
}
}
}
freeifaddrs(ifaphead);
return result;
@@ -557,6 +653,68 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
//
// Linux
//
#if defined(POCO_HAVE_IPv6)
#include <sys/types.h>
#include <ifaddrs.h>
namespace Poco {
namespace Net {
NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
NetworkInterfaceList result;
struct ifaddrs* ifaces = 0;
struct ifaddrs* currIface = 0;
if (getifaddrs(&ifaces) < 0)
throw NetException("cannot get network adapter list");
try
{
for (currIface = ifaces; currIface != 0; currIface = currIface->ifa_next)
{
IPAddress addr;
bool haveAddr = false;
int ifIndex(-1);
switch (currIface->ifa_addr->sa_family)
{
case AF_INET6:
ifIndex = if_nametoindex(currIface->ifa_name);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(currIface->ifa_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
haveAddr = true;
break;
case AF_INET:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(currIface->ifa_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break;
default:
break;
}
if (haveAddr)
{
std::string name(currIface->ifa_name);
result.push_back(NetworkInterface(name, name, addr, ifIndex));
}
}
}
catch (...)
{
}
if (ifaces) freeifaddrs(ifaces);
return result;
}
} } // namespace Poco::Net
#else // !POCO_HAVE_IPv6
namespace Poco {
@@ -599,32 +757,22 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
{
const struct ifreq* ifr = reinterpret_cast<const struct ifreq*>(ptr);
IPAddress addr;
bool haveAddr = false;
switch (ifr->ifr_addr.sa_family)
{
#if defined(POCO_HAVE_IPv6)
case AF_INET6:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr));
haveAddr = true;
break;
#endif
case AF_INET:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
bool haveAddr = false;
switch (ifr->ifr_addr.sa_family)
{
case AF_INET:
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in*>(&ifr->ifr_addr)->sin_addr, sizeof(struct in_addr));
haveAddr = true;
break;
default:
break;
}
if (haveAddr)
{
#if defined(POCO_HAVE_IPv6)
int index = if_nametoindex(ifr->ifr_name);
#else
int index = -1;
#endif
std::string name(ifr->ifr_name);
result.push_back(NetworkInterface(name, name, addr, index));
}
}
if (haveAddr)
{
int index = -1;
std::string name(ifr->ifr_name);
result.push_back(NetworkInterface(name, name, addr, index));
}
ptr += sizeof(struct ifreq);
}
}
@@ -641,6 +789,9 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
} } // namespace Poco::Net
#endif // POCO_HAVE_IPv6
#else
//
// Non-BSD Unix variants
@@ -692,16 +843,18 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
#else
len = sizeof(struct sockaddr);
#endif
IPAddress addr;
bool haveAddr = false;
switch (ifr->ifr_addr.sa_family)
{
IPAddress addr;
bool haveAddr = false;
int ifIndex(-1);
switch (ifr->ifr_addr.sa_family)
{
#if defined(POCO_HAVE_IPv6)
case AF_INET6:
if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr));
haveAddr = true;
break;
case AF_INET6:
ifIndex = if_nametoindex(ifr->ifr_name);
if (len < sizeof(struct sockaddr_in6)) len = sizeof(struct sockaddr_in6);
addr = IPAddress(&reinterpret_cast<const struct sockaddr_in6*>(&ifr->ifr_addr)->sin6_addr, sizeof(struct in6_addr), ifIndex);
haveAddr = true;
break;
#endif
case AF_INET:
if (len < sizeof(struct sockaddr_in)) len = sizeof(struct sockaddr_in);
@@ -710,19 +863,14 @@ NetworkInterface::NetworkInterfaceList NetworkInterface::list()
break;
default:
break;
}
if (haveAddr)
{
#if defined(POCO_HAVE_IPv6)
int index = if_nametoindex(ifr->ifr_name);
#else
int index = -1;
#endif
std::string name(ifr->ifr_name);
result.push_back(NetworkInterface(name, name, addr, index));
}
len += sizeof(ifr->ifr_name);
ptr += len;
}
if (haveAddr)
{
std::string name(ifr->ifr_name);
result.push_back(NetworkInterface(name, name, addr, ifIndex));
}
len += sizeof(ifr->ifr_name);
ptr += len;
}
}
catch (...)