1/***************************************************************************
2 * Copyright (C) 2005-2014 by the Quassel Project *
3 * devel@quassel-irc.org *
4 * *
5 * This program 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) version 3. *
9 * *
10 * This program 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 this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
20
21#include "identity.h"
22
23#include <QMetaProperty>
24#include <QVariantMap>
25#include <QString>
26
27#ifdef Q_OS_MAC
28# include <CoreServices/CoreServices.h>
29# include "mac_utils.h"
30#endif
31
32#ifdef Q_OS_UNIX
33# include <sys/types.h>
34# include <pwd.h>
35# include <unistd.h>
36#endif
37
38#ifdef Q_OS_WIN
39# include <windows.h>
40# include <Winbase.h>
41# define SECURITY_WIN32
42# include <Security.h>
43#endif
44
45INIT_SYNCABLE_OBJECT(Identity)
46Identity::Identity(IdentityId id, QObject *parent)
47 : SyncableObject(parent),
48 _identityId(id)
49{
50 init();
51 setToDefaults();
52}
53
54
55Identity::Identity(const Identity &other, QObject *parent)
56 : SyncableObject(parent),
57 _identityId(other.id()),
58 _identityName(other.identityName()),
59 _realName(other.realName()),
60 _nicks(other.nicks()),
61 _awayNick(other.awayNick()),
62 _awayNickEnabled(other.awayNickEnabled()),
63 _awayReason(other.awayReason()),
64 _awayReasonEnabled(other.awayReasonEnabled()),
65 _autoAwayEnabled(other.autoAwayEnabled()),
66 _autoAwayTime(other.autoAwayTime()),
67 _autoAwayReason(other.autoAwayReason()),
68 _autoAwayReasonEnabled(other.autoAwayReasonEnabled()),
69 _detachAwayEnabled(other.detachAwayEnabled()),
70 _detachAwayReason(other.detachAwayReason()),
71 _detachAwayReasonEnabled(other.detachAwayReasonEnabled()),
72 _ident(other.ident()),
73 _kickReason(other.kickReason()),
74 _partReason(other.partReason()),
75 _quitReason(other.quitReason())
76{
77 init();
78}
79
80
81#ifdef Q_OS_WIN
82#ifdef UNICODE
83QString tcharToQString(TCHAR *tchar)
84{
85 return QString::fromUtf16(reinterpret_cast<ushort *>(tchar));
86}
87
88
89#else
90QString tcharToQString(TCHAR *tchar)
91{
92 return QString::fromLocal8Bit(tchar);
93}
94
95
96#endif
97
98#endif
99void Identity::init()
100{
101 setObjectName(QString::number(id().toInt()));
102 setAllowClientUpdates(true);
103}
104
105
106QString Identity::defaultNick()
107{
108 QString nick = QString("quassel%1").arg(qrand() & 0xff); // FIXME provide more sensible default nicks
109
110#ifdef Q_OS_MAC
111 QString shortUserName = CFStringToQString(CSCopyUserName(true));
112 if (!shortUserName.isEmpty())
113 nick = shortUserName;
114
115#elif defined(Q_OS_UNIX)
116 QString userName;
117 struct passwd *pwd = getpwuid(getuid());
118 if (pwd)
119 userName = pwd->pw_name;
120 if (!userName.isEmpty())
121 nick = userName;
122
123#elif defined(Q_OS_WIN)
124 TCHAR infoBuf[128];
125 DWORD bufCharCount = 128;
126 //if(GetUserNameEx(/* NameSamCompatible */ 1, infoBuf, &bufCharCount))
127 if (GetUserNameEx(NameSamCompatible, infoBuf, &bufCharCount)) {
128 QString nickName(tcharToQString(infoBuf));
129 int lastBs = nickName.lastIndexOf('\\');
130 if (lastBs != -1) {
131 nickName = nickName.mid(lastBs + 1);
132 }
133 if (!nickName.isEmpty())
134 nick = nickName;
135 }
136#endif
137
138 // cleaning forbidden characters from nick
139 QRegExp rx(QString("(^[\\d-]+|[^A-Za-z0-9\x5b-\x60\x7b-\x7d])"));
140 nick.remove(rx);
141 return nick;
142}
143
144
145QString Identity::defaultRealName()
146{
147 QString generalDefault = tr("Quassel IRC User");
148
149#ifdef Q_OS_MAC
150 return CFStringToQString(CSCopyUserName(false));
151
152#elif defined(Q_OS_UNIX)
153 QString realName;
154 struct passwd *pwd = getpwuid(getuid());
155 if (pwd)
156 realName = QString::fromUtf8(pwd->pw_gecos);
157 if (!realName.isEmpty())
158 return realName;
159 else
160 return generalDefault;
161
162#elif defined(Q_OS_WIN)
163 TCHAR infoBuf[128];
164 DWORD bufCharCount = 128;
165 if (GetUserName(infoBuf, &bufCharCount))
166 return tcharToQString(infoBuf);
167 else
168 return generalDefault;
169#else
170 return generalDefault;
171#endif
172}
173
174
175void Identity::setToDefaults()
176{
177 setIdentityName(tr("<empty>"));
178 setRealName(defaultRealName());
179 QStringList n = QStringList() << defaultNick();
180 setNicks(n);
181 setAwayNick("");
182 setAwayNickEnabled(false);
183 setAwayReason(tr("Gone fishing."));
184 setAwayReasonEnabled(true);
185 setAutoAwayEnabled(false);
186 setAutoAwayTime(10);
187 setAutoAwayReason(tr("Not here. No, really. not here!"));
188 setAutoAwayReasonEnabled(false);
189 setDetachAwayEnabled(false);
190 setDetachAwayReason(tr("All Quassel clients vanished from the face of the earth..."));
191 setDetachAwayReasonEnabled(false);
192 setIdent("quassel");
193 setKickReason(tr("Kindergarten is elsewhere!"));
194 setPartReason(tr("http://quassel-irc.org - Chat comfortably. Anywhere."));
195 setQuitReason(tr("http://quassel-irc.org - Chat comfortably. Anywhere."));
196}
197
198
199/*** setters ***/
200
201void Identity::setId(IdentityId _id)
202{
203 _identityId = _id;
204 SYNC(ARG(_id))
205 emit idSet(_id);
206 renameObject(QString::number(id().toInt()));
207}
208
209
210void Identity::setIdentityName(const QString &identityName)
211{
212 _identityName = identityName;
213 SYNC(ARG(identityName))
214}
215
216
217void Identity::setRealName(const QString &realName)
218{
219 _realName = realName;
220 SYNC(ARG(realName))
221}
222
223
224void Identity::setNicks(const QStringList &nicks)
225{
226 _nicks = nicks;
227 SYNC(ARG(nicks))
228 emit nicksSet(nicks);
229}
230
231
232void Identity::setAwayNick(const QString &nick)
233{
234 _awayNick = nick;
235 SYNC(ARG(nick))
236}
237
238
239void Identity::setAwayReason(const QString &reason)
240{
241 _awayReason = reason;
242 SYNC(ARG(reason))
243}
244
245
246void Identity::setAwayNickEnabled(bool enabled)
247{
248 _awayNickEnabled = enabled;
249 SYNC(ARG(enabled))
250}
251
252
253void Identity::setAwayReasonEnabled(bool enabled)
254{
255 _awayReasonEnabled = enabled;
256 SYNC(ARG(enabled))
257}
258
259
260void Identity::setAutoAwayEnabled(bool enabled)
261{
262 _autoAwayEnabled = enabled;
263 SYNC(ARG(enabled))
264}
265
266
267void Identity::setAutoAwayTime(int time)
268{
269 _autoAwayTime = time;
270 SYNC(ARG(time))
271}
272
273
274void Identity::setAutoAwayReason(const QString &reason)
275{
276 _autoAwayReason = reason;
277 SYNC(ARG(reason))
278}
279
280
281void Identity::setAutoAwayReasonEnabled(bool enabled)
282{
283 _autoAwayReasonEnabled = enabled;
284 SYNC(ARG(enabled))
285}
286
287
288void Identity::setDetachAwayEnabled(bool enabled)
289{
290 _detachAwayEnabled = enabled;
291 SYNC(ARG(enabled))
292}
293
294
295void Identity::setDetachAwayReason(const QString &reason)
296{
297 _detachAwayReason = reason;
298 SYNC(ARG(reason))
299}
300
301
302void Identity::setDetachAwayReasonEnabled(bool enabled)
303{
304 _detachAwayReasonEnabled = enabled;
305 SYNC(ARG(enabled))
306}
307
308
309void Identity::setIdent(const QString &ident)
310{
311 _ident = ident;
312 SYNC(ARG(ident))
313}
314
315
316void Identity::setKickReason(const QString &reason)
317{
318 _kickReason = reason;
319 SYNC(ARG(reason))
320}
321
322
323void Identity::setPartReason(const QString &reason)
324{
325 _partReason = reason;
326 SYNC(ARG(reason))
327}
328
329
330void Identity::setQuitReason(const QString &reason)
331{
332 _quitReason = reason;
333 SYNC(ARG(reason))
334}
335
336
337/*** ***/
338
339void Identity::copyFrom(const Identity &other)
340{
341 for (int idx = staticMetaObject.propertyOffset(); idx < staticMetaObject.propertyCount(); idx++) {
342 QMetaProperty metaProp = staticMetaObject.property(idx);
343 Q_ASSERT(metaProp.isValid());
344 if (this->property(metaProp.name()) != other.property(metaProp.name())) {
345 setProperty(metaProp.name(), other.property(metaProp.name()));
346 }
347 }
348}
349
350
351bool Identity::operator==(const Identity &other) const
352{
353 for (int idx = staticMetaObject.propertyOffset(); idx < staticMetaObject.propertyCount(); idx++) {
354 QMetaProperty metaProp = staticMetaObject.property(idx);
355 Q_ASSERT(metaProp.isValid());
356 QVariant v1 = this->property(metaProp.name());
357 QVariant v2 = other.property(metaProp.name()); // qDebug() << v1 << v2;
358 // QVariant cannot compare custom types, so we need to check for this special case
359 if (QString(v1.typeName()) == "IdentityId") {
360 if (v1.value<IdentityId>() != v2.value<IdentityId>()) return false;
361 }
362 else {
363 if (v1 != v2) return false;
364 }
365 }
366 return true;
367}
368
369
370bool Identity::operator!=(const Identity &other) const
371{
372 return !(*this == other);
373}
374
375
376///////////////////////////////
377
378QDataStream &operator<<(QDataStream &out, Identity id)
379{
380 out << id.toVariantMap();
381 return out;
382}
383
384
385QDataStream &operator>>(QDataStream &in, Identity &id)
386{
387 QVariantMap i;
388 in >> i;
389 id.fromVariantMap(i);
390 return in;
391}
392
393
394#ifdef HAVE_SSL
395INIT_SYNCABLE_OBJECT(CertManager)
396#endif // HAVE_SSL
397