1 /***************************************************************************
2 buffer.cpp - description
3 -------------------
4 begin : Thu Jun 6 2002
5
6 Copyright (c) 2002 by Tom Linsky <twl6@po.cwru.edu>
7 Copyright (c) 2004,2005 by Matt Rogers <mattr@kde.org>
8 Kopete (c) 2002-2005 by the Kopete developers <kopete-devel@kde.org>
9
10 *************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 *************************************************************************
18 */
19
20 #include "buffer.h"
21
22 #include <ctype.h>
23 #include <kdebug.h>
24
Buffer()25 Buffer::Buffer()
26 {
27 mReadPos=0;
28 }
29
Buffer(const Buffer & other)30 Buffer::Buffer( const Buffer& other )
31 {
32 mBuffer = other.mBuffer;
33 mReadPos = other.mReadPos;
34 mBlockStack = other.mBlockStack;
35 }
36
Buffer(const char * b,int len)37 Buffer::Buffer(const char *b, int len)
38 {
39 mBuffer = QByteArray::fromRawData( b, len );
40 mReadPos = 0;
41 }
42
Buffer(const QByteArray & data)43 Buffer::Buffer( const QByteArray& data )
44 {
45 mBuffer = data;
46 mReadPos = 0;
47 }
48
~Buffer()49 Buffer::~Buffer()
50 {
51 }
52
addByte(Oscar::BYTE b)53 int Buffer::addByte(Oscar::BYTE b)
54 {
55 expandBuffer(1);
56 mBuffer[mBuffer.size()-1] = b;
57
58 return mBuffer.size();
59 }
60
addLEByte(Oscar::BYTE b)61 int Buffer::addLEByte(Oscar::BYTE b)
62 {
63 expandBuffer(1);
64 mBuffer[mBuffer.size()-1] = ((b) & 0xff);
65
66 return mBuffer.size();
67 }
68
addWord(Oscar::WORD w)69 int Buffer::addWord(Oscar::WORD w)
70 {
71 expandBuffer(2);
72 mBuffer[mBuffer.size()-2] = ((w & 0xff00) >> 8);
73 mBuffer[mBuffer.size()-1] = (w & 0x00ff);
74
75 return mBuffer.size();
76 }
77
addLEWord(Oscar::WORD w)78 int Buffer::addLEWord(Oscar::WORD w)
79 {
80 expandBuffer(2);
81 mBuffer[mBuffer.size()-2] = (unsigned char) ((w >> 0) & 0xff);
82 mBuffer[mBuffer.size()-1] = (unsigned char) ((w >> 8) & 0xff);
83
84 return mBuffer.size();
85 }
86
addDWord(Oscar::DWORD dw)87 int Buffer::addDWord(Oscar::DWORD dw)
88 {
89 expandBuffer(4);
90 mBuffer[mBuffer.size()-4] = (dw & 0xff000000) >> 24;
91 mBuffer[mBuffer.size()-3] = (dw & 0x00ff0000) >> 16;
92 mBuffer[mBuffer.size()-2] = (dw & 0x0000ff00) >> 8;
93 mBuffer[mBuffer.size()-1] = (dw & 0x000000ff);
94
95 return mBuffer.size();
96 }
97
addLEDWord(Oscar::DWORD dw)98 int Buffer::addLEDWord(Oscar::DWORD dw)
99 {
100 expandBuffer(4);
101 mBuffer[mBuffer.size()-4] = (unsigned char) ((dw >> 0) & 0xff);
102 mBuffer[mBuffer.size()-3] = (unsigned char) ((dw >> 8) & 0xff);
103 mBuffer[mBuffer.size()-2] = (unsigned char) ((dw >> 16) & 0xff);
104 mBuffer[mBuffer.size()-1] = (unsigned char) ((dw >> 24) & 0xff);
105
106 return mBuffer.size();
107 }
108
addString(const QByteArray & s)109 int Buffer::addString( const QByteArray& s )
110 {
111 mBuffer.append( s );
112 return mBuffer.size();
113 }
114
addString(QByteArray s,Oscar::DWORD len)115 int Buffer::addString(QByteArray s, Oscar::DWORD len)
116 {
117 Q_UNUSED( len );
118 return addString( s );
119 }
120
addString(const char * s,Oscar::DWORD len)121 int Buffer::addString( const char* s, Oscar::DWORD len )
122 {
123 QByteArray qba( s, len );
124 return addString( qba );
125 }
126
addString(const unsigned char * s,Oscar::DWORD len)127 int Buffer::addString(const unsigned char* s, Oscar::DWORD len)
128 {
129 QByteArray qba( (const char*) s, len );
130 return addString( qba );
131 }
132
addLEString(const char * s,Oscar::DWORD len)133 int Buffer::addLEString(const char *s, Oscar::DWORD len)
134 {
135 unsigned int pos = mBuffer.size();
136 expandBuffer(len);
137 //concatenate the new string onto the buffer
138 for(unsigned int i=0; i<len; i++)
139 {
140 mBuffer[pos+i]=((s[i]) & 0xff);
141 }
142 return mBuffer.size();
143 }
144
clear()145 void Buffer::clear()
146 {
147 mBuffer.truncate( 0 );
148 mReadPos=0;
149 }
150
addTLV(const TLV & t)151 int Buffer::addTLV( const TLV& t )
152 {
153 return addTLV( t.type, t.data );
154 }
155
addTLV(Oscar::WORD type,const QByteArray & data)156 int Buffer::addTLV( Oscar::WORD type, const QByteArray& data )
157 {
158 addWord( type );
159 addWord( data.length() );
160 return addString( data );
161 }
162
addLETLV(Oscar::WORD type,const QByteArray & data)163 int Buffer::addLETLV( Oscar::WORD type, const QByteArray& data )
164 {
165 addLEWord( type );
166 addLEWord( data.length() );
167 return addString( data );
168 }
169
getByte()170 Oscar::BYTE Buffer::getByte()
171 {
172 Oscar::BYTE thebyte = 0x00;
173
174 if(mReadPos < mBuffer.size())
175 {
176 thebyte = mBuffer[mReadPos];
177 mReadPos++;
178 }
179 else
180 kDebug(14150) << "Buffer::getByte(): mBuffer empty";
181
182 return thebyte;
183 }
184
skipBytes(int bytesToSkip)185 void Buffer::skipBytes( int bytesToSkip )
186 {
187 if (mReadPos < mBuffer.size())
188 mReadPos += bytesToSkip;
189 }
190
getLEByte()191 Oscar::BYTE Buffer::getLEByte()
192 {
193 Oscar::BYTE b = getByte();
194 return (b & 0xff);
195 }
196
getWord()197 Oscar::WORD Buffer::getWord()
198 {
199 Oscar::WORD theword, theword2, retword;
200 theword = getByte();
201 theword2 = getByte();
202 retword = (theword << 8) | theword2;
203 return retword;
204 }
205
getLEWord()206 Oscar::WORD Buffer::getLEWord()
207 {
208 Oscar::WORD theword1, theword2, retword;
209 theword1 = getLEByte();
210 theword2 = getLEByte();
211 retword = (theword2 << 8) | theword1;
212 return retword;
213 }
214
getDWord()215 Oscar::DWORD Buffer::getDWord()
216 {
217 Oscar::DWORD word1, word2;
218 Oscar::DWORD retdword;
219 word1 = getWord();
220 word2 = getWord();
221 retdword = (word1 << 16) | word2;
222 return retdword;
223 }
224
getLEDWord()225 Oscar::DWORD Buffer::getLEDWord()
226 {
227 Oscar::DWORD word1, word2, retdword;
228 word1 = getLEWord();
229 word2 = getLEWord();
230 retdword = (word2 << 16) | word1;
231 return retdword;
232 }
233
setBuf(char * b,Oscar::WORD len)234 void Buffer::setBuf(char *b, Oscar::WORD len)
235 {
236 mBuffer = QByteArray::fromRawData(b, len);
237 mReadPos = 0;
238 }
239
getBlock(Oscar::DWORD len)240 QByteArray Buffer::getBlock(Oscar::DWORD len)
241 {
242 if ( len > (Oscar::DWORD)(mBuffer.size() - mReadPos) )
243 {
244 kDebug(14150) << "Buffer::getBlock(DWORD): mBuffer underflow!!!";
245 len = mBuffer.size() - mReadPos;
246 }
247
248 QByteArray ch;
249 ch.resize( len );
250
251 for ( Oscar::DWORD i = 0; i < len; i++ )
252 {
253 ch[i] = getByte();
254 }
255
256 return ch;
257 }
258
getBBlock(Oscar::WORD len)259 QByteArray Buffer::getBBlock(Oscar::WORD len)
260 {
261 QByteArray data = QByteArray::fromRawData( mBuffer.data() + mReadPos, len);
262 mReadPos += len;
263 return data;
264 }
265
getWordBlock(Oscar::WORD len)266 Oscar::WORD *Buffer::getWordBlock(Oscar::WORD len)
267 {
268 kDebug(14150) << "of length " << len;
269 Oscar::WORD *ch=new Oscar::WORD[len+1];
270 for (unsigned int i=0; i<len; i++)
271 {
272 ch[i]=getWord();
273 }
274 ch[len]=0;
275 return ch;
276 }
277
getLEBlock(Oscar::WORD len)278 QByteArray Buffer::getLEBlock(Oscar::WORD len)
279 {
280 QByteArray ch;
281 for (unsigned int i=0;i<len;i++)
282 ch += getLEByte();
283
284 return ch;
285 }
286
addTLV32(Oscar::WORD type,Oscar::DWORD data)287 int Buffer::addTLV32(Oscar::WORD type, Oscar::DWORD data)
288 {
289 addWord(type);
290 addWord(0x0004); //4 Oscar::BYTEs long
291 return addDWord(data);
292 }
293
addLETLV32(Oscar::WORD type,Oscar::DWORD data)294 int Buffer::addLETLV32(Oscar::WORD type, Oscar::DWORD data)
295 {
296 addLEWord(type);
297 addLEWord(0x0004); //4 Oscar::BYTEs long
298 return addLEDWord(data);
299 }
300
addTLV16(Oscar::WORD type,Oscar::WORD data)301 int Buffer::addTLV16(Oscar::WORD type, Oscar::WORD data)
302 {
303 addWord(type);
304 addWord(0x0002); //2 Oscar::BYTEs long
305 return addWord(data);
306 }
307
addLETLV16(Oscar::WORD type,Oscar::WORD data)308 int Buffer::addLETLV16(Oscar::WORD type, Oscar::WORD data)
309 {
310 addLEWord(type);
311 addLEWord(0x0002); //2 Oscar::BYTEs long
312 return addLEWord(data);
313 }
314
addTLV8(Oscar::WORD type,Oscar::BYTE data)315 int Buffer::addTLV8(Oscar::WORD type, Oscar::BYTE data)
316 {
317 addWord(type);
318 addWord(0x0001); //1 Oscar::BYTE long
319 return addByte(data);
320 }
321
addLETLV8(Oscar::WORD type,Oscar::BYTE data)322 int Buffer::addLETLV8(Oscar::WORD type, Oscar::BYTE data)
323 {
324 addLEWord(type);
325 addLEWord(0x0001); //1 Oscar::BYTE long
326 return addLEByte(data);
327 }
328
getTLV()329 TLV Buffer::getTLV()
330 {
331 TLV t;
332 if(bytesAvailable() >= 4)
333 {
334 t.type = getWord();
335 t.length = getWord();
336 if ( t )
337 t.data = getBlock( t.length );
338 /*else
339 kDebug(OSCAR_RAW_DEBUG) << "Invalid TLV in buffer";*/
340 }
341
342 //kDebug(OSCAR_RAW_DEBUG) << "TLV data is " << t.data;
343 return t;
344 }
345
getTLVList()346 QList<TLV> Buffer::getTLVList()
347 {
348 QList<TLV> ql;
349
350 while (mReadPos < mBuffer.size())
351 {
352 TLV t;
353
354 t = getTLV();
355 if ( !t )
356 {
357 kDebug(14150) << "Invalid TLV found";
358 continue;
359 }
360
361 //kDebug(14150) << "got TLV(" << t.type << ")";
362 ql.append(t);
363 }
364
365 return ql;
366 }
367
addChatTLV(Oscar::WORD type,Oscar::WORD exchange,const QString & roomname,Oscar::WORD instance)368 int Buffer::addChatTLV(Oscar::WORD type, Oscar::WORD exchange,
369 const QString &roomname, Oscar::WORD instance)
370 {
371 addWord(type);
372 addWord(0x0005 + roomname.length());
373 addWord(exchange);
374 addByte(roomname.length());
375 addString(roomname.toLatin1()); // TODO: check encoding
376
377 return addWord(instance);
378 }
379
expandBuffer(unsigned int inc)380 void Buffer::expandBuffer(unsigned int inc)
381 {
382 mBuffer.resize(mBuffer.size()+inc);
383 }
384
getLNTS()385 QByteArray Buffer::getLNTS()
386 {
387 Oscar::WORD len = getWord();
388 QByteArray qcs;
389 if ( len > 0 )
390 {
391 qcs = getBlock(len - 1);
392 skipBytes( 1 );
393 }
394
395 return qcs;
396 }
397
getLELNTS()398 QByteArray Buffer::getLELNTS()
399 {
400 Oscar::WORD len = getLEWord();
401 QByteArray qcs;
402 if ( len > 0 )
403 {
404 qcs = getBlock(len - 1);
405 skipBytes( 1 );
406 }
407
408 return qcs;
409 }
410
addLNTS(const char * s)411 int Buffer::addLNTS(const char *s)
412 {
413 unsigned int len = strlen(s);
414
415 addLEWord(len+1);
416 if(len > 0)
417 addString(s, len);
418 int ret = addByte(0x00);
419 return ret;
420 }
421
addLELNTS(const char * s)422 int Buffer::addLELNTS(const char *s)
423 {
424 unsigned int len = strlen(s);
425 int ret = addLEWord(len+1);
426 if(len > 0)
427 ret = addLEString(s, len);
428 ret = addByte(0x00);
429 return ret;
430 }
431
addBSTR(const char * s)432 int Buffer::addBSTR(const char * s)
433 {
434 unsigned int len = strlen(s);
435 int ret = addWord(len);
436 if(len > 0)
437 ret = addString(s, len);
438 return ret;
439 }
440
getBSTR()441 QByteArray Buffer::getBSTR()
442 {
443 Oscar::WORD len = getWord();
444 QByteArray qba( getBlock(len) );
445 return qba;
446 }
447
addBUIN(const char * s)448 int Buffer::addBUIN(const char * s)
449 {
450 unsigned int len = strlen(s);
451 int ret = addByte(len);
452 ret = addString(s, len);
453 return ret;
454 }
455
getBUIN()456 QByteArray Buffer::getBUIN()
457 {
458 Oscar::BYTE len = getByte();
459 QByteArray qba( getBlock(len) );
460 return qba;
461 }
462
buffer() const463 QByteArray Buffer::buffer() const
464 {
465 return mBuffer;
466 }
467
length() const468 int Buffer::length() const
469 {
470 return mBuffer.size();
471 }
472
bytesAvailable() const473 int Buffer::bytesAvailable() const
474 {
475 return (mBuffer.size() - mReadPos);
476 }
477
toString() const478 QString Buffer::toString() const
479 {
480 // line format:
481 //00 03 00 0b 00 00 90 b8 f5 9f 09 31 31 33 37 38 |;tJ�..........|
482
483 int i = 0;
484 QString output = QStringLiteral("\n");
485 QString hex, ascii;
486
487 QByteArray::ConstIterator it;
488 for ( it = mBuffer.begin(); it != mBuffer.end(); ++it )
489 {
490 i++;
491
492 unsigned char c = static_cast<unsigned char>(*it);
493
494 if ( c < 0x10 )
495 hex.append("0");
496 hex.append(QStringLiteral("%1 ").arg(c, 0, 16));
497
498 ascii.append(isprint(c) ? c : '.');
499
500 if (i == 16)
501 {
502 output += hex + " |" + ascii + "|\n";
503 i=0;
504 hex.clear();
505 ascii.clear();
506 }
507 }
508
509 if(!hex.isEmpty())
510 output += hex.leftJustified(48, ' ') + " |" + ascii.leftJustified(16, ' ') + '|';
511 output.append('\n');
512
513 return output;
514 }
515
peekBSTR()516 QString Buffer::peekBSTR()
517 {
518 int lastPos = mReadPos;
519 QByteArray qba = getBSTR();
520 mReadPos = lastPos;
521 return QString( qba );
522 }
peekBUIN()523 QString Buffer::peekBUIN()
524 {
525 int lastPos = mReadPos;
526 QByteArray qba = getBUIN();
527 mReadPos = lastPos;
528 return QString( qba );
529 }
530
addGuid(const Guid & g)531 int Buffer::addGuid( const Guid & g )
532 {
533 if (g.isValid())
534 return addString( g.data() );
535 return mBuffer.size();
536 }
537
getGuid()538 Guid Buffer::getGuid()
539 {
540 return Guid(getBBlock(16)); //block or bblock?
541 }
542
addLEBlock(const QByteArray & block)543 int Buffer::addLEBlock( const QByteArray& block )
544 {
545 int ret = addLEWord( block.length() );
546 if ( block.length() > 0 )
547 ret = addString( block );
548
549 return ret;
550 }
551
getLEBlock()552 QByteArray Buffer::getLEBlock()
553 {
554 Oscar::DWORD len = getLEWord();
555 return getBlock( len );
556 }
557
addLEDBlock(const QByteArray & block)558 int Buffer::addLEDBlock( const QByteArray& block )
559 {
560 int ret = addLEDWord( block.length() );
561 if ( block.length() > 0 )
562 ret = addString( block );
563
564 return ret;
565 }
566
getLEDBlock()567 QByteArray Buffer::getLEDBlock()
568 {
569 Oscar::DWORD len = getLEDWord();
570 return getBlock( len );
571 }
572
startBlock(BlockType type,ByteOrder byteOrder)573 void Buffer::startBlock( BlockType type, ByteOrder byteOrder )
574 {
575 Block block = { type, byteOrder, mBuffer.size() };
576 mBlockStack.push( block );
577
578 if ( type == BWord )
579 expandBuffer( 2 );
580 else if ( type == BDWord )
581 expandBuffer( 4 );
582 }
583
endBlock()584 void Buffer::endBlock()
585 {
586 Q_ASSERT( mBlockStack.size() > 0 );
587 Block block = mBlockStack.pop();
588
589 int size = 0;
590 if ( block.type == BWord )
591 size = mBuffer.size() - block.pos - 2;
592 else if ( block.type == BDWord )
593 size = mBuffer.size() - block.pos - 4;
594
595 if ( block.byteOrder == BigEndian )
596 {
597 if ( block.type == BWord )
598 {
599 mBuffer[block.pos++] = (unsigned char) ((size & 0x0000ff00) >> 8);
600 mBuffer[block.pos++] = (unsigned char) ((size & 0x000000ff) >> 0);
601 }
602 else if ( block.type == BDWord )
603 {
604 mBuffer[block.pos++] = (unsigned char) ((size & 0xff000000) >> 24);
605 mBuffer[block.pos++] = (unsigned char) ((size & 0x00ff0000) >> 16);
606 mBuffer[block.pos++] = (unsigned char) ((size & 0x0000ff00) >> 8);
607 mBuffer[block.pos++] = (unsigned char) ((size & 0x000000ff) >> 0);
608 }
609 }
610 else
611 {
612 if ( block.type == BWord )
613 {
614 mBuffer[block.pos++] = (unsigned char) ((size >> 0) & 0xff);
615 mBuffer[block.pos++] = (unsigned char) ((size >> 8) & 0xff);
616 }
617 else if ( block.type == BDWord )
618 {
619 mBuffer[block.pos++] = (unsigned char) ((size >> 0) & 0xff);
620 mBuffer[block.pos++] = (unsigned char) ((size >> 8) & 0xff);
621 mBuffer[block.pos++] = (unsigned char) ((size >> 16) & 0xff);
622 mBuffer[block.pos++] = (unsigned char) ((size >> 24) & 0xff);
623 }
624 }
625 }
626
operator QByteArray() const627 Buffer::operator QByteArray() const
628 {
629 return mBuffer;
630 }
631