Coverage Report

Created: 2023-01-17 06:15

/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
}