~ubuntu-branches/ubuntu/wily/afnix/wily

« back to all changes in this revision

Viewing changes to src/mod/nwg/shl/HttpRequest.cpp

  • Committer: Package Import Robot
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2015-07-11 02:00:35 UTC
  • mfrom: (10.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20150711020035-2nhpztq7s15qyc0v
Tags: 2.5.1-1
* New upstream release. (Closes: #789968)
* Update debian/control.
  - Update Standards-Version to 3.9.6.
* Add support mips64(el) and ppc64el. (Closes: #741508, #748146)
* Add patches/support-gcc-5.x.patch. (Closes: #777767)
  - Fix build with gcc-5.x.
* Add patches/Disable-NET0001.als.patch.
  - Disable test of NET0001.als.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
// - the copyright holder be liable for any  direct, indirect, incidental or -
12
12
// - special damages arising in any way out of the use of this software.     -
13
13
// ---------------------------------------------------------------------------
14
 
// - copyright (c) 1999-2012 amaury darsch                                   -
 
14
// - copyright (c) 1999-2015 amaury darsch                                   -
15
15
// ---------------------------------------------------------------------------
16
16
 
17
17
#include "Regex.hpp"
18
18
#include "Vector.hpp"
19
19
#include "Strvec.hpp"
 
20
#include "Boolean.hpp"
20
21
#include "Utility.hpp"
21
22
#include "Runnable.hpp"
22
23
#include "QuarkZone.hpp"
55
56
  static const String HTTP_CONN_ATTR = "Connection";
56
57
  // the http connection value
57
58
  static const String HTTP_CONN_XDEF = "close";
 
59
  // the cookie attribute
 
60
  static const String HTTP_COOK_ATTR = "Cookie";
58
61
  // the form url encoded type
59
62
  static const String HTTP_CTYP_FORM = "application/x-www-form-urlencoded";
60
 
  // the maximum pos content-length with form
61
 
  static const long   HTTP_CLEN_MSIZ = 8192;
 
63
  // the multipart/form data type
 
64
  static const String HTTP_CTYP_PART = "multipart/form-data";
62
65
 
63
66
  // this procedure returns the default request uri by method
64
67
  static String http_rmth_ruri (const String rmth) {
97
100
 
98
101
  // this procedure parse a query string if any
99
102
  static String http_parse_query (const String& rmth, const String& ruri,
100
 
                                  const Plist& head,  InputStream& is) {
 
103
                                  const Plist&  head, const Buffer* rbuf) {
101
104
    // prepare result
102
105
    String result;
103
106
    // eventually normalize the request uri
113
116
    }
114
117
    // process the post method
115
118
    if (rmth ==  HTTP_RMTH_POST) {
 
119
      // check for valid buffer
 
120
      if (rbuf == nilp) return result;
116
121
      // check if the content type is application/x-www-form-urlencoded
117
122
      if (head.exists (HTTP_CTYP_ATTR) == false) return result;
118
123
      if (head.getpval (HTTP_CTYP_ATTR) != HTTP_CTYP_FORM) return result;
119
 
      // check if we have a content length
120
 
      if (head.exists (HTTP_CLEN_ATTR) == false) return result;
 
124
      // use the buffer as the content string
 
125
      result = rbuf->tostring ();
 
126
    }
 
127
    return result;
 
128
  }
 
129
 
 
130
  // this procedure read the content into a buffer
 
131
  static Buffer* http_read_content (const Plist& head, InputStream& is) {
 
132
    Buffer* result = nilp;
 
133
    try {
 
134
      // get the content length
 
135
      if (head.exists (HTTP_CLEN_ATTR) == false) return nilp;
121
136
      long clen = head.tolong (HTTP_CLEN_ATTR);
122
 
      if (clen > HTTP_CLEN_MSIZ) {
123
 
        throw Exception ("http-error", "content length is too large");
124
 
      }
125
 
      // read the string as the content length
126
 
      char rbuf[clen+1];
127
 
      if (is.copy (rbuf, clen) != clen) {
128
 
        throw Exception ("http-error", "cannot extract port query string");
129
 
      }
130
 
      rbuf[clen] = nilc;
131
 
      result = rbuf;
 
137
      // check for nil
 
138
      if (clen <= 0) return nilp;
 
139
      // allocate a buffer by size
 
140
      char* data = new char[clen];
 
141
      // copy the stream into the buffer
 
142
      if (is.copy (data, clen) != clen) {
 
143
        delete [] data;
 
144
        throw Exception ("http-error", 
 
145
                         "inconsistent content length in request");
 
146
      }
 
147
      result = new Buffer (clen, clen, data);
 
148
      // done
 
149
      return result;
 
150
    } catch (...) {
 
151
      delete result;
 
152
      throw;
132
153
    }
133
 
    return result;
 
154
  }
 
155
 
 
156
  // this procedure check if a content-type is multipart and get the boundary
 
157
  static String http_get_multipart_boundary (const Plist& head) {
 
158
    // check for a content type
 
159
    if (head.exists (HTTP_CTYP_ATTR) == false) return "";
 
160
    // get the content type
 
161
    String cval = head.getpval (HTTP_CTYP_ATTR);
 
162
    Strvec pvec = Strvec::split (cval, ";", false);
 
163
    if (pvec.length () != 2) return "";
 
164
    String part = pvec.get(0).strip ();
 
165
    if (part != HTTP_CTYP_PART) return "";
 
166
    Strvec bvec = Strvec::split (pvec.get(1).strip (), "=", false);
 
167
    if (bvec.length () != 2) return "";
 
168
    if (bvec.get(0).strip () != "boundary") return "";
 
169
    return bvec.get(1).strip ();
134
170
  }
135
171
 
136
172
  // -------------------------------------------------------------------------
140
176
  // create a default request
141
177
  
142
178
  HttpRequest::HttpRequest (void) : HttpProto (HTTP_CLIENT) {
 
179
    p_rbuf = nilp;
143
180
    reset ();
144
181
  }
145
182
 
146
183
  // create a http request by method
147
184
  
148
185
  HttpRequest::HttpRequest (const String& rmth) : HttpProto (HTTP_CLIENT) {
 
186
    p_rbuf = nilp;
149
187
    // reset protocol
150
188
    reset ();
151
189
    // set the request data
156
194
  // create a http request by uri
157
195
 
158
196
  HttpRequest::HttpRequest (const Uri& uri) : HttpProto (HTTP_CLIENT) {
 
197
    p_rbuf = nilp;
159
198
    // reset protocol
160
199
    reset ();
161
200
    // set the request data
162
201
    d_rmth = HTTP_RMTH_XDEF;  
163
202
    d_ruri = http_uri_ruri (uri);
164
203
    // set the default header
165
 
    hset (HTTP_HOST_ATTR, uri.getauth ());
166
 
    hset (HTTP_CONN_ATTR, HTTP_CONN_XDEF);
 
204
    HeaderPart::hset (HTTP_HOST_ATTR, uri.getauth ());
 
205
    HeaderPart::hset (HTTP_CONN_ATTR, HTTP_CONN_XDEF);
167
206
  }
168
207
 
169
208
  // create a http request by method and uri name
170
209
  
171
210
  HttpRequest::HttpRequest (const String& rmth,
172
211
                            const String& ruri) : HttpProto (HTTP_CLIENT) {
 
212
    p_rbuf = nilp;
173
213
    // reset protocol
174
214
    reset ();
175
215
    // set the request data
181
221
 
182
222
  HttpRequest::HttpRequest (const String& rmth, 
183
223
                            const Uri& uri) : HttpProto (HTTP_CLIENT) {
 
224
    p_rbuf = nilp;
184
225
    // reset protocol
185
226
    reset ();
186
227
    // set the request data
187
228
    d_rmth = rmth;
188
229
    d_ruri = http_uri_ruri (uri);
189
230
    // set the default header
190
 
    hset (HTTP_HOST_ATTR, uri.getauth ());
191
 
    hset (HTTP_CONN_ATTR, HTTP_CONN_XDEF);
 
231
    HeaderPart::hset (HTTP_HOST_ATTR, uri.getauth ());
 
232
    HeaderPart::hset (HTTP_CONN_ATTR, HTTP_CONN_XDEF);
192
233
  }
193
234
 
194
235
  HttpRequest::HttpRequest (InputStream& is) : HttpProto (HTTP_SERVER) {
 
236
    p_rbuf = nilp;
195
237
    parse (is);
196
238
  }
197
239
 
203
245
      HttpProto::operator = (that);
204
246
      d_rmth = that.d_rmth;
205
247
      d_ruri = that.d_ruri;
206
 
      d_rqry = that.d_rqry;
 
248
      p_rbuf = (that.p_rbuf == nilp) ? nilp : new Buffer (*that.p_rbuf);
 
249
      Object::iref (p_rbuf);
207
250
      that.unlock ();
208
251
    } catch (...) {
209
252
      that.unlock ();
211
254
    }
212
255
  }
213
256
 
 
257
  // destroy this object
 
258
 
 
259
  HttpRequest::~HttpRequest (void) {
 
260
    Object::dref (p_rbuf);
 
261
  }
 
262
 
214
263
  // return the class name
215
264
 
216
265
  String HttpRequest::repr (void) const {
235
284
      HttpProto::operator = (that);
236
285
      d_rmth = that.d_rmth;
237
286
      d_ruri = that.d_ruri;
238
 
      d_rqry = that.d_rqry;
 
287
      Object::dref (p_rbuf); p_rbuf = nilp;
 
288
      p_rbuf = (that.p_rbuf == nilp) ? nilp : new Buffer (*that.p_rbuf);
 
289
      Object::iref (p_rbuf);
239
290
      unlock ();
240
291
      that.unlock ();
241
292
      return *this;
254
305
      HttpProto::reset ();
255
306
      d_rmth = HTTP_RMTH_XDEF;
256
307
      d_ruri = http_rmth_ruri (d_rmth);
257
 
      d_rqry = "";
258
308
      unlock ();
259
309
    } catch (...) {
260
310
      unlock ();
283
333
      }
284
334
      // read the header
285
335
      if (rlen == 3) hparse (is);
286
 
      // read the query string if any
287
 
      d_rqry = http_parse_query (d_rmth, d_ruri, d_head, is);
 
336
      // fill the request buffer
 
337
      p_rbuf = http_read_content (d_head, is);
 
338
      Object::iref (p_rbuf);
288
339
      // unlock and return
289
340
      unlock ();
290
341
    } catch (...) {
390
441
  String HttpRequest::getrqry (void) const {
391
442
    rdlock ();
392
443
    try {
393
 
      String result = d_rqry;
 
444
      String result = http_parse_query (d_rmth, d_ruri, d_head, p_rbuf);
 
445
      // unlock and return
 
446
      unlock ();
 
447
      return result;
 
448
    } catch (...) {
 
449
      unlock ();
 
450
      throw;
 
451
    }
 
452
  }
 
453
 
 
454
  // check if a cookie is defined
 
455
 
 
456
  bool HttpRequest::iscookie (void) const {
 
457
    rdlock ();
 
458
    try {
 
459
      bool result = d_head.exists (HTTP_COOK_ATTR);
 
460
      unlock ();
 
461
      return result;
 
462
    } catch (...) {
 
463
      unlock ();
 
464
      throw;
 
465
    }
 
466
  }
 
467
 
 
468
  // get a cookie object from the header
 
469
 
 
470
  String HttpRequest::getcookie (void) const {
 
471
    rdlock ();
 
472
    try {
 
473
      // check for a cookie string
 
474
      if (d_head.exists (HTTP_COOK_ATTR) == false) {
 
475
        throw Exception ("http-error", "cannot find cookie in request header");
 
476
      }
 
477
      // get the cookie header string
 
478
      String result = d_head.getpval (HTTP_COOK_ATTR);
 
479
      unlock ();
 
480
      return result;
 
481
    } catch (...) {
 
482
      unlock ();
 
483
      throw;
 
484
    }
 
485
  }
 
486
 
 
487
  // get the request buffer if any
 
488
 
 
489
  Buffer* HttpRequest::getrbuf (void) const {
 
490
    rdlock ();
 
491
    try {
 
492
      Buffer* result = p_rbuf;
 
493
      unlock ();
 
494
      return result;
 
495
    } catch (...) {
 
496
      unlock ();
 
497
      throw;
 
498
    }
 
499
  }
 
500
 
 
501
  MultiPart* HttpRequest::getmpart (void) {
 
502
    wrlock ();
 
503
    try {
 
504
      // check for a boundary string
 
505
      String bnds = http_get_multipart_boundary (d_head);
 
506
      // get the multipart content
 
507
      MultiPart* result = nilp;
 
508
      if ((bnds.isnil () == false) && (p_rbuf != nilp)) {
 
509
        result = new MultiPart (bnds, *p_rbuf);
 
510
      }
394
511
      unlock ();
395
512
      return result;
396
513
    } catch (...) {
404
521
  // -------------------------------------------------------------------------
405
522
  
406
523
  // the quark zone
407
 
  static const long QUARK_ZONE_LENGTH = 5;
 
524
  static const long QUARK_ZONE_LENGTH = 9;
408
525
  static QuarkZone  zone (QUARK_ZONE_LENGTH);
409
526
  
410
527
  // the object supported quarks
413
530
  static const long QUARK_SETRURI = zone.intern ("set-uri");
414
531
  static const long QUARK_GETRURI = zone.intern ("get-uri");
415
532
  static const long QUARK_GETRQRY = zone.intern ("get-query");
 
533
  static const long QUARK_ISCOOKP = zone.intern ("cookie-p");
 
534
  static const long QUARK_GETCOOK = zone.intern ("get-cookie");
 
535
  static const long QUARK_GETRBUF = zone.intern ("get-buffer");
 
536
  static const long QUARK_GETMPRT = zone.intern ("get-multipart-content");
416
537
  
417
538
  // create a new object in a generic way
418
539
  
478
599
    
479
600
    // dispatch 0 argument
480
601
    if (argc == 0) {
481
 
      if (quark == QUARK_GETRMTH) return new String (getrmth ());
482
 
      if (quark == QUARK_GETRURI) return new String (getruri ());
483
 
      if (quark == QUARK_GETRQRY) return new String (getrqry ());
 
602
      if (quark == QUARK_GETRMTH) return new String  (getrmth ());
 
603
      if (quark == QUARK_GETRURI) return new String  (getruri ());
 
604
      if (quark == QUARK_GETRQRY) return new String  (getrqry ());
 
605
      if (quark == QUARK_ISCOOKP) return new Boolean (iscookie  ());
 
606
      if (quark == QUARK_GETCOOK) return new String  (getcookie ());
 
607
      if (quark == QUARK_GETMPRT) return getmpart ();
 
608
      if (quark == QUARK_GETRBUF) {
 
609
        rdlock ();
 
610
        try {
 
611
          Object* result = getrbuf ();
 
612
          robj->post (result);
 
613
          unlock ();
 
614
          return result;
 
615
        } catch (...) {
 
616
          unlock ();
 
617
          throw;
 
618
        }
 
619
      }
484
620
    }
485
621
    // dispatch 1 argument
486
622
    if (argc == 1) {