1 /*
2     Kopete Oscar Protocol
3     oscarmessage.cpp - Oscar Message Object
4 
5     Copyright (c) 2005 Matt Rogers <mattr@kde.org>
6     Copyright (c) 2005 Conrad Hoffmann <conrausch@gmx.de>
7     Copyright (c) 2006-2007 Roman Jarosz <kedgedev@centrum.cz>
8 
9     Kopete (c) 2002-2007 by the Kopete developers <kopete-devel@kde.org>
10 
11     *************************************************************************
12     *                                                                       *
13     * This library is free software; you can redistribute it and/or         *
14     * modify it under the terms of the GNU Lesser General Public            *
15     * License as published by the Free Software Foundation; either          *
16     * version 2 of the License, or (at your option) any later version.      *
17     *                                                                       *
18     *************************************************************************
19 */
20 
21 #include "oscarmessage.h"
22 
23 #include <QTextCodec>
24 #include <QByteArray>
25 #include <QSharedData>
26 
27 #include "oscarmessageplugin.h"
28 
29 namespace Oscar
30 {
31 
32 class Message::MessagePrivate : public QSharedData
33 {
34 public:
MessagePrivate()35 	MessagePrivate()
36 		: QSharedData()
37 	{
38 		channel = -1;
39 		properties = 0;
40 		messageType = 0;
41 		requestType = 0;
42 		port = 0;
43 		requestNumber = 1;
44 		protocolVersion = 0;
45 		channel2Counter = 0;
46 		encoding = UserDefined;
47 		fileSize = 0;
48 		fileCount = 0;
49 		plugin = 0;
50 		id = 0;
51 	}
MessagePrivate(const MessagePrivate & other)52 	MessagePrivate( const MessagePrivate &other )
53 		: QSharedData( other )
54 	{
55 		sender = other.sender;
56 		receiver = other.receiver;
57 		channel = other.channel;
58 		properties = other.properties;
59 		messageType = other.messageType;
60 		requestType = other.requestType;
61 		port = other.port;
62 		requestNumber = other.requestNumber;
63 		protocolVersion = other.protocolVersion;
64 		channel2Counter = other.channel2Counter;
65 		icbmCookie = other.icbmCookie;
66 		proxy = other.proxy;
67 		textArray = other.textArray;
68 		timestamp = other.timestamp;
69 		exchange = other.exchange;
70 		chatRoom = other.chatRoom;
71 		encoding = other.encoding;
72 		fileName = other.fileName;
73 		fileSize = other.fileSize;
74 		fileCount = other.fileCount;
75 		id = other.id;
76 
77 		if ( other.plugin )
78 			plugin = new MessagePlugin(*other.plugin);
79 		else
80 			plugin = 0;
81 	}
82 
~MessagePrivate()83 	~MessagePrivate()
84 	{
85 		delete plugin;
86 	}
87 
88 	QString sender;
89 	QString receiver;
90 	int channel;
91 	int properties;
92 	int messageType;
93 	int requestType;
94 	int port;
95 	int requestNumber;
96 	int protocolVersion;
97 	int channel2Counter;
98 	QByteArray icbmCookie;
99 	QByteArray proxy;
100 	QByteArray textArray;
101 	QDateTime timestamp;
102 	WORD exchange;
103 	QString chatRoom;
104 	Encoding encoding;
105 	QString fileName;
106 	DWORD fileSize;
107 	WORD fileCount;
108 	MessagePlugin* plugin;
109 	uint id;
110 };
111 
Message()112 Message::Message()
113 	: d( new MessagePrivate )
114 {
115 }
116 /*
117 Message::Message( Encoding messageEncoding, const QByteArray& messageText, int channel, int properties, QDateTime timestamp )
118 	: d( new MessagePrivate )
119 {
120 	d->channel = channel;
121 	d->properties = properties;
122 	d->textArray = messageText;
123 	d->timestamp = timestamp;
124 	d->encoding = messageEncoding;
125 }
126 
127 Message::Message( Encoding messageEncoding, const QString& messageText, int channel, int properties, QDateTime timestamp, QTextCodec* codec )
128 	: d( new MessagePrivate )
129 {
130 	d->channel = channel;
131 	d->properties = properties;
132 	d->timestamp = timestamp;
133 
134 	setText( messageEncoding, messageText, codec );
135 }
136 */
Message(const Message & m)137 Message::Message( const Message& m )
138 	: d( m.d )
139 {
140 }
141 
operator =(const Message & m)142 Message& Message::operator=( const Message& m )
143 {
144 	d = m.d;
145 	return *this;
146 }
147 
~Message()148 Message::~Message()
149 {
150 }
151 
sender() const152 QString Message::sender() const
153 {
154 	return d->sender;
155 }
156 
setSender(const QString & sender)157 void Message::setSender( const QString& sender  )
158 {
159 	d->sender = sender;
160 }
161 
receiver() const162 QString Message::receiver() const
163 {
164 	return d->receiver;
165 }
166 
setReceiver(const QString & receiver)167 void Message::setReceiver( const QString& receiver )
168 {
169 	d->receiver = receiver;
170 }
171 
textArray() const172 QByteArray Message::textArray() const
173 {
174     return d->textArray;
175 }
176 
text(QTextCodec * codec) const177 QString Message::text( QTextCodec *codec ) const
178 {
179 	switch ( d->encoding )
180 	{
181 	case Message::UserDefined:
182 		return codec->toUnicode( d->textArray );
183 	case Message::ASCII:
184 		return QString::fromAscii( d->textArray.data(), d->textArray.size() );
185 	case Message::LATIN1:
186 		return QString::fromLatin1( d->textArray.data(), d->textArray.size() );
187 	case Message::UTF8:
188 		return QString::fromUtf8( d->textArray.data(), d->textArray.size() );
189 	case Message::UCS2:
190 	{
191 		uint len = d->textArray.size() / 2;
192 		QString result;
193 		result.resize( len );
194 		QByteArray::ConstIterator p = d->textArray.begin();
195 		for ( uint i = 0; i < len; i++)
196 		{
197 			char row = *p++;
198 			char cell = *p++;
199 			result[i] = QChar( cell, row );
200 		}
201 		//check if last character isn't null
202 		if ( result.at(len-1).isNull() )
203 			result.resize( len - 1 );
204 
205 		return result;
206 	}
207 	default:
208 		break; // Should never happen.
209 	}
210 	return QString();
211 	//FIXME: warn at least with kdWarning if an unrecognised encoding style was seen.
212 }
213 
encodingForText(const QString & newText,bool allowUCS2)214 Message::Encoding Message::encodingForText( const QString& newText, bool allowUCS2 )
215 {
216 	Message::Encoding encoding = Message::ASCII;
217 	const QChar *ch = newText.constData();
218 	const int len = newText.length();
219 
220 	for ( int i = 0; i < len; ++i )
221 	{
222 		if ( ch[i] > 0xff )
223 		{
224 			encoding = ( allowUCS2 ) ? Message::UCS2 : Message::UserDefined;
225 			break;
226 		}
227 		else if ( encoding == Message::ASCII && ch[i] > 0x7f )
228 		{
229 			encoding = Message::LATIN1;
230 		}
231 	}
232 
233 	return encoding;
234 }
235 
setText(Message::Encoding newEncoding,const QString & newText,QTextCodec * codec)236 void Message::setText( Message::Encoding newEncoding, const QString& newText, QTextCodec* codec )
237 {
238 	uint len;
239 	switch ( newEncoding )
240 	{
241 	case Message::UserDefined:
242 		// Message::setTextArray( const QCString& )
243 		// strips trailing null byte automatically.
244 		setTextArray( codec->fromUnicode( newText ) );
245 		break;
246 	case Message::ASCII:
247 		setTextArray( newText.toAscii() );
248 		break;
249 	case Message::LATIN1:
250 		setTextArray( newText.toLatin1() );
251 		break;
252 	case Message::UTF8:
253 		// Message::setTextArray( const QCString& )
254 		// strips trailing null byte automatically.
255 		setTextArray( newText.toUtf8() );
256 		break;
257 	case Message::UCS2:
258 	{
259 		len = newText.length();
260 		d->textArray.resize( len * 2 );
261 		QByteArray::Iterator p = d->textArray.begin();
262 		for ( uint i = 0; i < len; i++)
263 		{
264 			*p++ = newText[i].row();
265 			*p++ = newText[i].cell();
266 		}
267 		break;
268 	}
269 	default:
270 		break; // Should never happen.
271 	}
272 	d->encoding = newEncoding;
273 }
274 
setTextArray(const QByteArray & newTextArray)275 void Message::setTextArray( const QByteArray& newTextArray )
276 {
277 	d->textArray = newTextArray;
278 }
279 
properties() const280 int Message::properties() const
281 {
282 	return d->properties;
283 }
284 
addProperty(int prop)285 void Message::addProperty( int prop )
286 {
287 	d->properties = d->properties | prop;
288 }
289 
hasProperty(int prop) const290 bool Message::hasProperty( int prop ) const
291 {
292 	if ( ( d->properties & prop ) == 0 )
293 		return false;
294 	else
295 		return true;
296 }
297 
channel() const298 int Message::channel() const
299 {
300 	return d->channel;
301 }
302 
setChannel(int newChannel)303 void Message::setChannel( int newChannel )
304 {
305 	d->channel = newChannel;
306 }
307 
timestamp() const308 QDateTime Message::timestamp() const
309 {
310 	return d->timestamp;
311 }
312 
setTimestamp(QDateTime ts)313 void Message::setTimestamp( QDateTime ts )
314 {
315 	d->timestamp = ts;
316 }
317 
icbmCookie() const318 QByteArray Message::icbmCookie() const
319 {
320 	return d->icbmCookie;
321 }
322 
setIcbmCookie(const QByteArray & cookie)323 void Message::setIcbmCookie( const QByteArray& cookie )
324 {
325 	d->icbmCookie = cookie;
326 }
327 
protocolVersion() const328 int Message::protocolVersion() const
329 {
330 	return d->protocolVersion;
331 }
332 
setProtocolVersion(int version)333 void Message::setProtocolVersion( int version )
334 {
335 	d->protocolVersion = version;
336 }
337 
channel2Counter() const338 int Message::channel2Counter() const
339 {
340 	return d->channel2Counter;
341 }
342 
setChannel2Counter(int value)343 void Message::setChannel2Counter( int value )
344 {
345 	d->channel2Counter = value;
346 }
347 
messageType() const348 int Message::messageType() const
349 {
350 	return d->messageType;
351 }
352 
setMessageType(int type)353 void Message::setMessageType( int type )
354 {
355 	d->messageType = type;
356 }
357 
requestType() const358 int Message::requestType() const
359 {
360 	return d->requestType;
361 }
362 
setRequestType(int type)363 void Message::setRequestType( int type )
364 {
365 	d->requestType = type;
366 }
367 
port() const368 int Message::port() const
369 {
370 	return d->port;
371 }
372 
setPort(int port)373 void Message::setPort( int port )
374 {
375 	d->port = port;
376 }
377 
proxy() const378 QByteArray Message::proxy() const
379 {
380 	return d->proxy;
381 }
382 
setProxy(QByteArray proxy)383 void Message::setProxy( QByteArray proxy )
384 {
385 	d->proxy = proxy;
386 }
387 
requestNumber() const388 int Message::requestNumber() const
389 {
390 	return d->requestNumber;
391 }
392 
setRequestNumber(int n)393 void Message::setRequestNumber( int n )
394 {
395 	d->requestNumber = n;
396 }
397 
fileName() const398 QString Message::fileName() const
399 {
400 	return d->fileName;
401 }
402 
filesSize() const403 DWORD Message::filesSize() const
404 {
405 	return d->fileSize;
406 }
407 
fileCount() const408 WORD Message::fileCount() const
409 {
410 	return d->fileCount;
411 }
412 
setFileName(const QString & name)413 void Message::setFileName( const QString &name )
414 {
415 	d->fileName = name;
416 }
417 
setFilesSize(DWORD size)418 void Message::setFilesSize( DWORD size )
419 {
420 	d->fileSize = size;
421 }
422 
setFileCount(WORD count)423 void Message::setFileCount( WORD count )
424 {
425 	d->fileCount = count;
426 }
427 
exchange() const428 WORD Message::exchange() const
429 {
430     return d->exchange;
431 }
432 
setExchange(WORD exchange)433 void Message::setExchange( WORD exchange )
434 {
435     d->exchange = exchange;
436 }
437 
chatRoom() const438 QString Message::chatRoom() const
439 {
440     return d->chatRoom;
441 }
442 
setChatRoom(const QString & room)443 void Message::setChatRoom( const QString& room )
444 {
445     d->chatRoom = room;
446 }
447 
encoding() const448 Message::Encoding Message::encoding() const
449 {
450 	return d->encoding;
451 }
452 
setEncoding(Message::Encoding newEncoding)453 void Message::setEncoding( Message::Encoding newEncoding )
454 {
455 	d->encoding = newEncoding;
456 }
457 
plugin() const458 MessagePlugin* Message::plugin() const
459 {
460 	return d->plugin;
461 }
462 
setPlugin(MessagePlugin * plugin)463 void Message::setPlugin( MessagePlugin* plugin )
464 {
465 	if ( d->plugin )
466 		delete d->plugin;
467 
468 	d->plugin = plugin;
469 }
470 
id() const471 uint Message::id() const
472 {
473 	return d->id;
474 }
475 
setId(uint id)476 void Message::setId( uint id )
477 {
478 	d->id = id;
479 }
480 
operator bool() const481 Message::operator bool() const
482 {
483 	return d->channel != -1;
484 }
485 
486 }
487 
488