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