Added Xerces-C++ 3.1.2
This commit is contained in:
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id: UnixHTTPURLInputStream.cpp 936316 2010-04-21 14:19:58Z borisk $
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#if HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#if HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
#if HAVE_ARPA_INET_H
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
#if HAVE_NETDB_H
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include <xercesc/util/NetAccessors/Socket/UnixHTTPURLInputStream.hpp>
|
||||
#include <xercesc/util/XMLString.hpp>
|
||||
#include <xercesc/util/XMLExceptMsgs.hpp>
|
||||
#include <xercesc/util/Janitor.hpp>
|
||||
|
||||
XERCES_CPP_NAMESPACE_BEGIN
|
||||
|
||||
class SocketJanitor
|
||||
{
|
||||
public:
|
||||
// -----------------------------------------------------------------------
|
||||
// Constructors and Destructor
|
||||
// -----------------------------------------------------------------------
|
||||
SocketJanitor(int* toDelete) : fData(toDelete) {}
|
||||
~SocketJanitor() { reset(); }
|
||||
|
||||
int* get() const { return fData; }
|
||||
int* release() { int* p = fData; fData = 0; return p; }
|
||||
|
||||
void reset(int* p = 0)
|
||||
{
|
||||
if(fData) {
|
||||
shutdown(*fData, 2);
|
||||
close(*fData);
|
||||
}
|
||||
fData = p;
|
||||
}
|
||||
bool isDataNull() { return (fData == 0); }
|
||||
|
||||
private :
|
||||
// -----------------------------------------------------------------------
|
||||
// Unimplemented constructors and operators
|
||||
// -----------------------------------------------------------------------
|
||||
SocketJanitor();
|
||||
SocketJanitor(const SocketJanitor&);
|
||||
SocketJanitor& operator=(const SocketJanitor&);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Private data members
|
||||
//
|
||||
// fData
|
||||
// This is the pointer to the socket that must be closed when
|
||||
// this object is destroyed.
|
||||
// -----------------------------------------------------------------------
|
||||
int* fData;
|
||||
};
|
||||
|
||||
UnixHTTPURLInputStream::UnixHTTPURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo/*=0*/)
|
||||
: BinHTTPInputStreamCommon(urlSource.getMemoryManager()),
|
||||
fSocket(0)
|
||||
{
|
||||
//
|
||||
// Convert the hostName to the platform's code page for gethostbyname and
|
||||
// inet_addr functions.
|
||||
//
|
||||
|
||||
MemoryManager *memoryManager = urlSource.getMemoryManager();
|
||||
|
||||
const XMLCh* hostName = urlSource.getHost();
|
||||
|
||||
if (hostName == 0)
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::File_CouldNotOpenFile,
|
||||
urlSource.getURLText(),
|
||||
memoryManager);
|
||||
|
||||
char* hostNameAsCharStar = XMLString::transcode(hostName, memoryManager);
|
||||
ArrayJanitor<char> janHostNameAsCharStar(hostNameAsCharStar, memoryManager);
|
||||
|
||||
XMLURL url(urlSource);
|
||||
int redirectCount = 0;
|
||||
SocketJanitor janSock(0);
|
||||
|
||||
do {
|
||||
//
|
||||
// Set up a socket.
|
||||
//
|
||||
|
||||
#if HAVE_GETADDRINFO
|
||||
struct addrinfo hints, *res, *ai;
|
||||
|
||||
CharBuffer portBuffer(10, memoryManager);
|
||||
portBuffer.appendDecimalNumber(url.getPortNum());
|
||||
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_family = PF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
int n = getaddrinfo(hostNameAsCharStar,portBuffer.getRawBuffer(),&hints, &res);
|
||||
if(n != 0)
|
||||
{
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
n = getaddrinfo(hostNameAsCharStar,portBuffer.getRawBuffer(),&hints, &res);
|
||||
if(n != 0)
|
||||
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager);
|
||||
}
|
||||
janSock.reset();
|
||||
for (ai = res; ai != NULL; ai = ai->ai_next) {
|
||||
// Open a socket with the correct address family for this address.
|
||||
fSocket = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||
if (fSocket < 0)
|
||||
continue;
|
||||
janSock.reset(&fSocket);
|
||||
if (connect(fSocket, ai->ai_addr, ai->ai_addrlen) < 0)
|
||||
{
|
||||
freeaddrinfo(res);
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager);
|
||||
}
|
||||
break;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
if (fSocket < 0)
|
||||
{
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager);
|
||||
}
|
||||
#else
|
||||
struct hostent *hostEntPtr = 0;
|
||||
struct sockaddr_in sa;
|
||||
|
||||
// Use the hostName in the local code page ....
|
||||
if((hostEntPtr = gethostbyname(hostNameAsCharStar)) == NULL)
|
||||
{
|
||||
unsigned long numAddress = inet_addr(hostNameAsCharStar);
|
||||
if ((hostEntPtr =
|
||||
gethostbyaddr((char *) &numAddress,
|
||||
sizeof(unsigned long), AF_INET)) == NULL)
|
||||
{
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager);
|
||||
}
|
||||
}
|
||||
|
||||
memset(&sa, '\0', sizeof(sockaddr_in)); // iSeries fix ??
|
||||
memcpy((void *) &sa.sin_addr,
|
||||
(const void *) hostEntPtr->h_addr, hostEntPtr->h_length);
|
||||
sa.sin_family = hostEntPtr->h_addrtype;
|
||||
sa.sin_port = htons((unsigned short)url.getPortNum());
|
||||
|
||||
janSock.reset();
|
||||
fSocket = socket(hostEntPtr->h_addrtype, SOCK_STREAM, 0);
|
||||
if(fSocket < 0)
|
||||
{
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager);
|
||||
}
|
||||
janSock.reset(&fSocket);
|
||||
|
||||
if(connect(fSocket, (struct sockaddr *) &sa, sizeof(sa)) < 0)
|
||||
{
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager);
|
||||
}
|
||||
#endif
|
||||
|
||||
int status = sendRequest(url, httpInfo);
|
||||
|
||||
if(status == 200) {
|
||||
// HTTP 200 OK response means we're done.
|
||||
break;
|
||||
}
|
||||
// a 3xx response means there was an HTTP redirect
|
||||
else if(status >= 300 && status <= 307) {
|
||||
redirectCount++;
|
||||
|
||||
XMLCh *newURLString = findHeader("Location");
|
||||
ArrayJanitor<XMLCh> janNewURLString(newURLString, memoryManager);
|
||||
|
||||
if(newURLString == 0 || *newURLString == 0) {
|
||||
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, url.getURLText(), memoryManager);
|
||||
}
|
||||
|
||||
XMLURL newURL(memoryManager);
|
||||
newURL.setURL(url, newURLString);
|
||||
if(newURL.getProtocol() != XMLURL::HTTP) {
|
||||
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, newURL.getURLText(), memoryManager);
|
||||
}
|
||||
|
||||
url = newURL;
|
||||
hostName = newURL.getHost();
|
||||
|
||||
if (hostName == 0)
|
||||
ThrowXMLwithMemMgr1(NetAccessorException,
|
||||
XMLExcepts::File_CouldNotOpenFile,
|
||||
newURL.getURLText(),
|
||||
memoryManager);
|
||||
|
||||
janHostNameAsCharStar.release();
|
||||
hostNameAsCharStar = XMLString::transcode(hostName, memoryManager);
|
||||
janHostNameAsCharStar.reset(hostNameAsCharStar, memoryManager);
|
||||
}
|
||||
else {
|
||||
// Most likely a 404 Not Found error.
|
||||
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, url.getURLText(), memoryManager);
|
||||
}
|
||||
} while(redirectCount < 6);
|
||||
|
||||
janSock.release();
|
||||
}
|
||||
|
||||
|
||||
UnixHTTPURLInputStream::~UnixHTTPURLInputStream()
|
||||
{
|
||||
shutdown(fSocket, 2);
|
||||
close(fSocket);
|
||||
}
|
||||
|
||||
bool UnixHTTPURLInputStream::send(const char *buf, XMLSize_t len)
|
||||
{
|
||||
XMLSize_t done = 0;
|
||||
int ret;
|
||||
|
||||
while(done < len) {
|
||||
ret = ::send(fSocket, buf + done, len - done, 0);
|
||||
if(ret == -1) return false;
|
||||
done += ret;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int UnixHTTPURLInputStream::receive(char *buf, XMLSize_t len)
|
||||
{
|
||||
return ::recv(fSocket, buf, len, 0);
|
||||
}
|
||||
|
||||
XERCES_CPP_NAMESPACE_END
|
||||
Reference in New Issue
Block a user