]>
Commit | Line | Data |
---|---|---|
95d2589c CT |
1 | /* |
2 | * $Id$ | |
3 | */ | |
4 | ||
5 | #include "config.h" | |
6 | #include "ssl/crtd_message.h" | |
7 | #if HAVE_CSTDLIB | |
8 | #include <cstdlib> | |
9 | #endif | |
10 | #if HAVE_CSTRING | |
11 | #include <cstring> | |
12 | #endif | |
13 | ||
14 | Ssl::CrtdMessage::CrtdMessage() | |
15 | : body_size(0), state(BEFORE_CODE) | |
16 | {} | |
17 | ||
18 | Ssl::CrtdMessage::ParseResult Ssl::CrtdMessage::parse(const char * buffer, size_t len) | |
19 | { | |
20 | char const *current_pos = buffer; | |
21 | while (current_pos != buffer + len && state != END) { | |
22 | switch (state) { | |
23 | case BEFORE_CODE: { | |
24 | if (xisspace(*current_pos)) { | |
25 | current_pos++; | |
26 | break; | |
27 | } | |
28 | if (xisalpha(*current_pos)) { | |
29 | state = CODE; | |
30 | break; | |
31 | } | |
32 | clear(); | |
33 | return ERROR; | |
34 | } | |
35 | case CODE: { | |
36 | if (xisalnum(*current_pos) || *current_pos == '_') { | |
37 | current_block += *current_pos; | |
38 | current_pos++; | |
39 | break; | |
40 | } | |
41 | if (xisspace(*current_pos)) { | |
42 | code = current_block; | |
43 | current_block.clear(); | |
44 | state = BEFORE_LENGTH; | |
45 | break; | |
46 | } | |
47 | clear(); | |
48 | return ERROR; | |
49 | } | |
50 | case BEFORE_LENGTH: { | |
51 | if (xisspace(*current_pos)) { | |
52 | current_pos++; | |
53 | break; | |
54 | } | |
55 | if (xisdigit(*current_pos)) { | |
56 | state = LENGTH; | |
57 | break; | |
58 | } | |
59 | clear(); | |
60 | return ERROR; | |
61 | } | |
62 | case LENGTH: { | |
63 | if (xisdigit(*current_pos)) { | |
64 | current_block += *current_pos; | |
65 | current_pos++; | |
66 | break; | |
67 | } | |
68 | if (xisspace(*current_pos)) { | |
69 | body_size = atoi(current_block.c_str()); | |
70 | current_block.clear(); | |
71 | state = BEFORE_BODY; | |
72 | break; | |
73 | } | |
74 | clear(); | |
75 | return ERROR; | |
76 | } | |
77 | case BEFORE_BODY: { | |
78 | if (body_size == 0) { | |
79 | state = END; | |
80 | break; | |
81 | } | |
82 | if (xisspace(*current_pos)) { | |
83 | current_pos++; | |
84 | break; | |
85 | } else { | |
86 | state = BODY; | |
87 | break; | |
88 | } | |
89 | } | |
90 | case BODY: { | |
91 | size_t body_len = (static_cast<size_t>(buffer + len - current_pos) >= body_size - current_block.length()) | |
92 | ? body_size - current_block.length() | |
93 | : static_cast<size_t>(buffer + len - current_pos); | |
94 | current_block += std::string(current_pos, body_len); | |
95 | current_pos += body_len; | |
96 | if (current_block.length() == body_size) { | |
97 | body = current_block; | |
98 | state = END; | |
99 | } | |
100 | if (current_block.length() > body_size) { | |
101 | clear(); | |
102 | return ERROR; | |
103 | } | |
104 | break; | |
105 | } | |
106 | case END: { | |
107 | return OK; | |
108 | } | |
109 | } | |
110 | } | |
111 | if (state != END) return INCOMPLETE; | |
112 | return OK; | |
113 | } | |
114 | ||
115 | std::string const & Ssl::CrtdMessage::getBody() const { return body; } | |
116 | ||
117 | std::string const & Ssl::CrtdMessage::getCode() const { return code; } | |
118 | ||
119 | void Ssl::CrtdMessage::setBody(std::string const & aBody) { body = aBody; } | |
120 | ||
121 | void Ssl::CrtdMessage::setCode(std::string const & aCode) { code = aCode; } | |
122 | ||
123 | ||
124 | std::string Ssl::CrtdMessage::compose() const | |
125 | { | |
126 | if (code.empty()) return std::string(); | |
127 | char buffer[10]; | |
128 | snprintf(buffer, sizeof(buffer), "%zd", body.length()); | |
129 | return code + ' ' + buffer + ' ' + body + '\n'; | |
130 | } | |
131 | ||
132 | void Ssl::CrtdMessage::clear() | |
133 | { | |
134 | body_size = 0; | |
135 | state = BEFORE_CODE; | |
136 | body.clear(); | |
137 | code.clear(); | |
138 | current_block.clear(); | |
139 | } | |
140 | ||
141 | void Ssl::CrtdMessage::parseBody(CrtdMessage::BodyParams & map, std::string & other_part) const | |
142 | { | |
143 | other_part.clear(); | |
144 | // Copy string for using it as temp buffer. | |
145 | std::string temp_body(body.c_str(), body.length()); | |
146 | char * buffer = const_cast<char *>(temp_body.c_str()); | |
147 | char * token = strtok(buffer, "\r\n"); | |
148 | while (token != NULL) { | |
149 | std::string current_string(token); | |
150 | size_t equal_pos = current_string.find('='); | |
151 | if (equal_pos == std::string::npos) { | |
152 | size_t offset_body_part = token - temp_body.c_str(); | |
153 | other_part = std::string(body.c_str() + offset_body_part, body.length() - offset_body_part); | |
154 | break; | |
155 | } else { | |
156 | std::string param(current_string.c_str(), current_string.c_str() + equal_pos); | |
157 | std::string value(current_string.c_str() + equal_pos + 1); | |
158 | map.insert(std::make_pair(param, value)); | |
159 | } | |
160 | token = strtok(NULL, "\r\n"); | |
161 | } | |
162 | } | |
163 | ||
164 | void Ssl::CrtdMessage::composeBody(CrtdMessage::BodyParams const & map, std::string const & other_part) | |
165 | { | |
166 | body.clear(); | |
167 | for (BodyParams::const_iterator i = map.begin(); i != map.end(); i++) { | |
168 | if (i != map.begin()) | |
169 | body += "\n"; | |
170 | body += i->first + "=" + i->second; | |
171 | } | |
172 | if (!other_part.empty()) | |
4e903d59 | 173 | body += '\n' + other_part; |
95d2589c CT |
174 | } |
175 | ||
176 | const std::string Ssl::CrtdMessage::code_new_certificate("new_certificate"); | |
177 | const std::string Ssl::CrtdMessage::param_host("host"); |