mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-23 16:48:06 +02:00
backport changes from 1.4.3 branch
This commit is contained in:
212
Net/src/DNS.cpp
212
Net/src/DNS.cpp
@@ -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
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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())
|
||||
|
@@ -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 (...)
|
||||
{
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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 (...)
|
||||
|
Reference in New Issue
Block a user