3 * centerim event manager class
4 * $Id: eventmanager.cc,v 1.27 2005/08/28 01:33:21 konst Exp $
6 * Copyright (C) 2001,2002 by Konstantin Klyagin <k@thekonst.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 #include "eventmanager.h"
29 #include "icqcontacts.h"
30 #include "abstracthook.h"
32 #include "imexternal.h"
37 imeventmanager::imeventmanager(): unsent(0), lastevent(0), recentlysent(0) {
40 imeventmanager::~imeventmanager() {
43 void imeventmanager::store(const imevent
&cev
) {
47 auto_ptr
<imevent
> icev(cev
.getevent());
48 imevent
&ev
= *icev
.get();
50 static int preoptions
[imevent::imdirection_size
] = {
51 imexternal::aoprereceive
,
55 external
.exec(&ev
, proceed
, preoptions
[ev
.getdirection()]);
60 if(ev
.getdirection() == imevent::incoming
) {
61 if(!lst
.inlist(ev
.getcontact(), csignore
)) {
64 c
= clist
.get(ev
.getcontact());
67 proceed
= !conf
.getantispam() ||
68 ((ev
.gettype() == imevent::authorization
) && !conf
.getdropauthreq()) ||
69 conf
.getusingcaptcha();
72 c
= clist
.addnew(ev
.getcontact());
74 if (conf
.getdebug()) face
.log("captcha: enabled = %i", conf
.getusingcaptcha());
75 if (conf
.getusingcaptcha()) {
76 if (conf
.getdebug()) face
.log("captcha: start");
77 /* If the turing test was failed or not completed, remove
78 * contact (WE DONT WANT YOU!)
79 * Note tat below, we always remove the contact if it is not verified */
80 if (!conf
.thecaptcha
.docaptcha(ev
.getcontact())) {
81 if (conf
.getdebug()) face
.log("captcha: starting a new turing test with: %s", ev
.getcontact().totext().c_str());
82 /* have not started the turing test, so send our greeter and message */
84 c
->getdesc(), imevent::outgoing
,
85 conf
.getcaptchagreet() + "\n" +
86 conf
.thecaptcha
.getcaptchaquestion(ev
.getcontact())));
87 clist
.remove(c
->getdesc());
90 if(conf
.getdebug()) face
.log("captcha: got an answer: %s", ev
.gettext().c_str());
91 /* have started the test, now must verify the answer */
92 if (conf
.thecaptcha
.checkcaptcha(ev
.getcontact(), ev
.gettext())) {
93 if (conf
.getdebug()) face
.log("captcha: received correct answer");
96 c
->getdesc(), imevent::outgoing
,
97 conf
.getcaptchasuccess()));
98 conf
.thecaptcha
.donecaptcha(ev
.getcontact());
100 if (conf
.getdebug()) face
.log("captcha: received intorrent answer");
101 /* bad, a computer (or very dumb human :) */
103 c
->getdesc(), imevent::outgoing
,
104 conf
.getcaptchafailure() + "\n" +
105 conf
.thecaptcha
.getcaptchaquestion(ev
.getcontact())));
106 clist
.remove(c
->getdesc());
110 if (conf
.getdebug()) face
.log("captcha: end");
113 face
.log("Dropped an authorization request from %s", ev
.getcontact().totext().c_str());
118 face
.xtermtitle(_("event from %s (%s)"), cev
.getcontact().totext().c_str(), c
->getdispnick().c_str());
119 eventwrite(ev
, history
);
121 c
->sethasevents(true);
122 c
->playsound(ev
.gettype());
126 face
.relaxedupdate();
129 } else if(ev
.getdirection() == imevent::outgoing
) {
132 // All the SMSes are to be sent through the icqhook class..
134 if(ev
.gettype() == imevent::sms
) {
135 hook
= &gethook(icq
);
137 hook
= &gethook(ev
.getcontact().pname
);
140 // Some self-flood protection..
142 if(time(0)-lastevent
> PERIOD_ATONCE
)
145 proceed
= (hook
->logged() || ev
.getcontact().pname
== rss
)
146 && recentlysent
< MAX_ATONCE
;
148 // 3.. 2.. 1.. LAUNCH!
152 eventwrite(cev
, history
);
153 logger
.putevent(cev
);
158 eventwrite(cev
, offline
);
161 eventwrite(cev
, offline
);
166 vector
<imevent
*> imeventmanager::getevents(const imcontact
&cont
, time_t lastread
) const {
170 icqcontact
*c
= clist
.get(cont
);
173 fhist
.open((c
->getdirname() + "history").c_str());
175 if(fhist
.is_open()) {
177 fhist
.seekg(c
->gethistoffset(), ios::beg
);
180 while(!fhist
.eof()) {
181 rev
= eventread(fhist
);
184 if(rev
->gettimestamp() > lastread
) {
185 rev
->setcontact(cont
);
201 void imeventmanager::eventwrite(const imevent
&ev
, eventwritemode mode
) {
203 string fname
, lockfname
;
206 if(c
= clist
.get(ev
.getcontact())) {
209 fname
= c
->getdirname() + "history";
212 fname
= c
->getdirname() + "offline";
214 face
.relaxedupdate();
220 fhist
.open(fname
.c_str(), ios::app
);
222 if(fhist
.is_open()) {
231 imevent
*imeventmanager::eventread(ifstream
&f
) const {
234 if(rev
= ev
.getevent()) {
237 if(rev
->gettype() == imevent::imeventtype_size
) {
246 void imeventmanager::resend() {
249 string fname
, tfname
;
253 for(unsent
= i
= 0; i
< clist
.count
; i
++) {
254 c
= (icqcontact
*) clist
.at(i
);
256 fname
= c
->getdirname() + "offline";
257 tfname
= fname
+ "_";
259 if(!access(fname
.c_str(), F_OK
))
260 if(!rename(fname
.c_str(), tfname
.c_str())) {
261 f
.open(tfname
.c_str());
268 rev
->setcontact(c
->getdesc());
270 if(rev
->gettimestamp() > PERIOD_RESEND
) {
273 eventwrite(*rev
, offline
);
284 unlink(tfname
.c_str());
289 int imeventmanager::getunsentcount() const {
293 void imeventmanager::setlock(const string
&fname
) const {
294 string lockfname
= fname
+ ".lock";
298 while(!access(lockfname
.c_str(), F_OK
) && (ntries
< 10)) {
303 f
.open(lockfname
.c_str());
304 if(f
.is_open()) f
.close();
307 void imeventmanager::releaselock(const string
&fname
) const {
308 string lockfname
= fname
+ ".lock";
309 unlink(lockfname
.c_str());