Merge branch 'master' into jwi-bcc64xsingletonwarning
[ACE_TAO.git] / ACE / apps / JAWS2 / JAWS / Parse_Headers.cpp
blobe1ce02ce1299c303bf8dcd381fad96438ec46cce
1 #include "JAWS/Parse_Headers.h"
2 #include "ace/OS_NS_string.h"
3 #include "ace/Log_Msg.h"
5 #define ACCESSOR(T,C,x) \
6 T C :: x () const { return this-> x##_; }\
7 void C :: x (T t) { this-> x##_ = t; }
9 int
10 JAWS_Parse_Headers::parse_headers (JAWS_Header_Info *info,
11 ACE_Message_Block &mb)
13 for (;;)
15 if (mb.rd_ptr () == mb.wr_ptr ())
16 break;
18 char *p = mb.rd_ptr ();
20 if (info->end_of_line ()
21 && (*p != ' ' && *p != '\t'))
23 int r = this->parse_header_name (info, mb);
24 if (r == 1)
25 return info->end_of_headers ();
26 continue;
28 else
30 int r = this->parse_header_value (info, mb);
31 if (r == 1)
33 if (info->end_of_headers ())
34 return 1;
35 break;
37 continue;
41 // If we arrive here, it means either there is nothing more to read,
42 // or parse_header_value ran into difficulties (like maybe the
43 // header value was too long).
45 if (mb.rd_ptr () != mb.base ())
47 mb.crunch ();
48 return 0;
50 else if (mb.length () < mb.size ())
52 return 0;
54 else if (mb.length () == mb.size ())
56 // This is one of those cases that should rarely ever happen.
57 // If we get here, the header type name is over 8K long. We
58 // flag this as a bad thing.
60 // In HTTP/1.1, I have to remember that a bad request means the
61 // connection needs to be closed and the client has to
62 // reinitiate the connection.
64 info->status (JAWS_Header_Info::STATUS_CODE_TOO_LONG);
65 return 1;
67 else if (mb.length () > mb.size ())
69 ACE_DEBUG ((LM_DEBUG, "JAWS_Parse_Headers: buffer overrun!!\n"));
70 info->status (JAWS_Header_Info::STATUS_CODE_TOO_LONG);
71 return 1;
74 ACE_DEBUG ((LM_DEBUG, "JAWS_Parse_Headers -- shouldn't be here!\n"));
75 return 1;
78 char *
79 JAWS_Parse_Headers::skipset (const char *set, char *start, char *end)
81 char *p = start;
82 while (p < end)
84 if (ACE_OS::strchr (set, *p) != 0)
85 break;
86 p++;
88 return p;
91 char *
92 JAWS_Parse_Headers::skipcset (const char *set, char *start, char *end)
94 char *p = start;
95 while (p < end)
97 if (ACE_OS::strchr (set, *p) == 0)
98 break;
99 p++;
101 return p;
105 JAWS_Parse_Headers::parse_header_name (JAWS_Header_Info *info,
106 ACE_Message_Block &mb)
108 char *p = mb.rd_ptr ();
109 char *q;
111 q = this->skipset (":\n", p, mb.wr_ptr ());
112 if (q == mb.wr_ptr ())
114 // no more progress can be made until we find a ':'
115 return 1;
117 if (*q != '\n' && q == p)
119 // Ignore empty header type names
120 info->finish_last_header_value ();
121 info->create_next_header_value (0);
122 info->end_of_line (0);
123 mb.rd_ptr (q+1);
124 return 0;
126 if (*q == '\n')
128 // ignore this line
129 mb.rd_ptr (q+1);
130 if (q == p || ((q-1) == p && q[-1] == '\r'))
132 // blank line means end of headers
133 info->finish_last_header_value ();
134 info->create_next_header_value (0);
135 info->end_of_headers (1);
136 if (mb.rd_ptr () == mb.wr_ptr ())
137 mb.crunch ();
138 return 1;
141 // not a blank line, but no ':', so ignore it
142 info->finish_last_header_value ();
143 info->create_next_header_value (0);
144 return 0;
147 // otherwise, we have a header type name!
148 *q = '\0';
149 info->create_next_header_value (p);
150 info->end_of_line (0);
152 mb.rd_ptr (q+1);
153 return 0;
157 JAWS_Parse_Headers::parse_header_value (JAWS_Header_Info *info,
158 ACE_Message_Block &mb)
160 // break --> return 1;
161 // continue --> return 0;
163 char *q = mb.rd_ptr ();
165 if (info->last_header_data () == 0)
167 // Ignoring this header (it is too long or something).
169 q = this->skipset ("\n", mb.rd_ptr (), mb.wr_ptr ());
170 if (q == mb.wr_ptr ())
172 info->end_of_line (0);
173 mb.rd_ptr (q);
175 // Move the rd_ptr back one character if the last thing we
176 // see is a carriage return. Assert: wr_ptr > rd_ptr.
177 if (q[-1] == '\r')
178 mb.rd_ptr (q-1);
180 return 1;
183 if (*q == '\0')
185 // We are in the middle of binary data. Get out!
186 mb.rd_ptr (q);
187 info->end_of_line (1);
188 info->end_of_headers (1);
189 return 1;
192 // Move past the newline, set the end of line flag
193 if (*q == '\n')
195 info->end_of_line (1);
196 q++;
198 mb.rd_ptr (q);
200 return 0;
202 else
204 if (info->end_of_line ())
206 // Skip over leading linear white space
207 q = this->skipcset (" \t", mb.rd_ptr (), mb.wr_ptr ());
208 if (q == mb.wr_ptr ())
210 // need more input
211 info->end_of_line (1);
212 mb.rd_ptr (q-1);
213 return 1;
216 if (*q != '\n')
217 info->append_last_header_value (' ');
220 // Append to last header value character by character
221 while (q < mb.wr_ptr ())
223 if (*q == '\n')
224 break;
225 info->append_last_header_value (*q);
226 q++;
229 // Need more input
230 if (q == mb.wr_ptr ())
232 mb.rd_ptr (q);
233 info->end_of_line (0);
234 return 1;
237 // Reached a newline
238 if (*q == '\n')
240 // Reduce by one character if line discipline is "\r\n"
241 if (info->append_last_header_value () == '\r')
242 info->reduce_last_header_value ();
244 // Move past newline, set end of line flag
245 mb.rd_ptr (q+1);
246 info->end_of_line (1);
248 return 0;
252 // NOT REACHED
253 return 1;
257 JAWS_Header_Info::JAWS_Header_Info ()
258 : end_of_headers_ (0),
259 end_of_line_ (1),
260 last_header_data_ (0),
261 last_header_length_ (0),
262 status_ (0)
266 JAWS_Header_Info::~JAWS_Header_Info ()
268 JAWS_Header_Table_Iterator iter (this->table_);
269 JAWS_Header_Data *data_ptr;
271 for (iter.first (); !iter.done (); iter.advance ())
273 data_ptr = iter.next ();
274 if (data_ptr)
275 delete data_ptr;
279 void
280 JAWS_Header_Info::dump ()
282 JAWS_Header_Table_Iterator iter (this->table_);
284 ACE_DEBUG ((LM_DEBUG, "== BEGIN HEADER INFO DUMP ==\n"));
285 for (iter.first (); ! iter.done (); iter.advance ())
287 JAWS_Header_Data *data;
288 data = iter.next ();
289 if (data != 0)
290 ACE_DEBUG ((LM_DEBUG,
291 "%s -- %s\n",
292 data->header_name (), data->header_value ()));
293 else
294 ACE_DEBUG ((LM_DEBUG, "NULL ENTRY\n"));
296 ACE_DEBUG ((LM_DEBUG, "== END HEADER INFO DUMP ==\n"));
299 JAWS_Headers *
300 JAWS_Header_Info::table ()
302 return &(this->table_);
305 void
306 JAWS_Header_Info::append_last_header_value (char c)
308 if (this->last_header_data_ == 0)
309 return;
311 if (this->last_header_length_ == 0 && (c == ' ' || c == '\t'))
312 return;
314 if (this->last_header_length_ < MAX_HEADER_LENGTH-1)
316 this->header_buf_[this->last_header_length_] = c;
317 this->last_header_length_++;
318 this->header_buf_[this->last_header_length_] = '\0';
324 JAWS_Header_Info::append_last_header_value ()
326 if (this->last_header_data_ == 0 || this->last_header_length_ == 0)
327 return -1;
329 return this->header_buf_[this->last_header_length_-1];
332 void
333 JAWS_Header_Info::append_last_header_value (const char *begin, const char *end)
335 if (this->last_header_data_ == 0)
336 return;
338 while (this->last_header_length_ < MAX_HEADER_LENGTH-1)
340 if (begin == end)
341 break;
343 this->header_buf_[this->last_header_length_] = *begin;
344 this->last_header_length_++;
345 begin++;
348 this->header_buf_[this->last_header_length_] = '\0';
351 void
352 JAWS_Header_Info::reduce_last_header_value ()
354 if (this->last_header_data_ == 0) return;
356 if (this->last_header_length_ > 0)
358 this->last_header_length_--;
359 this->header_buf_[this->last_header_length_] = '\0';
363 void
364 JAWS_Header_Info::create_next_header_value (char *ht)
366 if (ht == 0)
368 // discard last header data
370 delete this->last_header_data_;
371 this->last_header_data_ = 0;
372 this->last_header_length (0);
373 return;
376 this->finish_last_header_value ();
378 if (this->status () == JAWS_Header_Info::STATUS_CODE_OK)
380 // create a new last_header_data_ node
382 this->last_header_data_ = new JAWS_Header_Data (ht, 0);
383 // The above performs a strdup.
385 if (this->last_header_data_ == 0 || this->last_header_name () == 0)
387 this->status (JAWS_Header_Info::STATUS_CODE_NO_MEMORY);
388 delete this->last_header_data_;
389 this->last_header_data_ = 0;
391 this->last_header_length (0);
392 this->header_buf_[0] = '\0';
396 void
397 JAWS_Header_Info::finish_last_header_value ()
399 if (this->last_header_data_ != 0)
401 // prepare to insert last header data into the table.
403 this->last_header_data_->header_value (this->header_buf ());
404 // The above performs a strdup.
406 if (this->status () == JAWS_Header_Info::STATUS_CODE_OK)
407 this->table_.insert (this->last_header_data_);
408 else
409 delete this->last_header_data_;
410 this->last_header_data_ = 0;
414 char *
415 JAWS_Header_Info::header_buf ()
417 return this->header_buf_;
420 const char *
421 JAWS_Header_Info::last_header_name () const
423 return this->last_header_data_ ? this->last_header_data_->header_name () : 0;
426 const JAWS_Header_Data *
427 JAWS_Header_Info::last_header_data () const
429 return this->last_header_data_;
432 ACCESSOR(int,JAWS_Header_Info,last_header_length)
433 ACCESSOR(int,JAWS_Header_Info,end_of_line)
434 ACCESSOR(int,JAWS_Header_Info,end_of_headers)
435 ACCESSOR(int,JAWS_Header_Info,status)