Added Xerces-C++ 3.1.2
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user