1 /*
2  * This file is part of Licq, an instant messaging client for UNIX.
3  * Copyright (C) 1998-2014 Licq developers <licq-dev@googlegroups.com>
4  *
5  * Licq is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Licq is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Licq; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #include <licq/buffer.h>
21 
22 #include "config.h"
23 
24 #include <cstdlib>
25 #include <cstdio>
26 #include <ctype.h>
27 #include <cstring>
28 
29 #include <licq/byteorder.h>
30 #include <licq/logging/log.h>
31 
32 #include "gettext.h"
33 
34 using Licq::Buffer;
35 using std::string;
36 
Buffer()37 Buffer::Buffer()
38 {
39   m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL;
40   m_nDataSize = 0;
41 }
42 
43 
Buffer(unsigned long _nDataSize)44 Buffer::Buffer(unsigned long _nDataSize)
45 {
46   m_nDataSize = _nDataSize;
47   if (_nDataSize)
48     m_pDataStart = new char[m_nDataSize];
49   else
50     m_pDataStart = NULL;
51   m_pDataPosRead = m_pDataPosWrite = m_pDataStart;
52 }
53 
Buffer(const Buffer & b)54 Buffer::Buffer(const Buffer& b)
55 {
56   m_nDataSize = b.getDataMaxSize();
57   if (m_nDataSize)
58   {
59     m_pDataStart = new char[m_nDataSize];
60     memcpy(m_pDataStart, b.getDataStart(), m_nDataSize);
61   }
62   else
63   {
64     m_pDataStart = NULL;
65   }
66   m_pDataPosRead = m_pDataStart + (b.getDataPosRead() - b.getDataStart());
67   m_pDataPosWrite = m_pDataStart + (b.getDataPosWrite() - b.getDataStart());
68 }
69 
70 #if 0
71 Buffer::Buffer(Buffer* b)
72 {
73   if (b == NULL)
74   {
75      m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL;
76      m_nDataSize = 0;
77   }
78   else
79   {
80     m_nDataSize = b->getDataMaxSize();
81     m_pDataStart = new char[m_nDataSize];
82     memcpy(m_pDataStart, b->getDataStart(), m_nDataSize);
83     m_pDataPosRead = m_pDataStart + (b->getDataPosRead() - b->getDataStart());
84     m_pDataPosWrite = m_pDataStart + (b->getDataPosWrite() - b->getDataStart());
85   }
86 }
87 #endif
88 
operator =(const Buffer & b)89 Buffer& Buffer::operator=(const Buffer& b)
90 {
91    if (m_pDataStart != NULL) delete [] m_pDataStart;
92    m_nDataSize = b.getDataSize();
93    if (m_nDataSize)
94    {
95      m_pDataStart = new char[m_nDataSize];
96      memcpy(m_pDataStart, b.getDataStart(), m_nDataSize);
97    }
98    else
99      m_pDataStart = NULL;
100    m_pDataPosRead = m_pDataStart + (b.getDataPosRead() - b.getDataStart());
101    m_pDataPosWrite = m_pDataStart + (b.getDataPosWrite() - b.getDataStart());
102 
103    return (*this);
104 }
105 
operator +(const Buffer & b0,const Buffer & b1)106 Buffer Licq::operator+(const Buffer& b0, const Buffer& b1)
107 {
108    unsigned long nB0Size = b0.getDataPosWrite() - b0.getDataStart();
109    unsigned long nB1Size = b1.getDataPosWrite() - b1.getDataStart();
110   Buffer bCat(b0.getDataSize() + b1.getDataSize());
111 
112    memcpy(bCat.getDataPosWrite(), b0.getDataStart(), nB0Size);
113    bCat.incDataPosWrite(nB0Size);
114    memcpy(bCat.getDataPosWrite(), b1.getDataStart(), nB1Size);
115    bCat.incDataPosWrite(nB1Size);
116 
117    return bCat;
118 }
119 
operator +=(const Buffer & b)120 Buffer& Buffer::operator+=(const Buffer& b)
121 {
122   Buffer buf = *this + b;
123   *this = buf;
124   return *this;
125 }
126 
127 //-----create-------------------------------------------------------------------
Create(unsigned long _nDataSize)128 void Buffer::Create(unsigned long _nDataSize)
129 {
130    if (m_pDataStart != NULL) delete[] m_pDataStart;
131    if (_nDataSize != 0) m_nDataSize = _nDataSize;
132    m_pDataStart = new char[m_nDataSize];
133    m_pDataPosRead = m_pDataPosWrite = m_pDataStart;
134 }
135 
136 //----->>-----------------------------------------------------------------------
operator >>(char & in)137 Buffer& Buffer::operator>>(char& in)
138 {
139   in = unpackInt8();
140   return *this;
141 }
142 
operator >>(unsigned char & in)143 Buffer& Buffer::operator>>(unsigned char& in)
144 {
145   in = unpackUInt8();
146   return *this;
147 }
148 
operator >>(unsigned short & in)149 Buffer& Buffer::operator>>(unsigned short& in)
150 {
151   in = unpackUInt16LE();
152   return *this;
153 }
154 
operator >>(unsigned long & in)155 Buffer& Buffer::operator>>(unsigned long& in)
156 {
157   in = unpackUInt32LE();
158   return *this;
159 }
160 
unpackRawString(size_t size)161 string Buffer::unpackRawString(size_t size)
162 {
163   if (remainingDataToRead() < size)
164     size = remainingDataToRead();
165   string ret(getDataPosRead(), size);
166   incDataPosRead(size);
167   return ret;
168 }
169 
unpackByteString()170 string Buffer::unpackByteString()
171 {
172   uint8_t len = unpackUInt8();
173   return unpackRawString(len);
174 }
175 
unpackShortStringLE()176 string Buffer::unpackShortStringLE()
177 {
178   uint16_t len = unpackUInt16LE();
179   return unpackRawString(len);
180 }
181 
unpackShortStringBE()182 string Buffer::unpackShortStringBE()
183 {
184   uint16_t len = unpackUInt16BE();
185   return unpackRawString(len);
186 }
187 
unpackLongStringLE()188 string Buffer::unpackLongStringLE()
189 {
190   uint32_t len = unpackUInt32LE();
191   return unpackRawString(len);
192 }
193 
unpackLongStringBE()194 string Buffer::unpackLongStringBE()
195 {
196   uint32_t len = unpackUInt32BE();
197   return unpackRawString(len);
198 }
199 
unpackUInt32LE()200 uint32_t Buffer::unpackUInt32LE()
201 {
202   if (remainingDataToRead() < 4)
203     return 0;
204 
205   uint32_t n = LE_32(*(uint32_t*)getDataPosRead());
206   incDataPosRead(4);
207   return n;
208 }
209 
unpackUInt32BE()210 uint32_t Buffer::unpackUInt32BE()
211 {
212   if (remainingDataToRead() < 4)
213     return 0;
214 
215   uint32_t n = BE_32(*(uint32_t*)getDataPosRead());
216   incDataPosRead(4);
217   return n;
218 }
219 
unpackUInt16LE()220 uint16_t Buffer::unpackUInt16LE()
221 {
222   if (remainingDataToRead() < 2)
223     return 0;
224 
225   uint16_t n = LE_16(*(uint16_t*)getDataPosRead());
226   incDataPosRead(2);
227   return n;
228 }
229 
unpackUInt16BE()230 uint16_t Buffer::unpackUInt16BE()
231 {
232   if (remainingDataToRead() < 2)
233     return 0;
234 
235   uint16_t n = BE_16(*(uint16_t*)getDataPosRead());
236   incDataPosRead(2);
237   return n;
238 }
239 
unpackUInt8()240 uint8_t Buffer::unpackUInt8()
241 {
242   if (remainingDataToRead() < 1)
243     return 0;
244 
245   uint8_t n = *((uint8_t*)getDataPosRead());
246   incDataPosRead(1);
247   return n;
248 }
249 
unpackInt8()250 int8_t Buffer::unpackInt8()
251 {
252   if (remainingDataToRead() < 1)
253     return 0;
254 
255   int8_t n = *((int8_t*)getDataPosRead());
256   incDataPosRead(1);
257   return n;
258 }
259 
260 
261 //-----clear--------------------------------------------------------------------
Clear()262 void Buffer::Clear()
263 {
264   if (m_pDataStart != NULL) delete[] m_pDataStart;
265   m_pDataStart = m_pDataPosRead = m_pDataPosWrite = NULL;
266   m_nDataSize = 0;
267 }
268 
269 
270 //-----reset--------------------------------------------------------------------
Reset()271 void Buffer::Reset()
272 {
273   m_pDataPosRead = m_pDataStart;
274 }
275 
276 //-----Empty--------------------------------------------------------------------
Empty() const277 bool Buffer::Empty() const
278 {
279   return (m_pDataStart == NULL);
280 }
281 
282 //-----Full---------------------------------------------------------------------
Full() const283 bool Buffer::Full() const
284 {
285   return (!Empty() && getDataPosWrite() >= (getDataStart() + getDataMaxSize()));
286 }
287 
288 
289 //-----Copy---------------------------------------------------------------------
Copy(Buffer * b)290 void Buffer::Copy(Buffer* b)
291 {
292   Create(b->getDataSize());
293   Pack(b);
294 }
295 
296 
~Buffer()297 Buffer::~Buffer()
298 {
299   if (m_pDataStart != NULL) delete[] m_pDataStart;
300 }
301 
302 //-----add----------------------------------------------------------------------
packUInt32LE(uint32_t data)303 void Buffer::packUInt32LE(uint32_t data)
304 {
305   if (remainingDataToWrite() < 4)
306   {
307     gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
308     return;
309   }
310   *(uint32_t*)getDataPosWrite() = LE_32(data);
311   incDataPosWrite(4);
312 }
313 
packUInt32BE(uint32_t data)314 void Buffer::packUInt32BE(uint32_t data)
315 {
316   if (remainingDataToWrite() < 4)
317   {
318     gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
319     return;
320   }
321   *(uint32_t*)getDataPosWrite() = BE_32(data);
322   incDataPosWrite(4);
323 }
324 
packUInt16LE(uint16_t data)325 void Buffer::packUInt16LE(uint16_t data)
326 {
327   if (remainingDataToWrite() < 2)
328   {
329     gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
330     return;
331   }
332   *(uint16_t*)getDataPosWrite() = LE_16(data);
333   incDataPosWrite(2);
334 }
335 
packUInt16BE(uint16_t data)336 void Buffer::packUInt16BE(uint16_t data)
337 {
338   if (remainingDataToWrite() < 2)
339   {
340     gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
341     return;
342   }
343   *(uint16_t*)getDataPosWrite() = BE_16(data);
344   incDataPosWrite(2);
345 }
346 
packUInt8(uint8_t data)347 void Buffer::packUInt8(uint8_t data)
348 {
349   if (remainingDataToWrite() < 1)
350   {
351     gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
352     return;
353   }
354   *(uint8_t*)getDataPosWrite() = data;
355   incDataPosWrite(1);
356 }
357 
packInt8(int8_t data)358 void Buffer::packInt8(int8_t data)
359 {
360   if (remainingDataToWrite() < 1)
361   {
362     gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
363     return;
364   }
365   *(int8_t*)getDataPosWrite() = data;
366   incDataPosWrite(1);
367 }
368 
packRaw(const void * data,size_t length)369 void Buffer::packRaw(const void* data, size_t length)
370 {
371   if (data == NULL)
372     return;
373   if (remainingDataToWrite() < length)
374   {
375     gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
376     return;
377   }
378   memcpy(getDataPosWrite(), data, length);
379   incDataPosWrite(length);
380 }
381 
packShortNullStringLE(const string & data)382 void Buffer::packShortNullStringLE(const string& data)
383 {
384   if (remainingDataToWrite() < data.size() + 3)
385   {
386     gLog.warning(tr("Trying to pack more data than Licq::Buffer can hold!"));
387     return;
388   }
389 
390   *(uint16_t*)getDataPosWrite() = LE_16(data.size()+1);
391   incDataPosWrite(2);
392   memcpy(getDataPosWrite(), data.c_str(), data.size()+1);
393   incDataPosWrite(data.size()+1);
394 }
395 
packString16BE(const char * data,size_t length)396 void Buffer::packString16BE(const char* data, size_t length)
397 {
398   assert(remainingDataToWrite() >= length + 2);
399 
400   *(uint16_t*)getDataPosWrite() = BE_16(length);
401   incDataPosWrite(2);
402   if (length > 0)
403   {
404     memcpy(getDataPosWrite(), data, length);
405     incDataPosWrite(length);
406   }
407 }
408 
packString32LE(const char * data,size_t length)409 void Buffer::packString32LE(const char* data, size_t length)
410 {
411   assert(remainingDataToWrite() >= length + 4);
412 
413   *(uint32_t*)getDataPosWrite() = LE_32(length);
414   incDataPosWrite(4);
415   if (length > 0)
416   {
417     memcpy(getDataPosWrite(), data, length);
418     incDataPosWrite(length);
419   }
420 }
421 
Pack(Buffer * buf)422 void Buffer::Pack(Buffer* buf)
423 {
424   if ( getDataSize() + buf->getDataSize() > getDataMaxSize() )
425   {
426     gLog.warning(tr("Pack(): Trying to pack more data than "
427         "Licq::Buffer can hold!"));
428     return;
429   }
430   memcpy(getDataPosWrite(), buf->getDataStart(), buf->getDataSize());
431   incDataPosWrite(buf->getDataSize());
432 }
433 
log(Log::Level level,const char * format,...) const434 void Buffer::log(Log::Level level, const char* format, ...) const
435 {
436   va_list args;
437   va_start(args, format);
438 
439   gLog.packet(level,
440               reinterpret_cast<const uint8_t*>(getDataStart()),
441               getDataSize(),
442               format, args);
443 
444   va_end(args);
445 }
446