~zorba-coders/zorba/bugs-912586-912593-912722

« back to all changes in this revision

Viewing changes to modules/com/zorba-xquery/www/modules/http-client.xq.src/http_response_parser.cpp

  • Committer: Cezar Andrei
  • Date: 2012-03-28 15:42:12 UTC
  • mfrom: (10606.1.129 zorba)
  • Revision ID: cezar.lp@cezarandrei.com-20120328154212-jh2heq49xcqjppce
Merge from trunck and resolve ChangeLog conflict.

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <zorba/error.h>
27
27
#include <zorba/xquery_exception.h>
28
28
#include <zorba/xquery_functions.h>
 
29
#include <zorba/transcode_stream.h>
29
30
 
30
31
#include "http_response_parser.h"
31
32
#include "http_request_handler.h"
32
33
#include "curl_stream_buffer.h"
33
34
 
34
 
namespace zorba { namespace http_client {
 
35
namespace zorba {
 
36
 
 
37
static void parse_content_type( std::string const &s, std::string *mime_type,
 
38
                                std::string *charset ) {
 
39
  std::string::size_type pos = s.find( ';' );
 
40
  *mime_type = s.substr( 0, pos );
 
41
 
 
42
  if ( pos != std::string::npos ) {
 
43
    //
 
44
    // Parse: charset="?XXXXX"?[ (comment)]
 
45
    //
 
46
    if ( (pos = s.find( '=' )) != std::string::npos ) {
 
47
      std::string t = s.substr( pos + 1 );
 
48
      if ( !t.empty() ) {
 
49
        if ( t[0] == '"' ) {
 
50
          t.erase( 0, 1 );
 
51
          if ( (pos = t.find( '"' )) != std::string::npos )
 
52
            t.erase( pos );
 
53
        } else {
 
54
          if ( (pos = t.find( ' ' )) != std::string::npos )
 
55
            t.erase( pos );
 
56
        }
 
57
        *charset = t;
 
58
      } 
 
59
    }
 
60
  } else {
 
61
    // The HTTP/1.1 spec says that the default charset is ISO-8859-1.
 
62
    *charset = "ISO-8859-1";
 
63
  }
 
64
}
 
65
 
 
66
namespace http_client {
35
67
  
36
68
  HttpResponseParser::HttpResponseParser(RequestHandler& aHandler, CURL* aCurl,
37
69
                                         ErrorThrower& aErrorThrower,
60
92
    if (lCode)
61
93
      return lCode; 
62
94
    if (!theStatusOnly) {
63
 
      std::auto_ptr<std::istream> lStream(new std::istream(theStreamBuffer));
 
95
 
 
96
      if (!theOverridenContentType.empty()) {
 
97
        parse_content_type(
 
98
          theOverridenContentType, &theCurrentContentType, &theCurrentCharset
 
99
        );
 
100
      }
 
101
 
 
102
      std::auto_ptr<std::istream> lStream;
 
103
      if ( transcode::is_necessary( theCurrentCharset.c_str() ) ) {
 
104
        lStream.reset(
 
105
          new transcode::stream<std::istream>(
 
106
            theCurrentCharset.c_str(), theStreamBuffer
 
107
          )
 
108
        );
 
109
      } else
 
110
        lStream.reset(new std::istream(theStreamBuffer));
 
111
 
64
112
      Item lItem;
65
 
      if (theOverridenContentType != "") {
66
 
        theCurrentContentType = theOverridenContentType;
67
 
      }
68
113
      if (theCurrentContentType == "text/xml" ||
69
114
          theCurrentContentType == "application/xml" ||
70
115
          theCurrentContentType == "text/xml-external-parsed-entity" ||
71
116
          theCurrentContentType == "application/xml-external-parsed-entity" ||
72
117
          theCurrentContentType.find("+xml") == theCurrentContentType.size()-4) {
73
118
        lItem = createXmlItem(*lStream.get());
74
 
      } else if (theCurrentContentType.find("text/html") == 0) {
75
 
        lItem = createTextItem(lStream.release());
76
119
      } else if (theCurrentContentType.find("text/") == 0) {
77
120
        lItem = createTextItem(lStream.release());
78
121
      } else {
106
149
    }
107
150
    theInsideRead = true;
108
151
    theHandler.beginResponse(theStatus, theMessage);
109
 
    std::vector<std::pair<std::string, std::string> >::iterator lIter;
110
 
    for (lIter = theHeaders.begin(); lIter != theHeaders.end(); ++lIter) {
 
152
    for ( headers_type::const_iterator
 
153
          lIter = theHeaders.begin(); lIter != theHeaders.end(); ++lIter) {
111
154
      theHandler.header(lIter->first, lIter->second);
112
155
    }
113
156
    if (!theStatusOnly)
120
163
 
121
164
  void HttpResponseParser::registerHandler()
122
165
  {
123
 
    curl_easy_setopt(theCurl, CURLOPT_HEADERFUNCTION,
124
 
      &HttpResponseParser::headerfunction);
 
166
    curl_easy_setopt(theCurl, CURLOPT_HEADERFUNCTION, &curl_headerfunction);
125
167
    curl_easy_setopt(theCurl, CURLOPT_HEADERDATA, this);
126
168
  }
127
169
 
128
 
  size_t HttpResponseParser::headerfunction(void *ptr,
129
 
                                            size_t size,
130
 
                                            size_t nmemb,
131
 
                                            void *stream)
 
170
  size_t HttpResponseParser::curl_headerfunction( void *ptr, size_t size,
 
171
                                                  size_t nmemb, void *data )
132
172
  {
133
173
    size_t lSize = size*nmemb;
134
174
    size_t lResult = lSize;
135
 
    HttpResponseParser* lParser = static_cast<HttpResponseParser*>(stream);
 
175
    HttpResponseParser* lParser = static_cast<HttpResponseParser*>(data);
136
176
    if (lParser->theInsideRead) {
137
177
      lParser->theHandler.endBody();
 
178
      lParser->theInsideRead = false;
138
179
    }
139
 
    lParser->theInsideRead = false;
140
180
    const char* lDataChar = (const char*) ptr;
141
181
    while (lSize != 0 && (lDataChar[lSize - 1] == 10
142
182
          || lDataChar[lSize - 1] == 13)) {
173
213
    }
174
214
    String lNameS = fn::lower_case( lName );
175
215
    if (lNameS == "content-type") {
176
 
      lParser->theCurrentContentType = lValue.substr(0, lValue.find(';'));
 
216
      parse_content_type(
 
217
        lValue, &lParser->theCurrentContentType, &lParser->theCurrentCharset
 
218
      );
177
219
    } else if (lNameS == "content-id") {
178
220
      lParser->theId = lValue;
179
221
    } else if (lNameS == "content-description") {
184
226
    return lResult;
185
227
  }
186
228
 
187
 
  void HttpResponseParser::parseStatusAndMessage(std::string aHeader)
 
229
  void HttpResponseParser::parseStatusAndMessage(std::string const &aHeader)
188
230
  {
189
231
    std::string::size_type lPos = aHeader.find(' ');
190
232
    assert(lPos != std::string::npos);
215
257
  static void streamReleaser(std::istream* aStream)
216
258
  {
217
259
    // This istream contains our curl stream buffer, so we have to delete it too
218
 
    delete aStream->rdbuf();
 
260
    std::streambuf *const sbuf = aStream->rdbuf();
 
261
    if ( transcode::streambuf *tbuf =
 
262
          dynamic_cast<transcode::streambuf*>( sbuf ) )
 
263
      delete tbuf->orig_streambuf();
 
264
    else
 
265
      delete sbuf;
219
266
    delete aStream;
220
267
  }
221
268
 
265
312
      return Item(); 
266
313
    }
267
314
  }
268
 
}}
 
315
 
 
316
} // namespace http_client
 
317
} // namespace zorba
 
318
/* vim:set et sw=2 ts=2: */