/src/PcapPlusPlus/Packet++/src/TextBasedProtocol.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | #include "TextBasedProtocol.h" |
2 | | #include "Logger.h" |
3 | | #include "PayloadLayer.h" |
4 | | #include <string.h> |
5 | | #include <algorithm> |
6 | | #include <stdlib.h> |
7 | | |
8 | | namespace pcpp |
9 | | { |
10 | | |
11 | | // this implementation of strnlen is required since mingw doesn't have strnlen |
12 | | size_t tbp_my_own_strnlen(const char* s, size_t maxlen) |
13 | 55.0k | { |
14 | 55.0k | if (s == NULL || maxlen == 0) |
15 | 27.8k | return 0; |
16 | | |
17 | 27.1k | size_t i = 0; |
18 | 135k | for(; (i < maxlen) && s[i]; ++i); |
19 | 27.1k | return i; |
20 | 55.0k | } |
21 | | |
22 | | |
23 | | // -------- Class TextBasedProtocolMessage ----------------- |
24 | | |
25 | | |
26 | | TextBasedProtocolMessage::TextBasedProtocolMessage(uint8_t* data, size_t dataLen, Layer* prevLayer, Packet* packet) : Layer(data, dataLen, prevLayer, packet), |
27 | 48.9k | m_FieldList(NULL), m_LastField(NULL), m_FieldsOffset(0) {} |
28 | | |
29 | | TextBasedProtocolMessage::TextBasedProtocolMessage(const TextBasedProtocolMessage& other) : Layer(other) |
30 | 0 | { |
31 | 0 | copyDataFrom(other); |
32 | 0 | } |
33 | | |
34 | | TextBasedProtocolMessage& TextBasedProtocolMessage::operator=(const TextBasedProtocolMessage& other) |
35 | 0 | { |
36 | 0 | Layer::operator=(other); |
37 | 0 | HeaderField* curField = m_FieldList; |
38 | 0 | while (curField != NULL) |
39 | 0 | { |
40 | 0 | HeaderField* temp = curField; |
41 | 0 | curField = curField->getNextField(); |
42 | 0 | delete temp; |
43 | 0 | } |
44 | |
|
45 | 0 | copyDataFrom(other); |
46 | |
|
47 | 0 | return *this; |
48 | 0 | } |
49 | | |
50 | | void TextBasedProtocolMessage::copyDataFrom(const TextBasedProtocolMessage& other) |
51 | 0 | { |
52 | | // copy field list |
53 | 0 | if (other.m_FieldList != NULL) |
54 | 0 | { |
55 | 0 | m_FieldList = new HeaderField(*(other.m_FieldList)); |
56 | 0 | HeaderField* curField = m_FieldList; |
57 | 0 | curField->attachToTextBasedProtocolMessage(this, other.m_FieldList->m_NameOffsetInMessage); |
58 | 0 | HeaderField* curOtherField = other.m_FieldList; |
59 | 0 | while (curOtherField->getNextField() != NULL) |
60 | 0 | { |
61 | 0 | HeaderField* newField = new HeaderField(*(curOtherField->getNextField())); |
62 | 0 | newField->attachToTextBasedProtocolMessage(this, curOtherField->getNextField()->m_NameOffsetInMessage); |
63 | 0 | curField->setNextField(newField); |
64 | 0 | curField = curField->getNextField(); |
65 | 0 | curOtherField = curOtherField->getNextField(); |
66 | 0 | } |
67 | |
|
68 | 0 | m_LastField = curField; |
69 | 0 | } |
70 | 0 | else |
71 | 0 | { |
72 | 0 | m_FieldList = NULL; |
73 | 0 | m_LastField = NULL; |
74 | 0 | } |
75 | |
|
76 | 0 | m_FieldsOffset = other.m_FieldsOffset; |
77 | | |
78 | | // copy map |
79 | 0 | for(HeaderField* field = m_FieldList; field != NULL; field = field->getNextField()) |
80 | 0 | { |
81 | 0 | m_FieldNameToFieldMap.insert(std::pair<std::string, HeaderField*>(field->getFieldName(), field)); |
82 | 0 | } |
83 | 0 | } |
84 | | |
85 | | |
86 | | void TextBasedProtocolMessage::parseFields() |
87 | 48.9k | { |
88 | 48.9k | char nameValueSeparator = getHeaderFieldNameValueSeparator(); |
89 | 48.9k | bool spacesAllowedBetweenNameAndValue = spacesAllowedBetweenHeaderFieldNameAndValue(); |
90 | | |
91 | 48.9k | HeaderField* firstField = new HeaderField(this, m_FieldsOffset, nameValueSeparator, spacesAllowedBetweenNameAndValue); |
92 | 48.9k | PCPP_LOG_DEBUG("Added new field: name='" << firstField->getFieldName() << "'; offset in packet=" << firstField->m_NameOffsetInMessage << "; length=" << firstField->getFieldSize()); |
93 | 48.9k | PCPP_LOG_DEBUG(" Field value = " << firstField->getFieldValue()); |
94 | | |
95 | 48.9k | if (m_FieldList == NULL) |
96 | 48.9k | m_FieldList = firstField; |
97 | 0 | else |
98 | 0 | m_FieldList->setNextField(firstField); |
99 | | |
100 | 48.9k | std::string fieldName = firstField->getFieldName(); |
101 | 48.9k | std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); |
102 | 48.9k | m_FieldNameToFieldMap.insert(std::pair<std::string, HeaderField*>(fieldName, firstField)); |
103 | | |
104 | | // Last field will be empty and contain just "\n" or "\r\n". This field will mark the end of the header |
105 | 48.9k | HeaderField* curField = m_FieldList; |
106 | 48.9k | int curOffset = m_FieldsOffset; |
107 | | // last field can be one of: |
108 | | // a.) \r\n\r\n or \n\n marking the end of the header |
109 | | // b.) the end of the packet |
110 | 128k | while (!curField->isEndOfHeader() && curOffset + curField->getFieldSize() < m_DataLen) |
111 | 88.5k | { |
112 | 88.5k | curOffset += curField->getFieldSize(); |
113 | 88.5k | HeaderField* newField = new HeaderField(this, curOffset, nameValueSeparator, spacesAllowedBetweenNameAndValue); |
114 | 88.5k | if(newField->getFieldSize() > 0) |
115 | 79.1k | { |
116 | 79.1k | PCPP_LOG_DEBUG("Added new field: name='" << newField->getFieldName() << "'; offset in packet=" << newField->m_NameOffsetInMessage << "; length=" << newField->getFieldSize()); |
117 | 79.1k | PCPP_LOG_DEBUG(" Field value = " << newField->getFieldValue()); |
118 | 79.1k | curField->setNextField(newField); |
119 | 79.1k | curField = newField; |
120 | 79.1k | fieldName = newField->getFieldName(); |
121 | 79.1k | std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); |
122 | 79.1k | m_FieldNameToFieldMap.insert(std::pair<std::string, HeaderField*>(fieldName, newField)); |
123 | 79.1k | } |
124 | 9.40k | else |
125 | 9.40k | { |
126 | 9.40k | delete newField; |
127 | 9.40k | break; |
128 | 9.40k | } |
129 | 88.5k | } |
130 | | |
131 | 48.9k | m_LastField = curField; |
132 | 48.9k | } |
133 | | |
134 | | |
135 | | TextBasedProtocolMessage::~TextBasedProtocolMessage() |
136 | 48.9k | { |
137 | 177k | while (m_FieldList != NULL) |
138 | 128k | { |
139 | 128k | HeaderField* temp = m_FieldList; |
140 | 128k | m_FieldList = m_FieldList->getNextField(); |
141 | 128k | delete temp; |
142 | 128k | } |
143 | 48.9k | } |
144 | | |
145 | | |
146 | | HeaderField* TextBasedProtocolMessage::addField(const std::string& fieldName, const std::string& fieldValue) |
147 | 0 | { |
148 | 0 | HeaderField newField(fieldName, fieldValue, getHeaderFieldNameValueSeparator(), spacesAllowedBetweenHeaderFieldNameAndValue()); |
149 | 0 | return addField(newField); |
150 | 0 | } |
151 | | |
152 | | HeaderField* TextBasedProtocolMessage::addField(const HeaderField& newField) |
153 | 0 | { |
154 | 0 | return insertField(m_LastField, newField); |
155 | 0 | } |
156 | | |
157 | | HeaderField* TextBasedProtocolMessage::addEndOfHeader() |
158 | 0 | { |
159 | 0 | HeaderField endOfHeaderField(PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER, "", '\0', false); |
160 | 0 | return insertField(m_LastField, endOfHeaderField); |
161 | 0 | } |
162 | | |
163 | | |
164 | | HeaderField* TextBasedProtocolMessage::insertField(HeaderField* prevField, const std::string& fieldName, const std::string& fieldValue) |
165 | 0 | { |
166 | 0 | HeaderField newField(fieldName, fieldValue, getHeaderFieldNameValueSeparator(), spacesAllowedBetweenHeaderFieldNameAndValue()); |
167 | 0 | return insertField(prevField, newField); |
168 | 0 | } |
169 | | |
170 | | HeaderField* TextBasedProtocolMessage::insertField(std::string prevFieldName, const std::string& fieldName, const std::string& fieldValue) |
171 | 0 | { |
172 | 0 | if (prevFieldName == "") |
173 | 0 | { |
174 | 0 | return insertField(NULL, fieldName, fieldValue); |
175 | 0 | } |
176 | 0 | else |
177 | 0 | { |
178 | 0 | HeaderField* prevField = getFieldByName(prevFieldName); |
179 | 0 | if (prevField == NULL) |
180 | 0 | return NULL; |
181 | | |
182 | 0 | return insertField(prevField, fieldName, fieldValue); |
183 | 0 | } |
184 | 0 | } |
185 | | |
186 | | |
187 | | HeaderField* TextBasedProtocolMessage::insertField(HeaderField* prevField, const HeaderField& newField) |
188 | 0 | { |
189 | 0 | if (newField.m_TextBasedProtocolMessage != NULL) |
190 | 0 | { |
191 | 0 | PCPP_LOG_ERROR("This field is already associated with another message"); |
192 | 0 | return NULL; |
193 | 0 | } |
194 | | |
195 | 0 | if (prevField != NULL && prevField->getFieldName() == PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) |
196 | 0 | { |
197 | 0 | PCPP_LOG_ERROR("Cannot add a field after end of header"); |
198 | 0 | return NULL; |
199 | 0 | } |
200 | | |
201 | 0 | HeaderField* newFieldToAdd = new HeaderField(newField); |
202 | |
|
203 | 0 | int newFieldOffset = m_FieldsOffset; |
204 | 0 | if (prevField != NULL) |
205 | 0 | newFieldOffset = prevField->m_NameOffsetInMessage + prevField->getFieldSize(); |
206 | | |
207 | | // extend layer to make room for the new field. Field will be added just before the last field |
208 | 0 | if (!extendLayer(newFieldOffset, newFieldToAdd->getFieldSize())) |
209 | 0 | { |
210 | 0 | PCPP_LOG_ERROR("Cannot extend layer to insert the header"); |
211 | 0 | delete newFieldToAdd; |
212 | 0 | return NULL; |
213 | 0 | } |
214 | | |
215 | 0 | HeaderField* curField = m_FieldList; |
216 | 0 | if (prevField != NULL) |
217 | 0 | curField = prevField->getNextField(); |
218 | | |
219 | | // go over all fields after prevField and update their offsets |
220 | 0 | shiftFieldsOffset(curField, newFieldToAdd->getFieldSize()); |
221 | | |
222 | | // copy new field data to message |
223 | 0 | memcpy(m_Data + newFieldOffset, newFieldToAdd->m_NewFieldData, newFieldToAdd->getFieldSize()); |
224 | | |
225 | | // attach new field to message |
226 | 0 | newFieldToAdd->attachToTextBasedProtocolMessage(this, newFieldOffset); |
227 | | |
228 | | // insert field into fields link list |
229 | 0 | if (prevField == NULL) |
230 | 0 | { |
231 | 0 | newFieldToAdd->setNextField(m_FieldList); |
232 | 0 | m_FieldList = newFieldToAdd; |
233 | 0 | } |
234 | 0 | else |
235 | 0 | { |
236 | 0 | newFieldToAdd->setNextField(prevField->getNextField()); |
237 | 0 | prevField->setNextField(newFieldToAdd); |
238 | 0 | } |
239 | | |
240 | | // if newField is the last field, update m_LastField |
241 | 0 | if (newFieldToAdd->getNextField() == NULL) |
242 | 0 | m_LastField = newFieldToAdd; |
243 | | |
244 | | // insert the new field into name to field map |
245 | 0 | std::string fieldName = newFieldToAdd->getFieldName(); |
246 | 0 | std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); |
247 | 0 | m_FieldNameToFieldMap.insert(std::pair<std::string, HeaderField*>(fieldName, newFieldToAdd)); |
248 | |
|
249 | 0 | return newFieldToAdd; |
250 | 0 | } |
251 | | |
252 | | bool TextBasedProtocolMessage::removeField(std::string fieldName, int index) |
253 | 0 | { |
254 | 0 | std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); |
255 | |
|
256 | 0 | HeaderField* fieldToRemove = NULL; |
257 | |
|
258 | 0 | std::pair <std::multimap<std::string,HeaderField*>::iterator, std::multimap<std::string,HeaderField*>::iterator> range; |
259 | 0 | range = m_FieldNameToFieldMap.equal_range(fieldName); |
260 | 0 | int i = 0; |
261 | 0 | for (std::multimap<std::string,HeaderField*>::iterator iter = range.first; iter != range.second; ++iter) |
262 | 0 | { |
263 | 0 | if (i == index) |
264 | 0 | { |
265 | 0 | fieldToRemove = iter->second; |
266 | 0 | break; |
267 | 0 | } |
268 | | |
269 | 0 | i++; |
270 | 0 | } |
271 | |
|
272 | 0 | if (fieldToRemove != NULL) |
273 | 0 | return removeField(fieldToRemove); |
274 | 0 | else |
275 | 0 | { |
276 | 0 | PCPP_LOG_ERROR("Cannot find field '" << fieldName << "'"); |
277 | 0 | return false; |
278 | 0 | } |
279 | 0 | } |
280 | | |
281 | | bool TextBasedProtocolMessage::removeField(HeaderField* fieldToRemove) |
282 | 0 | { |
283 | 0 | if (fieldToRemove == NULL) |
284 | 0 | return true; |
285 | | |
286 | 0 | if (fieldToRemove->m_TextBasedProtocolMessage != this) |
287 | 0 | { |
288 | 0 | PCPP_LOG_ERROR("Field isn't associated with this message"); |
289 | 0 | return false; |
290 | 0 | } |
291 | | |
292 | 0 | std::string fieldName = fieldToRemove->getFieldName(); |
293 | | |
294 | | // shorten layer and delete this field |
295 | 0 | if (!shortenLayer(fieldToRemove->m_NameOffsetInMessage, fieldToRemove->getFieldSize())) |
296 | 0 | { |
297 | 0 | PCPP_LOG_ERROR("Cannot shorten layer"); |
298 | 0 | return false; |
299 | 0 | } |
300 | | |
301 | | // update offsets of all fields after this field |
302 | 0 | HeaderField* curField = fieldToRemove->getNextField(); |
303 | 0 | shiftFieldsOffset(curField, 0-fieldToRemove->getFieldSize()); |
304 | | // while (curField != NULL) |
305 | | // { |
306 | | // curField->m_NameOffsetInMessage -= fieldToRemove->getFieldSize(); |
307 | | // if (curField->m_ValueOffsetInMessage != -1) |
308 | | // curField->m_ValueOffsetInMessage -= fieldToRemove->getFieldSize(); |
309 | | // |
310 | | // curField = curField->getNextField(); |
311 | | // } |
312 | | |
313 | | // update fields link list |
314 | 0 | if (fieldToRemove == m_FieldList) |
315 | 0 | m_FieldList = m_FieldList->getNextField(); |
316 | 0 | else |
317 | 0 | { |
318 | 0 | curField = m_FieldList; |
319 | 0 | while (curField->getNextField() != fieldToRemove) |
320 | 0 | curField = curField->getNextField(); |
321 | |
|
322 | 0 | curField->setNextField(fieldToRemove->getNextField()); |
323 | 0 | } |
324 | | |
325 | | // re-calculate m_LastField if needed |
326 | 0 | if (fieldToRemove == m_LastField) |
327 | 0 | { |
328 | 0 | if (m_FieldList == NULL) |
329 | 0 | m_LastField = NULL; |
330 | 0 | else |
331 | 0 | { |
332 | 0 | curField = m_FieldList; |
333 | 0 | while (curField->getNextField() != NULL) |
334 | 0 | curField = curField->getNextField(); |
335 | 0 | m_LastField = curField; |
336 | 0 | } |
337 | 0 | } |
338 | | |
339 | | // remove the hash entry for this field |
340 | 0 | std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); |
341 | 0 | std::pair <std::multimap<std::string,HeaderField*>::iterator, std::multimap<std::string,HeaderField*>::iterator> range; |
342 | 0 | range = m_FieldNameToFieldMap.equal_range(fieldName); |
343 | 0 | for (std::multimap<std::string,HeaderField*>::iterator iter = range.first; iter != range.second; ++iter) |
344 | 0 | { |
345 | 0 | if (iter->second == fieldToRemove) |
346 | 0 | { |
347 | 0 | m_FieldNameToFieldMap.erase(iter); |
348 | 0 | break; |
349 | 0 | } |
350 | 0 | } |
351 | | |
352 | | // finally - delete this field |
353 | 0 | delete fieldToRemove; |
354 | |
|
355 | 0 | return true; |
356 | 0 | } |
357 | | |
358 | | bool TextBasedProtocolMessage::isHeaderComplete() const |
359 | 0 | { |
360 | 0 | if (m_LastField == NULL) |
361 | 0 | return false; |
362 | | |
363 | 0 | return (m_LastField->getFieldName() == PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER); |
364 | 0 | } |
365 | | |
366 | | void TextBasedProtocolMessage::shiftFieldsOffset(HeaderField* fromField, int numOfBytesToShift) |
367 | 0 | { |
368 | 0 | while (fromField != NULL) |
369 | 0 | { |
370 | 0 | fromField->m_NameOffsetInMessage += numOfBytesToShift; |
371 | 0 | if (fromField->m_ValueOffsetInMessage != -1) |
372 | 0 | fromField->m_ValueOffsetInMessage += numOfBytesToShift; |
373 | 0 | fromField = fromField->getNextField(); |
374 | 0 | } |
375 | 0 | } |
376 | | |
377 | | HeaderField* TextBasedProtocolMessage::getFieldByName(std::string fieldName, int index) const |
378 | 12.6k | { |
379 | 12.6k | std::transform(fieldName.begin(), fieldName.end(), fieldName.begin(), ::tolower); |
380 | | |
381 | 12.6k | std::pair <std::multimap<std::string,HeaderField*>::const_iterator, std::multimap<std::string,HeaderField*>::const_iterator> range; |
382 | 12.6k | range = m_FieldNameToFieldMap.equal_range(fieldName); |
383 | 12.6k | int i = 0; |
384 | 12.6k | for (std::multimap<std::string,HeaderField*>::const_iterator iter = range.first; iter != range.second; ++iter) |
385 | 5.30k | { |
386 | 5.30k | if (i == index) |
387 | 5.30k | return iter->second; |
388 | | |
389 | 0 | i++; |
390 | 0 | } |
391 | | |
392 | 7.37k | return NULL; |
393 | 12.6k | } |
394 | | |
395 | | int TextBasedProtocolMessage::getFieldCount() const |
396 | 0 | { |
397 | 0 | int result = 0; |
398 | |
|
399 | 0 | HeaderField* curField = getFirstField(); |
400 | 0 | while (curField != NULL) |
401 | 0 | { |
402 | 0 | if (!curField->isEndOfHeader()) |
403 | 0 | result++; |
404 | 0 | curField = curField->getNextField(); |
405 | 0 | } |
406 | |
|
407 | 0 | return result; |
408 | 0 | } |
409 | | |
410 | | void TextBasedProtocolMessage::parseNextLayer() |
411 | 24.8k | { |
412 | 24.8k | size_t headerLen = getHeaderLen(); |
413 | 24.8k | if (m_DataLen <= headerLen) |
414 | 20.3k | return; |
415 | | |
416 | 4.42k | m_NextLayer = new PayloadLayer(m_Data + headerLen, m_DataLen - headerLen, this, m_Packet); |
417 | 4.42k | } |
418 | | |
419 | | size_t TextBasedProtocolMessage::getHeaderLen() const |
420 | 61.6k | { |
421 | 61.6k | return m_LastField->m_NameOffsetInMessage + m_LastField->m_FieldSize; |
422 | 61.6k | } |
423 | | |
424 | | void TextBasedProtocolMessage::computeCalculateFields() |
425 | 0 | { |
426 | | //nothing to do for now |
427 | 0 | } |
428 | | |
429 | | |
430 | | |
431 | | |
432 | | |
433 | | // -------- Class HeaderField ----------------- |
434 | | |
435 | | |
436 | | HeaderField::HeaderField(TextBasedProtocolMessage* TextBasedProtocolMessage, int offsetInMessage, char nameValueSeparator, bool spacesAllowedBetweenNameAndValue) : |
437 | | m_NewFieldData(NULL), m_TextBasedProtocolMessage(TextBasedProtocolMessage), m_NameOffsetInMessage(offsetInMessage), m_NextField(NULL), |
438 | | m_NameValueSeparator(nameValueSeparator), m_SpacesAllowedBetweenNameAndValue(spacesAllowedBetweenNameAndValue) |
439 | 137k | { |
440 | 137k | char* fieldData = (char*)(m_TextBasedProtocolMessage->m_Data + m_NameOffsetInMessage); |
441 | 137k | char* fieldEndPtr = (char*)memchr(fieldData, '\n', m_TextBasedProtocolMessage->m_DataLen - (size_t)m_NameOffsetInMessage); |
442 | 137k | if (fieldEndPtr == NULL) |
443 | 55.0k | m_FieldSize = tbp_my_own_strnlen(fieldData, m_TextBasedProtocolMessage->m_DataLen - (size_t)m_NameOffsetInMessage); |
444 | 82.5k | else |
445 | 82.5k | m_FieldSize = fieldEndPtr - fieldData + 1; |
446 | | |
447 | 137k | if (m_FieldSize == 0 || (*fieldData) == '\r' || (*fieldData) == '\n') |
448 | 44.9k | { |
449 | 44.9k | m_FieldNameSize = -1; |
450 | 44.9k | m_ValueOffsetInMessage = -1; |
451 | 44.9k | m_FieldValueSize = -1; |
452 | 44.9k | m_FieldNameSize = -1; |
453 | 44.9k | m_IsEndOfHeaderField = true; |
454 | 44.9k | return; |
455 | 44.9k | } |
456 | 92.5k | else |
457 | 92.5k | m_IsEndOfHeaderField = false; |
458 | | |
459 | 92.5k | char* fieldValuePtr = (char*)memchr(fieldData, nameValueSeparator, m_TextBasedProtocolMessage->m_DataLen - (size_t)m_NameOffsetInMessage); |
460 | | // could not find the position of the separator, meaning field value position is unknown |
461 | 92.5k | if (fieldValuePtr == NULL || (fieldEndPtr != NULL && fieldValuePtr >= fieldEndPtr)) |
462 | 62.0k | { |
463 | 62.0k | m_ValueOffsetInMessage = -1; |
464 | 62.0k | m_FieldValueSize = -1; |
465 | 62.0k | m_FieldNameSize = m_FieldSize; |
466 | 62.0k | } |
467 | 30.5k | else |
468 | 30.5k | { |
469 | 30.5k | m_FieldNameSize = fieldValuePtr - fieldData; |
470 | | // Header field looks like this: <field_name>[separator]<zero or more spaces><field_Value> |
471 | | // So fieldValuePtr give us the position of the separator. Value offset is the first non-space byte forward |
472 | 30.5k | fieldValuePtr++; |
473 | | |
474 | | // reached the end of the packet and value start offset wasn't found |
475 | 30.5k | if ((size_t)(fieldValuePtr - (char*)(m_TextBasedProtocolMessage->m_Data)) >= m_TextBasedProtocolMessage->getDataLen()) |
476 | 260 | { |
477 | 260 | m_ValueOffsetInMessage = -1; |
478 | 260 | m_FieldValueSize = -1; |
479 | 260 | return; |
480 | 260 | } |
481 | | |
482 | 30.2k | if (spacesAllowedBetweenNameAndValue) |
483 | 29.6k | { |
484 | | // advance fieldValuePtr 1 byte forward while didn't get to end of packet and fieldValuePtr points to a space char |
485 | 31.5k | while ((size_t)(fieldValuePtr - (char*)m_TextBasedProtocolMessage->m_Data) < m_TextBasedProtocolMessage->getDataLen() && (*fieldValuePtr) == ' ') |
486 | 1.89k | { |
487 | 1.89k | fieldValuePtr++; |
488 | 1.89k | } |
489 | 29.6k | } |
490 | | |
491 | | // reached the end of the packet and value start offset wasn't found |
492 | 30.2k | if ((size_t)(fieldValuePtr - (char*)(m_TextBasedProtocolMessage->m_Data)) >= m_TextBasedProtocolMessage->getDataLen()) |
493 | 223 | { |
494 | 223 | m_ValueOffsetInMessage = -1; |
495 | 223 | m_FieldValueSize = -1; |
496 | 223 | } |
497 | 30.0k | else |
498 | 30.0k | { |
499 | 30.0k | m_ValueOffsetInMessage = fieldValuePtr - (char*)m_TextBasedProtocolMessage->m_Data; |
500 | | // couldn't find the end of the field, so assuming the field value length is from m_ValueOffsetInMessage until the end of the packet |
501 | 30.0k | if (fieldEndPtr == NULL) |
502 | 3.60k | m_FieldValueSize = (char*)(m_TextBasedProtocolMessage->m_Data + m_TextBasedProtocolMessage->getDataLen()) - fieldValuePtr; |
503 | 26.4k | else |
504 | 26.4k | { |
505 | 26.4k | m_FieldValueSize = fieldEndPtr - fieldValuePtr; |
506 | | // if field ends with \r\n, decrease the value length by 1 |
507 | 26.4k | if ((*(--fieldEndPtr)) == '\r') |
508 | 340 | m_FieldValueSize--; |
509 | 26.4k | } |
510 | 30.0k | } |
511 | 30.2k | } |
512 | 92.5k | } |
513 | | |
514 | | HeaderField::HeaderField(std::string name, std::string value, char nameValueSeparator, bool spacesAllowedBetweenNameAndValue) |
515 | 0 | { |
516 | 0 | m_NameValueSeparator = nameValueSeparator; |
517 | 0 | m_SpacesAllowedBetweenNameAndValue = spacesAllowedBetweenNameAndValue; |
518 | 0 | initNewField(name, value); |
519 | 0 | } |
520 | | |
521 | | void HeaderField::initNewField(std::string name, std::string value) |
522 | 0 | { |
523 | 0 | m_TextBasedProtocolMessage = NULL; |
524 | 0 | m_NameOffsetInMessage = 0; |
525 | 0 | m_NextField = NULL; |
526 | | |
527 | | // first building the name-value separator |
528 | 0 | std::string nameValueSeparation(1, m_NameValueSeparator); |
529 | 0 | if (m_SpacesAllowedBetweenNameAndValue) |
530 | 0 | nameValueSeparation += " "; |
531 | | |
532 | | // Field size is: name_length + separator_len + value_length + '\r\n' |
533 | 0 | if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) |
534 | 0 | m_FieldSize = name.length() + nameValueSeparation.length() + value.length() + 2; |
535 | 0 | else |
536 | | // Field is \r\n (2B) |
537 | 0 | m_FieldSize = 2; |
538 | |
|
539 | 0 | m_NewFieldData = new uint8_t[m_FieldSize]; |
540 | 0 | std::string fieldData; |
541 | |
|
542 | 0 | if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) |
543 | 0 | fieldData = name + nameValueSeparation + value + "\r\n"; |
544 | 0 | else |
545 | 0 | fieldData = "\r\n"; |
546 | | |
547 | | // copy field data to m_NewFieldData |
548 | 0 | memcpy(m_NewFieldData, fieldData.c_str(), m_FieldSize); |
549 | | |
550 | | // calculate value offset |
551 | 0 | if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) |
552 | 0 | m_ValueOffsetInMessage = name.length() + nameValueSeparation.length(); |
553 | 0 | else |
554 | 0 | m_ValueOffsetInMessage = 0; |
555 | 0 | m_FieldNameSize = name.length(); |
556 | 0 | m_FieldValueSize = value.length(); |
557 | |
|
558 | 0 | if (name != PCPP_END_OF_TEXT_BASED_PROTOCOL_HEADER) |
559 | 0 | m_IsEndOfHeaderField = false; |
560 | 0 | else |
561 | 0 | m_IsEndOfHeaderField = true; |
562 | 0 | } |
563 | | |
564 | | HeaderField::~HeaderField() |
565 | 137k | { |
566 | 137k | if (m_NewFieldData != NULL) |
567 | 0 | delete [] m_NewFieldData; |
568 | 137k | } |
569 | | |
570 | | HeaderField::HeaderField(const HeaderField& other) : m_NameValueSeparator('\0'), m_SpacesAllowedBetweenNameAndValue(false) |
571 | 0 | { |
572 | 0 | m_NameValueSeparator = other.m_NameValueSeparator; |
573 | 0 | m_SpacesAllowedBetweenNameAndValue = other.m_SpacesAllowedBetweenNameAndValue; |
574 | 0 | initNewField(other.getFieldName(), other.getFieldValue()); |
575 | 0 | } |
576 | | |
577 | | HeaderField& HeaderField::operator=(const HeaderField& other) |
578 | 0 | { |
579 | 0 | m_NameValueSeparator = other.m_NameValueSeparator; |
580 | 0 | m_SpacesAllowedBetweenNameAndValue = other.m_SpacesAllowedBetweenNameAndValue; |
581 | 0 | if (m_NewFieldData != NULL) |
582 | 0 | delete [] m_NewFieldData; |
583 | 0 | initNewField(other.getFieldName(), other.getFieldValue()); |
584 | |
|
585 | 0 | return (*this); |
586 | 0 | } |
587 | | |
588 | | char* HeaderField::getData() const |
589 | 97.5k | { |
590 | 97.5k | if (m_TextBasedProtocolMessage == NULL) |
591 | 0 | return (char*)m_NewFieldData; |
592 | 97.5k | else |
593 | 97.5k | return (char*)(m_TextBasedProtocolMessage->m_Data); |
594 | 97.5k | } |
595 | | |
596 | | void HeaderField::setNextField(HeaderField* nextField) |
597 | 79.1k | { |
598 | 79.1k | m_NextField = nextField; |
599 | 79.1k | } |
600 | | |
601 | | HeaderField* HeaderField::getNextField() const |
602 | 128k | { |
603 | 128k | return m_NextField; |
604 | 128k | } |
605 | | |
606 | | std::string HeaderField::getFieldName() const |
607 | 128k | { |
608 | 128k | std::string result; |
609 | | |
610 | 128k | if (m_FieldNameSize != (size_t)-1) |
611 | 92.5k | result.assign((const char*)(((HeaderField*)this)->getData() + m_NameOffsetInMessage), m_FieldNameSize); |
612 | | |
613 | 128k | return result; |
614 | 128k | } |
615 | | |
616 | | std::string HeaderField::getFieldValue() const |
617 | 5.30k | { |
618 | 5.30k | std::string result; |
619 | 5.30k | if (m_ValueOffsetInMessage != -1) |
620 | 4.98k | result.assign((const char*)(((HeaderField*)this)->getData() + m_ValueOffsetInMessage), m_FieldValueSize); |
621 | 5.30k | return result; |
622 | 5.30k | } |
623 | | |
624 | | bool HeaderField::setFieldValue(std::string newValue) |
625 | 0 | { |
626 | | // Field isn't linked with any message yet |
627 | 0 | if (m_TextBasedProtocolMessage == NULL) |
628 | 0 | { |
629 | 0 | std::string name = getFieldName(); |
630 | 0 | delete [] m_NewFieldData; |
631 | 0 | initNewField(name, newValue); |
632 | 0 | return true; |
633 | 0 | } |
634 | | |
635 | 0 | std::string curValue = getFieldValue(); |
636 | 0 | int lengthDifference = newValue.length() - curValue.length(); |
637 | | // new value is longer than current value |
638 | 0 | if (lengthDifference > 0) |
639 | 0 | { |
640 | 0 | if (!m_TextBasedProtocolMessage->extendLayer(m_ValueOffsetInMessage, lengthDifference)) |
641 | 0 | { |
642 | 0 | PCPP_LOG_ERROR("Could not extend layer"); |
643 | 0 | return false; |
644 | 0 | } |
645 | 0 | } |
646 | | // new value is shorter than current value |
647 | 0 | else if (lengthDifference < 0) |
648 | 0 | { |
649 | 0 | if (!m_TextBasedProtocolMessage->shortenLayer(m_ValueOffsetInMessage, 0 - lengthDifference)) |
650 | 0 | { |
651 | 0 | PCPP_LOG_ERROR("Could not shorten layer"); |
652 | 0 | return false; |
653 | 0 | } |
654 | 0 | } |
655 | | |
656 | 0 | if (lengthDifference != 0) |
657 | 0 | m_TextBasedProtocolMessage->shiftFieldsOffset(getNextField(), lengthDifference); |
658 | | |
659 | | // update sizes |
660 | 0 | m_FieldValueSize += lengthDifference; |
661 | 0 | m_FieldSize += lengthDifference; |
662 | | |
663 | | // write new value to field data |
664 | 0 | memcpy(getData() + m_ValueOffsetInMessage, newValue.c_str(), newValue.length()); |
665 | |
|
666 | 0 | return true; |
667 | 0 | } |
668 | | |
669 | | void HeaderField::attachToTextBasedProtocolMessage(TextBasedProtocolMessage* message, int fieldOffsetInMessage) |
670 | 0 | { |
671 | 0 | if (m_TextBasedProtocolMessage != NULL && m_TextBasedProtocolMessage != message) |
672 | 0 | { |
673 | 0 | PCPP_LOG_ERROR("Header field already associated with another message"); |
674 | 0 | return; |
675 | 0 | } |
676 | | |
677 | 0 | if (m_NewFieldData == NULL) |
678 | 0 | { |
679 | 0 | PCPP_LOG_ERROR("Header field doesn't have new field data"); |
680 | 0 | return; |
681 | 0 | } |
682 | | |
683 | 0 | delete [] m_NewFieldData; |
684 | 0 | m_NewFieldData = NULL; |
685 | 0 | m_TextBasedProtocolMessage = message; |
686 | |
|
687 | 0 | int valueAndNameDifference = m_ValueOffsetInMessage - m_NameOffsetInMessage; |
688 | 0 | m_NameOffsetInMessage = fieldOffsetInMessage; |
689 | 0 | m_ValueOffsetInMessage = m_NameOffsetInMessage + valueAndNameDifference; |
690 | 0 | } |
691 | | |
692 | | } |