GME
13
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /* 00019 * $Id: BinFileInputStream.cpp 553903 2007-07-06 14:43:42Z amassari $ 00020 */ 00021 00022 00023 // --------------------------------------------------------------------------- 00024 // Includes 00025 // --------------------------------------------------------------------------- 00026 00027 #if HAVE_CONFIG_H 00028 # include <config.h> 00029 #endif 00030 00031 #include <stdlib.h> 00032 #include <string.h> 00033 00034 #include <xercesc/util/NetAccessors/BinHTTPInputStreamCommon.hpp> 00035 00036 #include <xercesc/util/XMLString.hpp> 00037 #include <xercesc/util/XMLExceptMsgs.hpp> 00038 #include <xercesc/util/Janitor.hpp> 00039 #include <xercesc/util/TransService.hpp> 00040 #include <xercesc/util/PlatformUtils.hpp> 00041 #include <xercesc/util/Base64.hpp> 00042 00043 XERCES_CPP_NAMESPACE_BEGIN 00044 00045 BinHTTPInputStreamCommon::BinHTTPInputStreamCommon(MemoryManager *manager) 00046 : fBytesProcessed(0) 00047 , fBuffer(1023, manager) 00048 , fContentType(0) 00049 , fMemoryManager(manager) 00050 { 00051 } 00052 00053 00054 BinHTTPInputStreamCommon::~BinHTTPInputStreamCommon() 00055 { 00056 if(fContentType) fMemoryManager->deallocate(fContentType); 00057 } 00058 00059 static const char *CRLF = "\r\n"; 00060 00061 void BinHTTPInputStreamCommon::createHTTPRequest(const XMLURL &urlSource, const XMLNetHTTPInfo *httpInfo, CharBuffer &buffer) 00062 { 00063 static const char *GET = "GET "; 00064 static const char *PUT = "PUT "; 00065 static const char *POST = "POST "; 00066 static const char *HTTP10 = " HTTP/1.0\r\n"; 00067 static const char *HOST = "Host: "; 00068 static const char *AUTHORIZATION = "Authorization: Basic "; 00069 static const char *COLON = ":"; 00070 00071 XMLTransService::Codes failReason; 00072 const XMLSize_t blockSize = 2048; 00073 00074 XMLTranscoder* trans = XMLPlatformUtils::fgTransService->makeNewTranscoderFor("ISO8859-1", failReason, blockSize, fMemoryManager); 00075 Janitor<XMLTranscoder> janTrans(trans); 00076 00077 TranscodeToStr hostName(urlSource.getHost(), trans, fMemoryManager); 00078 TranscodeToStr path(urlSource.getPath(), trans, fMemoryManager); 00079 TranscodeToStr fragment(urlSource.getFragment(), trans, fMemoryManager); 00080 TranscodeToStr query(urlSource.getQuery(), trans, fMemoryManager); 00081 00082 // Build up the http GET command to send to the server. 00083 // To do: We should really support http 1.1. This implementation 00084 // is weak. 00085 if(httpInfo) { 00086 switch(httpInfo->fHTTPMethod) { 00087 case XMLNetHTTPInfo::GET: buffer.append(GET); break; 00088 case XMLNetHTTPInfo::PUT: buffer.append(PUT); break; 00089 case XMLNetHTTPInfo::POST: buffer.append(POST); break; 00090 } 00091 } 00092 else { 00093 buffer.append(GET); 00094 } 00095 00096 if(path.str() != 0) { 00097 buffer.append((char*)path.str()); 00098 } 00099 else { 00100 buffer.append("/"); 00101 } 00102 00103 if(query.str() != 0) { 00104 buffer.append("?"); 00105 buffer.append((char*)query.str()); 00106 } 00107 00108 if(fragment.str() != 0) { 00109 buffer.append((char*)fragment.str()); 00110 } 00111 buffer.append(HTTP10); 00112 00113 buffer.append(HOST); 00114 buffer.append((char*)hostName.str()); 00115 if(urlSource.getPortNum() != 80) 00116 { 00117 buffer.append(COLON); 00118 buffer.appendDecimalNumber(urlSource.getPortNum()); 00119 } 00120 buffer.append(CRLF); 00121 00122 const XMLCh *username = urlSource.getUser(); 00123 const XMLCh *password = urlSource.getPassword(); 00124 if(username && password) { 00125 XMLBuffer userPassBuf(256, fMemoryManager); 00126 userPassBuf.append(username); 00127 userPassBuf.append(chColon); 00128 userPassBuf.append(password); 00129 00130 TranscodeToStr userPass(userPassBuf.getRawBuffer(), trans, fMemoryManager); 00131 00132 XMLSize_t len; 00133 XMLByte* encodedData = Base64::encode(userPass.str(), userPass.length(), &len, fMemoryManager); 00134 ArrayJanitor<XMLByte> janBuf2(encodedData, fMemoryManager); 00135 00136 if(encodedData) { 00137 // HTTP doesn't want the 0x0A separating the data in chunks of 76 chars per line 00138 XMLByte* authData = (XMLByte*)fMemoryManager->allocate((len+1)*sizeof(XMLByte)); 00139 ArrayJanitor<XMLByte> janBuf(authData, fMemoryManager); 00140 XMLByte *cursor = authData; 00141 for(XMLSize_t i = 0; i < len; ++i) 00142 if(encodedData[i] != chLF) 00143 *cursor++ = encodedData[i]; 00144 *cursor++ = 0; 00145 buffer.append(AUTHORIZATION); 00146 buffer.append((char*)authData); 00147 buffer.append(CRLF); 00148 } 00149 } 00150 00151 if(httpInfo && httpInfo->fHeaders) 00152 buffer.append(httpInfo->fHeaders, httpInfo->fHeadersLen); 00153 00154 buffer.append(CRLF); 00155 } 00156 00157 XMLCh *BinHTTPInputStreamCommon::findHeader(const char *name) 00158 { 00159 XMLSize_t len = strlen(name); 00160 00161 char *p = strstr(fBuffer.getRawBuffer(), name); 00162 while(p != 0) { 00163 if(*(p - 1) == '\n' && 00164 *(p + len) == ':' && 00165 *(p + len + 1) == ' ') { 00166 00167 p += len + 2; 00168 00169 char *endP = strstr(p, CRLF); 00170 if(endP == 0) { 00171 for(endP = p; *endP != 0; ++endP) ; 00172 } 00173 00174 // Transcode from iso-8859-1 00175 TranscodeFromStr value((XMLByte*)p, endP - p, "ISO8859-1", fMemoryManager); 00176 return value.adopt(); 00177 } 00178 00179 p = strstr(p + 1, name); 00180 } 00181 00182 return 0; 00183 } 00184 00185 int BinHTTPInputStreamCommon::sendRequest(const XMLURL &url, const XMLNetHTTPInfo *httpInfo) 00186 { 00187 // 00188 // Constants in ASCII to send/check in the HTTP request/response 00189 // 00190 00191 static const char *CRLF2X = "\r\n\r\n"; 00192 static const char *LF2X = "\n\n"; 00193 00194 // The port is open and ready to go. 00195 // Build up the http GET command to send to the server. 00196 CharBuffer requestBuffer(1023, fMemoryManager); 00197 createHTTPRequest(url, httpInfo, requestBuffer); 00198 00199 // Send the http request 00200 if(!send(requestBuffer.getRawBuffer(), requestBuffer.getLen())) { 00201 ThrowXMLwithMemMgr1(NetAccessorException, 00202 XMLExcepts::NetAcc_WriteSocket, url.getURLText(), fMemoryManager); 00203 } 00204 00205 if(httpInfo && httpInfo->fPayload) { 00206 if(!send(httpInfo->fPayload, httpInfo->fPayloadLen)) { 00207 ThrowXMLwithMemMgr1(NetAccessorException, 00208 XMLExcepts::NetAcc_WriteSocket, url.getURLText(), fMemoryManager); 00209 } 00210 } 00211 00212 // 00213 // get the response, check the http header for errors from the server. 00214 // 00215 char tmpBuf[1024]; 00216 int ret; 00217 00218 fBuffer.reset(); 00219 while(true) { 00220 ret = receive(tmpBuf, sizeof(tmpBuf)); 00221 if(ret == -1) { 00222 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, url.getURLText(), fMemoryManager); 00223 } 00224 00225 fBuffer.append(tmpBuf, ret); 00226 00227 fBufferPos = strstr(fBuffer.getRawBuffer(), CRLF2X); 00228 if(fBufferPos != 0) { 00229 fBufferPos += 4; 00230 *(fBufferPos - 2) = 0; 00231 break; 00232 } 00233 00234 fBufferPos = strstr(fBuffer.getRawBuffer(), LF2X); 00235 if(fBufferPos != 0) { 00236 fBufferPos += 2; 00237 *(fBufferPos - 1) = 0; 00238 break; 00239 } 00240 } 00241 00242 // Parse the response status 00243 char *p = strstr(fBuffer.getRawBuffer(), "HTTP"); 00244 if(p == 0) { 00245 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, url.getURLText(), fMemoryManager); 00246 } 00247 00248 p = strchr(p, chSpace); 00249 if(p == 0) { 00250 ThrowXMLwithMemMgr1(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, url.getURLText(), fMemoryManager); 00251 } 00252 00253 return atoi(p); 00254 } 00255 00256 const XMLCh *BinHTTPInputStreamCommon::getContentType() const 00257 { 00258 if(fContentType == 0) { 00259 // mutable 00260 const_cast<BinHTTPInputStreamCommon*>(this)->fContentType = 00261 const_cast<BinHTTPInputStreamCommon*>(this)->findHeader("Content-Type"); 00262 } 00263 return fContentType; 00264 } 00265 00266 XMLSize_t BinHTTPInputStreamCommon::readBytes(XMLByte* const toFill, 00267 const XMLSize_t maxToRead) 00268 { 00269 XMLSize_t len = fBuffer.getRawBuffer() + fBuffer.getLen() - fBufferPos; 00270 if(len > 0) 00271 { 00272 // If there's any data left over in the buffer into which we first 00273 // read from the server (to get the http header), return that. 00274 if (len > maxToRead) 00275 len = maxToRead; 00276 memcpy(toFill, fBufferPos, len); 00277 fBufferPos += len; 00278 } 00279 else 00280 { 00281 // There was no data in the local buffer. 00282 // Read some from the socket, straight into our caller's buffer. 00283 // 00284 int cbRead = receive((char *)toFill, maxToRead); 00285 if (cbRead == -1) 00286 { 00287 ThrowXMLwithMemMgr(NetAccessorException, XMLExcepts::NetAcc_ReadSocket, fMemoryManager); 00288 } 00289 len = cbRead; 00290 } 00291 00292 fBytesProcessed += len; 00293 return len; 00294 } 00295 00296 XERCES_CPP_NAMESPACE_END