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; }
10 JAWS_Parse_Headers::parse_headers (JAWS_Header_Info
*info
,
11 ACE_Message_Block
&mb
)
15 if (mb
.rd_ptr () == mb
.wr_ptr ())
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
);
25 return info
->end_of_headers ();
30 int r
= this->parse_header_value (info
, mb
);
33 if (info
->end_of_headers ())
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 ())
50 else if (mb
.length () < mb
.size ())
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
);
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
);
74 ACE_DEBUG ((LM_DEBUG
, "JAWS_Parse_Headers -- shouldn't be here!\n"));
79 JAWS_Parse_Headers::skipset (const char *set
, char *start
, char *end
)
84 if (ACE_OS::strchr (set
, *p
) != 0)
92 JAWS_Parse_Headers::skipcset (const char *set
, char *start
, char *end
)
97 if (ACE_OS::strchr (set
, *p
) == 0)
105 JAWS_Parse_Headers::parse_header_name (JAWS_Header_Info
*info
,
106 ACE_Message_Block
&mb
)
108 char *p
= mb
.rd_ptr ();
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 ':'
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);
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 ())
141 // not a blank line, but no ':', so ignore it
142 info
->finish_last_header_value ();
143 info
->create_next_header_value (0);
147 // otherwise, we have a header type name!
149 info
->create_next_header_value (p
);
150 info
->end_of_line (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);
175 // Move the rd_ptr back one character if the last thing we
176 // see is a carriage return. Assert: wr_ptr > rd_ptr.
185 // We are in the middle of binary data. Get out!
187 info
->end_of_line (1);
188 info
->end_of_headers (1);
192 // Move past the newline, set the end of line flag
195 info
->end_of_line (1);
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 ())
211 info
->end_of_line (1);
217 info
->append_last_header_value (' ');
220 // Append to last header value character by character
221 while (q
< mb
.wr_ptr ())
225 info
->append_last_header_value (*q
);
230 if (q
== mb
.wr_ptr ())
233 info
->end_of_line (0);
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
246 info
->end_of_line (1);
257 JAWS_Header_Info::JAWS_Header_Info ()
258 : end_of_headers_ (0),
260 last_header_data_ (0),
261 last_header_length_ (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 ();
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
;
290 ACE_DEBUG ((LM_DEBUG
,
292 data
->header_name (), data
->header_value ()));
294 ACE_DEBUG ((LM_DEBUG
, "NULL ENTRY\n"));
296 ACE_DEBUG ((LM_DEBUG
, "== END HEADER INFO DUMP ==\n"));
300 JAWS_Header_Info::table ()
302 return &(this->table_
);
306 JAWS_Header_Info::append_last_header_value (char c
)
308 if (this->last_header_data_
== 0)
311 if (this->last_header_length_
== 0 && (c
== ' ' || c
== '\t'))
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)
329 return this->header_buf_
[this->last_header_length_
-1];
333 JAWS_Header_Info::append_last_header_value (const char *begin
, const char *end
)
335 if (this->last_header_data_
== 0)
338 while (this->last_header_length_
< MAX_HEADER_LENGTH
-1)
343 this->header_buf_
[this->last_header_length_
] = *begin
;
344 this->last_header_length_
++;
348 this->header_buf_
[this->last_header_length_
] = '\0';
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';
364 JAWS_Header_Info::create_next_header_value (char *ht
)
368 // discard last header data
370 delete this->last_header_data_
;
371 this->last_header_data_
= 0;
372 this->last_header_length (0);
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';
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_
);
409 delete this->last_header_data_
;
410 this->last_header_data_
= 0;
415 JAWS_Header_Info::header_buf ()
417 return this->header_buf_
;
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
)