source: icXML/icXML-devel/src/xercesc/util/NetAccessors/BinHTTPInputStreamCommon.cpp @ 2722

Last change on this file since 2722 was 2722, checked in by cameron, 6 years ago

Original Xerces files with import mods for icxercesc

File size: 9.1 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: BinFileInputStream.cpp 553903 2007-07-06 14:43:42Z amassari $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
26
27#if HAVE_CONFIG_H
28#  include <config.h>
29#endif
30
31#include <stdlib.h>
32#include <string.h>
33
34#include <xercesc/util/NetAccessors/BinHTTPInputStreamCommon.hpp>
35
36#include <icxercesc/util/XMLString.hpp>
37#include <xercesc/util/XMLExceptMsgs.hpp>
38#include <xercesc/util/Janitor.hpp>
39#include <icxercesc/util/TransService.hpp>
40#include <icxercesc/util/PlatformUtils.hpp>
41#include <xercesc/util/Base64.hpp>
42
43XERCES_CPP_NAMESPACE_BEGIN
44
45BinHTTPInputStreamCommon::BinHTTPInputStreamCommon(MemoryManager *manager)
46      : fBytesProcessed(0)
47      , fBuffer(1023, manager)
48      , fContentType(0)
49      , fMemoryManager(manager)
50{
51}
52
53
54BinHTTPInputStreamCommon::~BinHTTPInputStreamCommon()
55{
56    if(fContentType) fMemoryManager->deallocate(fContentType);
57}
58
59static const char *CRLF = "\r\n";
60
61void BinHTTPInputStreamCommon::createHTTPRequest(const XMLURL &urlSource, const XMLNetHTTPInfo *httpInfo, CharBuffer &buffer)
62{
63    static const char *GET = "GET ";
64    static const char *PUT = "PUT ";
65    static const char *POST = "POST ";
66    static const char *HTTP10 = " HTTP/1.0\r\n";
67    static const char *HOST = "Host: ";
68    static const char *AUTHORIZATION = "Authorization: Basic ";
69    static const char *COLON = ":";
70
71    XMLTransService::Codes failReason;
72    const XMLSize_t blockSize = 2048;
73
74    XMLTranscoder* trans = XMLPlatformUtils::fgTransService->makeNewTranscoderFor("ISO8859-1", failReason, blockSize, fMemoryManager);
75    Janitor<XMLTranscoder> janTrans(trans);
76
77    TranscodeToStr hostName(urlSource.getHost(), trans, fMemoryManager);
78    TranscodeToStr path(urlSource.getPath(), trans, fMemoryManager);
79    TranscodeToStr fragment(urlSource.getFragment(), trans, fMemoryManager);
80    TranscodeToStr query(urlSource.getQuery(), trans, fMemoryManager);
81
82    // Build up the http GET command to send to the server.
83    // To do:  We should really support http 1.1.  This implementation
84    //         is weak.
85    if(httpInfo) {
86        switch(httpInfo->fHTTPMethod) {
87        case XMLNetHTTPInfo::GET:   buffer.append(GET); break;
88        case XMLNetHTTPInfo::PUT:   buffer.append(PUT); break;
89        case XMLNetHTTPInfo::POST:  buffer.append(POST); break;
90        }
91    }
92    else {
93        buffer.append(GET);
94    }
95
96    if(path.str() != 0) {
97        buffer.append((char*)path.str());
98    }
99    else {
100        buffer.append("/");
101    }
102
103    if(query.str() != 0) {
104        buffer.append("?");
105        buffer.append((char*)query.str());
106    }
107
108    if(fragment.str() != 0) {
109        buffer.append((char*)fragment.str());
110    }
111    buffer.append(HTTP10);
112
113    buffer.append(HOST);
114    buffer.append((char*)hostName.str());
115    if(urlSource.getPortNum() != 80)
116    {
117        buffer.append(COLON);
118        buffer.appendDecimalNumber(urlSource.getPortNum());
119    }
120    buffer.append(CRLF);
121
122    const XMLCh *username = urlSource.getUser();
123    const XMLCh *password = urlSource.getPassword();
124    if(username && password) {
125        XMLBuffer userPassBuf(256, fMemoryManager);
126        userPassBuf.append(username);
127        userPassBuf.append(chColon);
128        userPassBuf.append(password);
129
130        TranscodeToStr userPass(userPassBuf.getRawBuffer(), trans, fMemoryManager);
131
132        XMLSize_t len;
133        XMLByte* encodedData = Base64::encode(userPass.str(), userPass.length(), &len, fMemoryManager);
134        ArrayJanitor<XMLByte> janBuf2(encodedData, fMemoryManager);
135
136        if(encodedData) {
137            // HTTP doesn't want the 0x0A separating the data in chunks of 76 chars per line
138            XMLByte* authData = (XMLByte*)fMemoryManager->allocate((len+1)*sizeof(XMLByte));
139            ArrayJanitor<XMLByte> janBuf(authData, fMemoryManager);
140            XMLByte *cursor = authData;
141            for(XMLSize_t i = 0; i < len; ++i)
142                if(encodedData[i] != chLF)
143                    *cursor++ = encodedData[i];
144            *cursor++ = 0;
145            buffer.append(AUTHORIZATION);
146            buffer.append((char*)authData);
147            buffer.append(CRLF);
148        }
149    }
150
151    if(httpInfo && httpInfo->fHeaders)
152        buffer.append(httpInfo->fHeaders, httpInfo->fHeadersLen);
153
154    buffer.append(CRLF);
155}
156
157XMLCh *BinHTTPInputStreamCommon::findHeader(const char *name)
158{
159    XMLSize_t len = strlen(name);
160
161    char *p = strstr(fBuffer.getRawBuffer(), name);
162    while(p != 0) {
163        if(*(p - 1) == '\n' &&
164            *(p + len) == ':' &&
165            *(p + len + 1) == ' ') {
166
167            p += len + 2;
168
169            char *endP = strstr(p, CRLF);
170            if(endP == 0) {
171                for(endP = p; *endP != 0; ++endP) ;
172            }
173
174            // Transcode from iso-8859-1
175            TranscodeFromStr value((XMLByte*)p, endP - p, "ISO8859-1", fMemoryManager);
176            return value.adopt();
177        }
178
179        p = strstr(p + 1, name);
180    }
181
182    return 0;
183}
184
185int BinHTTPInputStreamCommon::sendRequest(const XMLURL &url, const XMLNetHTTPInfo *httpInfo)
186{
187    //
188    //  Constants in ASCII to send/check in the HTTP request/response
189    //
190
191    static const char *CRLF2X = "\r\n\r\n";
192    static const char *LF2X = "\n\n";
193
194    // The port is open and ready to go.
195    // Build up the http GET command to send to the server.
196    CharBuffer requestBuffer(1023, fMemoryManager);
197    createHTTPRequest(url, httpInfo, requestBuffer);
198
199    // Send the http request
200    if(!send(requestBuffer.getRawBuffer(), requestBuffer.getLen())) {
201        ThrowXMLwithMemMgr1(NetAccessorException,
202                            XMLExcepts::NetAcc_WriteSocket, url.getURLText(), fMemoryManager);
203    }
204
205    if(httpInfo && httpInfo->fPayload) {
206        if(!send(httpInfo->fPayload, httpInfo->fPayloadLen)) {
207            ThrowXMLwithMemMgr1(NetAccessorException,
208                                XMLExcepts::NetAcc_WriteSocket, url.getURLText(), fMemoryManager);
209        }
210    }
211
212    //
213    // get the response, check the http header for errors from the server.
214    //
215    char tmpBuf[1024];
216    int ret;
217
218    fBuffer.reset();
219    while(true) {
220        ret = receive(tmpBuf, sizeof(tmpBuf));
221        if(ret == -1) {
222            ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, url.getURLText(), fMemoryManager);
223        }
224
225        fBuffer.append(tmpBuf, ret);
226
227        fBufferPos = strstr(fBuffer.getRawBuffer(), CRLF2X);
228        if(fBufferPos != 0) {
229            fBufferPos += 4;
230            *(fBufferPos - 2) = 0;
231            break;
232        }
233
234        fBufferPos = strstr(fBuffer.getRawBuffer(), LF2X);
235        if(fBufferPos != 0) {
236            fBufferPos += 2;
237            *(fBufferPos - 1) = 0;
238            break;
239        }
240    }
241
242    // Parse the response status
243    char *p = strstr(fBuffer.getRawBuffer(), "HTTP");
244    if(p == 0) {
245        ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, url.getURLText(), fMemoryManager);
246    }
247
248    p = strchr(p, chSpace);
249    if(p == 0) {
250        ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, url.getURLText(), fMemoryManager);
251    }
252
253    return atoi(p);
254}
255
256const XMLCh *BinHTTPInputStreamCommon::getContentType() const
257{
258    if(fContentType == 0) {
259        // mutable
260        const_cast<BinHTTPInputStreamCommon*>(this)->fContentType =
261        const_cast<BinHTTPInputStreamCommon*>(this)->findHeader("Content-Type");
262    }
263    return fContentType;
264}
265
266XMLSize_t BinHTTPInputStreamCommon::readBytes(XMLByte* const    toFill,
267                                              const XMLSize_t    maxToRead)
268{
269    XMLSize_t len = fBuffer.getRawBuffer() + fBuffer.getLen() - fBufferPos;
270    if(len > 0)
271    {
272        // If there's any data left over in the buffer into which we first
273        //   read from the server (to get the http header), return that.
274        if (len > maxToRead)
275            len = maxToRead;
276        memcpy(toFill, fBufferPos, len);
277        fBufferPos += len;
278    }
279    else
280    {
281        // There was no data in the local buffer.
282        // Read some from the socket, straight into our caller's buffer.
283        //
284        int cbRead = receive((char *)toFill, maxToRead);
285        if (cbRead == -1)
286        {
287            ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, fMemoryManager);
288        }
289        len = cbRead;
290    }
291
292    fBytesProcessed += len;
293    return len;
294}
295
296XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.