Added Xerces-C++ 3.1.2

This commit is contained in:
sippeangelo
2015-12-01 10:23:50 +01:00
parent 65d3f3bc31
commit 1b478d3159
815 changed files with 262638 additions and 0 deletions
@@ -0,0 +1,301 @@
/*
* 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: BinFileInputStream.cpp 553903 2007-07-06 14:43:42Z amassari $
*/
// ---------------------------------------------------------------------------
// Includes
// ---------------------------------------------------------------------------
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <xercesc/util/NetAccessors/BinHTTPInputStreamCommon.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/TransService.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/Base64.hpp>
XERCES_CPP_NAMESPACE_BEGIN
BinHTTPInputStreamCommon::BinHTTPInputStreamCommon(MemoryManager *manager)
: fBytesProcessed(0)
, fBuffer(1023, manager)
, fContentType(0)
, fMemoryManager(manager)
{
}
BinHTTPInputStreamCommon::~BinHTTPInputStreamCommon()
{
if(fContentType) fMemoryManager->deallocate(fContentType);
}
static const char *CRLF = "\r\n";
void BinHTTPInputStreamCommon::createHTTPRequest(const XMLURL &urlSource, const XMLNetHTTPInfo *httpInfo, CharBuffer &buffer)
{
static const char *GET = "GET ";
static const char *PUT = "PUT ";
static const char *POST = "POST ";
static const char *HTTP10 = " HTTP/1.0\r\n";
static const char *HOST = "Host: ";
static const char *AUTHORIZATION = "Authorization: Basic ";
static const char *COLON = ":";
XMLTransService::Codes failReason;
const XMLSize_t blockSize = 2048;
XMLTranscoder* trans = XMLPlatformUtils::fgTransService->makeNewTranscoderFor("ISO8859-1", failReason, blockSize, fMemoryManager);
Janitor<XMLTranscoder> janTrans(trans);
TranscodeToStr hostName(urlSource.getHost(), trans, fMemoryManager);
TranscodeToStr path(urlSource.getPath(), trans, fMemoryManager);
TranscodeToStr fragment(urlSource.getFragment(), trans, fMemoryManager);
TranscodeToStr query(urlSource.getQuery(), trans, fMemoryManager);
// Build up the http GET command to send to the server.
// To do: We should really support http 1.1. This implementation
// is weak.
if(httpInfo) {
switch(httpInfo->fHTTPMethod) {
case XMLNetHTTPInfo::GET: buffer.append(GET); break;
case XMLNetHTTPInfo::PUT: buffer.append(PUT); break;
case XMLNetHTTPInfo::POST: buffer.append(POST); break;
}
}
else {
buffer.append(GET);
}
if(path.str() != 0) {
buffer.append((char*)path.str());
}
else {
buffer.append("/");
}
if(query.str() != 0) {
buffer.append("?");
buffer.append((char*)query.str());
}
if(fragment.str() != 0) {
buffer.append((char*)fragment.str());
}
buffer.append(HTTP10);
buffer.append(HOST);
buffer.append((char*)hostName.str());
if(urlSource.getPortNum() != 80)
{
buffer.append(COLON);
buffer.appendDecimalNumber(urlSource.getPortNum());
}
buffer.append(CRLF);
const XMLCh *username = urlSource.getUser();
const XMLCh *password = urlSource.getPassword();
if(username && password) {
XMLBuffer userPassBuf(256, fMemoryManager);
userPassBuf.append(username);
userPassBuf.append(chColon);
userPassBuf.append(password);
TranscodeToStr userPass(userPassBuf.getRawBuffer(), trans, fMemoryManager);
XMLSize_t len;
XMLByte* encodedData = Base64::encode(userPass.str(), userPass.length(), &len, fMemoryManager);
ArrayJanitor<XMLByte> janBuf2(encodedData, fMemoryManager);
if(encodedData) {
// HTTP doesn't want the 0x0A separating the data in chunks of 76 chars per line
XMLByte* authData = (XMLByte*)fMemoryManager->allocate((len+1)*sizeof(XMLByte));
ArrayJanitor<XMLByte> janBuf(authData, fMemoryManager);
XMLByte *cursor = authData;
for(XMLSize_t i = 0; i < len; ++i)
if(encodedData[i] != chLF)
*cursor++ = encodedData[i];
*cursor++ = 0;
buffer.append(AUTHORIZATION);
buffer.append((char*)authData);
buffer.append(CRLF);
}
}
if(httpInfo && httpInfo->fHeaders)
buffer.append(httpInfo->fHeaders, httpInfo->fHeadersLen);
buffer.append(CRLF);
}
XMLCh *BinHTTPInputStreamCommon::findHeader(const char *name)
{
XMLSize_t len = strlen(name);
char *p = strstr(fBuffer.getRawBuffer(), name);
while(p != 0) {
if(*(p - 1) == '\n' &&
*(p + len) == ':' &&
*(p + len + 1) == ' ') {
p += len + 2;
char *endP = strstr(p, CRLF);
if(endP == 0) {
for(endP = p; *endP != 0; ++endP) ;
}
// Transcode from iso-8859-1
TranscodeFromStr value((XMLByte*)p, endP - p, "ISO8859-1", fMemoryManager);
return value.adopt();
}
p = strstr(p + 1, name);
}
return 0;
}
int BinHTTPInputStreamCommon::sendRequest(const XMLURL &url, const XMLNetHTTPInfo *httpInfo)
{
//
// Constants in ASCII to send/check in the HTTP request/response
//
static const char *CRLF2X = "\r\n\r\n";
static const char *LF2X = "\n\n";
// The port is open and ready to go.
// Build up the http GET command to send to the server.
CharBuffer requestBuffer(1023, fMemoryManager);
createHTTPRequest(url, httpInfo, requestBuffer);
// Send the http request
if(!send(requestBuffer.getRawBuffer(), requestBuffer.getLen())) {
ThrowXMLwithMemMgr1(NetAccessorException,
XMLExcepts::NetAcc_WriteSocket, url.getURLText(), fMemoryManager);
}
if(httpInfo && httpInfo->fPayload) {
if(!send(httpInfo->fPayload, httpInfo->fPayloadLen)) {
ThrowXMLwithMemMgr1(NetAccessorException,
XMLExcepts::NetAcc_WriteSocket, url.getURLText(), fMemoryManager);
}
}
//
// get the response, check the http header for errors from the server.
//
char tmpBuf[1024];
int ret;
fBuffer.reset();
while(true) {
ret = receive(tmpBuf, sizeof(tmpBuf));
if(ret == -1) {
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, url.getURLText(), fMemoryManager);
}
// connection closed
if (ret == 0) {
break;
}
fBuffer.append(tmpBuf, ret);
fBufferPos = strstr(fBuffer.getRawBuffer(), CRLF2X);
if(fBufferPos != 0) {
fBufferPos += 4;
*(fBufferPos - 2) = 0;
break;
}
fBufferPos = strstr(fBuffer.getRawBuffer(), LF2X);
if(fBufferPos != 0) {
fBufferPos += 2;
*(fBufferPos - 1) = 0;
break;
}
}
// Parse the response status
char *p = strstr(fBuffer.getRawBuffer(), "HTTP");
if(p == 0) {
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, url.getURLText(), fMemoryManager);
}
p = strchr(p, chSpace);
if(p == 0) {
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, url.getURLText(), fMemoryManager);
}
return atoi(p);
}
const XMLCh *BinHTTPInputStreamCommon::getContentType() const
{
if(fContentType == 0) {
// mutable
const_cast<BinHTTPInputStreamCommon*>(this)->fContentType =
const_cast<BinHTTPInputStreamCommon*>(this)->findHeader("Content-Type");
}
return fContentType;
}
XMLSize_t BinHTTPInputStreamCommon::readBytes(XMLByte* const toFill,
const XMLSize_t maxToRead)
{
XMLSize_t len = fBuffer.getRawBuffer() + fBuffer.getLen() - fBufferPos;
if(len > 0)
{
// If there's any data left over in the buffer into which we first
// read from the server (to get the http header), return that.
if (len > maxToRead)
len = maxToRead;
memcpy(toFill, fBufferPos, len);
fBufferPos += len;
}
else
{
// There was no data in the local buffer.
// Read some from the socket, straight into our caller's buffer.
//
int cbRead = receive((char *)toFill, maxToRead);
if (cbRead == -1)
{
ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, fMemoryManager);
}
len = cbRead;
}
fBytesProcessed += len;
return len;
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,228 @@
/*
* 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: BinFileInputStream.hpp 553903 2007-07-06 14:43:42Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_BINHTTPINPUTSTREAMCOMMON_HPP)
#define XERCESC_INCLUDE_GUARD_BINHTTPINPUTSTREAMCOMMON_HPP
#include <xercesc/util/XMLURL.hpp>
#include <xercesc/util/BinInputStream.hpp>
#include <xercesc/util/XMLNetAccessor.hpp>
#include <xercesc/framework/MemoryManager.hpp>
#include <string.h>
XERCES_CPP_NAMESPACE_BEGIN
//
// This class implements a simple expanding character buffer
//
class XMLUTIL_EXPORT CharBuffer
{
public:
CharBuffer(XMLSize_t capacity = 1023,
MemoryManager *manager = XMLPlatformUtils::fgMemoryManager)
: fCapacity(capacity),
fIndex(0),
fMemoryManager(manager)
{
fBuffer = (char*)fMemoryManager->allocate((fCapacity + 1) * sizeof(char));
}
~CharBuffer()
{
fMemoryManager->deallocate(fBuffer);
}
const char* getRawBuffer() const
{
fBuffer[fIndex] = 0;
return fBuffer;
}
char* getRawBuffer()
{
fBuffer[fIndex] = 0;
return fBuffer;
}
XMLSize_t getLen() const
{
return fIndex;
}
void reset()
{
fIndex = 0;
}
void append(const char *chars)
{
if(chars != 0 && *chars != 0) {
// get length of chars
XMLSize_t count = 0;
for(; *(chars+count); ++count) ;
if(fIndex + count >= fCapacity) {
ensureCapacity(count);
}
memcpy(&fBuffer[fIndex], chars, count * sizeof(char));
fIndex += count;
}
}
void append(const char *chars, XMLSize_t len)
{
if(chars != 0 && len != 0) {
if(fIndex + len >= fCapacity) {
ensureCapacity(len);
}
memcpy(&fBuffer[fIndex], chars, len * sizeof(char));
fIndex += len;
}
}
void appendDecimalNumber(unsigned int n)
{
if(n >= 10) {
appendDecimalNumber(n / 10);
n = n % 10;
}
if(fIndex + 1 >= fCapacity)
ensureCapacity(1);
fBuffer[fIndex] = '0' + n;
++fIndex;
}
void set(const char *chars)
{
reset();
append(chars);
}
private:
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
CharBuffer(const CharBuffer &);
CharBuffer &operator=(const CharBuffer &);
void ensureCapacity(XMLSize_t extraNeeded)
{
// If we can't handle it, try doubling the buffer size.
XMLSize_t newCap = (fIndex + extraNeeded) * 2;
if(newCap > fCapacity)
{
// Allocate new buffer
char* newBuf = (char*)fMemoryManager->allocate((newCap + 1) * sizeof(char));
// Copy over the old stuff
memcpy(newBuf, fBuffer, fIndex * sizeof(char));
// Clean up old buffer and store new stuff
fMemoryManager->deallocate(fBuffer);
fBuffer = newBuf;
fCapacity = newCap;
}
}
// -----------------------------------------------------------------------
// Private data members
// -----------------------------------------------------------------------
char *fBuffer;
XMLSize_t fCapacity;
XMLSize_t fIndex;
MemoryManager *fMemoryManager;
};
//
// Common base implementation of HTTP BinInputStream that is used by some
// platform-specific implementations.
//
class XMLUTIL_EXPORT BinHTTPInputStreamCommon : public BinInputStream
{
public :
virtual XMLFilePos curPos() const;
virtual XMLSize_t readBytes
(
XMLByte* const toFill
, const XMLSize_t maxToRead
);
virtual const XMLCh *getContentType() const;
protected :
BinHTTPInputStreamCommon(MemoryManager *manager);
virtual ~BinHTTPInputStreamCommon();
/**
* \return The HTTP status code
*/
int sendRequest(const XMLURL &url, const XMLNetHTTPInfo *httpInfo);
XMLCh *findHeader(const char *name);
virtual bool send(const char *buf, XMLSize_t len) = 0;
/**
* \return The length of the data received, or -1 if an error occured
*/
virtual int receive(char *buf, XMLSize_t len) = 0;
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
BinHTTPInputStreamCommon(const BinHTTPInputStreamCommon&);
BinHTTPInputStreamCommon& operator=(const BinHTTPInputStreamCommon&);
void createHTTPRequest(const XMLURL &urlSource, const XMLNetHTTPInfo *httpInfo, CharBuffer &buffer);
// -----------------------------------------------------------------------
// Private data members
//
// fBytesProcessed
// Its a rolling count of the number of bytes processed off this
// input stream.
// fBuffer
// Holds the http header, plus the first part of the actual
// data. Filled at the time the stream is opened, data goes
// out to user in response to readBytes().
// fBufferPos
// Pointers into fBuffer, showing start and end+1 of content
// that readBytes must return.
// -----------------------------------------------------------------------
XMLSize_t fBytesProcessed;
CharBuffer fBuffer;
char * fBufferPos;
XMLCh * fContentType;
MemoryManager* fMemoryManager;
};
inline XMLFilePos BinHTTPInputStreamCommon::curPos() const
{
return fBytesProcessed;
}
XERCES_CPP_NAMESPACE_END
#endif
@@ -0,0 +1,93 @@
/*
* 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: CurlNetAccessor.cpp 471747 2006-11-06 14:31:56Z amassari $
*/
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/XMLUni.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/NetAccessors/Curl/CurlURLInputStream.hpp>
#include <xercesc/util/NetAccessors/Curl/CurlNetAccessor.hpp>
XERCES_CPP_NAMESPACE_BEGIN
const XMLCh CurlNetAccessor::fgMyName[] =
{
chLatin_C, chLatin_u, chLatin_r, chLatin_l, chLatin_N, chLatin_e,
chLatin_t, chLatin_A, chLatin_c, chLatin_c, chLatin_e, chLatin_s,
chLatin_s, chLatin_o, chLatin_r, chNull
};
CurlNetAccessor::CurlNetAccessor()
{
initCurl();
}
CurlNetAccessor::~CurlNetAccessor()
{
cleanupCurl();
}
//
// Global once-only init and cleanup of curl
//
// The init count used here is not thread protected; we assume
// that creation of the CurlNetAccessor will be serialized by
// the application. If the application is also using curl, then
// care must be taken that curl is initialized only once, by some
// other means, or by overloading these methods.
//
int CurlNetAccessor::fgCurlInitCount = 0;
void
CurlNetAccessor::initCurl()
{
if (fgCurlInitCount++ == 0)
curl_global_init( 0
| CURL_GLOBAL_ALL // Initialize all curl modules
// | CURL_GLOBAL_WIN32 // Initialize Windows sockets first
// | CURL_GLOBAL_SSL // Initialize SSL first
);
}
void
CurlNetAccessor::cleanupCurl()
{
if (fgCurlInitCount > 0 && --fgCurlInitCount == 0)
curl_global_cleanup();
}
BinInputStream*
CurlNetAccessor::makeNew(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo/*=0*/)
{
// Just create a CurlURLInputStream
// We defer any checking of the url type for curl in CurlURLInputStream
CurlURLInputStream* retStrm =
new (urlSource.getMemoryManager()) CurlURLInputStream(urlSource, httpInfo);
return retStrm;
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,71 @@
/*
* 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: CurlNetAccessor.hpp 527149 2007-04-10 14:56:39Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CURLNETACCESSOR_HPP)
#define XERCESC_INCLUDE_GUARD_CURLNETACCESSOR_HPP
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/XMLURL.hpp>
#include <xercesc/util/BinInputStream.hpp>
#include <xercesc/util/XMLNetAccessor.hpp>
XERCES_CPP_NAMESPACE_BEGIN
//
// This class is the wrapper for the socket based code which
// provides the ability to fetch a resource specified using
// a HTTP or FTP URL.
//
class XMLUTIL_EXPORT CurlNetAccessor : public XMLNetAccessor
{
public :
CurlNetAccessor();
~CurlNetAccessor();
virtual BinInputStream* makeNew(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo=0);
virtual const XMLCh* getId() const;
virtual void initCurl(void);
virtual void cleanupCurl(void);
private :
static int fgCurlInitCount;
static const XMLCh fgMyName[];
CurlNetAccessor(const CurlNetAccessor&);
CurlNetAccessor& operator=(const CurlNetAccessor&);
}; // CurlNetAccessor
inline const XMLCh* CurlNetAccessor::getId() const
{
return fgMyName;
}
XERCES_CPP_NAMESPACE_END
#endif // CURLNETACCESSOR_HPP
@@ -0,0 +1,392 @@
/*
* 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: CurlURLInputStream.cpp 936316 2010-04-21 14:19:58Z borisk $
*/
#if HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_ERRNO_H
#include <errno.h>
#endif
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/XMLNetAccessor.hpp>
#include <xercesc/util/NetAccessors/Curl/CurlURLInputStream.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/TransService.hpp>
#include <xercesc/util/TranscodingException.hpp>
#include <xercesc/util/PlatformUtils.hpp>
XERCES_CPP_NAMESPACE_BEGIN
CurlURLInputStream::CurlURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo/*=0*/)
: fMulti(0)
, fEasy(0)
, fMemoryManager(urlSource.getMemoryManager())
, fURLSource(urlSource)
, fTotalBytesRead(0)
, fWritePtr(0)
, fBytesRead(0)
, fBytesToRead(0)
, fDataAvailable(false)
, fBufferHeadPtr(fBuffer)
, fBufferTailPtr(fBuffer)
, fPayload(0)
, fPayloadLen(0)
, fContentType(0)
{
// Allocate the curl multi handle
fMulti = curl_multi_init();
// Allocate the curl easy handle
fEasy = curl_easy_init();
// Set URL option
TranscodeToStr url(fURLSource.getURLText(), "ISO8859-1", fMemoryManager);
curl_easy_setopt(fEasy, CURLOPT_URL, (char*)url.str());
// Set up a way to recieve the data
curl_easy_setopt(fEasy, CURLOPT_WRITEDATA, this); // Pass this pointer to write function
curl_easy_setopt(fEasy, CURLOPT_WRITEFUNCTION, staticWriteCallback); // Our static write function
// Do redirects
curl_easy_setopt(fEasy, CURLOPT_FOLLOWLOCATION, (long)1);
curl_easy_setopt(fEasy, CURLOPT_MAXREDIRS, (long)6);
// Add username and password if authentication is required
const XMLCh *username = urlSource.getUser();
const XMLCh *password = urlSource.getPassword();
if(username && password) {
XMLBuffer userPassBuf(256, fMemoryManager);
userPassBuf.append(username);
userPassBuf.append(chColon);
userPassBuf.append(password);
TranscodeToStr userPass(userPassBuf.getRawBuffer(), "ISO8859-1", fMemoryManager);
curl_easy_setopt(fEasy, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
curl_easy_setopt(fEasy, CURLOPT_USERPWD, (char*)userPass.str());
}
if(httpInfo) {
// Set the correct HTTP method
switch(httpInfo->fHTTPMethod) {
case XMLNetHTTPInfo::GET:
break;
case XMLNetHTTPInfo::PUT:
curl_easy_setopt(fEasy, CURLOPT_UPLOAD, (long)1);
break;
case XMLNetHTTPInfo::POST:
curl_easy_setopt(fEasy, CURLOPT_POST, (long)1);
break;
}
// Add custom headers
if(httpInfo->fHeaders) {
struct curl_slist *headersList = 0;
const char *headersBuf = httpInfo->fHeaders;
const char *headersBufEnd = httpInfo->fHeaders + httpInfo->fHeadersLen;
const char *headerStart = headersBuf;
while(headersBuf < headersBufEnd) {
if(*headersBuf == '\r' && (headersBuf + 1) < headersBufEnd &&
*(headersBuf + 1) == '\n') {
XMLSize_t length = headersBuf - headerStart;
ArrayJanitor<char> header((char*)fMemoryManager->allocate((length + 1) * sizeof(char)),
fMemoryManager);
memcpy(header.get(), headerStart, length);
header.get()[length] = 0;
headersList = curl_slist_append(headersList, header.get());
headersBuf += 2;
headerStart = headersBuf;
continue;
}
++headersBuf;
}
curl_easy_setopt(fEasy, CURLOPT_HTTPHEADER, headersList);
curl_slist_free_all(headersList);
}
// Set up the payload
if(httpInfo->fPayload) {
fPayload = httpInfo->fPayload;
fPayloadLen = httpInfo->fPayloadLen;
curl_easy_setopt(fEasy, CURLOPT_READDATA, this);
curl_easy_setopt(fEasy, CURLOPT_READFUNCTION, staticReadCallback);
curl_easy_setopt(fEasy, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fPayloadLen);
}
}
// Add easy handle to the multi stack
curl_multi_add_handle(fMulti, fEasy);
// Start reading, to get the content type
while(fBufferHeadPtr == fBuffer)
{
int runningHandles = 0;
readMore(&runningHandles);
if(runningHandles == 0) break;
}
// Find the content type
char *contentType8 = 0;
curl_easy_getinfo(fEasy, CURLINFO_CONTENT_TYPE, &contentType8);
if(contentType8)
fContentType = TranscodeFromStr((XMLByte*)contentType8, XMLString::stringLen(contentType8), "ISO8859-1", fMemoryManager).adopt();
}
CurlURLInputStream::~CurlURLInputStream()
{
// Remove the easy handle from the multi stack
curl_multi_remove_handle(fMulti, fEasy);
// Cleanup the easy handle
curl_easy_cleanup(fEasy);
// Cleanup the multi handle
curl_multi_cleanup(fMulti);
if(fContentType) fMemoryManager->deallocate(fContentType);
}
size_t
CurlURLInputStream::staticWriteCallback(char *buffer,
size_t size,
size_t nitems,
void *outstream)
{
return ((CurlURLInputStream*)outstream)->writeCallback(buffer, size, nitems);
}
size_t
CurlURLInputStream::staticReadCallback(char *buffer,
size_t size,
size_t nitems,
void *stream)
{
return ((CurlURLInputStream*)stream)->readCallback(buffer, size, nitems);
}
size_t
CurlURLInputStream::writeCallback(char *buffer,
size_t size,
size_t nitems)
{
XMLSize_t cnt = size * nitems;
XMLSize_t totalConsumed = 0;
// Consume as many bytes as possible immediately into the buffer
XMLSize_t consume = (cnt > fBytesToRead) ? fBytesToRead : cnt;
memcpy(fWritePtr, buffer, consume);
fWritePtr += consume;
fBytesRead += consume;
fTotalBytesRead += consume;
fBytesToRead -= consume;
//printf("write callback consuming %d bytes\n", consume);
// If bytes remain, rebuffer as many as possible into our holding buffer
buffer += consume;
totalConsumed += consume;
cnt -= consume;
if (cnt > 0)
{
XMLSize_t bufAvail = sizeof(fBuffer) - (fBufferHeadPtr - fBuffer);
consume = (cnt > bufAvail) ? bufAvail : cnt;
memcpy(fBufferHeadPtr, buffer, consume);
fBufferHeadPtr += consume;
buffer += consume;
totalConsumed += consume;
//printf("write callback rebuffering %d bytes\n", consume);
}
// Return the total amount we've consumed. If we don't consume all the bytes
// then an error will be generated. Since our buffer size is equal to the
// maximum size that curl will write, this should never happen unless there
// is a logic error somewhere here.
return totalConsumed;
}
size_t
CurlURLInputStream::readCallback(char *buffer,
size_t size,
size_t nitems)
{
XMLSize_t len = size * nitems;
if(len > fPayloadLen) len = fPayloadLen;
memcpy(buffer, fPayload, len);
fPayload += len;
fPayloadLen -= len;
return len;
}
bool CurlURLInputStream::readMore(int *runningHandles)
{
// Ask the curl to do some work
CURLMcode curlResult = curl_multi_perform(fMulti, runningHandles);
// Process messages from curl
int msgsInQueue = 0;
for (CURLMsg* msg = NULL; (msg = curl_multi_info_read(fMulti, &msgsInQueue)) != NULL; )
{
//printf("msg %d, %d from curl\n", msg->msg, msg->data.result);
if (msg->msg != CURLMSG_DONE)
return true;
switch (msg->data.result)
{
case CURLE_OK:
// We completed successfully. runningHandles should have dropped to zero, so we'll bail out below...
break;
case CURLE_UNSUPPORTED_PROTOCOL:
ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_UnsupportedProto, fMemoryManager);
break;
case CURLE_COULDNT_RESOLVE_HOST:
case CURLE_COULDNT_RESOLVE_PROXY:
{
if (fURLSource.getHost())
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_TargetResolution, fURLSource.getHost(), fMemoryManager);
else
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, fURLSource.getURLText(), fMemoryManager);
break;
}
case CURLE_COULDNT_CONNECT:
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ConnSocket, fURLSource.getURLText(), fMemoryManager);
break;
case CURLE_RECV_ERROR:
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, fURLSource.getURLText(), fMemoryManager);
break;
default:
ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_InternalError, fURLSource.getURLText(), fMemoryManager);
break;
}
}
// If nothing is running any longer, bail out
if(*runningHandles == 0)
return false;
// If there is no further data to read, and we haven't
// read any yet on this invocation, call select to wait for data
if (curlResult != CURLM_CALL_MULTI_PERFORM && fBytesRead == 0)
{
fd_set readSet;
fd_set writeSet;
fd_set exceptSet;
int fdcnt=0;
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
FD_ZERO(&exceptSet);
// Ask curl for the file descriptors to wait on
curl_multi_fdset(fMulti, &readSet, &writeSet, &exceptSet, &fdcnt);
// Wait on the file descriptors
timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
select(fdcnt+1, &readSet, &writeSet, &exceptSet, &tv);
}
return curlResult == CURLM_CALL_MULTI_PERFORM;
}
XMLSize_t
CurlURLInputStream::readBytes(XMLByte* const toFill
, const XMLSize_t maxToRead)
{
fBytesRead = 0;
fBytesToRead = maxToRead;
fWritePtr = toFill;
for (bool tryAgain = true; fBytesToRead > 0 && (tryAgain || fBytesRead == 0); )
{
// First, any buffered data we have available
XMLSize_t bufCnt = fBufferHeadPtr - fBufferTailPtr;
bufCnt = (bufCnt > fBytesToRead) ? fBytesToRead : bufCnt;
if (bufCnt > 0)
{
memcpy(fWritePtr, fBufferTailPtr, bufCnt);
fWritePtr += bufCnt;
fBytesRead += bufCnt;
fTotalBytesRead += bufCnt;
fBytesToRead -= bufCnt;
fBufferTailPtr += bufCnt;
if (fBufferTailPtr == fBufferHeadPtr)
fBufferHeadPtr = fBufferTailPtr = fBuffer;
//printf("consuming %d buffered bytes\n", bufCnt);
tryAgain = true;
continue;
}
// Ask the curl to do some work
int runningHandles = 0;
tryAgain = readMore(&runningHandles);
// If nothing is running any longer, bail out
if (runningHandles == 0)
break;
}
return fBytesRead;
}
const XMLCh *CurlURLInputStream::getContentType() const
{
return fContentType;
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,136 @@
/*
* 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: CurlURLInputStream.hpp 835245 2009-11-12 05:57:31Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_CURLURLINPUTSTREAM_HPP)
#define XERCESC_INCLUDE_GUARD_CURLURLINPUTSTREAM_HPP
#include <curl/curl.h>
#include <curl/multi.h>
#include <curl/easy.h>
#include <xercesc/util/XMLURL.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/BinInputStream.hpp>
#include <xercesc/util/XMLNetAccessor.hpp>
XERCES_CPP_NAMESPACE_BEGIN
//
// This class implements the BinInputStream interface specified by the XML
// parser.
//
class XMLUTIL_EXPORT CurlURLInputStream : public BinInputStream
{
public :
CurlURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo=0);
~CurlURLInputStream();
virtual XMLFilePos curPos() const;
virtual XMLSize_t readBytes
(
XMLByte* const toFill
, const XMLSize_t maxToRead
);
virtual const XMLCh *getContentType() const;
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
CurlURLInputStream(const CurlURLInputStream&);
CurlURLInputStream& operator=(const CurlURLInputStream&);
static size_t staticWriteCallback(char *buffer,
size_t size,
size_t nitems,
void *outstream);
size_t writeCallback( char *buffer,
size_t size,
size_t nitems);
static size_t staticReadCallback(char *buffer,
size_t size,
size_t nitems,
void *stream);
size_t readCallback( char *buffer,
size_t size,
size_t nitems);
bool readMore(int *runningHandles);
// -----------------------------------------------------------------------
// Private data members
//
// fSocket
// The socket representing the connection to the remote file.
// fBytesProcessed
// Its a rolling count of the number of bytes processed off this
// input stream.
// fBuffer
// Holds the http header, plus the first part of the actual
// data. Filled at the time the stream is opened, data goes
// out to user in response to readBytes().
// fBufferPos, fBufferEnd
// Pointers into fBuffer, showing start and end+1 of content
// that readBytes must return.
// -----------------------------------------------------------------------
CURLM* fMulti;
CURL* fEasy;
MemoryManager* fMemoryManager;
XMLURL fURLSource;
XMLSize_t fTotalBytesRead;
XMLByte* fWritePtr;
XMLSize_t fBytesRead;
XMLSize_t fBytesToRead;
bool fDataAvailable;
// Overflow buffer for when curl writes more data to us
// than we've asked for.
XMLByte fBuffer[CURL_MAX_WRITE_SIZE];
XMLByte* fBufferHeadPtr;
XMLByte* fBufferTailPtr;
// Upload data
const char* fPayload;
XMLSize_t fPayloadLen;
XMLCh * fContentType;
}; // CurlURLInputStream
inline XMLFilePos
CurlURLInputStream::curPos() const
{
return fTotalBytesRead;
}
XERCES_CPP_NAMESPACE_END
#endif // CURLURLINPUTSTREAM_HPP
@@ -0,0 +1,62 @@
/*
* 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: MacOSURLAccessCF.cpp 471747 2006-11-06 14:31:56Z amassari $
*/
#include <xercesc/util/XMLUni.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/NetAccessors/MacOSURLAccessCF/MacOSURLAccessCF.hpp>
#include <xercesc/util/NetAccessors/MacOSURLAccessCF/URLAccessCFBinInputStream.hpp>
XERCES_CPP_NAMESPACE_BEGIN
const XMLCh
MacOSURLAccessCF::sMyID[] =
{
chLatin_M, chLatin_a, chLatin_c, chLatin_O, chLatin_S, chLatin_U,
chLatin_R, chLatin_L, chLatin_A, chLatin_c, chLatin_c, chLatin_e,
chLatin_s, chLatin_s, chLatin_C, chLatin_F,
chNull
};
MacOSURLAccessCF::MacOSURLAccessCF()
{
}
MacOSURLAccessCF::~MacOSURLAccessCF()
{
}
BinInputStream*
MacOSURLAccessCF::makeNew(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo/*=0*/)
{
if(httpInfo!=0 && httpInfo->fHTTPMethod!=XMLNetHTTPInfo::GET)
ThrowXML(NetAccessorException, XMLExcepts::NetAcc_UnsupportedMethod);
BinInputStream* result = new (urlSource.getMemoryManager()) URLAccessCFBinInputStream(urlSource);
return result;
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,66 @@
/*
* 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: MacOSURLAccessCF.hpp 527149 2007-04-10 14:56:39Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_MACOSURLACCESSCF_HPP)
#define XERCESC_INCLUDE_GUARD_MACOSURLACCESSCF_HPP
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/XMLURL.hpp>
#include <xercesc/util/BinInputStream.hpp>
#include <xercesc/util/XMLNetAccessor.hpp>
XERCES_CPP_NAMESPACE_BEGIN
//
// This class is the wrapper for the Mac OS CFURLAccess code
// (in CoreServices.framework) which provides access to network
// resources. It's being used here to add the ability to
// use HTTP URL's as the system id's in the XML decl clauses.
//
class XMLUTIL_EXPORT MacOSURLAccessCF : public XMLNetAccessor
{
public :
MacOSURLAccessCF();
~MacOSURLAccessCF();
BinInputStream* makeNew(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo=0);
const XMLCh* getId() const;
private :
static const XMLCh sMyID[];
MacOSURLAccessCF(const MacOSURLAccessCF&);
MacOSURLAccessCF& operator=(const MacOSURLAccessCF&);
};
inline const XMLCh*
MacOSURLAccessCF::getId() const
{
return sMyID;
}
XERCES_CPP_NAMESPACE_END
#endif // MACOSURLACCESSCF_HPP
@@ -0,0 +1,180 @@
/*
* 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: URLAccessCFBinInputStream.cpp 936316 2010-04-21 14:19:58Z borisk $
*/
#include <cstdlib>
#include <cstring>
#include <xercesc/util/XMLNetAccessor.hpp>
#include <xercesc/util/NetAccessors/MacOSURLAccessCF/URLAccessCFBinInputStream.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/Janitor.hpp>
XERCES_CPP_NAMESPACE_BEGIN
URLAccessCFBinInputStream::URLAccessCFBinInputStream(const XMLURL& urlSource)
: mBytesProcessed(0),
mDataRef(NULL)
{
// Figure out what we're dealing with
const XMLCh* urlText = urlSource.getURLText();
unsigned int urlLength = XMLString::stringLen(urlText);
// Create a CFString from the path
CFStringRef stringRef = NULL;
if (urlText)
{
stringRef = CFStringCreateWithCharacters(
kCFAllocatorDefault,
urlText,
urlLength
);
}
// Create a URLRef from the CFString
CFURLRef urlRef = NULL;
if (stringRef)
{
urlRef = CFURLCreateWithString(
kCFAllocatorDefault,
stringRef,
NULL // CFURLRef baseURL
);
}
// Fetch the data
mDataRef = NULL;
SInt32 errorCode = 0;
Boolean success = false;
if (stringRef)
{
success = CFURLCreateDataAndPropertiesFromResource(
kCFAllocatorDefault,
urlRef,
&mDataRef,
NULL, // CFDictionaryRef *properties,
NULL, // CFArrayRef desiredProperties,
&errorCode
);
}
// Cleanup temporary stuff
if (stringRef)
CFRelease(stringRef);
if (urlRef)
CFRelease(urlRef);
// Check for an error in fetching the data
if (!success || errorCode)
{
// Dispose any potential dataRef
if (mDataRef)
{
CFRelease(mDataRef);
mDataRef = NULL;
}
// Do a best attempt at mapping some errors
switch (errorCode)
{
case kCFURLUnknownSchemeError:
ThrowXML(MalformedURLException, XMLExcepts::URL_UnsupportedProto);
break;
case kCFURLRemoteHostUnavailableError:
{
if (urlSource.getHost())
ThrowXML1(NetAccessorException, XMLExcepts::NetAcc_TargetResolution, urlSource.getHost());
else
ThrowXML1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, urlText);
break;
}
case kCFURLUnknownError:
ThrowXML1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, urlText);
break;
case kCFURLResourceNotFoundError:
case kCFURLResourceAccessViolationError:
case kCFURLTimeoutError:
ThrowXML1(NetAccessorException, XMLExcepts::File_CouldNotOpenFile, urlText);
break;
case kCFURLImproperArgumentsError:
case kCFURLUnknownPropertyKeyError:
case kCFURLPropertyKeyUnavailableError:
default:
ThrowXML1(NetAccessorException, XMLExcepts::NetAcc_InternalError, urlText);
break;
}
}
}
URLAccessCFBinInputStream::~URLAccessCFBinInputStream()
{
// Release any dataRef
if (mDataRef)
CFRelease(mDataRef);
}
//
// We've already read the data into a dataRef.
// Just spoon it out to the caller as they ask for it.
//
XMLSize_t
URLAccessCFBinInputStream::readBytes(XMLByte* const toFill
, const XMLSize_t maxToRead)
{
// If we don't have a dataRef, we can't return any data
if (!mDataRef)
return 0;
// Get the length of the data we've fetched
CFIndex dataLength = CFDataGetLength(mDataRef);
// Calculate how much to return based on how much
// we've already returned, and how much the user wants
CFIndex n = dataLength - mBytesProcessed; // Amount remaining
CFIndex desired = maxToRead & 0x7fffffff; // CFIndex is signed
if (n > desired) // Amount desired
n = desired;
// Read the appropriate bytes into the user buffer
CFRange range = CFRangeMake(mBytesProcessed, n);
CFDataGetBytes(mDataRef, range, reinterpret_cast<UInt8*>(toFill));
// Update bytes processed
mBytesProcessed += n;
// Return the number of bytes delivered
return n;
}
const XMLCh* URLAccessCFBinInputStream::getContentType() const
{
// TODO
//
return 0;
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,75 @@
/*
* 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: URLAccessCFBinInputStream.hpp 670359 2008-06-22 13:43:45Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_URLACCESSCFBININPUTSTREAM_HPP)
#define XERCESC_INCLUDE_GUARD_URLACCESSCFBININPUTSTREAM_HPP
#include <xercesc/util/XMLURL.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/BinInputStream.hpp>
#if defined(__APPLE__)
// Framework includes from ProjectBuilder
#include <CoreServices/CoreServices.h>
#else
// Classic includes otherwise
#include <CFURL.h>
#include <CFURLAccess.h>
#endif
XERCES_CPP_NAMESPACE_BEGIN
//
// This class implements the BinInputStream interface specified by the XML
// parser.
//
class XMLUTIL_EXPORT URLAccessCFBinInputStream : public BinInputStream
{
public :
URLAccessCFBinInputStream(const XMLURL& urlSource);
~URLAccessCFBinInputStream();
virtual XMLFilePos curPos() const;
virtual XMLSize_t readBytes
(
XMLByte* const toFill
, const XMLSize_t maxToRead
);
virtual const XMLCh* getContentType() const;
private :
CFDataRef mDataRef;
CFIndex mBytesProcessed;
};
inline XMLFilePos
URLAccessCFBinInputStream::curPos() const
{
return mBytesProcessed;
}
XERCES_CPP_NAMESPACE_END
#endif // URLACCESSCFBININPUTSTREAM_HPP
@@ -0,0 +1,76 @@
/*
* 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: SocketNetAccessor.cpp 471747 2006-11-06 14:31:56Z amassari $
*/
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/XMLUni.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/NetAccessors/Socket/UnixHTTPURLInputStream.hpp>
#include <xercesc/util/NetAccessors/Socket/SocketNetAccessor.hpp>
XERCES_CPP_NAMESPACE_BEGIN
const XMLCh SocketNetAccessor::fgMyName[] =
{
chLatin_S, chLatin_o, chLatin_c, chLatin_k, chLatin_e, chLatin_t,
chLatin_N, chLatin_e, chLatin_t, chLatin_A, chLatin_c, chLatin_c,
chLatin_e, chLatin_s, chLatin_s, chLatin_o, chLatin_r, chNull
};
SocketNetAccessor::SocketNetAccessor()
{
// Do any one time initialization here.
// Nothing to do, in this case.
}
SocketNetAccessor::~SocketNetAccessor()
{
// Again, nothing to do here.
}
BinInputStream* SocketNetAccessor::makeNew(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo/*=0*/)
{
XMLURL::Protocols protocol = urlSource.getProtocol();
switch(protocol)
{
case XMLURL::HTTP:
{
UnixHTTPURLInputStream* retStrm =
new (urlSource.getMemoryManager()) UnixHTTPURLInputStream(urlSource, httpInfo);
return retStrm;
}
//
// These are the only protocols we support now. So throw and
// unsupported protocol exception for the others.
//
default :
ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_UnsupportedProto, urlSource.getMemoryManager());
break;
}
return 0;
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,64 @@
/*
* 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: SocketNetAccessor.hpp 527149 2007-04-10 14:56:39Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_SOCKETNETACCESSOR_HPP)
#define XERCESC_INCLUDE_GUARD_SOCKETNETACCESSOR_HPP
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/XMLURL.hpp>
#include <xercesc/util/BinInputStream.hpp>
#include <xercesc/util/XMLNetAccessor.hpp>
XERCES_CPP_NAMESPACE_BEGIN
//
// This class is the wrapper for the socket based code which
// provides the ability to fetch a resource specified using
// a HTTP or FTP URL.
//
class XMLUTIL_EXPORT SocketNetAccessor : public XMLNetAccessor
{
public :
SocketNetAccessor();
~SocketNetAccessor();
virtual BinInputStream* makeNew(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo=0);
virtual const XMLCh* getId() const;
private :
static const XMLCh fgMyName[];
SocketNetAccessor(const SocketNetAccessor&);
SocketNetAccessor& operator=(const SocketNetAccessor&);
}; // SocketNetAccessor
inline const XMLCh* SocketNetAccessor::getId() const
{
return fgMyName;
}
XERCES_CPP_NAMESPACE_END
#endif // SOCKETNETACCESSOR_HPP
@@ -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
@@ -0,0 +1,61 @@
/*
* 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.hpp 670359 2008-06-22 13:43:45Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_UNIXHTTPURLINPUTSTREAM_HPP)
#define XERCESC_INCLUDE_GUARD_UNIXHTTPURLINPUTSTREAM_HPP
#include <xercesc/util/NetAccessors/BinHTTPInputStreamCommon.hpp>
XERCES_CPP_NAMESPACE_BEGIN
//
// This class implements the BinInputStream interface specified by the XML
// parser.
//
class XMLUTIL_EXPORT UnixHTTPURLInputStream : public BinHTTPInputStreamCommon
{
public :
UnixHTTPURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo=0);
~UnixHTTPURLInputStream();
virtual bool send(const char *buf, XMLSize_t len);
virtual int receive(char *buf, XMLSize_t len);
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
UnixHTTPURLInputStream(const UnixHTTPURLInputStream&);
UnixHTTPURLInputStream& operator=(const UnixHTTPURLInputStream&);
// -----------------------------------------------------------------------
// Private data members
//
// fSocket
// The socket representing the connection to the remote file.
// -----------------------------------------------------------------------
int fSocket;
};
XERCES_CPP_NAMESPACE_END
#endif // UNIXHTTPURLINPUTSTREAM_HPP
@@ -0,0 +1,495 @@
/*
* 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: BinHTTPURLInputStream.cpp 936316 2010-04-21 14:19:58Z borisk $
*/
#include <xercesc/util/NetAccessors/WinSock/BinHTTPURLInputStream.hpp>
#include <windows.h>
#ifdef WITH_IPV6
#include <ws2tcpip.h>
#endif
#include <stdio.h>
#include <string.h>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/util/XMLNetAccessor.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/Mutexes.hpp>
XERCES_CPP_NAMESPACE_BEGIN
typedef u_short (WSAAPI * LPFN_HTONS)(u_short hostshort);
typedef SOCKET (WSAAPI * LPFN_SOCKET)(int af, int type, int protocol);
typedef int (WSAAPI * LPFN_CONNECT)(SOCKET s, const struct sockaddr* name, int namelen);
typedef int (WSAAPI * LPFN_SEND)(SOCKET s, const char* buf, int len, int flags);
typedef int (WSAAPI * LPFN_RECV)(SOCKET s, char* buf, int len, int flags);
typedef int (WSAAPI * LPFN_SHUTDOWN)(SOCKET s, int how);
typedef int (WSAAPI * LPFN_CLOSESOCKET)(SOCKET s);
typedef int (WSAAPI * LPFN_WSACLEANUP)();
typedef int (WSAAPI * LPFN_WSASTARTUP)(WORD wVersionRequested, LPWSADATA lpWSAData);
#ifdef WITH_IPV6
typedef int (WSAAPI * LPFN_GETADDRINFO)(const char* nodename, const char * servname, const struct addrinfo * hints, struct addrinfo ** res);
typedef void (WSAAPI * LPFN_FREEADDRINFO)(struct addrinfo * ai);
#else
typedef struct hostent *(WSAAPI * LPFN_GETHOSTBYNAME)(const char* name);
typedef struct hostent *(WSAAPI * LPFN_GETHOSTBYADDR)(const char* addr, int len, int type);
typedef unsigned long (WSAAPI * LPFN_INET_ADDR)(const char* cp);
#endif
static HMODULE gWinsockLib = NULL;
static LPFN_HTONS gWShtons = NULL;
static LPFN_SOCKET gWSsocket = NULL;
static LPFN_CONNECT gWSconnect = NULL;
static LPFN_SEND gWSsend = NULL;
static LPFN_RECV gWSrecv = NULL;
static LPFN_SHUTDOWN gWSshutdown = NULL;
static LPFN_CLOSESOCKET gWSclosesocket = NULL;
static LPFN_WSACLEANUP gWSACleanup = NULL;
#ifdef WITH_IPV6
static LPFN_GETADDRINFO gWSgetaddrinfo = NULL;
static LPFN_FREEADDRINFO gWSfreeaddrinfo = NULL;
#else
static LPFN_GETHOSTBYNAME gWSgethostbyname = NULL;
static LPFN_GETHOSTBYADDR gWSgethostbyaddr = NULL;
static LPFN_INET_ADDR gWSinet_addr = NULL;
#endif
static u_short wrap_htons(u_short hostshort)
{
return (*gWShtons)(hostshort);
}
static SOCKET wrap_socket(int af,int type,int protocol)
{
return (*gWSsocket)(af,type,protocol);
}
static int wrap_connect(SOCKET s,const struct sockaddr* name,int namelen)
{
return (*gWSconnect)(s,name,namelen);
}
static int wrap_send(SOCKET s,const char* buf,int len,int flags)
{
return (*gWSsend)(s,buf,len,flags);
}
static int wrap_recv(SOCKET s,char* buf,int len,int flags)
{
return (*gWSrecv)(s,buf,len,flags);
}
static int wrap_shutdown(SOCKET s,int how)
{
return (*gWSshutdown)(s,how);
}
static int wrap_closesocket(SOCKET socket)
{
return (*gWSclosesocket)(socket);
}
#ifdef WITH_IPV6
static int wrap_getaddrinfo(const char* nodename,const char* servname,const struct addrinfo* hints,struct addrinfo** res)
{
return (*gWSgetaddrinfo)(nodename,servname,hints,res);
}
static void wrap_freeaddrinfo(struct addrinfo* ai)
{
(*gWSfreeaddrinfo)(ai);
}
#else
static struct hostent* wrap_gethostbyname(const char* name)
{
return (*gWSgethostbyname)(name);
}
static struct hostent* wrap_gethostbyaddr(const char* addr,int len,int type)
{
return (*gWSgethostbyaddr)(addr,len,type);
}
static unsigned long wrap_inet_addr(const char* cp)
{
return (*gWSinet_addr)(cp);
}
#endif
class SocketJanitor
{
public:
// -----------------------------------------------------------------------
// Constructors and Destructor
// -----------------------------------------------------------------------
SocketJanitor(SOCKET* toDelete) : fData(toDelete) {}
~SocketJanitor() { reset(); }
SOCKET* get() const { return fData; }
SOCKET* release() { SOCKET* p = fData; fData = 0; return p; }
void reset(SOCKET* p = 0)
{
if(fData) {
wrap_shutdown(*fData, SD_BOTH);
wrap_closesocket(*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.
// -----------------------------------------------------------------------
SOCKET* fData;
};
bool BinHTTPURLInputStream::fInitialized = false;
void BinHTTPURLInputStream::Initialize(MemoryManager* const manager)
{
//
// Initialize the WinSock library here.
//
WORD wVersionRequested;
WSADATA wsaData;
LPFN_WSASTARTUP startup = NULL;
if(gWinsockLib == NULL)
{
#ifdef WITH_IPV6
gWinsockLib = LoadLibraryA("WS2_32");
#else
gWinsockLib = LoadLibraryA("WSOCK32");
#endif
if(gWinsockLib == NULL)
{
ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_InitFailed, manager);
}
else
{
startup = (LPFN_WSASTARTUP) GetProcAddress(gWinsockLib,"WSAStartup");
gWSACleanup = (LPFN_WSACLEANUP) GetProcAddress(gWinsockLib,"WSACleanup");
gWShtons = (LPFN_HTONS) GetProcAddress(gWinsockLib,"htons");
gWSsocket = (LPFN_SOCKET) GetProcAddress(gWinsockLib,"socket");
gWSconnect = (LPFN_CONNECT) GetProcAddress(gWinsockLib,"connect");
gWSsend = (LPFN_SEND) GetProcAddress(gWinsockLib,"send");
gWSrecv = (LPFN_RECV) GetProcAddress(gWinsockLib,"recv");
gWSshutdown = (LPFN_SHUTDOWN) GetProcAddress(gWinsockLib,"shutdown");
gWSclosesocket = (LPFN_CLOSESOCKET) GetProcAddress(gWinsockLib,"closesocket");
#ifdef WITH_IPV6
gWSgetaddrinfo = (LPFN_GETADDRINFO) GetProcAddress(gWinsockLib,"getaddrinfo");
gWSfreeaddrinfo = (LPFN_FREEADDRINFO) GetProcAddress(gWinsockLib,"freeaddrinfo");
#else
gWSgethostbyname = (LPFN_GETHOSTBYNAME) GetProcAddress(gWinsockLib,"gethostbyname");
gWSgethostbyaddr = (LPFN_GETHOSTBYADDR) GetProcAddress(gWinsockLib,"gethostbyaddr");
gWSinet_addr = (LPFN_INET_ADDR) GetProcAddress(gWinsockLib,"inet_addr");
#endif
if(startup == NULL
|| gWSACleanup == NULL
|| gWShtons == NULL
|| gWSsocket == NULL
|| gWSconnect == NULL
|| gWSsend == NULL
|| gWSrecv == NULL
|| gWSshutdown == NULL
|| gWSclosesocket == NULL
#ifdef WITH_IPV6
|| gWSgetaddrinfo == NULL
|| gWSfreeaddrinfo == NULL
#else
|| gWSgethostbyname == NULL
|| gWSgethostbyaddr == NULL
|| gWSinet_addr == NULL
#endif
)
{
gWSACleanup = NULL;
Cleanup();
ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_InitFailed, manager);
}
}
}
wVersionRequested = MAKEWORD( 2, 2 );
int err = (*startup)(wVersionRequested, &wsaData);
if (err != 0)
{
// Call WSAGetLastError() to get the last error.
ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_InitFailed, manager);
}
fInitialized = true;
}
void BinHTTPURLInputStream::Cleanup()
{
XMLMutexLock lock(XMLPlatformUtils::fgAtomicMutex);
if(fInitialized)
{
if(gWSACleanup) (*gWSACleanup)();
gWSACleanup = NULL;
FreeLibrary(gWinsockLib);
gWinsockLib = NULL;
gWShtons = NULL;
gWSsocket = NULL;
gWSconnect = NULL;
gWSsend = NULL;
gWSrecv = NULL;
gWSshutdown = NULL;
gWSclosesocket = NULL;
#ifdef WITH_IPV6
gWSgetaddrinfo = NULL;
gWSfreeaddrinfo = NULL;
#else
gWSgethostbyname = NULL;
gWSgethostbyaddr = NULL;
gWSinet_addr = NULL;
#endif
fInitialized = false;
}
}
BinHTTPURLInputStream::BinHTTPURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo /*=0*/)
: BinHTTPInputStreamCommon(urlSource.getMemoryManager())
, fSocketHandle(0)
{
MemoryManager *memoryManager = urlSource.getMemoryManager();
// Check if we need to load the winsock library. While locking the
// mutex every time may be somewhat slow, we don't care in this
// particular case since the next operation will most likely be
// the network access which is a lot slower.
//
{
XMLMutexLock lock(XMLPlatformUtils::fgAtomicMutex);
if (!fInitialized)
Initialize(memoryManager);
}
//
// Pull all of the parts of the URL out of th urlSource object, and transcode them
// and transcode them back to ASCII.
//
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.
//
#ifdef WITH_IPV6
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 = wrap_getaddrinfo(hostNameAsCharStar,portBuffer.getRawBuffer(),&hints, &res);
if(n != 0)
{
hints.ai_flags = AI_NUMERICHOST;
n = wrap_getaddrinfo(hostNameAsCharStar,(const char*)tempbuf,&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.
fSocketHandle = wrap_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (fSocketHandle == INVALID_SOCKET)
continue;
janSock.reset(&fSocketHandle);
if (wrap_connect(fSocketHandle, ai->ai_addr, (int)ai->ai_addrlen) == SOCKET_ERROR)
{
wrap_freeaddrinfo(res);
// Call WSAGetLastError() to get the error number.
ThrowXMLwithMemMgr1(NetAccessorException,
XMLExcepts::NetAcc_ConnSocket, url.getURLText(), memoryManager);
}
break;
}
wrap_freeaddrinfo(res);
if (fSocketHandle == INVALID_SOCKET)
{
// Call WSAGetLastError() to get the error number.
ThrowXMLwithMemMgr1(NetAccessorException,
XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager);
}
#else
struct hostent* hostEntPtr = 0;
struct sockaddr_in sa;
if ((hostEntPtr = wrap_gethostbyname(hostNameAsCharStar)) == NULL)
{
unsigned long numAddress = wrap_inet_addr(hostNameAsCharStar);
if (numAddress == INADDR_NONE)
{
// Call WSAGetLastError() to get the error number.
ThrowXMLwithMemMgr1(NetAccessorException,
XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager);
}
if ((hostEntPtr =
wrap_gethostbyaddr((const char *) &numAddress,
sizeof(unsigned long), AF_INET)) == NULL)
{
// Call WSAGetLastError() to get the error number.
ThrowXMLwithMemMgr1(NetAccessorException,
XMLExcepts::NetAcc_TargetResolution, hostName, memoryManager);
}
}
memcpy((void *) &sa.sin_addr,
(const void *) hostEntPtr->h_addr, hostEntPtr->h_length);
sa.sin_family = hostEntPtr->h_addrtype;
sa.sin_port = wrap_htons((unsigned short)url.getPortNum());
janSock.reset();
fSocketHandle = wrap_socket(hostEntPtr->h_addrtype, SOCK_STREAM, 0);
if (fSocketHandle == INVALID_SOCKET)
{
// Call WSAGetLastError() to get the error number.
ThrowXMLwithMemMgr1(NetAccessorException,
XMLExcepts::NetAcc_CreateSocket, url.getURLText(), memoryManager);
}
janSock.reset(&fSocketHandle);
if (wrap_connect(fSocketHandle, (struct sockaddr *) &sa, sizeof(sa)) == SOCKET_ERROR)
{
// Call WSAGetLastError() to get the error number.
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.
// 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();
}
BinHTTPURLInputStream::~BinHTTPURLInputStream()
{
wrap_shutdown(fSocketHandle, SD_BOTH);
wrap_closesocket(fSocketHandle);
}
bool BinHTTPURLInputStream::send(const char *buf, XMLSize_t len)
{
XMLSize_t done = 0;
int ret;
while(done < len) {
ret = wrap_send(fSocketHandle, buf + done, (int)(len - done), 0);
if(ret == SOCKET_ERROR) return false;
done += ret;
}
return true;
}
int BinHTTPURLInputStream::receive(char *buf, XMLSize_t len)
{
int iLen = wrap_recv(fSocketHandle, buf, (int)len, 0);
if (iLen == SOCKET_ERROR) return -1;
return iLen;
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,71 @@
/*
* 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: BinHTTPURLInputStream.hpp 670359 2008-06-22 13:43:45Z borisk $
*/
#if !defined(XERCESC_INCLUDE_GUARD_BINHTTPURLINPUTSTREAM_HPP)
#define XERCESC_INCLUDE_GUARD_BINHTTPURLINPUTSTREAM_HPP
#include <xercesc/util/NetAccessors/BinHTTPInputStreamCommon.hpp>
#include <winsock2.h>
XERCES_CPP_NAMESPACE_BEGIN
//
// This class implements the BinInputStream interface specified by the XML
// parser.
//
class XMLUTIL_EXPORT BinHTTPURLInputStream : public BinHTTPInputStreamCommon
{
public :
BinHTTPURLInputStream(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo=0);
~BinHTTPURLInputStream();
virtual bool send(const char *buf, XMLSize_t len);
virtual int receive(char *buf, XMLSize_t len);
static void Cleanup();
private :
// -----------------------------------------------------------------------
// Unimplemented constructors and operators
// -----------------------------------------------------------------------
BinHTTPURLInputStream(const BinHTTPURLInputStream&);
BinHTTPURLInputStream& operator=(const BinHTTPURLInputStream&);
// -----------------------------------------------------------------------
// Private data members
//
// fSocketHandle
// The socket representing the connection to the remote file.
// We deliberately did not define the type to be SOCKET, so as to
// avoid bringing in any Windows header into this file.
// -----------------------------------------------------------------------
SOCKET fSocketHandle;
static bool fInitialized;
static void Initialize(MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager);
};
XERCES_CPP_NAMESPACE_END
#endif // BINHTTPURLINPUTSTREAM_HPP
@@ -0,0 +1,80 @@
/*
* 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: WinSockNetAccessor.cpp 635984 2008-03-11 15:54:37Z borisk $
*/
#define _WINSOCKAPI_
#include <windows.h>
#include <xercesc/util/XMLUniDefs.hpp>
#include <xercesc/util/XMLUni.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/NetAccessors/WinSock/BinHTTPURLInputStream.hpp>
#include <xercesc/util/NetAccessors/WinSock/WinSockNetAccessor.hpp>
XERCES_CPP_NAMESPACE_BEGIN
const XMLCh WinSockNetAccessor::fgMyName[] =
{
chLatin_W, chLatin_i, chLatin_n, chLatin_S, chLatin_o, chLatin_c,
chLatin_k, chLatin_N, chLatin_e, chLatin_t, chLatin_A, chLatin_c,
chLatin_c, chLatin_e, chLatin_s, chLatin_s, chLatin_o, chLatin_r,
chNull
};
WinSockNetAccessor::WinSockNetAccessor()
{
}
WinSockNetAccessor::~WinSockNetAccessor()
{
// Cleanup code for the WinSock library here.
BinHTTPURLInputStream::Cleanup();
}
BinInputStream* WinSockNetAccessor::makeNew(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo /*=0*/)
{
XMLURL::Protocols protocol = urlSource.getProtocol();
switch(protocol)
{
case XMLURL::HTTP:
{
BinHTTPURLInputStream* retStrm =
new (urlSource.getMemoryManager()) BinHTTPURLInputStream(urlSource, httpInfo);
return retStrm;
break;
}
//
// These are the only protocols we support now. So throw and
// unsupported protocol exception for the others.
//
default :
ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_UnsupportedProto, urlSource.getMemoryManager());
break;
}
return 0;
}
XERCES_CPP_NAMESPACE_END
@@ -0,0 +1,65 @@
/*
* 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: WinSockNetAccessor.hpp 527149 2007-04-10 14:56:39Z amassari $
*/
#if !defined(XERCESC_INCLUDE_GUARD_WINSOCKNETACCESSOR_HPP)
#define XERCESC_INCLUDE_GUARD_WINSOCKNETACCESSOR_HPP
#include <xercesc/util/XercesDefs.hpp>
#include <xercesc/util/XMLURL.hpp>
#include <xercesc/util/BinInputStream.hpp>
#include <xercesc/util/XMLNetAccessor.hpp>
XERCES_CPP_NAMESPACE_BEGIN
//
// This class is the wrapper for the WinSock library which provides
// support for sockets. Its being used here to add the ability to
// use HTTP URL's as the system id's in the XML decl clauses.
//
class XMLUTIL_EXPORT WinSockNetAccessor : public XMLNetAccessor
{
public :
WinSockNetAccessor();
~WinSockNetAccessor();
virtual BinInputStream* makeNew(const XMLURL& urlSource, const XMLNetHTTPInfo* httpInfo=0);
virtual const XMLCh* getId() const;
private :
static const XMLCh fgMyName[];
WinSockNetAccessor(const WinSockNetAccessor&);
WinSockNetAccessor& operator=(const WinSockNetAccessor&);
}; // WinSockNetAccessor
inline const XMLCh* WinSockNetAccessor::getId() const
{
return fgMyName;
}
XERCES_CPP_NAMESPACE_END
#endif // WINSOCKNETACCESSOR_HPP