source: box/trunk/lib/httpserver/HTTPQueryDecoder.cpp @ 2428

Revision 2428, 3.7 KB checked in by chris, 3 years ago (diff)

Add ability to send an HTTPRequest to a socket and to parse an
HTTPResponse from a socket, to create a simple HTTP client.

Line 
1// --------------------------------------------------------------------------
2//
3// File
4//              Name:    HTTPQueryDecoder.cpp
5//              Purpose: Utility class to decode HTTP query strings
6//              Created: 26/3/04
7//
8// --------------------------------------------------------------------------
9
10#include "Box.h"
11
12#include <stdlib.h>
13
14#include "HTTPQueryDecoder.h"
15
16#include "MemLeakFindOn.h"
17
18
19// --------------------------------------------------------------------------
20//
21// Function
22//              Name:    HTTPQueryDecoder::HTTPQueryDecoder(
23//                       HTTPRequest::Query_t &)
24//              Purpose: Constructor. Pass in the query contents you want
25//                       to decode the query string into.
26//              Created: 26/3/04
27//
28// --------------------------------------------------------------------------
29HTTPQueryDecoder::HTTPQueryDecoder(HTTPRequest::Query_t &rDecodeInto)
30        : mrDecodeInto(rDecodeInto),
31          mInKey(true),
32          mEscapedState(0)
33{
34        // Insert the terminator for escaped characters
35        mEscaped[2] = '\0';
36}
37
38
39// --------------------------------------------------------------------------
40//
41// Function
42//              Name:    HTTPQueryDecoder::~HTTPQueryDecoder()
43//              Purpose: Destructor.
44//              Created: 26/3/04
45//
46// --------------------------------------------------------------------------
47HTTPQueryDecoder::~HTTPQueryDecoder()
48{
49}
50
51
52// --------------------------------------------------------------------------
53//
54// Function
55//              Name:    HTTPQueryDecoder::Decode(const char *, int)
56//              Purpose: Decode a chunk of query string -- call several times with
57//                               the bits as they are received, and then call Finish()
58//              Created: 26/3/04
59//
60// --------------------------------------------------------------------------
61void HTTPQueryDecoder::DecodeChunk(const char *pQueryString, int QueryStringSize)
62{
63        for(int l = 0; l < QueryStringSize; ++l)
64        {
65                char c = pQueryString[l];
66               
67                // BEFORE unescaping, check to see if we need to flip key / value
68                if(mEscapedState == 0)
69                {
70                        if(mInKey && c == '=')
71                        {
72                                // Set to store characters in the value
73                                mInKey = false;
74                                continue;
75                        }
76                        else if(!mInKey && c == '&')
77                        {
78                                // Need to store the current key/value pair
79                                mrDecodeInto.insert(HTTPRequest::QueryEn_t(mCurrentKey, mCurrentValue));
80                                // Blank the strings
81                                mCurrentKey.erase();
82                                mCurrentValue.erase();
83                       
84                                // Set to store characters in the key
85                                mInKey = true;
86                                continue;
87                        }
88                }
89               
90                // Decode an escaped value?
91                if(mEscapedState == 1)
92                {
93                        // Waiting for char one of the escaped hex value
94                        mEscaped[0] = c;
95                        mEscapedState = 2;
96                        continue;
97                }
98                else if(mEscapedState == 2)
99                {
100                        // Escaped value, decode it
101                        mEscaped[1] = c;        // str terminated in constructor
102                        mEscapedState = 0;      // stop being in escaped mode
103                        long ch = ::strtol(mEscaped, NULL, 16);
104                        if(ch <= 0 || ch > 255)
105                        {
106                                // Bad character, just ignore
107                                continue;
108                        }
109                       
110                        // Use this instead
111                        c = (char)ch;
112                }               
113                else if(c == '+')
114                {
115                        c = ' ';
116                }
117                else if(c == '%')
118                {
119                        mEscapedState = 1;
120                        continue;
121                }
122
123                // Store decoded value into the appropriate string
124                if(mInKey)
125                {
126                        mCurrentKey += c;
127                }
128                else
129                {
130                        mCurrentValue += c;
131                }
132        }
133       
134        // Don't do anything here with left over values, DecodeChunk might be called
135        // again. Let Finish() clean up.
136}
137
138
139// --------------------------------------------------------------------------
140//
141// Function
142//              Name:    HTTPQueryDecoder::Finish()
143//              Purpose: Finish the decoding. Necessary to get the last item!
144//              Created: 26/3/04
145//
146// --------------------------------------------------------------------------
147void HTTPQueryDecoder::Finish()
148{
149        // Insert any remaining value.
150        if(!mCurrentKey.empty())
151        {
152                mrDecodeInto.insert(HTTPRequest::QueryEn_t(mCurrentKey, mCurrentValue));
153                // Blank values, just in case
154                mCurrentKey.erase();
155                mCurrentValue.erase();
156        }
157}
158
159
Note: See TracBrowser for help on using the repository browser.