1
/****************************************************************************
2
** jabber.cpp - communicates with the Jabber network
3
** Copyright (C) 2001, 2002 Justin Karneges
5
** This program is free software; you can redistribute it and/or
6
** modify it under the terms of the GNU General Public License
7
** as published by the Free Software Foundation; either version 2
8
** of the License, or (at your option) any later version.
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.
15
** You should have received a copy of the GNU General Public License
16
** along with this program; if not, write to the Free Software
17
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA.
19
****************************************************************************/
28
/****************************************************************************
30
****************************************************************************/
36
v_status = STATUS_OFFLINE;
38
v_offlineEnabled = FALSE;
40
connect(&stream, SIGNAL(connected()), SLOT(streamConnected()));
41
connect(&stream, SIGNAL(error(int)), SLOT(streamError(int)));
42
connect(&stream, SIGNAL(receivePacket(const QDomElement &)), SLOT(receivePacket(const QDomElement &)));
44
//io.stream = &stream;
45
connect(&io, SIGNAL(done(JabTask *)), SLOT(ioDone(JabTask *)));
46
connect(&io, SIGNAL(outgoingPacket(const QDomElement &)), SLOT(ioOutgoingPacket(const QDomElement &)));
47
connect(&io, SIGNAL(anyDone(JabTask *)), SLOT(doUpdate()));
50
queue = new JT_Queue(io.root());
51
connect(queue, SIGNAL(countChanged()), SLOT(doUpdate()));
60
void Jabber::setHost(const QString &xhost, int xport)
65
me.jid = QString("%1@%2").arg(user).arg(host);
68
void Jabber::setAccount(const QString &xuser, const QString &xpass, const QString &xresource)
74
me.jid = QString("%1@%2").arg(user).arg(host);
78
void Jabber::setNoop(int mills)
80
stream.setNoop(mills);
83
void Jabber::send(const QString &str)
85
if(stream.isConnected()) {
86
stream.sendString(str.latin1());
87
pdb(DEBUG_JABBER, QString("Jabber: wrote: [\n%1]\n").arg(str.latin1()));
91
void Jabber::streamConnected()
93
pdb(DEBUG_JABBER, "Jabber: stream connected\n");
98
if(connType == JABCONN_LOGIN) {
99
JT_Login *l = new JT_Login(io.root());
100
connect(l, SIGNAL(receiveAuth()), SLOT(ioAuth()));
101
connect(l, SIGNAL(receivePresence(int, const QString &)), SLOT(ioPresence(int, const QString &)));
102
connect(l, SIGNAL(receiveRoster(JabRoster &)), SLOT(ioReceiveRoster(JabRoster &)));
103
connect(l, SIGNAL(stepChanged()), SLOT(doUpdate()));
105
l->login(user, pass, stream.id(), resource, i_status, i_statusString, i_priority, usePlain);
109
JT_PushPresence *pp = new JT_PushPresence(io.root());
110
connect(pp, SIGNAL(subscription(const Jid &, int)), SLOT(pushSubscription(const Jid &, int)));
111
connect(pp, SIGNAL(presence(const JT_PushPresence::Info &)), SLOT(pushPresence(const JT_PushPresence::Info &)));
114
JT_PushRoster *pr = new JT_PushRoster(io.root());
115
connect(pr, SIGNAL(roster(JabRoster &)), SLOT(pushRoster(JabRoster &)));
118
JT_PushMessage *pm = new JT_PushMessage(io.root());
119
connect(pm, SIGNAL(message(const JabMessage &)), SLOT(pushMessage(const JabMessage &)));
122
new JT_ServInfo(io.root());
125
userTask = new JabTask(io.root());
126
connect(userTask, SIGNAL(childAdded(JabTask *)), SLOT(doUpdate()));
127
connect(userTask, SIGNAL(childRemoved(JabTask *)), SLOT(doUpdate()));
129
else if(connType == JABCONN_REGISTER) {
130
JT_Register *r = new JT_Register(io.root());
136
void Jabber::streamError(int x)
138
pdb(DEBUG_JABBER, QString("Jabber: stream error=[%1]\n").arg(x));
141
case JABSTREAM_ERR_DNS:
142
err.msg = tr("Unable to resolve hostname");
143
err.type = JABERR_CONNECT;
145
case JABSTREAM_ERR_CONNREFUSED:
146
err.msg = tr("Connection refused");
147
err.type = JABERR_CONNECT;
149
case JABSTREAM_ERR_CONNTIMEOUT:
150
err.msg = tr("Connection timeout");
151
err.type = JABERR_CONNECT;
153
case JABSTREAM_ERR_HANDSHAKE:
154
err.msg = tr("Unable to establish stream handshake");
155
err.type = JABERR_CONNECT;
157
case JABSTREAM_ERR_DISC:
158
case JABSTREAM_ERR_SOCKET:
160
err.type = JABERR_DISCONNECT;
170
void Jabber::cleanup(bool fast)
172
pdb(DEBUG_JABBER, "Jabber: cleanup\n");
175
//printf("JT_Queue::toString() = [%s]\n", queue->toString().latin1());
180
// set all contacts to offline
181
for(JabRosterEntry *i = roster.first(); i; i = roster.next()) {
182
QPtrListIterator<JabResource> it(i->res);
184
while((r = it.current())) {
185
// clean the jid first, in case it has an attached resource already (like /registered)
186
Jid j = QString("%1/%2").arg(cleanJid(i->jid)).arg(r->name);
188
resourceUnavailable(j);
190
// not offline mode? delete!
191
if(!v_offlineEnabled)
194
// not offline mode? clear our local roster
195
if(!v_offlineEnabled)
198
// remove 'me' resources (in reverse order)
199
QPtrListIterator<JabResource> it(me.res);
202
while((r = it.current())) {
203
Jid j = QString("%1/%2").arg(cleanJid(me.jid)).arg(r->name);
205
resourceUnavailable(j);
212
v_status = STATUS_OFFLINE;
213
//presenceChanged(v_status, "");
215
// update the offline status since we're now offline
218
x.pending = olr.numInteresting();
221
JabUpdate x = makeUpdate();
228
stream.connectToHost(host, port);
233
void Jabber::disc(bool fast)
236
//JT_Presence *p = new JT_Presence(io.root());
237
//p->pres(STATUS_OFFLINE, "Logged out", 0);
241
pdb(DEBUG_JABBER, "Jabber: disconnecting.\n");
249
// this should clear the contact list (and signal the changes), and clear the offline queue (FIXME: shouldn't this just be cleanup() ?)
253
for(JabRosterEntry *i = roster.first(); i; i = roster.next())
260
void Jabber::ioAuth()
264
void Jabber::ioPresence(int status, const QString &statusString)
267
r = me.res.find(resource);
274
r->statusString = statusString;
275
r->timeStamp = QDateTime::currentDateTime();
276
Jid myjid = QString("%1/%2").arg(me.jid).arg(r->name);
277
resourceAvailable(myjid, *r);
280
void Jabber::ioReceiveRoster(JabRoster &r)
283
for(i = roster.first(); i; i = roster.next())
284
i->flagForDelete = TRUE;
286
pdb(DEBUG_JABBER, QString("[Roster item(s) received: %1]\n").arg(r.size()));
287
JabRosterEntry *item;
288
for(item = r.first(); item != 0; item = r.next()) {
289
processRosterEntryRecv(*item);
292
// remove flagged entries
293
for(i = roster.first(); i; ) {
294
if(i->flagForDelete) {
295
//printf("Would have deleted: [%s]\n", i->jid.latin1());
298
i = roster.current();
304
// release the hounds!
308
void Jabber::pushRoster(JabRoster &r)
310
pdb(DEBUG_JABBER, QString("[Roster item(s) received: %1]\n").arg(r.size()));
311
JabRosterEntry *item;
312
for(item = r.first(); item != 0; item = r.next()) {
313
processRosterEntryRecv(*item);
317
void Jabber::pushSubscription(const Jid &from, int subType)
319
if(subType == JABSUB_SUBSCRIBE) {
320
pdb(DEBUG_JABBER, QString("[%1 wants to add you to their list]\n").arg(from.full()));
323
else if(subType == JABSUB_SUBSCRIBED) {
324
pdb(DEBUG_JABBER, QString("[%1 has authorized you]\n").arg(from.full()));
327
else if(subType == JABSUB_UNSUBSCRIBE) {
328
pdb(DEBUG_JABBER, QString("[%1 has deleted you from their list]\n").arg(from.full()));
331
else if(subType == JABSUB_UNSUBSCRIBED) {
332
pdb(DEBUG_JABBER, QString("[%1 has removed your authorization!]\n").arg(from.full()));
337
void Jabber::pushPresence(const JT_PushPresence::Info &i)
339
if(i.status == STATUS_OFFLINE) {
340
pdb(DEBUG_JABBER, QString("[%1 went offline]\n").arg(i.jid.full()));
343
pdb(DEBUG_JABBER, QString("[%1 is online]\n").arg(i.jid.full()));
346
JabRosterEntry *entry;
350
Jid myjid = QString("%1@%2").arg(user).arg(host);
354
entry = roster.findByJid(j.s());
359
r = entry->res.find(j.resource());
361
// unavailable? remove the resource
362
if(i.status == STATUS_OFFLINE) {
364
entry->res.remove(r);
365
entry->unavailableStatusString = i.statusString;
366
resourceUnavailable(j);
369
// available? add/update the resource
373
r->name = j.resource();
374
entry->res.append(r);
377
dstr = QString("Adding resource to [%1]: name=[%2], status=[%3]\n").arg(j.s()).arg(j.resource()).arg(status2txt(i.status));
378
pdb(DEBUG_JABBER, dstr);
382
dstr = QString("Updating resource to [%1]: name=[%2], status=[%3]\n").arg(j.s()).arg(j.resource()).arg(status2txt(i.status));
383
pdb(DEBUG_JABBER, dstr);
386
if(!i.songTitle.isEmpty())
387
pdb(DEBUG_JABBER, QString("Listening to: %1\n").arg(i.songTitle));
389
r->status = i.status;
390
r->statusString = i.statusString;
391
r->priority = i.priority;
392
r->songTitle = i.songTitle;
393
r->timeStamp = i.timeStamp;
395
resourceAvailable(j, *r);
400
void Jabber::pushMessage(const JabMessage &message)
402
pdb(DEBUG_JABBER, QString("[Message]\nFrom: %1\nText: %2\n").arg(message.from.full()).arg(message.body));
404
messageReceived(message);
407
void Jabber::processRosterEntryRecv(const JabRosterEntry &item)
410
if(item.sub == "none")
412
if(item.sub == "both")
414
if(item.sub == "from")
418
if(item.sub == "remove")
421
QString dstr; dstr.sprintf(" %s %-32s\n", str.latin1(), item.jid.latin1());
422
pdb(DEBUG_JABBER, dstr);
424
// remove from contact list
425
if(item.sub == "remove") {
426
JabRosterEntry *entry = roster.findByJid(item.jid);
428
contactRemove(entry);
429
roster.remove(entry);
432
// update/add to contact list
434
JabRosterEntry *entry = roster.findByJid(item.jid);
436
entry->flagForDelete = FALSE;
438
// don't process if we have an outgoing entry (FIXME)
440
//JabReq *r = out.findSetRoster(item.jid);
441
//if(r && !r->active)
445
// don't copy, only update "roster-related" entries
446
entry->jid = item.jid;
447
entry->nick = item.nick;
448
entry->groups = item.groups;
449
entry->sub = item.sub;
450
entry->ask = item.ask;
452
contactChanged(entry);
457
JabRosterEntry *newEntry = new JabRosterEntry(item);
458
roster.add(newEntry);
461
contactNew(newEntry);
466
void Jabber::login(int status, const QString &statusStr, int priority, bool plain)
469
i_statusString = statusStr;
470
i_priority = priority;
473
connType = JABCONN_LOGIN;
477
void Jabber::accRegister()
479
connType = JABCONN_REGISTER;
483
void Jabber::setPresence(int status, const QString &statusStr, int priority)
485
// if we're currently logging in, alter the login
486
JT_Login *l = (JT_Login*)io.find("JT_Login");
489
l->statusString = statusStr;
490
l->priority = priority;
494
// send a presence change
495
JT_Presence *p = new JT_Presence(io.root());
496
connect(p, SIGNAL(receivePresence(int, const QString &)), SLOT(ioPresence(int, const QString &)));
497
p->pres(status, statusStr, priority);
501
void Jabber::setRoster(const QString &jid, const QString &nick, const QString &group)
503
/*JabReq *req = new JabReq(JABREQ_ROSTER);
504
req->action = JABACT_SET;
510
// see if we have the entry already
511
JabRosterEntry *entry = roster.findByJid(jid);
513
// copy over the groups
514
groups = entry->groups;
516
if(!groups.isEmpty()) {
517
// new group not the same as the base group?
518
if(group != groups[0]) {
519
// nuke the grouplist, and start fresh with just the one group
522
groups.append(group);
526
if(!group.isEmpty()) {
527
groups.append(group);
533
groups.append(group);
536
JT_Roster *p = new JT_Roster(queue);
537
p->set(jid, nick, groups);
540
// make the effect happen locally
541
if(v_offlineEnabled) {
543
JabRosterEntry item( *entry );
545
item.groups = groups;
546
processRosterEntryRecv(item);
549
// FIXME: make new entry?
554
void Jabber::remove(const QString &jid)
556
JabRosterEntry *entry = roster.findByJid(jid);
560
JT_Roster *p = new JT_Roster(io.root());
561
p->remove(entry->jid);
564
// make the effect happen locally
565
if(v_offlineEnabled) {
566
JabRosterEntry item(*entry);
568
processRosterEntryRecv(item);
573
void Jabber::sendMessage(const JabMessage &msg)
575
JT_Message *p = new JT_Message(io.root(), msg);
579
// FIXME: change these to Jids instead of QString
580
void Jabber::subscribe(const QString &to)
582
JT_Presence *p = new JT_Presence(io.root());
583
p->sub(to, JABSUB_SUBSCRIBE);
587
void Jabber::subscribed(const QString &to)
589
JT_Presence *p = new JT_Presence(io.root());
590
p->sub(to, JABSUB_SUBSCRIBED);
594
void Jabber::unsubscribe(const QString &to)
596
JT_Presence *p = new JT_Presence(io.root());
597
p->sub(to, JABSUB_UNSUBSCRIBE);
603
void Jabber::unsubscribed(const QString &to)
605
JT_Presence *p = new JT_Presence(io.root());
606
p->sub(to, JABSUB_UNSUBSCRIBED);
610
void Jabber::cancelTransaction(const QString &id)
612
JabTask *j = userTask->findById(id);
617
QCString Jabber::encodeXML(const QString &str)
621
data.replace(QRegExp("&"), "&"); // This _must_ come first
622
data.replace(QRegExp("<"), "<");
623
data.replace(QRegExp(">"), ">");
624
data.replace(QRegExp("\""), """);
625
data.replace(QRegExp("'"), "'");
627
QCString locallyEncoded = data.utf8();
628
return locallyEncoded;
632
void Jabber::insertXml(const QString &str)
635
pdb(DEBUG_JABBER, "Jabber: can't send Xml unless connected.\n");
642
void Jabber::agentSetStatus(const QString &jid, int x)
644
JabRosterEntry *r = roster.findByJid(jid);
651
if(x == STATUS_OFFLINE)
652
str = QString("<presence to=\"%1\" type='unavailable'/>\n").arg(encodeXML(j.full()));
654
str = QString("<presence to=\"%1\"/>\n").arg(encodeXML(j.full()));
657
pdb(DEBUG_JABBER, QString("Jabber: agentSetStatus: [%1] [%2]\n").arg(r->jid).arg(x));
660
JabRosterEntry * Jabber::findByJid(const QString &jid)
662
return roster.findByJid(jid);
665
void Jabber::setOfflineEnabled(bool x)
667
v_offlineEnabled = x;
670
void Jabber::setCurrentRoster(JabRoster *x_roster)
674
//printf("rolo disk begin: [%d]\n", (int)clock() / 1000);
675
// alert the world of the new entries
676
for(JabRosterEntry *i = roster.first(); i; i = roster.next())
678
//printf("rolo disk end: [%d]\n", (int)clock() / 1000);
681
JabRoster *Jabber::getCurrentRoster()
686
// this signals a delayed error, by putting it in the Qt event loop
687
void Jabber::delayedError()
689
QTimer *t = new QTimer(this);
690
connect(t, SIGNAL(timeout()), SLOT(doError()));
694
void Jabber::doError()
699
void Jabber::setOLR(const QString &str)
701
/*QStringList list = lineDecodeList(str);
703
for(QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
704
JabReq *req = JabReq::fromString(*it);
709
queue->fromString(str);
711
// update the offline status since we're offline (or we should be, no sane person should call setOLR when online)
714
x.pending = olr.numInteresting();
717
JabUpdate x = makeUpdate();
721
QString Jabber::getOLR()
725
for(JabReq *req = olr.last(); req; req = olr.prev()) {
726
QString str = req->toString();
731
return lineEncodeList(list);*/
733
return queue->toString();
736
void Jabber::receivePacket(const QDomElement &chunk)
738
io.incomingPacket(chunk);
741
void Jabber::ioDone(JabTask *p)
743
if(p->isA("JT_Login")) {
745
JT_Login *j = (JT_Login *)p;
747
err.type = JABERR_AUTH;
749
err.type = JABERR_CREATE;
750
err.msg = j->errorString();
753
//printf("jabber: failed!\n");
758
//printf("jabber: success!\n");
761
else if(p->isA("JT_Register")) {
762
JT_Register *r = (JT_Register *)p;
763
bool b = r->success();
764
QString err = r->errorString();
766
accRegisterFinished(b, err);
770
//printf("jabber: deleting task\n");
776
void Jabber::ioOutgoingPacket(const QDomElement &x)
778
stream.sendPacket(x);
781
JabUpdate Jabber::makeUpdate()
789
// are we connected yet?
790
if(!stream.isConnected())
791
str = tr("Connecting...");
792
// so we must be logging in then
793
else if((j = io.find("JT_Login")) && !j->isDone()) {
794
JT_Login *l = (JT_Login *)j;
796
str = tr("Registering...");
798
str = tr("Requesting roster...");
800
str = tr("Authorizing...");
802
// waiting for outgoing roster requests to process?
803
else if(queue->count() > 0) {
804
str = tr("Updating Roster...");
806
// some other type of request somewhere?
807
else if((x = notSpecial()) > 0) {
808
str = tr("Awaiting response...");
809
//printf("notspecial = [%d]\n", x);
812
str = tr("Connected.");
816
if(queue->count() > 0)
817
str = tr("Requests pending.");
819
str = tr("Not connected.");
824
x.queuePending = queue->count();
828
JabUpdate Jabber::getJU()
833
void Jabber::doUpdate()
835
JabUpdate x = makeUpdate();
839
int Jabber::notSpecial()
844
const QObjectList *p = io.root()->children();
847
QObjectListIt it(*p);
848
for(JabTask *j; (j = (JabTask *)it.current()); ++it) {
849
if(j->isA("JT_Login") || j->isA("JT_Queue") || j->isDone() || j->isDaemon() || (userTask && j->id() == userTask->id()))
856
const QObjectList *p = userTask->children();
859
QObjectListIt it(*p);
860
for(JabTask *j; (j = (JabTask *)it.current()); ++it) {
871
/****************************************************************************
872
SHA1 - from a public domain implementation by Steve Reid (steve@edmweb.com)
873
****************************************************************************/
875
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
876
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15]^block->l[(i+2)&15]^block->l[i&15],1))
878
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
879
#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
880
#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
881
#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
882
#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
883
#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
890
qSysInfo(&wordSize, &bigEndian);
893
unsigned long SHA1::blk0(Q_UINT32 i)
898
return (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) | (rol(block->l[i],8)&0x00FF00FF));
901
// Hash a single 512-bit block. This is the core of the algorithm.
902
void SHA1::transform(Q_UINT32 state[5], unsigned char buffer[64])
904
Q_UINT32 a, b, c, d, e;
906
block = (CHAR64LONG16*)buffer;
908
// Copy context->state[] to working vars
915
// 4 rounds of 20 operations each. Loop unrolled.
916
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
917
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
918
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
919
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
920
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
921
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
922
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
923
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
924
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
925
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
926
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
927
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
928
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
929
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
930
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
931
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
932
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
933
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
934
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
935
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
937
// Add the working vars back into context.state[]
945
a = b = c = d = e = 0;
948
// SHA1Init - Initialize new context
949
void SHA1::init(SHA1_CONTEXT* context)
951
// SHA1 initialization constants
952
context->state[0] = 0x67452301;
953
context->state[1] = 0xEFCDAB89;
954
context->state[2] = 0x98BADCFE;
955
context->state[3] = 0x10325476;
956
context->state[4] = 0xC3D2E1F0;
957
context->count[0] = context->count[1] = 0;
960
// Run your data through this
961
void SHA1::update(SHA1_CONTEXT* context, unsigned char* data, Q_UINT32 len)
965
j = (context->count[0] >> 3) & 63;
966
if((context->count[0] += len << 3) < (len << 3))
969
context->count[1] += (len >> 29);
972
memcpy(&context->buffer[j], data, (i = 64-j));
973
transform(context->state, context->buffer);
974
for ( ; i + 63 < len; i += 64) {
975
transform(context->state, &data[i]);
980
memcpy(&context->buffer[j], &data[i], len - i);
983
// Add padding and return the message digest
984
void SHA1::final(unsigned char digest[20], SHA1_CONTEXT* context)
987
unsigned char finalcount[8];
989
for (i = 0; i < 8; i++) {
990
finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
991
>> ((3-(i & 3)) * 8) ) & 255); // Endian independent
993
update(context, (unsigned char *)"\200", 1);
994
while ((context->count[0] & 504) != 448) {
995
update(context, (unsigned char *)"\0", 1);
997
update(context, finalcount, 8); // Should cause a transform()
998
for (i = 0; i < 20; i++) {
999
digest[i] = (unsigned char) ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
1004
memset(context->buffer, 0, 64);
1005
memset(context->state, 0, 20);
1006
memset(context->count, 0, 8);
1007
memset(&finalcount, 0, 8);
1011
/* static */ QString SHA1::digest(QString in)
1013
SHA1_CONTEXT context;
1014
unsigned char digest[20];
1017
QCString data = in.latin1();
1020
s.update(&context, (unsigned char *)data.data(), (unsigned int)data.length());
1021
s.final(digest, &context);
1024
for(int n = 0; n < 20; ++n) {
1026
str.sprintf("%02x", digest[n]);