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

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Anibal Monsalve Salazar
  • Date: 2011-03-16 21:31:18 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110316213118-gk4k3ez3e5d2huna
Tags: 2.0.0-1
* QA upload.
* New upstream release
* Debian source format is 3.0 (quilt)
* Fix debhelper-but-no-misc-depends
* Fix ancient-standards-version
* Fix package-contains-linda-override
* debhelper compatibility is 7
* Fix dh-clean-k-is-deprecated

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// ---------------------------------------------------------------------------
2
 
// - HttpReply.cpp                                                           -
3
 
// - afnix:nwg module - http reply class implementation                      -
4
 
// ---------------------------------------------------------------------------
5
 
// - This program is free software;  you can redistribute it  and/or  modify -
6
 
// - it provided that this copyright notice is kept intact.                  -
7
 
// -                                                                         -
8
 
// - This program  is  distributed in  the hope  that it will be useful, but -
9
 
// - without  any  warranty;  without  even   the   implied    warranty   of -
10
 
// - merchantability or fitness for a particular purpose.  In no event shall -
11
 
// - the copyright holder be liable for any  direct, indirect, incidental or -
12
 
// - special damages arising in any way out of the use of this software.     -
13
 
// ---------------------------------------------------------------------------
14
 
// - copyright (c) 1999-2007 amaury darsch                                   -
15
 
// ---------------------------------------------------------------------------
16
 
 
17
 
#include "Vector.hpp"
18
 
#include "Runnable.hpp"
19
 
#include "HttpReply.hpp"
20
 
#include "QuarkZone.hpp"
21
 
#include "Exception.hpp"
22
 
 
23
 
namespace afnix {
24
 
 
25
 
  // -------------------------------------------------------------------------
26
 
  // - private section                                                       -
27
 
  // -------------------------------------------------------------------------
28
 
 
29
 
  // the content type header as a mime property
30
 
  static const String HTTP_MIME_NAME = "Content-Type";
31
 
  static const String HTTP_MIME_PVAL = "text/plain";
32
 
 
33
 
  // the http location name
34
 
  static const String HTTP_RLOC_NAME = "Location";
35
 
  // the http cookie version 0 name
36
 
  static const String HTTP_COK0_NAME = "Set-Cookie";
37
 
  // the http cookie version 1 name
38
 
  static const String HTTP_COK1_NAME = "Set-Cookie2";
39
 
 
40
 
  // the http status name
41
 
  static const String HTTP_STAT_NAME = "Status";
42
 
 
43
 
  // this procedure returns true if the header contains a status code that
44
 
  // prohibits the existence of a message body
45
 
  static bool is_body_valid (const Plist& head) {
46
 
    // check if the status property is defined
47
 
    if (head.exists (HTTP_STAT_NAME) == false) return true;
48
 
    // get the status value and check
49
 
    String mesg = head.getpval (HTTP_STAT_NAME);
50
 
    if (mesg == HttpProto::mapcode (100)) return false;
51
 
    if (mesg == HttpProto::mapcode (101)) return false;
52
 
    if (mesg == HttpProto::mapcode (204)) return false;
53
 
    if (mesg == HttpProto::mapcode (304)) return false;
54
 
    return true;
55
 
  }
56
 
 
57
 
  // -------------------------------------------------------------------------
58
 
  // - class section                                                         -
59
 
  // -------------------------------------------------------------------------
60
 
 
61
 
  // create an empty http reply
62
 
 
63
 
  HttpReply::HttpReply (void) {
64
 
    // add the content-type property
65
 
    sethead (HTTP_MIME_NAME, HTTP_MIME_PVAL);
66
 
  }
67
 
 
68
 
  // create an empty http reply with a type
69
 
 
70
 
  HttpReply::HttpReply (const String& type) {
71
 
    sethead (HTTP_MIME_NAME, type);
72
 
  }
73
 
 
74
 
  // return the class name
75
 
 
76
 
  String HttpReply::repr (void) const {
77
 
    return "HttpReply";
78
 
  }
79
 
 
80
 
  // set a cookie in the header
81
 
 
82
 
  void HttpReply::setcook (const Cookie& cook) {
83
 
    wrlock ();
84
 
    try {
85
 
      if (cook.getvers () == 0) {
86
 
        sethead (HTTP_COK0_NAME, cook.tostring ());
87
 
      } else if (cook.getvers () == 1) {
88
 
        sethead (HTTP_COK1_NAME, cook.tostring ());
89
 
      } else {
90
 
        throw Exception ("http-error", "invalid cookie version");
91
 
      }
92
 
      unlock ();
93
 
    } catch (...) {
94
 
      unlock ();
95
 
      throw;
96
 
    }
97
 
  }
98
 
 
99
 
  // add a string in the http buffer
100
 
 
101
 
  void HttpReply::addhbuf (const Literal& lval) {
102
 
    wrlock ();
103
 
    try {
104
 
      d_hbuf.add (lval.tostring ());
105
 
      unlock ();
106
 
    } catch (...) {
107
 
      unlock ();
108
 
      throw;
109
 
    }
110
 
  }
111
 
 
112
 
  // add a mime document in the http buffer
113
 
 
114
 
  void HttpReply::addhbuf (const Mime& mime) {
115
 
    wrlock ();
116
 
    try {
117
 
      // get he mime type
118
 
      String type = mime.getmime ();
119
 
      sethead (HTTP_MIME_NAME, type);
120
 
      // while the mime dcoument to the http buffer
121
 
      mime.write (d_hbuf);
122
 
      unlock ();
123
 
    } catch (...) {
124
 
      unlock ();
125
 
      throw;
126
 
    }
127
 
  }
128
 
 
129
 
  // add a buffer in the http buffer
130
 
 
131
 
  void HttpReply::addhbuf (const Buffer& buf) {
132
 
    wrlock ();
133
 
    try {
134
 
      d_hbuf.add (buf);
135
 
      unlock ();
136
 
    } catch (...) {
137
 
      unlock ();
138
 
      throw;
139
 
    }
140
 
  }
141
 
 
142
 
  // set a http status by code
143
 
 
144
 
  void HttpReply::setstatus (const long code) {
145
 
    wrlock ();
146
 
    try {
147
 
      // get the status message
148
 
      sethead (HTTP_STAT_NAME, HttpProto::mapcode (code));
149
 
      unlock ();
150
 
    } catch (...) {
151
 
      unlock ();
152
 
      throw;
153
 
    }
154
 
  }
155
 
 
156
 
  // redirect a to a certain location
157
 
 
158
 
  void HttpReply::redirect (const String& url) {
159
 
    wrlock ();
160
 
    try {
161
 
      // set a status 303 (see other)
162
 
      setstatus (303);
163
 
      // set the redirection location
164
 
      sethead (HTTP_RLOC_NAME, url);
165
 
      unlock ();
166
 
    } catch (...) {
167
 
      unlock ();
168
 
      throw;
169
 
    }
170
 
  }
171
 
 
172
 
  // write the http reply to an output stream
173
 
 
174
 
  void HttpReply:: write (Output& os) const {
175
 
    rdlock ();
176
 
    try {
177
 
      // write the header
178
 
      HttpProto::write (os);
179
 
      // write the body
180
 
      if (is_body_valid (d_head) == true) {
181
 
        d_hbuf.write (os);
182
 
      }
183
 
      // done
184
 
      unlock ();
185
 
    } catch (...) {
186
 
      unlock ();
187
 
      throw;
188
 
    }
189
 
  }
190
 
 
191
 
  // write the http reply to a buffer
192
 
 
193
 
  void HttpReply:: write (Buffer& buf) const {
194
 
    rdlock ();
195
 
    try {
196
 
      // write the header
197
 
      HttpProto::write (buf);
198
 
      // write the body
199
 
      if (is_body_valid (d_head) == true) {
200
 
        buf.add (d_hbuf);
201
 
      }
202
 
      // done
203
 
      unlock ();
204
 
    } catch (...) {
205
 
      unlock ();
206
 
      throw;
207
 
    }
208
 
  }
209
 
 
210
 
  // -------------------------------------------------------------------------
211
 
  // - object section                                                        -
212
 
  // -------------------------------------------------------------------------
213
 
 
214
 
  // the quark zone
215
 
  static const long QUARK_ZONE_LENGTH = 4;
216
 
  static QuarkZone  zone (QUARK_ZONE_LENGTH);
217
 
 
218
 
  // the object supported quarks
219
 
  static const long QUARK_SETCOOK   = zone.intern ("set-cookie");
220
 
  static const long QUARK_ADDHBUF   = zone.intern ("add-buffer");
221
 
  static const long QUARK_REDIRECT  = zone.intern ("redirect");
222
 
  static const long QUARK_SETSTATUS = zone.intern ("set-status");
223
 
 
224
 
  // create a new object in a generic way
225
 
 
226
 
  Object* HttpReply::mknew (Vector* argv) {
227
 
    long argc = (argv == nilp) ? 0 : argv->length ();
228
 
    // check for 0 argument
229
 
    if (argc == 0) return new HttpReply;
230
 
    //check for 1 argument
231
 
    if (argc == 1) {
232
 
      String type = argv->getstring (0);
233
 
      return new HttpReply (type);
234
 
    }
235
 
    // wrong arguments
236
 
    throw Exception ("argument-error", 
237
 
                     "too many arguments with http reply constructor");
238
 
  }
239
 
 
240
 
  // return true if the given quark is defined
241
 
 
242
 
  bool HttpReply::isquark (const long quark, const bool hflg) const {
243
 
    rdlock ();
244
 
    if (zone.exists (quark) == true) {
245
 
      unlock ();
246
 
      return true;
247
 
    }
248
 
    bool result = hflg ? HttpProto::isquark (quark, hflg) : false;
249
 
    unlock ();
250
 
    return result;
251
 
  }
252
 
 
253
 
  // apply this object with a set of arguments and a quark
254
 
 
255
 
  Object* HttpReply::apply (Runnable* robj, Nameset* nset, const long quark,
256
 
                            Vector* argv) {
257
 
    // get the number of arguments
258
 
    long argc = (argv == nilp) ? 0 : argv->length ();
259
 
    
260
 
    // dispatch 1 argument
261
 
    if (argc == 1) {
262
 
      if (quark == QUARK_ADDHBUF) {
263
 
        Object* obj = argv->get (0);
264
 
        // check for a literal
265
 
        Literal* lobj = dynamic_cast <Literal*> (obj);
266
 
        if (lobj != nilp) {
267
 
          addhbuf (*lobj);
268
 
          return nilp;
269
 
        }
270
 
        // check for a buffer
271
 
        Buffer* buf = dynamic_cast <Buffer*> (obj);
272
 
        if (buf != nilp) {
273
 
          addhbuf (*buf);
274
 
          return nilp;
275
 
        }
276
 
        // check for a mime document
277
 
        Mime* mobj = dynamic_cast <Mime*> (obj);
278
 
        if (mobj != nilp) {
279
 
          addhbuf (*mobj);
280
 
          return nilp;
281
 
        }
282
 
        throw Exception ("type-error", "invalid object with add-buffer",
283
 
                         Object::repr (obj));
284
 
      }
285
 
      if (quark == QUARK_REDIRECT) {
286
 
        String url = argv->getstring (0);
287
 
        redirect (url);
288
 
        return nilp;
289
 
      }
290
 
      if (quark == QUARK_SETSTATUS) {
291
 
        long code = argv->getint (0);
292
 
        setstatus (code);
293
 
        return nilp;
294
 
      }
295
 
      if (quark == QUARK_SETCOOK) {
296
 
        Object*   obj = argv->get (0);
297
 
        Cookie*  cobj = dynamic_cast <Cookie*> (obj);
298
 
        if (cobj == nilp) {
299
 
          throw Exception ("type-error", "invalid object with set-cookie",
300
 
                           Object::repr (obj));
301
 
        }
302
 
        setcook (*cobj);
303
 
        return nilp;
304
 
      }
305
 
    }
306
 
    // call the http proto method
307
 
    return HttpProto::apply (robj, nset, quark, argv);
308
 
  }
309
 
}