1 /*
2 *
3 * centerim protocol specific user interface related routines
4 * $Id: imcontroller.cc,v 1.56 2004/07/20 22:16:40 konst Exp $
5 *
6 * Copyright (C) 2001-2004 by Konstantin Klyagin <k@thekonst.net>
7 *
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.
12 *
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.
17 *
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
21 * USA
22 *
23 */
24 
25 #include "imcontroller.h"
26 #include "icqface.h"
27 #include "icqhook.h"
28 #include "yahoohook.h"
29 #include "aimhook.h"
30 #include "irchook.h"
31 #include "jabberhook.h"
32 #include "msnhook.h"
33 #include "gaduhook.h"
34 #include "icqcontacts.h"
35 #include "eventmanager.h"
36 
37 #define clr(c)     conf->getcolor(c)
38 
39 imcontroller imcontrol;
40 
imcontroller()41 imcontroller::imcontroller() {
42 }
43 
~imcontroller()44 imcontroller::~imcontroller() {
45 }
46 
regdialog(protocolname pname)47 bool imcontroller::regdialog(protocolname pname) {
48     bool finished, success;
49     int n, i, b;
50     string pcheck;
51     string prserv = conf->getsockshost() + ":" + i2str(conf->getsocksport());
52     dialogbox db;
53 
54     ruin = 0;
55     finished = success = false;
56     rnick = rfname = rlname = remail = rpasswd = "";
57 
58     rserver = icqconf::defservers[pname].server + ":" +
59 	i2str(icqconf::defservers[pname].port);
60 
61     db.setwindow(new textwindow(0, 0, face.sizeDlg.width, face.sizeDlg.height,
62 	clr(cp_dialog_frame), TW_CENTERED));
63 
64     db.getwindow()->set_titlef(clr(cp_dialog_highlight),
65 	_(" Register on the %s network "),
66 	conf->getprotocolname(pname).c_str());
67 
68     db.settree(new treeview(clr(cp_dialog_text), clr(cp_dialog_selected),
69 	clr(cp_dialog_highlight), clr(cp_dialog_text)));
70 
71     db.setbar(new horizontalbar(clr(cp_dialog_text), clr(cp_dialog_selected),
72 	_("Change"), _("Go ahead"), 0));
73 
74     db.addautokeys();
75     treeview &t = *db.gettree();
76 
77     while(!finished) {
78 	t.clear();
79 
80 	i = db.gettree()->addnode(_(" Details "));
81 	t.addleaff(i, 0, 4, _(" Nickname : %s "), rnick.c_str());
82 
83 	t.addleaff(i, 0, 5, _(" E-Mail : %s "), remail.c_str());
84 	t.addleaff(i, 0, 6, _(" First name : %s "), rfname.c_str());
85 	t.addleaff(i, 0, 7, _(" Last name : %s "), rlname.c_str());
86 
87 	i = db.gettree()->addnode(_(" Password "));
88 	t.addleaff(i, 0, 2, _(" Password to set : %s "), string(rpasswd.size(), '*').c_str());
89 	t.addleaff(i, 0, 3, _(" Check the password : %s "), string(pcheck.size(), '*').c_str());
90 
91 	if(pname != gadu) {
92 	    i = db.gettree()->addnode(_(" Details "));
93 	    t.addleaff(i, 0, 8, _(" Server to use : %s "), rserver.c_str());
94 	}
95 
96 	finished = !db.open(n, b, (void **) &i);
97 
98 	if(!finished)
99 	switch(b) {
100 	    case 0:
101 		switch(i) {
102 		    case 2: rpasswd = face.inputstr(_("Password: "), rpasswd, '*'); break;
103 		    case 3: pcheck = face.inputstr(_("Check the password you entered: "), pcheck, '*'); break;
104 		    case 4: rnick = face.inputstr(_("Nickname to set: "), rnick); break;
105 		    case 5: remail = face.inputstr(_("E-Mail: "), remail); break;
106 		    case 6: rfname = face.inputstr(_("First name: "), rfname); break;
107 		    case 7: rlname = face.inputstr(_("Last name: "), rlname); break;
108 		    case 8: rserver = face.inputstr(_("Server: "), rserver); break;
109 		}
110 		break;
111 
112 	    case 1:
113 		if(rpasswd != pcheck) {
114 		    face.status(_("Passwords do not match"));
115 		} else if(rpasswd.empty()) {
116 		    face.status(_("Password must be entered"));
117 		} else if(pname == icq && rpasswd.size() < 6) {
118 		    face.status(_("Password must be at least 6 chars long"));
119 		} else {
120 		    finished = success = true;
121 		}
122 		break;
123 	}
124     }
125 
126     db.close();
127 
128     return success;
129 }
130 
uinreg(icqconf::imaccount & account)131 bool imcontroller::uinreg(icqconf::imaccount &account) {
132     bool fin, success;
133     abstracthook &hook = gethook(account.pname);
134 
135     if(success = regdialog(account.pname)) {
136 	unlink((conf->getdirname() + conf->getprotocolname(account.pname) + "-infoset").c_str());
137 	face.progress.show(_(" Registration progress "));
138 
139 	for(fin = false; !fin; ) {
140 	    face.progress.log(_("Connecting to the server %s ..."), rserver.c_str());
141 
142 	    if(hook.regconnect(rserver)) {
143 		while(!fin) {
144 		    face.progress.log(_("Sending request"));
145 
146 		    while(!ruin && !fin) {
147 			fin = hook.regattempt(ruin, rpasswd, remail);
148 
149 			if(!fin) {
150 			    if(fin = (face.ask(_("Timed out waiting for a new uin. Retry?"),
151 			    ASK_YES | ASK_NO, ASK_YES) == ASK_NO)) {
152 				success = false;
153 			    } else {
154 				face.progress.log(_("Retrying.."));
155 			    }
156 			}
157 		    }
158 
159 		    if(success) {
160 			face.progress.log(_("New UIN received, %lu"), ruin);
161 			account.uin = ruin;
162 			account.password = rpasswd;
163 
164 			conf->checkdir();
165 			ofstream f((conf->getdirname() + conf->getprotocolname(account.pname) + "-infoset").c_str());
166 			if(f.is_open()) {
167 			    f << rnick << endl <<
168 				remail << endl <<
169 				rfname << endl <<
170 				rlname << endl;
171 			    f.close();
172 			}
173 		    }
174 		}
175 
176 		face.progress.log(_("Disconnected"));
177 		sleep(2);
178 	    } else {
179 		fin = (face.ask(_("Unable to connect to icq server. Retry?"),
180 		    ASK_YES | ASK_NO) == ASK_NO);
181 	    }
182 	}
183 
184 	face.progress.hide();
185     }
186 
187     return success;
188 }
189 
jabberregistration(icqconf::imaccount & account)190 bool imcontroller::jabberregistration(icqconf::imaccount &account) {
191 #ifdef BUILD_JABBER
192     bool success;
193     string err;
194     int pos;
195 
196     if(success = regdialog(account.pname)) {
197 	unlink((conf->getdirname() + "jabber-infoset").c_str());
198 	face.progress.show(_(" Registration progress "));
199 
200 	face.progress.log(_("Trying to register %s at %s ..."),
201 	    rnick.c_str(), rserver.c_str());
202 
203 	if(success = jhook.regnick(rnick, rpasswd, rserver, err)) {
204 	    account.nickname = rnick;
205 	    account.password = rpasswd;
206 	    account.server = rserver;
207 
208 	    if((pos = account.server.find(":")) != -1) {
209 		account.port = atoi(account.server.substr(pos+1).c_str());
210 		account.server.erase(pos);
211 	    } else {
212 		account.port = icqconf::defservers[jabber].port;
213 	    }
214 
215 	    face.progress.log(_("The Jabber ID was successfully registered"));
216 
217 	    conf->checkdir();
218 	    ofstream f((conf->getdirname() + "jabber-infoset").c_str());
219 	    if(f.is_open()) {
220 		f << rnick << endl <<
221 		    remail << endl <<
222 		    rfname << endl <<
223 		    rlname << endl;
224 		f.close();
225 	    }
226 
227 	} else {
228 	    string msgerr = _("Failed");
229 	    if(!err.empty()) msgerr += (string) ": " + err;
230 	    face.progress.log("%s", msgerr.c_str());
231 
232 	}
233 
234 	face.progress.log(_("Disconnected"));
235 	sleep(2);
236 	face.progress.hide();
237     }
238 
239     return success;
240 #else
241     return false;
242 #endif
243 }
244 
icqupdatedetails()245 void imcontroller::icqupdatedetails() {
246 #ifdef BUILD_ICQ
247     icqcontact *c = clist.get(contactroot);
248 
249     if(ihook.logged()) {
250 	c->clear();
251 	ihook.requestinfo(imcontact(conf->getourid(icq).uin, icq));
252 
253 	if(face.updatedetails()) {
254 	    ihook.sendupdateuserinfo(*c);
255 	}
256     } else {
257 	face.status(_("You must be logged to the ICQ network to update the details"));
258     }
259 #endif
260 }
261 
aimupdateprofile()262 void imcontroller::aimupdateprofile() {
263 #ifdef BUILD_AIM
264     icqcontact *c = clist.get(contactroot);
265 
266     c->clear();
267     ahook.requestinfo(imcontact(conf->getourid(aim).nickname, aim));
268     if(face.updatedetails(0, aim)) ahook.sendupdateuserinfo(*c);
269 #endif
270 }
271 
msnupdateprofile()272 void imcontroller::msnupdateprofile() {
273 #ifdef BUILD_MSN
274     if(mhook.logged()) {
275 	mhook.requestinfo(imcontact(conf->getourid(msn).nickname, msn));
276 	string tmp = face.inputstr(_("new MSN friendly nick: "), clist.get(contactroot)->getnick());
277 
278 	if(face.getlastinputkey() != KEY_ESC && !tmp.empty()) {
279 	    icqcontact *c = clist.get(contactroot);
280 	    c->setnick(tmp);
281 	    mhook.sendupdateuserinfo(*c);
282 	}
283     } else {
284 	face.status(_("You must be logged to the MSN network to update the friendly nick"));
285     }
286 #endif
287 }
288 
jabberupdateprofile()289 void imcontroller::jabberupdateprofile() {
290 #ifdef BUILD_JABBER
291     if(jhook.logged()) {
292 	icqcontact *c;
293 
294 	(c = clist.get(contactroot))->clear();
295 	jhook.requestinfo(imcontact(conf->getourid(jabber).nickname, jabber));
296 
297 	if(face.updatedetails(0, jabber))
298 	    jhook.sendupdateuserinfo(*c);
299 
300     } else {
301 	face.status(_("You must be logged to the Jabber network to update your details"));
302     }
303 #endif
304 }
305 
gaduupdateprofile()306 void imcontroller::gaduupdateprofile() {
307 #ifdef BUILD_GADU
308     if(ghook.logged()) {
309 	icqcontact *c;
310 
311 	(c = clist.get(contactroot))->clear();
312 	ghook.requestinfo(imcontact(conf->getourid(gadu).uin, jabber));
313 
314 	if(face.updatedetails(0, gadu))
315 	    ghook.sendupdateuserinfo(*c);
316 
317     } else {
318 	face.status(_("You must be logged to the Gadu-Gadu network to update your details"));
319     }
320 #endif
321 }
322 
registration(icqconf::imaccount & account)323 void imcontroller::registration(icqconf::imaccount &account) {
324     switch(account.pname) {
325 	case icq:
326 #ifdef HAVE_LIBJPEG
327 	case gadu:
328 #endif
329 	    uinreg(account);
330 	    break;
331 	case jabber:
332 	    jabberregistration(account);
333 	    break;
334 	default:
335 	    face.status("[" + conf->getprotocolname(account.pname) + "] " +
336 		_("registration is not supported"));
337 	    break;
338     }
339 }
340 
updateinfo(icqconf::imaccount & account)341 void imcontroller::updateinfo(icqconf::imaccount &account) {
342     switch(account.pname) {
343 	case icq: icqupdatedetails(); break;
344 	case aim: aimupdateprofile(); break;
345 	case msn: msnupdateprofile(); break;
346 	case jabber: jabberupdateprofile(); break;
347 	case gadu: gaduupdateprofile(); break;
348     }
349 }
350 
351 // ----------------------------------------------------------------------------
352 
save(const string & prname) const353 void imsearchparams::save(const string &prname) const {
354     string fname = conf->getconfigfname("search-profiles"), buf, orig;
355 
356     ifstream rf;
357     ofstream of;
358 
359     of.open((fname + ".tmp").c_str());
360 
361     if(of.is_open()) {
362 	rf.open(fname.c_str());
363 
364 	if(rf.is_open()) {
365 	    while(!rf.eof()) {
366 		getstring(rf, orig);
367 		if(getword(buf = orig, "\t") != prname)
368 		    of << orig << endl;
369 	    }
370 
371 	    rf.close();
372 	    rf.clear();
373 	}
374 
375 	of.close();
376 	of.clear();
377 
378 	rename((fname + ".tmp").c_str(), fname.c_str());
379     }
380 
381     of.open(fname.c_str(), ios::app);
382 
383     if(of.is_open()) {
384 	of << prname << "\t"
385 	    << (int) pname << "\t"
386 	    << (onlineonly ? "1" : "0") << "\t"
387 	    << uin << "\t"
388 	    << minage << "\t"
389 	    << maxage << "\t"
390 	    << country << "\t"
391 	    << language << "\t"
392 	    << (int) agerange << "\t"
393 	    << (int) gender << "\t"
394 	    << firstname << "\t"
395 	    << lastname << "\t"
396 	    << nick << "\t"
397 	    << city << "\t"
398 	    << state << "\t"
399 	    << company << "\t"
400 	    << department << "\t"
401 	    << position << "\t"
402 	    << email << "\t"
403 	    << room << "\t"
404 	    << (sincelast ? "1" : "0") << "\t"
405 	    << (reverse ? "1" : "0") << "\t"
406 	    << service << "\t"
407 	    << (photo ? "1" : "0") << "\t"
408 	    << kwords << "\t"
409 	    << randomgroup;
410 
411 	vector<pair<string, string> >::const_iterator
412 	    ifp = flexparams.begin();
413 
414 	while(ifp != flexparams.end()) {
415 	    of << ifp->first << "\t" << ifp->second << "\t";
416 	    ++ifp;
417 	}
418 
419 	of.close();
420     }
421 }
422 
getfield(string & buf)423 static string getfield(string &buf) {
424     string r;
425     int pos;
426 
427     if((pos = buf.find("\t")) == -1)
428 	pos = buf.size();
429 
430     r = buf.substr(0, pos);
431     buf.erase(0, pos+1);
432 
433     return r;
434 }
435 
load(const string & prname)436 bool imsearchparams::load(const string &prname) {
437     ifstream f(conf->getconfigfname("search-profiles").c_str());
438     string buf, flexparam;
439     bool r = false;
440 
441     if(f.is_open()) {
442 	while(!f.eof()) {
443 	    getstring(f, buf);
444 
445 	    if(r = (getword(buf, "\t") == prname)) {
446 		pname = (protocolname) strtoul(getfield(buf).c_str(), 0, 0);
447 		onlineonly = getfield(buf) == "1";
448 		uin = strtoul(getfield(buf).c_str(), 0, 0);
449 		minage = strtoul(getfield(buf).c_str(), 0, 0);
450 		maxage = strtoul(getfield(buf).c_str(), 0, 0);
451 		country = strtoul(getfield(buf).c_str(), 0, 0);
452 		language = strtoul(getfield(buf).c_str(), 0, 0);
453 		agerange = (ICQ2000::AgeRange) strtoul(getfield(buf).c_str(), 0, 0);
454 		gender = (imgender) strtoul(getfield(buf).c_str(), 0, 0);
455 		firstname = getfield(buf);
456 		lastname = getfield(buf);
457 		nick = getfield(buf);
458 		city = getfield(buf);
459 		state = getfield(buf);
460 		company = getfield(buf);
461 		department = getfield(buf);
462 		position = getfield(buf);
463 		email = getfield(buf);
464 		room = getfield(buf);
465 		sincelast = getfield(buf) == "1";
466 		reverse = getfield(buf) == "1";
467 		service = getfield(buf);
468 		photo = getfield(buf) == "1";
469 		kwords = getfield(buf);
470 		randomgroup = strtoul(getfield(buf).c_str(), 0, 0);
471 
472 		while(!buf.empty())
473 		    if(!(flexparam = getfield(buf)).empty())
474 			flexparams.push_back(make_pair(flexparam, getfield(buf)));
475 
476 		break;
477 	    }
478 	}
479 
480 	f.close();
481     }
482 
483     return r;
484 }
485