1 /*
2 *
3 * centerim configuration handling routines
4 * $Id: icqconf.cc,v 1.143 2005/09/02 15:20:59 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 <sys/types.h>
26 #include <sys/wait.h>
27 #include <dirent.h>
28 #include <fstream>
29 
30 
31 #if defined(__sun__) || defined(__NetBSD__) || defined(__sgi__)
32 #include <sys/statvfs.h>
33 #endif
34 
35 #include "centerim.h"
36 #include "icqconf.h"
37 #include "icqface.h"
38 #include "icqcontacts.h"
39 #include "abstracthook.h"
40 #include "imexternal.h"
41 #include "eventmanager.h"
42 #include "imlogger.h"
43 #include "connwrap.h"
44 
45 icqconf* icqconf::self=NULL;
46 
instance()47 icqconf* icqconf::instance()
48 {
49 	if(!self){
50 		self=new icqconf();
51 	}
52 
53 	return self;
54 }
55 
icqconf()56 icqconf::icqconf() : showopenedchats(false), quote(false), dropauthreq(false),
57     usingcaptcha(false), screenna(false), askquit(false), bidi(false)
58 {
59     DEFAULT_TIMESTAMP_FORMAT = "DD.MM.YY hh:mm";
60     DEFAULT_LOGTIMESTAMP_FORMAT = "%R ";
61     SECONDS_TIMESTAMP_FORMAT = "DD.MM.YY hh:mm:ss";
62     SECONDS_LOGTIMESTAMP_FORMAT = "%T ";
63 
64     rs = rscard;
65     rc = rcdark;
66     cm = cmproto;
67     fgroupmode = nogroups;
68     fsortmode = sort_by_status_and_activity;
69 
70     autoaway = autona = 0;
71 
72     hideoffline = antispam = makelog = askaway = logtimestamps =
73 	logonline = emacs = proxyssl = proxyconnect = notitles =
74 	debug = timestampstothesecond = vi = autoawayx = false;
75 
76     timestampformat = DEFAULT_TIMESTAMP_FORMAT;
77     logtimestampformat = DEFAULT_LOGTIMESTAMP_FORMAT;
78 
79     startoffline = false;
80 
81     savepwd = mailcheck = fenoughdiskspace = true;
82 
83     for(protocolname pname = icq; pname != protocolname_size; pname++) {
84         chatmode[pname] = true;
85         cpconvert[pname] = entersends[pname] = nonimonline[pname] = false;
86     }
87 
88     // quick and dirty fix to support .centerim as well as .centericq
89     char *home = getenv("HOME");
90     if( home != NULL ) {
91     basedir = string(home)  + "/.centerim/";
92     if ( access(basedir.c_str(), F_OK) != 0 ) {
93         basedir = string(home) + "/.centericq/";
94         if ( access(basedir.c_str(), F_OK) != 0 ) {
95             basedir = string(home) + "/.centerim/";
96         }
97     }
98     }
99     screensocketpath = "/var/run/screen";
100 
101     defaultAuthMessage = "Please accept my authorization to add you to my contact list.";
102 }
103 
~icqconf()104 icqconf::~icqconf() {
105 	if(self)
106 		delete self;
107 }
108 
getourid(protocolname pname) const109 icqconf::imaccount icqconf::getourid(protocolname pname) const {
110     imaccount im;
111     vector<imaccount>::const_iterator i;
112 
113     i = find(accounts.begin(), accounts.end(), pname);
114     im = i == accounts.end() ? imaccount(pname) : *i;
115 
116     return im;
117 }
118 
119 icqconf::imserver icqconf::defservers[protocolname_size] = {
120     { "login.icq.com", 5190, 0 },
121     { "scs.msg.yahoo.com", 5050, 0 },
122     { "messenger.hotmail.com", 1863, 0 },
123     { "toc.oscar.aol.com", 9898, 0 },
124     { "irc.oftc.net", 6667, 0 },
125     { "jabber.org", 5222, 5223 },
126     { "", 0, 0 },
127     { "livejournal.com", 80, 0 },
128     { "appmsg.gadu-gadu.pl", 80 }
129 };
130 
setourid(const imaccount & im)131 void icqconf::setourid(const imaccount &im) {
132     vector<imaccount>::iterator i;
133 
134     i = find(accounts.begin(), accounts.end(), im.pname);
135 
136     if(i != accounts.end()) {
137 	if(im.empty()) {
138 	    accounts.erase(i);
139 	    i = accounts.end();
140 	} else {
141 	    *i = im;
142 	}
143     } else if(!im.empty()) {
144 	accounts.push_back(im);
145 	i = accounts.end()-1;
146     }
147 
148     if(i != accounts.end()) {
149 	if(i->server.empty()) {
150 	    i->server = defservers[i->pname].server;
151 	    i->port = defservers[i->pname].port;
152 	}
153 
154 	if(!i->port)
155 	    i->port = defservers[i->pname].port;
156 
157 	switch(i->pname) {
158 	    case jabber:
159 		if(i->additional.find("prio") == i->additional.end())
160 		    i->additional["prio"] = "4";
161 #ifdef HAVE_UNAME
162 		if(i->additional.find("osinfo") == i->additional.end())
163 		    i->additional["osinfo"] = "1";
164 #endif
165 		break;
166 
167 	    case yahoo:
168 		if (i->additional.find("ssl") == i->additional.end())
169 		    i->additional["ssl"] = "1";
170 		break;
171 
172 	    case livejournal:
173 		if(i->additional.find("importfriends") == i->additional.end())
174 		    i->additional["importfriends"] = "1";
175 		break;
176 
177 	    case icq:
178 		if(i->password.size() > 8)
179 		    i->password = i->password.substr(0, 8);
180 		break;
181 	}
182     }
183 }
184 
getawaymsg(protocolname pname) const185 string icqconf::getawaymsg(protocolname pname) const {
186     string r, buf, fname;
187     ifstream f;
188 
189     if(!gethook(pname).getCapabs().count(hookcapab::setaway))
190 	return "";
191 
192     fname = conf->getconfigfname("awaymsg-" + getprotocolname(pname));
193     f.open(fname.c_str());
194 
195     if(f.is_open()) {
196 	while(!f.eof()) {
197 	    getstring(f, buf);
198 	    if(!r.empty()) r += "\n";
199 	    r += buf;
200 	}
201 
202 	f.close();
203     }
204 
205     if(r.empty()) {
206 	char buf[512];
207 
208 	snprintf(buf, sizeof(buf), _("I do really enjoy the default %s away message of %s %s."),
209 	    getprotocolname(pname).c_str(), PACKAGE, centerim::version);
210 
211 	return buf;
212     }
213 
214     return r;
215 }
216 
setawaymsg(protocolname pname,const string & amsg)217 void icqconf::setawaymsg(protocolname pname, const string &amsg) {
218     string fname;
219     ofstream f;
220 
221     if(!gethook(pname).getCapabs().count(hookcapab::setaway))
222 	return;
223 
224     fname = conf->getconfigfname("awaymsg-" + getprotocolname(pname));
225     f.open(fname.c_str());
226 
227     if(f.is_open()) {
228 	f << amsg;
229 	f.close();
230     }
231 }
232 
getextstatus(protocolname pname,imstatus status) const233 string icqconf::getextstatus(protocolname pname, imstatus status) const {
234     string r, buf, fname;
235     ifstream f;
236 
237     if(!gethook(pname).getCapabs().count(hookcapab::setextstatus))
238 	return "";
239 
240     fname = conf->getconfigfname("extmsg-" + getprotocolname(pname) + "-" + imstatus2char[status]);
241     f.open(fname.c_str());
242 
243     if(f.is_open()) {
244 	while(!f.eof()) {
245 	    getstring(f, buf);
246 	    if(!r.empty()) r += "\n";
247 	    r += buf;
248 	}
249 
250 	f.close();
251     }
252 
253     if(r.empty()) {
254 	return "";
255     }
256 
257     return r;
258 }
259 
setextstatus(protocolname pname,const string & amsg,imstatus status)260 void icqconf::setextstatus(protocolname pname, const string &amsg, imstatus status) {
261     string fname;
262     ofstream f;
263 
264     if(!gethook(pname).getCapabs().count(hookcapab::setextstatus))
265 	return;
266 
267     fname = conf->getconfigfname("extmsg-" + getprotocolname(pname) + "-" + imstatus2char[status]);
268     f.open(fname.c_str());
269 
270     if(f.is_open()) {
271 	f << amsg;
272 	f.close();
273     }
274 }
275 
checkdir()276 void icqconf::checkdir() {
277     string dname = getdirname();
278     dname.erase(dname.size()-1);
279     const char * dirstr = dname.c_str();
280     // The proper rights for the ~/.centerim-directory
281     const mode_t proper_rights = S_IRUSR | S_IWUSR | S_IXUSR;
282 
283     if(access(dirstr, F_OK) == 0) {
284          // Directory allready exists check the permissions of the directory.
285         struct stat dir_stat;
286         if (  stat(dirstr, &dir_stat) == 0 &&
287               (dir_stat.st_mode & ~proper_rights) != 0 ) {
288             DIR *pDir = NULL;
289             // group / other have some kind of permissions for this directory
290             // as mr Picard would have said: compensate!
291             chmod (dirstr, proper_rights);
292         }
293     }
294     else{
295         // create the ~/.centerim directory since
296         // ~/.centerim / ~/.centericq does not exist.
297         mkdir(dname.c_str(), proper_rights);
298     }
299 }
300 
load()301 void icqconf::load() {
302     loadmainconfig();
303     loadkeys();
304     loadcolors();
305     loadactions();
306     loadcaptcha();
307     external.load();
308 }
309 
310 vector<icqconf::keybinding> icqconf::keys;
311 
loadkeys()312 void icqconf::loadkeys() {
313     //int x; not used.
314     string fname = getconfigfname("keybindings"), buf, param;
315     struct keybinding k;
316     ifstream f;
317 
318     keys.clear();
319 
320     if(access(fname.c_str(), F_OK)) {
321 	ofstream of(fname.c_str());
322 
323 	if(of.is_open()) {
324 	    of << "# This file contains keybinding configuration for centerim" << endl;
325 	    of << "# Every line should look like: bind <section> <key> <command>" << endl << endl;
326 	    of << "bind contact\t?\tinfo" << endl;
327 	    of << "bind contact\tq\tquit" << endl;
328 	    of << "bind contact\t<F3>\tchange_status" << endl;
329 	    of << "bind contact\ts\tchange_status" << endl;
330 	    of << "bind contact\th\thistory" << endl;
331 	    of << "bind contact\tf\tfetch_away_message" << endl;
332 	    of << "bind contact\t<F2>\tuser_menu" << endl;
333 	    of << "bind contact\tm\tuser_menu" << endl;
334 	    of << "bind contact\t<F4>\tgeneral_menu" << endl;
335 	    of << "bind contact\tg\tgeneral_menu" << endl;
336 	    of << "bind contact\t<F5>\thide_offline" << endl;
337 	    of << "bind contact\t<F6>\tcontact_external_action" << endl;
338 	    of << "bind contact\ta\tadd" << endl;
339 	    of << "bind contact\t<delete> remove" << endl;
340 	    of << "bind contact\t<enter> compose" << endl;
341 	    of << "bind contact\tc\tsend_contact" << endl;
342 	    of << "bind contact\tc\trss_check" << endl;
343 	    of << "bind contact\tu\tsend_url" << endl;
344 	    of << "bind contact\tr\trename" << endl;
345 	    of << "bind contact\tv\tversion" << endl;
346 	    of << "bind contact\te\tedit" << endl;
347 	    of << "bind contact\ti\tignore" << endl;
348 	    of << "bind contact\t\\as\tquickfind" << endl;
349 	    of << "bind contact\t/\tquickfind" << endl << endl;
350 	    of << "bind contact\t\\cn\tnext_chat" << endl;
351 	    of << "bind contact\t\\cb\tprev_chat" << endl;
352 	    of << "bind contact\t[\tleft_panel_move_left" << endl;
353 	    of << "bind contact\t]\tleft_panel_move_right" << endl;
354 	    of << "bind contact\t{\tlog_panel_move_up" << endl;
355 	    of << "bind contact\t}\tlog_panel_move_down" << endl;
356 	    of << "bind history\t/\tsearch" << endl;
357 	    of << "bind history\ts\tsearch" << endl;
358 	    of << "bind history\tn\tsearch_again" << endl;
359 	    of << "bind history\t<F2>\tshow_urls" << endl;
360 	    of << "bind history\t<F9>\tfullscreen" << endl << endl;
361 	    of << "bind editor\t\\cx\tsend_message" << endl;
362 	    of << "bind editor\t<esc>\tquit" << endl;
363 	    of << "bind editor\t\\cp\tmultiple_recipients" << endl;
364 	    of << "bind editor\t\\co\thistory" << endl;
365 	    of << "bind editor\t\\cn\tnext_chat" << endl;
366 	    of << "bind editor\t\\cb\tprev_chat" << endl;
367 	    of << "bind editor\t\\cv\tout_chat" << endl;
368 	    of << "bind editor\t\\a?\tinfo" << endl;
369 	    of << "bind editor\t<F2>\tshow_urls" << endl;
370 	    of << "bind editor\t<F9>\tfullscreen" << endl << endl;
371 	    of << "bind editor\t<F4>\tchat_panel_move_up" << endl;
372 	    of << "bind editor\t<F5>\tchat_panel_move_down" << endl;
373 #ifdef HAVE_LIBOTR
374 	    of << "bind editor\t<F7>\totr_start_session" << endl;
375 	    of << "bind editor\t<F8>\totr_end_session" << endl;
376 #endif
377 	    of << "bind info\t<F2>\tshow_urls" << endl;
378 	    of << "bind info\t<F6>\tuser_external_action" << endl;
379 
380 	    of.close();
381 	}
382     }
383 
384     f.open(fname.c_str());
385 
386     if(f.is_open()) {
387 	while(!f.eof()) {
388 	    getstring(f, buf);
389 
390 	    if(buf.empty() || buf[0] == '#') continue;
391 
392 	    k.ctrl = false;
393 	    k.alt = false;
394 
395 	    param = getword(buf);       /* first word is always bind */
396 
397 	    param = getword(buf);       /* read section */
398 	    if(param == "contact")
399 		k.section = section_contact; else
400 	    if(param == "history")
401 		k.section = section_history; else
402 	    if (param == "editor")
403 		k.section = section_editor; else
404 	    if (param == "info")
405 		k.section = section_info;
406 
407 	    param = getword(buf);       /* key */
408 	    if(param == "\\c<space>" || param == "\\C<space>" || param == "^<space>") {
409 		k.ctrl = true;
410 		k.key = CTRL(' ');
411 	    } else if(param == "\\a<enter>" || param == "\\A<enter>" || param == "@<enter>") {
412 		k.alt = true;
413 		k.key = ALT('\r');
414 	    } else if(param == "\\a<space>" || param == "\\A<space>" || param == "@<space>") {
415 		k.ctrl = true;
416 		k.key = ALT(' ');
417 	    } else if(param[0] == '\\') {
418 		if(param[1] == 'c' || param[1] == 'C') {
419 		    k.ctrl = true;
420 		    k.key = CTRL(param[2]);
421 		} else if(param[1] == 'a' || param[1] == 'A') {
422 		    k.alt = true;
423 		    k.key = ALT(param[2]);
424 		} else if(param[1] == '\\') {
425 		    k.key = '\\';
426 		} else if(param[1] == '@') {
427 		    k.key = '@';
428 		} else if(param[1] == '^') {
429 		    k.key = '^';
430 		}
431 	    } else if(param[0] == '^') {
432 		k.ctrl = true;
433 		k.key = CTRL(param[1]);
434 	    } else if(param[0] == '@') {
435 		k.alt = true;
436 		k.key = ALT(param[1]);
437 	    } else if(param == "<delete>")
438 		k.key = KEY_DC;
439 	    else if(param == "<enter>")
440 		k.key = '\r';
441 	    else if(param == "<esc>")
442 		k.key = 27;
443 	    else if(param == "<space>")
444 		k.key = ' ';
445 	    else if(param == "<backspace>")
446 		k.key = '\b';
447 	    else if(param == "<pageup>")
448 		k.key = 339;
449 	    else if(param == "<pagedown>")
450 		k.key = 338;
451 	    else if(param == "<tab>")
452 		k.key = 9;
453 	    else if(param == "<insert>")
454 		k.key = 331;
455 	    else if(param[0] == '<' && param[1] == 'F') {
456 		k.alt = true;
457 		k.ctrl = true;
458 		k.key = KEY_F(param[2]-'0');
459 	    } else
460 		k.key = param[0];
461 
462 	    param = getword(buf);       /* action */
463 	    if(param == "info") k.action = key_info; else
464 	    if(param == "remove") k.action = key_remove; else
465 	    if(param == "quit") k.action = key_quit; else
466 	    if(param == "change_status") k.action = key_change_status; else
467 	    if(param == "history") k.action = key_history; else
468 	    if(param == "next_chat") k.action = key_next_chat; else
469 	    if(param == "prev_chat") k.action = key_prev_chat; else
470 	    if(param == "out_chat") k.action = key_out_chat; else
471 	    if(param == "fetch_away_message") k.action = key_fetch_away_message; else
472 	    if(param == "user_menu") k.action = key_user_menu; else
473 	    if(param == "general_menu") k.action = key_general_menu; else
474 	    if(param == "hide_offline") k.action = key_hide_offline; else
475 	    if(param == "contact_external_action") k.action = key_contact_external_action; else
476 	    if(param == "add") k.action = key_add; else
477 	    if(param == "remove") k.action = key_remove; else
478 	    if(param == "send_message") k.action = key_send_message; else
479 	    if(param == "send_contact") k.action = key_send_contact; else
480 	    if(param == "send_url") k.action = key_send_url; else
481 	    if(param == "rename") k.action = key_rename; else
482 	    if(param == "version") k.action = key_version; else
483 	    if(param == "fullscreen") k.action = key_fullscreen; else
484 	    if(param == "edit") k.action = key_edit; else
485 	    if(param == "ignore") k.action = key_ignore; else
486 	    if(param == "quickfind") k.action = key_quickfind; else
487 	    if(param == "search") k.action = key_search; else
488 	    if(param == "compose") k.action = key_compose; else
489 	    if(param == "search_again") k.action = key_search_again; else
490 	    if(param == "show_urls") k.action = key_show_urls; else
491 	    if(param == "rss_check") k.action = key_rss_check; else
492 	    if(param == "multiple_recipients") k.action = key_multiple_recipients; else
493 	    if(param == "user_external_action") k.action = key_user_external_action; else
494 	    if(param == "left_panel_move_left")  k.action = key_left_panel_move_left; else
495 	    if(param == "left_panel_move_right") k.action = key_left_panel_move_right; else
496 	    if(param == "log_panel_move_up")    k.action = key_log_panel_move_up; else
497 	    if(param == "log_panel_move_down")  k.action = key_log_panel_move_down; else
498 	    if(param == "chat_panel_move_up")  k.action = key_chat_panel_move_up; else
499 	    if(param == "chat_panel_move_down")  k.action = key_chat_panel_move_down; else
500 #ifdef HAVE_LIBOTR
501 	    if(param == "otr_start_session")  k.action = key_otr_start_session; else
502 	    if(param == "otr_end_session")  k.action = key_otr_end_session; else
503 #endif
504 		continue;
505 
506 	    keys.push_back(k);
507 	}
508 
509 	f.close();
510     }
511 /*
512     if(face.action2key(key_info, section_contact).empty()) keys.push_back(keybinding()); else
513     if(face.action2key(key_quit, section_contact).empty())
514     if(face.action2key(key_change_status, section_contact).empty())
515     if(face.action2key(key_history, section_contact).empty())
516     if(face.action2key(key_fetch_away_message, section_contact).empty())
517     if(face.action2key(key_user_menu, section_contact).empty())
518     if(face.action2key(key_general_menu, section_contact).empty())
519     if(face.action2key(key_hide_offline, section_contact).empty())
520     if(face.action2key(key_contact_external_action, section_contact).empty())
521     if(face.action2key(key_add, section_contact).empty())
522     if(face.action2key(key_remove, section_contact).empty())
523     if(face.action2key(key_compose, section_contact).empty())
524     if(face.action2key(key_send_contact, section_contact).empty())
525     if(face.action2key(key_rss_check, section_contact).empty())
526     if(face.action2key(key_send_url, section_contact).empty())
527     if(face.action2key(key_rename, section_contact).empty())
528     if(face.action2key(key_version, section_contact).empty())
529     if(face.action2key(key_edit, section_contact).empty())
530     if(face.action2key(key_ignore, section_contact).empty())
531     if(face.action2key(key_quickfind, section_contact).empty())
532     if(face.action2key(key_next_chat, section_contact).empty())
533     if(face.action2key(key_prev_chat, section_contact).empty())
534     if(face.action2key(key_search, section_history).empty())
535     if(face.action2key(key_search_again, section_history).empty())
536     if(face.action2key(key_show_urls, section_history).empty())
537     if(face.action2key(key_fullscreen, section_history).empty())
538     if(face.action2key(key_send_message, section_editor).empty())
539     if(face.action2key(key_quit, section_editor).empty())
540     if(face.action2key(key_multiple_recipients, section_editor).empty())
541     if(face.action2key(key_history, section_editor).empty())
542     if(face.action2key(key_next_chat, section_editor).empty())
543     if(face.action2key(key_prev_chat, section_editor).empty())
544     if(face.action2key(key_out_chat, section_editor).empty())
545     if(face.action2key(key_info, section_editor).empty())
546     if(face.action2key(key_show_urls, section_editor).empty())
547     if(face.action2key(key_fullscreen, section_editor).empty())
548     if(face.action2key(key_show_urls, section_info).empty())
549     if(face.action2key(key_user_external_action, section_info).empty()) {}
550 */
551 }
552 
loadmainconfig()553 void icqconf::loadmainconfig() {
554     string fname = getconfigfname("config"), buf, param, rbuf;
555     ifstream f(fname.c_str());
556     imaccount im;
557     protocolname pname;
558 
559     if(f.is_open()) {
560 	mailcheck = askaway = false;
561 	savepwd = bidi = true;
562 	setsmtphost("");
563 	setbrowser("");
564 	setpeertopeer(0, 65535);
565 
566 	while(!f.eof()) {
567 	    getstring(f, buf);
568 	    rbuf = buf;
569 	    param = getword(buf);
570 
571 	    if(param == "hideoffline") hideoffline = true; else
572 	    if(param == "emacs") emacs = true; else
573 	    if(param == "vi") vi = true; else
574 	    if(param == "autoaway") autoaway = atol(buf.c_str()); else
575 	    if(param == "autona") autona = atol(buf.c_str()); else
576 	    if(param == "auto_away_na_x") autoawayx = true; else
577 	    if(param == "antispam") antispam = true; else
578 	    if(param == "showopenedchats") setshowopenedchats(true); else
579 	    if(param == "dropauthreq") dropauthreq = true; else
580 	    if(param == "screenna") screenna = true; else
581 	    if(param == "screensocketpath") screensocketpath = buf; else
582 	    if(param == "mailcheck") mailcheck = true; else
583 	    if(param == "quotemsgs") quote = true; else
584 	    if(param == "sockshost") setsockshost(buf); else
585 	    if(param == "socksusername") socksuser = buf; else
586 	    if(param == "sockspass") sockspass = buf; else
587 	    if((param == "usegroups") || (param == "group1")) fgroupmode = group1; else
588 	    if(param == "group2") fgroupmode = group2; else
589 	    if(param == "protocolormode") cm = icqconf::cmproto; else
590 	    if(param == "statuscolormode") cm = icqconf::cmstatus; else
591 	    if(param == "sort_by_status_and_activity") setsortmode(icqconf::sort_by_status_and_activity); else
592 	    if(param == "sort_by_status_and_name") setsortmode(icqconf::sort_by_status_and_name); else
593 	    if(param == "sort_by_activity") setsortmode(icqconf::sort_by_activity); else
594 	    if(param == "sort_by_name") setsortmode(icqconf::sort_by_name); else
595 	    if(param == "smtp") setsmtphost(buf); else
596 	    if(param == "browser") setbrowser(buf); else
597 	    if(param == "http_proxy") sethttpproxyhost(buf); else
598 	    if(param == "log") makelog = true; else
599 	    if(param == "proxy_connect") proxyconnect = true; else
600 	    if(param == "proxy_ssl") proxyssl = true; else
601 	    if(param == "chatmode") initmultiproto(chatmode, buf, true); else
602 	    if(param == "entersends") initmultiproto(entersends, buf, true); else
603 	    if(param == "nonimonline") initmultiproto(nonimonline, buf, false); else
604 	    if(param == "captcha") usingcaptcha = true; else
605 	    if(param == "russian" || param == "convert") initmultiproto(cpconvert, buf, false); else
606 	    if(param == "nobidi") setbidi(false); else
607 	    if(param == "askaway") askaway = true; else
608 	    if(param == "askquit") askquit = true; else
609 	    if(param == "logtimestamps") logtimestamps = true; else
610 	    if(param == "logonline") logonline = true; else
611 	    if(param == "fromcharset") fromcharset = buf; else
612 	    if(param == "tocharset") tocharset = buf; else
613 	    if(param == "left_panel_width")  leftpanelwidth  = atol(buf.c_str()); else
614 	    if(param == "log_panel_height") logpanelheight = atol(buf.c_str()); else
615 	    if(param == "chat_panel_height") chatpanelheight = atol(buf.c_str()); else
616 	    if(param == "timestampstothesecond") settimestampstothesecond(true); else
617 	    if(param == "defaultauthmessage") defaultAuthMessage = buf; else
618 	    if(param == "ptp") {
619 		ptpmin = atoi(getword(buf, "-").c_str());
620 		ptpmax = atoi(buf.c_str());
621 	    } else {
622 		for(pname = icq; pname != protocolname_size; pname++) {
623 		    buf = getprotocolname(pname);
624 		    if(param.substr(0, buf.size()) == buf) {
625 			im = getourid(pname);
626 			im.read(rbuf);
627 			setourid(im);
628 		    }
629 		}
630 	    }
631 	}
632 
633 	if(fromcharset.empty() && tocharset.empty())
634 	for(pname = icq; pname != protocolname_size; pname++) {
635 	    if(getcpconvert(pname)) {
636 		fromcharset = "cp1251";
637 		tocharset = "koi8-r";
638 		break;
639 	    }
640 	}
641 
642 	setproxy();
643 	f.close();
644     }
645 }
646 
save()647 void icqconf::save() {
648     string fname = getconfigfname("config"), param;
649     int away, na;
650     bool usex = false;
651 
652     if(enoughdiskspace()) {
653 	ofstream f(fname.c_str());
654 
655 	if(f.is_open()) {
656 	    if(!getsockshost().empty()) {
657 		string user, pass;
658 		getsocksuser(user, pass);
659 		f << "sockshost\t" << getsockshost() + ":" + i2str(getsocksport()) << endl;
660 		f << "socksusername\t" << user << endl;
661 		f << "sockspass\t" << pass << endl;
662 	    }
663 
664 	    getauto(away, na, usex);
665 
666 	    if(away) f << "autoaway\t" << i2str(away) << endl;
667 	    if(na) f << "autona\t" << i2str(na) << endl;
668 	    if(autoawayx) f << "auto_away_na_x" << endl;
669 	    if(hideoffline) f << "hideoffline" << endl;
670 	    if(emacs) f << "emacs" << endl;
671 	    if(getquote()) f << "quotemsgs" << endl;
672 	    if(vi) f << "vi" << endl;
673             if(getantispam()) f << "antispam" << endl;
674             if(getshowopenedchats()) f << "showopenedchats" << endl;
675 	    if(getdropauthreq()) f << "dropauthreq" << endl;
676 	    if(getusingcaptcha()) f << "captcha" << endl;
677 	    if(getmailcheck()) f << "mailcheck" << endl;
678 	    if(getaskaway()) f << "askaway" << endl;
679             if(getscreenna()) f << "screenna" << endl;
680             if(!screensocketpath.empty()) f << "screensocketpath\t" << screensocketpath << endl;
681 
682 	    param = "";
683 	    for(protocolname pname = icq; pname != protocolname_size; pname++)
684 		if(getchatmode(pname)) param += (string) " " + conf->getprotocolname(pname);
685 	    if(!param.empty())
686 		f << "chatmode" << param << endl;
687 
688 	    param = "";
689 	    for(protocolname pname = icq; pname != protocolname_size; pname++)
690 		if(getentersends(pname)) param += (string) " " + conf->getprotocolname(pname);
691 	    if(!param.empty())
692 		f << "entersends" << param << endl;
693 
694 	    param = "";
695 	    for(protocolname pname = icq; pname != protocolname_size; pname++)
696 		if(getnonimonline(pname)) param += (string) " " + conf->getprotocolname(pname);
697 	    if(!param.empty())
698 		f << "nonimonline" << param << endl;
699 
700 	    param = "";
701 	    for(protocolname pname = icq; pname != protocolname_size; pname++)
702 		if(getcpconvert(pname)) param += (string) " " + conf->getprotocolname(pname);
703 	    if(!param.empty())
704 		f << "convert" << param << endl;
705 
706 	    param = "";
707 
708 	    f << "fromcharset\t" << fromcharset << endl;
709 	    f << "tocharset\t" << tocharset << endl;
710 
711 	    if(!getbidi()) f << "nobidi" << endl;
712 	    if(getaskquit()) f << "askquit" << endl;
713 	    if(logtimestamps) f << "logtimestamps" << endl;
714 	    if(timestampstothesecond) f << "timestampstothesecond" << endl;
715 	    if(logonline) f << "logonline" << endl;
716 
717 	    f << "smtp\t" << getsmtphost() << ":" << getsmtpport() << endl;
718 	    f << "browser\t" << getbrowser() << endl;
719 
720 	    if(!gethttpproxyhost().empty())
721 		if (!gethttpproxyuser().empty())
722 		    f << "http_proxy\t" << gethttpproxyuser() << ":" << gethttpproxypasswd() << "@" << gethttpproxyhost() << ":" << gethttpproxyport() << endl;
723 		else
724 		    f << "http_proxy\t" << gethttpproxyhost() << ":" << gethttpproxyport() << endl;
725 
726 	    f << "ptp\t" << ptpmin << "-" << ptpmax << endl;
727 
728 	    switch(getgroupmode()) {
729 		case group1: f << "group1" << endl; break;
730 		case group2: f << "group2" << endl; break;
731 	    }
732 
733 	    switch(getcolormode()) {
734 		case cmproto:
735 		    f << "protocolormode" << endl;
736 		    break;
737 		case cmstatus:
738 		    f << "statuscolormode" << endl;
739 		    break;
740 	    }
741 
742 	    switch(getsortmode()) {
743 		case sort_by_status_and_activity: f << "sort_by_status_and_activity" << endl; break;
744 		case sort_by_status_and_name: f << "sort_by_status_and_name" << endl; break;
745 		case sort_by_activity: f << "sort_by_activity" << endl; break;
746 		case sort_by_name: f << "sort_by_name" << endl; break;
747 	    }
748 
749 	    if(getmakelog()) f << "log" << endl;
750 	    if(getproxyconnect()) f << "proxy_connect" << endl;
751 	    if(getproxyssl()) f << "proxy_ssl" << endl;
752 
753 	    if(getleftpanelwidth())  f << "left_panel_width\t"  << getleftpanelwidth()  << endl;
754 	    if(getlogpanelheight()) f << "log_panel_height\t" << getlogpanelheight() << endl;
755 	    if(getchatpanelheight()) f << "chat_panel_height\t" << getchatpanelheight() << endl;
756 
757 	    f << "defaultauthmessage\t" << getDefaultAuthMessage() << endl;
758 
759 	    vector<imaccount>::iterator ia;
760 	    for(ia = accounts.begin(); ia != accounts.end(); ++ia)
761 		ia->write(f);
762 
763 	    f.close();
764 	}
765     }
766 }
767 
loadcolors()768 void icqconf::loadcolors() {
769     string tname = getconfigfname("colorscheme");
770 
771     switch(conf->getregcolor()) {
772 	case rcdark:
773 	    schemer.push(cp_status, "status black/white");
774 	    schemer.push(cp_dialog_text, "dialog_text   black/white");
775 	    schemer.push(cp_dialog_menu, "dialog_menu   black/white");
776 	    schemer.push(cp_dialog_selected, "dialog_selected   white/transparent   bold");
777 	    schemer.push(cp_dialog_highlight, "dialog_highlight red/white");
778 	    schemer.push(cp_dialog_frame, "dialog_frame blue/white");
779 	    schemer.push(cp_main_text, "main_text   cyan/transparent");
780 	    schemer.push(cp_main_menu, "main_menu   green/transparent");
781 	    schemer.push(cp_main_selected, "main_selected   black/white");
782 	    schemer.push(cp_main_highlight, "main_highlight yellow/transparent  bold");
783 	    schemer.push(cp_main_frame, "main_frame blue/transparent    bold");
784 	    schemer.push(cp_main_history_incoming, "main_history_incoming  yellow/transparent    bold");
785 	    schemer.push(cp_main_history_outgoing, "main_history_outgoing  cyan/transparent");
786 	    schemer.push(cp_clist_icq, "clist_icq   green/transparent");
787 	    schemer.push(cp_clist_yahoo, "clist_yahoo   magenta/transparent");
788 	    schemer.push(cp_clist_infocard, "clist_infocard white/transparent");
789 	    schemer.push(cp_clist_msn, "clist_msn   cyan/transparent");
790 	    schemer.push(cp_clist_aim, "clist_aim   yellow/transparent");
791 	    schemer.push(cp_clist_irc, "clist_irc    blue/transparent");
792 	    schemer.push(cp_clist_jabber, "clist_jabber    red/transparent");
793 	    schemer.push(cp_clist_rss, "clist_rss    white/transparent   bold");
794 	    schemer.push(cp_clist_lj, "clist_lj    cyan/transparent   bold");
795 	    schemer.push(cp_clist_gadu, "clist_gg    blue/transparent   bold");
796 	    schemer.push(cp_clist_online, "clist_online   green/transparent   bold");
797 	    schemer.push(cp_clist_offline, "clist_offline   red/transparent   bold");
798 	    schemer.push(cp_clist_away, "clist_away   yellow/transparent   bold");
799 	    schemer.push(cp_clist_dnd, "clist_dnd   cyan/transparent   bold");
800 	    schemer.push(cp_clist_na, "clist_na   blue/transparent   bold");
801 	    schemer.push(cp_clist_free_for_chat, "clist_free_for_chat   green/transparent   bold");
802 	    schemer.push(cp_clist_invisible, "clist_invisible   grey/transparent   bold");
803 	    schemer.push(cp_clist_not_in_list, "clist_not_in_list   white/transparent   bold");
804 	    schemer.push(cp_clist_unread, "clist_unread red/transparent	bold");
805 	    break;
806 
807 	case rcblue:
808 	    schemer.push(cp_status, "status  black/white");
809 	    schemer.push(cp_dialog_text, "dialog_text black/cyan");
810 	    schemer.push(cp_dialog_menu, "dialog_menu black/cyan");
811 	    schemer.push(cp_dialog_selected, "dialog_selected white/black bold");
812 	    schemer.push(cp_dialog_highlight, "dialog_highlight    white/cyan  bold");
813 	    schemer.push(cp_dialog_frame, "dialog_frame    black/cyan");
814 	    schemer.push(cp_main_text, "main_text   white/blue");
815 	    schemer.push(cp_main_menu, "main_menu   white/blue");
816 	    schemer.push(cp_main_selected, "main_selected   black/cyan");
817 	    schemer.push(cp_main_highlight, "main_highlight  white/blue  bold");
818 	    schemer.push(cp_main_frame, "main_frame  blue/blue   bold");
819 	    schemer.push(cp_main_history_incoming, "main_history_incoming  white/blue");
820 	    schemer.push(cp_main_history_outgoing, "main_history_outgoing  white/blue  bold");
821 	    schemer.push(cp_clist_icq, "clist_icq   green/blue");
822 	    schemer.push(cp_clist_yahoo, "clist_yahoo magenta/blue");
823 	    schemer.push(cp_clist_msn, "clist_msn   cyan/blue");
824 	    schemer.push(cp_clist_infocard, "clist_infocard  white/blue");
825 	    schemer.push(cp_clist_aim, "clist_aim   yellow/blue");
826 	    schemer.push(cp_clist_irc, "clist_irc   blue/blue   bold");
827 	    schemer.push(cp_clist_jabber, "clist_jabber    red/blue");
828 	    schemer.push(cp_clist_rss, "clist_rss    white/blue   bold");
829 	    schemer.push(cp_clist_lj, "clist_lj    cyan/blue   bold");
830 	    schemer.push(cp_clist_gadu, "clist_gg    blue/blue   bold");
831 	    schemer.push(cp_clist_online, "clist_online   green/transparent   bold");
832 	    schemer.push(cp_clist_offline, "clist_offline   red/transparent   bold");
833 	    schemer.push(cp_clist_away, "clist_away   yellow/transparent   bold");
834 	    schemer.push(cp_clist_dnd, "clist_dnd   cyan/transparent   bold");
835 	    schemer.push(cp_clist_na, "clist_na   blue/transparent   bold");
836 	    schemer.push(cp_clist_free_for_chat, "clist_free_for_chat   green/transparent   bold");
837 	    schemer.push(cp_clist_invisible, "clist_invisible   grey/transparent   bold");
838 	    schemer.push(cp_clist_not_in_list, "clist_not_in_list   white/transparent   bold");
839 	    schemer.push(cp_clist_unread, "clist_unread black/blue	bold");
840 	    break;
841     }
842 
843     if(access(tname.c_str(), F_OK)) {
844 	schemer.save(tname);
845     } else {
846 	schemer.load(tname);
847     }
848 }
849 
loadsounds()850 void icqconf::loadsounds() {
851     string tname = getconfigfname("sounds"), buf, suin, skey;
852     int i;
853     icqcontact *c;
854     imevent::imeventtype it;
855 
856     typedef pair<imevent::imeventtype, string> eventsound;
857     vector<eventsound> soundnames;
858     vector<eventsound>::iterator isn;
859 
860     soundnames.push_back(eventsound(imevent::message, "msg"));
861     soundnames.push_back(eventsound(imevent::sms, "sms"));
862     soundnames.push_back(eventsound(imevent::url, "url"));
863     soundnames.push_back(eventsound(imevent::online, "online"));
864     soundnames.push_back(eventsound(imevent::offline, "offline"));
865     soundnames.push_back(eventsound(imevent::email, "email"));
866 
867     for(i = 0; i < clist.count; i++) {
868 	c = (icqcontact *) clist.at(i);
869 
870 	for(it = imevent::message; it != imevent::imeventtype_size; it++) {
871 	    c->setsound(it, "");
872 	}
873     }
874 
875     if(access(tname.c_str(), F_OK)) {
876 	ofstream fo(tname.c_str());
877 
878 	if(fo.is_open()) {
879 	    fo << "# This file contains sound configuration for centerim" << endl;
880 	    fo << "# Every line should look like: <id> <event> <command>" << endl << "#" << endl;
881 
882 	    fo << "# <id>\tid of a contact; can be one of the following" << endl;
883 	    fo << "# *\tmeans default sound for all the contacts" << endl;
884 	    fo << "# icq_<uin>\tfor icq contacts (e.g. icq_123)" << endl;
885 	    fo << "# yahoo_<nickname>\tfor yahoo (e.g. yahoo_thekonst)" << endl;
886 	    fo << "# .. etc. Similar for the other protocols" << endl << "#" << endl;
887 
888 	    fo << "# <event>\tcan be: ";
889 	    for(isn = soundnames.begin(); isn != soundnames.end(); ++isn) {
890 		if(isn != soundnames.begin()) fo << ", ";
891 		fo << isn->second;
892 	    }
893 
894 	    fo << endl << "# <command>\tcommand line to be executed to play a sound" << endl << endl;
895 
896 	    switch(rs) {
897 		case rscard:
898 		    fo << "*\tmsg\taplay " << SHARE_DIR << "/msg.wav" << endl;
899 		    fo << "*\turl\taplay " << SHARE_DIR << "/url.wav" << endl;
900 		    fo << "*\temail\taplay " << SHARE_DIR << "/email.wav" << endl;
901 		    fo << "*\tonline\taplay " << SHARE_DIR << "/online.wav" << endl;
902 		    fo << "*\toffline\taplay " << SHARE_DIR << "/offline.wav" << endl;
903 		    fo << "*\tsms\taplay " << SHARE_DIR << "/sms.wav" << endl;
904 		    break;
905 
906 		case rsspeaker:
907 		    fo << "*\tmsg\t!spk1" << endl;
908 		    fo << "*\turl\t!spk2" << endl;
909 		    fo << "*\tsms\t!spk3" << endl;
910 		    fo << "*\temail\t!spk5" << endl;
911 		    break;
912 	    }
913 
914 	    fo.close();
915 	}
916     }
917 
918     ifstream fi(tname.c_str());
919     if(fi.is_open()) {
920 	while(!fi.eof()) {
921 	    getstring(fi, buf);
922 	    if(buf.empty() || (buf.substr(0, 1) == "#")) continue;
923 
924 	    suin = getword(buf);
925 	    skey = getword(buf);
926 
927 	    it = imevent::imeventtype_size;
928 
929 	    for(isn = soundnames.begin(); isn != soundnames.end(); ++isn) {
930 		if(skey == isn->second) {
931 		    it = isn->first;
932 		    break;
933 		}
934 	    }
935 
936 	    if(it == imevent::imeventtype_size)
937 		continue;
938 
939 	    c = 0;
940 
941 	    if(suin != "*") {
942 		if((i = suin.find("_")) != -1) {
943 		    skey = suin.substr(0, i);
944 		    suin.erase(0, i+1);
945 
946 		    imcontact ic;
947 		    protocolname pname;
948 
949 		    for(pname = icq; pname != protocolname_size && skey != getprotocolname(pname); pname++);
950 
951 		    if(pname != protocolname_size) {
952 			if(suin == "*") {
953 			    for(i = 0; i < clist.count; i++) {
954 				c = (icqcontact *) clist.at(i);
955 
956 				if(c->getdesc().pname == pname) c->setsound(it, buf);
957 			    }
958 			} else {
959 			    if(pname == icq) ic = imcontact(strtoul(suin.c_str(), 0, 0), pname);
960 				else ic = imcontact(suin, pname);
961 
962 			    c = clist.get(ic);
963 			}
964 		    }
965 		}
966 	    } else {
967 		c = clist.get(contactroot);
968 	    }
969 
970 	    if(c) c->setsound(it, buf);
971 	}
972 
973 	fi.close();
974     }
975 }
976 
loadactions()977 void icqconf::loadactions() {
978     string fname = getconfigfname("actions"), buf, name;
979     ifstream f;
980     bool cont;
981 
982     if(access(fname.c_str(), F_OK)) {
983 	buf = getenv("PATH") ? getenv("PATH") : "";
984 
985 	ofstream of(fname.c_str());
986 
987 	if(of.is_open()) {
988 	    of << "# This file contains external actions configuration for centerim" << endl;
989 	    of << "# Every line should look like: <action> <command>" << endl;
990 	    of << "# Possible actions are: openurl, detectmusic" << endl << endl;
991 
992 	    of << "openurl \\" << endl;
993 	    of << "    (if test ! -z \"`ps x | grep /" << browser << " | grep -v grep`\"; \\" << endl;
994 	    of << "\tthen DISPLAY=0:0 " << browser << " -remote 'openURL($url$, new-window)'; \\" << endl;
995 	    of << "\telse DISPLAY=0:0 " << browser << " '$url$'; \\" << endl;
996 	    of << "    fi) >/dev/null 2>&1 &" << endl;
997 
998 	    of << "detectmusic \\" << endl;
999 	    of << "     if test ! -z \"`ps x | grep orpheus | grep -v grep`\"; \\" << endl;
1000 	    of << "\tthen cat ~/.orpheus/currently_playing; \\" << endl;
1001 	    of << "     fi" << endl;
1002 
1003 	    of.close();
1004 	}
1005     }
1006 
1007     f.open(fname.c_str());
1008 
1009     if(f.is_open()) {
1010 	actions.clear();
1011 	cont = false;
1012 
1013 	while(!f.eof()) {
1014 	    getstring(f, buf);
1015 	    if(!cont) name = getword(buf);
1016 
1017 	    if(name == "openurl" || name == "detectmusic") {
1018 		if(!buf.empty())
1019 		if(cont = buf.substr(buf.size()-1, 1) == "\\")
1020 		    buf.erase(buf.size()-1, 1);
1021 
1022 		actions[name] += buf;
1023 	    }
1024 	}
1025 
1026 	f.close();
1027     }
1028 }
1029 
loadcaptcha()1030 void icqconf::loadcaptcha() {
1031     string fname = getconfigfname("captcha"), buf, entry;
1032     ifstream f;
1033 	vector<string>::const_iterator ic;
1034 
1035     if(access(fname.c_str(), F_OK)) {
1036 
1037 	ofstream of(fname.c_str());
1038 
1039 	if(of.is_open()) {
1040 	    of << "# This file contains sample configuration for captcha engine." << endl;
1041 	    of << "# Every line should look like: <param> <value>" << endl;
1042 	    of << "# Possible params are: greeting, quest, success, failure, timeout (min)" << endl;
1043 	    of << "# Quest fomat is: quest <question>//<answer>[::answer[...]]" << endl;
1044 	    of << endl;
1045 	    of << "greeting I'm using a test to determine if you are a computer or not. If you would please answer the question correctly, you will be added to my contact list automatically." << endl;
1046 	    of << endl;
1047 	    of << "quest How many legs does a dog have?//4::four" << endl;
1048 	    of << "quest What is the first word of this sentence?//what" << endl;
1049 	    of << "quest What is the sum of 1 and 1?//2::two" << endl;
1050 	    of << "quest What is not a fruit: lettuce, apple or banana?//lettuce" << endl;
1051 	    of << "quest How many fingers are there on one hand?//5::five" << endl;
1052 	    of << "quest How many wheels does a normal bicycle have?//2::two" << endl;
1053 	    of << "quest What colour does a banana have?//yellow::yelow" << endl;
1054 	    of << "quest What does a chicken lay?//eggs::egg" << endl;
1055 	    of << "quest What is the value of PI, accurate to 2 digits?//3.14::3,14" << endl;
1056 	    of << "quest Is a wheel round or not (yes or no)?//yes" << endl;
1057 	    of << endl;
1058 	    of << "success You answered the question correctly, you are now added to my contact list. Thank you for your patience." << endl;
1059 	    of << "failure You answered the question incorrectly, you can try again by answering the next question." << endl;
1060 	    of << "timeout 30" << endl;
1061 	    of.close();
1062 	}
1063     }
1064 
1065     f.open(fname.c_str());
1066 
1067     if(f.is_open()) {
1068 	while(!f.eof()) {
1069 	    getstring(f, buf);
1070 	    entry = getword(buf);
1071 
1072 		if(entry == "greeting")	captchagreet = buf; else
1073 		if(entry == "success") captchasuccess = buf; else
1074 		if(entry == "failure") captchafailure = buf; else
1075 		if(entry == "timeout") captchatimeout = atol(buf.c_str()); else
1076 		if(entry == "quest") thecaptcha.addquestion(buf);
1077 	}
1078 	if(thecaptcha.empty()) {
1079 		usingcaptcha = false;
1080 		face.log(_("+ ERROR: captcha disabled: no questions found!"));
1081 	}
1082 
1083 	f.close();
1084     }
1085 }
1086 
getregcolor() const1087 icqconf::regcolor icqconf::getregcolor() const {
1088     return rc;
1089 }
1090 
setregcolor(icqconf::regcolor c)1091 void icqconf::setregcolor(icqconf::regcolor c) {
1092     rc = c;
1093 }
1094 
getregsound() const1095 icqconf::regsound icqconf::getregsound() const {
1096     return rs;
1097 }
1098 
setregsound(icqconf::regsound s)1099 void icqconf::setregsound(icqconf::regsound s) {
1100     rs = s;
1101 }
1102 
getcolormode() const1103 icqconf::colormode icqconf::getcolormode() const {
1104     return cm;
1105 }
1106 
setcolormode(colormode c)1107 void icqconf::setcolormode(colormode c) {
1108     cm = c;
1109 }
1110 
setauto(int away,int na,bool usex)1111 void icqconf::setauto(int away, int na, bool usex) {
1112     autoaway = away;
1113     autona = na;
1114     autoawayx = usex;
1115 
1116     if(away == na)
1117 	autoaway = 0;
1118 }
1119 
getauto(int & away,int & na,bool & usex) const1120 void icqconf::getauto(int &away, int &na, bool& usex) const {
1121     away = autoaway;
1122     na = autona;
1123     usex = autoawayx;
1124 
1125     if(away == na)
1126 	away = 0;
1127 }
1128 
getscreenna() const1129 bool icqconf::getscreenna() const {
1130 	return screenna;
1131 }
1132 
setscreenna(bool sna)1133 void icqconf::setscreenna(bool sna) {
1134 	screenna = sna;
1135 }
1136 
getscreensocketpath() const1137 string icqconf::getscreensocketpath() const {
1138 	return screensocketpath;
1139 }
1140 
setscreensocketpath(string path)1141 void icqconf::setscreensocketpath(string path) {
1142 	screensocketpath = path;
1143 }
1144 
setquote(bool use)1145 void icqconf::setquote(bool use) {
1146     quote = use;
1147 }
setaskquit(bool faskquit)1148 void icqconf::setaskquit(bool faskquit) {
1149     askquit = faskquit;
1150 }
1151 
setsockshost(const string & nsockshost)1152 void icqconf::setsockshost(const string &nsockshost) {
1153     int pos;
1154 
1155     if(!nsockshost.empty()) {
1156 	if((pos = nsockshost.find(":")) != -1) {
1157 	    sockshost = nsockshost.substr(0, pos);
1158 	    socksport = atol(nsockshost.substr(pos+1).c_str());
1159 	} else {
1160 	    sockshost = nsockshost;
1161 	    socksport = 1080;
1162 	}
1163     } else {
1164 	sockshost = "";
1165     }
1166 }
1167 
getsockshost() const1168 string icqconf::getsockshost() const {
1169     return sockshost;
1170 }
1171 
getsocksport() const1172 unsigned int icqconf::getsocksport() const {
1173     return socksport;
1174 }
1175 
getsocksuser(string & name,string & pass) const1176 void icqconf::getsocksuser(string &name, string &pass) const {
1177     name = socksuser;
1178     pass = sockspass;
1179 }
1180 
setsocksuser(const string & name,const string & pass)1181 void icqconf::setsocksuser(const string &name, const string &pass) {
1182     socksuser = name;
1183     sockspass = pass;
1184 }
1185 
setsavepwd(bool ssave)1186 void icqconf::setsavepwd(bool ssave) {
1187     savepwd = ssave;
1188 }
1189 
sethideoffline(bool fho)1190 void icqconf::sethideoffline(bool fho) {
1191     hideoffline = fho;
1192 }
1193 
settimestampstothesecond(bool ttts)1194 void icqconf::settimestampstothesecond(bool ttts) {
1195     timestampstothesecond = ttts;
1196     if (timestampstothesecond) {
1197         timestampformat = SECONDS_TIMESTAMP_FORMAT;
1198 	logtimestampformat = SECONDS_LOGTIMESTAMP_FORMAT;
1199     } else {
1200         timestampformat = DEFAULT_TIMESTAMP_FORMAT;
1201 	logtimestampformat = DEFAULT_LOGTIMESTAMP_FORMAT;
1202     }
1203 }
1204 
setemacs(bool fem)1205 void icqconf::setemacs(bool fem) {
1206     emacs = fem;
1207 }
1208 
setvi(bool b)1209 void icqconf::setvi(bool b) {
1210     vi = b;
1211 }
1212 
setantispam(bool fas)1213 void icqconf::setantispam(bool fas) {
1214     antispam = fas;
1215 }
1216 
setshowopenedchats(bool fsoc)1217 void icqconf::setshowopenedchats(bool fsoc)
1218 {
1219     showopenedchats = fsoc;
1220 }
1221 
setdropauthreq(bool fas)1222 void icqconf::setdropauthreq(bool fas) {
1223     dropauthreq = fas;
1224 }
1225 
setusingcaptcha(bool fas)1226 void icqconf::setusingcaptcha(bool fas) {
1227     usingcaptcha = fas;
1228 }
1229 
setmailcheck(bool fmc)1230 void icqconf::setmailcheck(bool fmc) {
1231     mailcheck = fmc;
1232 }
1233 
setaskaway(bool faskaway)1234 void icqconf::setaskaway(bool faskaway) {
1235     askaway = faskaway;
1236 }
1237 
getchatmode(protocolname pname)1238 bool icqconf::getchatmode(protocolname pname) {
1239     switch(pname) {
1240 	case infocard:
1241 	case rss:
1242 	    return false;
1243     }
1244 
1245     return chatmode[pname];
1246 }
1247 
setchatmode(protocolname pname,bool fchatmode)1248 void icqconf::setchatmode(protocolname pname, bool fchatmode) {
1249     chatmode[pname] = fchatmode;
1250 }
1251 
getentersends(protocolname pname)1252 bool icqconf::getentersends(protocolname pname) {
1253     return entersends[pname];
1254 }
1255 
setentersends(protocolname pname,bool fentersends)1256 void icqconf::setentersends(protocolname pname, bool fentersends) {
1257     entersends[pname] = fentersends;
1258 }
1259 
getnonimonline(protocolname pname)1260 bool icqconf::getnonimonline(protocolname pname) {
1261     return nonimonline[pname];
1262 }
1263 
setnonimonline(protocolname pname,bool fnonimonline)1264 void icqconf::setnonimonline(protocolname pname, bool fnonimonline) {
1265     nonimonline[pname] = fnonimonline;
1266 }
1267 
getcpconvert(protocolname pname) const1268 bool icqconf::getcpconvert(protocolname pname) const {
1269     return cpconvert[pname];
1270 }
1271 
setcpconvert(protocolname pname,bool fcpconvert)1272 void icqconf::setcpconvert(protocolname pname, bool fcpconvert) {
1273     cpconvert[pname] = fcpconvert;
1274 }
1275 
execaction(const string & name,const string & param)1276 string icqconf::execaction(const string &name, const string &param) {
1277     int inpipe[2], outpipe[2], pid, npos;
1278     struct sigaction sact, osact;
1279     string torun = actions[name], out;
1280     fd_set rfds;
1281     char ch;
1282 
1283     if(name == "openurl")
1284     {
1285 	string url = param;
1286 	int pos = 0, fnd = -1;
1287 
1288 	char enc[4];
1289 
1290 	while( ((fnd = url.find("'", pos)) != -1) || ((fnd = url.find("\"", pos)) != -1) ) {
1291 		snprintf(enc, 4, "%%%02X", url[fnd]);
1292 	    url.replace(fnd, 1, enc);
1293     	pos = fnd+3;
1294 	}
1295 
1296 	while((npos = torun.find("$url$")) != -1)
1297 	    torun.replace(npos, 5, url);
1298     }
1299 
1300     if(!pipe(inpipe) && !pipe(outpipe)) {
1301 	memset(&sact, 0, sizeof(sact));
1302 	sigaction(SIGCHLD, &sact, &osact);
1303 	pid = fork();
1304 
1305 	if(!pid) {
1306 	    dup2(inpipe[1], STDOUT_FILENO);
1307 	    dup2(outpipe[0], STDIN_FILENO);
1308 
1309 	    close(inpipe[1]);
1310 	    close(inpipe[0]);
1311 	    close(outpipe[0]);
1312 	    close(outpipe[1]);
1313 
1314 	    execl("/bin/sh", "/bin/sh", "-c", torun.c_str(), (char *)NULL );
1315 	    _exit(0);
1316 	} else {
1317 	    close(outpipe[0]);
1318 	    close(inpipe[1]);
1319 
1320 	    while(1) {
1321 		FD_ZERO(&rfds);
1322 		FD_SET(inpipe[0], &rfds);
1323 
1324 		if(select(inpipe[0]+1, &rfds, 0, 0, 0) < 0) break; else {
1325 		    if(FD_ISSET(inpipe[0], &rfds)) {
1326 			if(read(inpipe[0], &ch, 1) != 1) break; else {
1327 			    out += ch;
1328 			}
1329 		    }
1330 		}
1331 	    }
1332 
1333 	    waitpid(pid, 0, 0);
1334 	    close(inpipe[0]);
1335 	    close(outpipe[1]);
1336 	}
1337 
1338 	sigaction(SIGCHLD, &osact, 0);
1339     }
1340     face.log(_("+ launched the %s action command"), name.c_str());
1341     return out;
1342 }
1343 
getprotocolname(protocolname pname) const1344 string icqconf::getprotocolname(protocolname pname) const {
1345     static const string ptextnames[protocolname_size] = {
1346 	"icq", "yahoo", "msn", "aim", "irc", "jab", "rss", "lj", "gg", "infocard"
1347     };
1348 
1349     return ptextnames[pname];
1350 }
1351 
getprotocolbyletter(char letter) const1352 protocolname icqconf::getprotocolbyletter(char letter) const {
1353     switch(letter) {
1354 	case 'y': return yahoo;
1355 	case 'a': return aim;
1356 	case 'i': return irc;
1357 	case 'm': return msn;
1358 	case 'n': return infocard;
1359 	case 'j': return jabber;
1360 	case 'r': return rss;
1361 	case 'l': return livejournal;
1362 	case 'g': return gadu;
1363 	case '0':
1364 	case '1':
1365 	case '2':
1366 	case '3':
1367 	case '4':
1368 	case '5':
1369 	case '6':
1370 	case '7':
1371 	case '8':
1372 	case '9': return icq;
1373     }
1374 
1375     return protocolname_size;
1376 }
1377 
getprotocolprefix(protocolname pname) const1378 string icqconf::getprotocolprefix(protocolname pname) const {
1379     static const string pprefixes[protocolname_size] = {
1380 	"", "y", "m", "a", "i", "j", "r", "l", "g", "n"
1381     };
1382 
1383     return pprefixes[pname];
1384 }
1385 
getstatus(protocolname pname)1386 imstatus icqconf::getstatus(protocolname pname) {
1387     if(startoffline)
1388 	return offline;
1389 
1390     imstatus st = available;
1391     map<string, string>::iterator ia;
1392     imaccount a = getourid(pname);
1393 
1394     if((ia = a.additional.find("status")) != a.additional.end()) {
1395 	if(!ia->second.empty()) {
1396 	    for(st = offline; st != imstatus_size && imstatus2char[st] != ia->second[0]; st++);
1397 	    if(st == imstatus_size) st = available;
1398 	}
1399     }
1400 
1401     return st;
1402 }
1403 
savestatus(protocolname pname,imstatus st)1404 void icqconf::savestatus(protocolname pname, imstatus st) {
1405     imaccount im = getourid(pname);
1406     im.additional["status"] = string(1, imstatus2char[st]);
1407     setourid(im);
1408 }
1409 
setavatar(protocolname pname,const string & ava)1410 void icqconf::setavatar(protocolname pname, const string &ava) {
1411     imaccount im = getourid(pname);
1412     im.additional["avatar"] = ava;
1413     setourid(im);
1414 }
1415 
getprotcolor(protocolname pname) const1416 int icqconf::getprotcolor(protocolname pname) const {
1417     switch(pname) {
1418 	case icq : return getcolor(cp_clist_icq);
1419 	case yahoo : return getcolor(cp_clist_yahoo);
1420 	case infocard : return getcolor(cp_clist_infocard);
1421 	case msn : return getcolor(cp_clist_msn);
1422 	case aim : return getcolor(cp_clist_aim);
1423 	case irc : return getcolor(cp_clist_irc);
1424 	case jabber : return getcolor(cp_clist_jabber);
1425 	case rss : return getcolor(cp_clist_rss);
1426 	case livejournal : return getcolor(cp_clist_lj);
1427 	case gadu : return getcolor(cp_clist_gadu);
1428 	default : return getcolor(cp_main_text);
1429     }
1430 }
1431 
getstatuscolor(imstatus status) const1432 int icqconf::getstatuscolor(imstatus status) const {
1433     switch(status) {
1434         case offline : return getcolor(cp_clist_offline);
1435         case available : return getcolor(cp_clist_online);
1436         case invisible : return getcolor(cp_clist_invisible);
1437         case freeforchat : return getcolor(cp_clist_free_for_chat);
1438         case dontdisturb : return getcolor(cp_clist_dnd);
1439         case occupied : return getcolor(cp_clist_occupied);
1440         case notavail : return getcolor(cp_clist_na);
1441         case outforlunch : return getcolor(cp_clist_na);
1442         case away : return getcolor(cp_clist_away);
1443 	default : return getcolor(cp_main_text);
1444     }
1445 }
1446 
setbidi(bool fbidi)1447 void icqconf::setbidi(bool fbidi) {
1448     bidi = fbidi;
1449 #ifdef USE_FRIBIDI
1450     use_fribidi = bidi;
1451 #endif
1452 }
1453 
commandline(int argc,char ** argv)1454 void icqconf::commandline(int argc, char **argv) {
1455     int i;
1456     string event, proto, dest, number;
1457     char st = 0;
1458 
1459     argv0 = argv[0];
1460 
1461     for(i = 1; i < argc; i++) {
1462 	string args = argv[i];
1463 
1464 	if((args == "-a") || (args == "--ascii")) {
1465 	    kintf_graph = 0;
1466 
1467 	} else if((args == "-b") || (args == "--basedir")) {
1468 	    if(argv[++i]) {
1469 		basedir = argv[i];
1470 		if(basedir.substr(basedir.size()-1) != "/") basedir += "/";
1471 	    }
1472 
1473 	} else if((args == "-B") || (args == "--bind")) {
1474 	    if(argv[++i]) {
1475 		bindhost = argv[i];
1476 		cw_setbind(bindhost.c_str());
1477 	    }
1478 
1479 	} else if((args == "-T") || (args == "--no-xtitles")) {
1480 	    notitles = true;
1481 
1482 	} else if((args == "-o") || (args == "--offline")) {
1483 	    startoffline = true;
1484 
1485 	} else if((args == "-s") || (args == "--send")) {
1486 	    if(argv[++i]) event = argv[i];
1487 
1488 	} else if((args == "-p") || (args == "--proto")) {
1489 	    if(argv[++i]) proto = argv[i];
1490 
1491 	} else if((args == "-t") || (args == "--to")) {
1492 	    if(argv[++i]) dest = argv[i];
1493 
1494 	} else if((args == "-n") || (args == "--number")) {
1495 	    if(argv[++i]) number = argv[i];
1496 
1497 	} else if((args == "-S") || (args == "--status")) {
1498 	    if(argv[++i])
1499 	    if(strlen(argv[i]))
1500 		st = argv[i][0];
1501 
1502 	} else if((args == "-d") || (args == "--debug")) {
1503 	    debug = true;
1504 
1505 	} else if((args == "-v") || (args == "--version")) {
1506 	    cout << PACKAGE << " " << centerim::version << endl
1507 		<< "Written by Konstantin Klyagin, 2005. Currently maintained by the CenterIM community." << endl
1508 		<< "Built-in protocols are:";
1509 
1510 	    for(protocolname pname = icq; pname != protocolname_size; pname++)
1511 		if(gethook(pname).enabled()) cout << " " << conf->getprotocolname(pname);
1512 
1513 	    cout << endl << endl
1514 		<< "This is free software; see the source for copying conditions.  There is NO" << endl
1515 		<< "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." << endl;
1516 
1517 	    exit(0);
1518 
1519 	} else {
1520 	    usage();
1521 	    exit(0);
1522 	}
1523     }
1524 
1525     if(!number.empty()) {
1526 	if(event.empty()) event = "sms";
1527 	if(proto.empty()) proto = "icq";
1528 	dest = "0";
1529     }
1530 
1531     constructevent(event, proto, dest, number);
1532     externalstatuschange(st, proto);
1533 }
1534 
constructevent(const string & event,const string & proto,const string & dest,const string & number) const1535 void icqconf::constructevent(const string &event, const string &proto,
1536 const string &dest, const string &number) const {
1537 
1538     imevent *ev = 0;
1539     imcontact cdest;
1540     string text, buf;
1541     int pos;
1542 
1543     if(event.empty() && dest.empty()) return; else
1544     if(event.empty() || proto.empty() || dest.empty()) {
1545 	cout << _("event sending error: not enough parameters") << endl;
1546 	exit(1);
1547     }
1548 
1549     while(getline(cin, buf)) {
1550 	if(!text.empty()) text += "\n";
1551 	text += buf;
1552     }
1553 
1554     if(proto == "icq") {
1555 	if(dest.find_first_not_of("0123456789") != -1) {
1556 	    cout << _("event sending error: only UINs are allowed with icq protocol") << endl;
1557 	    exit(1);
1558 	}
1559 	cdest = imcontact(strtoul(dest.c_str(), 0, 0), icq);
1560     } else {
1561 	protocolname pname;
1562 
1563 	for(pname = icq; pname != protocolname_size; pname++) {
1564 	    if(getprotocolname(pname) == proto) {
1565 		cdest = imcontact(dest, pname);
1566 		break;
1567 	    }
1568 	}
1569 
1570 	if(pname == protocolname_size) {
1571 	    cout << _("event sending error: unknown IM type") << endl;
1572 	    exit(1);
1573 	}
1574     }
1575 
1576     if(event == "msg") {
1577 	ev = new immessage(cdest, imevent::outgoing, text);
1578     } else if(event == "url") {
1579 	string url;
1580 
1581 	if((pos = text.find("\n")) != -1) {
1582 	    url = text.substr(0, pos);
1583 	    text.erase(0, pos+1);
1584 	} else {
1585 	    url = text;
1586 	    text = "";
1587 	}
1588 
1589 	ev = new imurl(cdest, imevent::outgoing, url, text);
1590     } else if(event == "sms") {
1591 	ev = new imsms(cdest, imevent::outgoing, text, number);
1592     } else {
1593 	cout << _("event sending error: unknown event type") << endl;
1594 	exit(1);
1595     }
1596 
1597     if(ev) {
1598 	icqcontact *c = new icqcontact(cdest);
1599 
1600 	if(access(c->getdirname().c_str(), X_OK)) {
1601 	    mkdir(c->getdirname().c_str(), S_IRUSR | S_IWUSR | S_IXUSR);
1602 	    selfsignal(SIGUSR2);
1603 	}
1604 
1605 	if(!access(c->getdirname().c_str(), X_OK)) {
1606 	    clist.add(c);
1607 	    em.store(*ev);
1608 
1609 	    char buf[512];
1610 	    snprintf(buf, sizeof(buf), _("%s to %s has been put to the queue"),
1611 		streventname(ev->gettype()),
1612 		number.empty() ? c->getdesc().totext().c_str() : number.c_str());
1613 
1614 	    cout << buf << endl;
1615 	} else {
1616 	    cout << _("event sending error: error creating directory for the contact") << endl;
1617 	    exit(1);
1618 	}
1619 
1620 	//delete c;
1621 	delete ev;
1622 
1623 	exit(0);
1624     }
1625 }
1626 
selfsignal(int signum) const1627 void icqconf::selfsignal(int signum) const {
1628     int rpid;
1629     ifstream f(conf->getconfigfname("pid").c_str());
1630 
1631     if(f.is_open()) {
1632 	f >> rpid;
1633 	f.close();
1634 
1635 	if(rpid > 0) {
1636 	    kill(rpid, signum);
1637 	}
1638     }
1639 }
1640 
externalstatuschange(char st,const string & proto) const1641 void icqconf::externalstatuschange(char st, const string &proto) const {
1642     imstatus imst;
1643     protocolname pname;
1644 
1645     if(st) {
1646 	for(pname = icq; pname != protocolname_size; pname++)
1647 	    if(getprotocolname(pname) == proto)
1648 		break;
1649 
1650 	for(imst = offline; imst != imstatus_size; imst++)
1651 	    if(imstatus2char[imst] == st)
1652 		break;
1653 
1654 	try {
1655 	    if(pname != protocolname_size) {
1656 		if(imst != imstatus_size) {
1657 		    string sfname = conf->getconfigfname((string) "status-" + proto);
1658 		    ofstream sf(sfname.c_str());
1659 		    if(sf.is_open()) sf << imstatus2char[imst], sf.close();
1660 
1661 		    selfsignal(SIGUSR1);
1662 		} else {
1663 		    throw _("unknown status character was given");
1664 		}
1665 	    } else {
1666 		throw _("unknown IM type");
1667 	    }
1668 	} catch(char *p) {
1669 	    cout << _("status change error: ") << p << endl;
1670 	    exit(1);
1671 	}
1672 
1673 	exit(0);
1674     }
1675 }
1676 
usage() const1677 void icqconf::usage() const {
1678 	cout << PACKAGE << " " << centerim::version << endl;
1679 
1680     cout << endl << _("Usage: ") << argv0 << _(" [OPTION]...") << endl;
1681 
1682     cout << endl << _("General options:") << endl;
1683     cout << _("  --ascii, -a              use ASCII characters for windows and UI controls") << endl;
1684     cout << _("  --basedir, -b <path>     set a custom base directory") << endl;
1685     cout << _("  --bind, -B <host/ip>     bind a custom local IP") << endl;
1686     cout << _("  --no-xtitles, -T         disable xterm titles") << endl;
1687     cout << _("  --offline, -o            set all protocols status to offline upon start") << endl;
1688     cout << _("  --debug, -d              enables debug info logging") << endl;
1689     cout << _("  --help                   display this stuff") << endl;
1690     cout << _("  --version, -v            show the program version info") << endl;
1691 
1692     cout << endl << _("Events sending options:") << endl;
1693     cout << _("  -s, --send <event type>  event type; can be msg, sms or url") << endl;
1694     cout << _("  -S, --status <status>    change the current IM status. Status; o, _, a, d, n, c, f, i") << endl;
1695     cout << _("  -p, --proto <protocol>   protocol type; can be icq, yahoo, msn, aim, irc, jab, rss, lj, gg or infocard") << endl;
1696 
1697     cout << _("  -t, --to <destination>   destination UIN or nick (depends on protocol)") << endl;
1698     cout << _("  -n, --number <phone#>    mobile number to send an event to (sms only)") << endl;
1699 
1700     cout << endl << _("Report bugs to http://bugzilla.centerim.org/.") << endl;
1701 }
1702 
setproxy()1703 void icqconf::setproxy() {
1704     if(getproxyconnect()) {
1705 	cw_setproxy(gethttpproxyhost().c_str(), gethttpproxyport(),
1706 	    gethttpproxyuser().c_str(),
1707 	    gethttpproxypasswd().c_str());
1708 
1709     } else {
1710 	cw_setproxy(0, 0, 0, 0);
1711 
1712     }
1713 }
1714 
setmakelog(bool slog)1715 void icqconf::setmakelog(bool slog) {
1716     makelog = slog;
1717 }
1718 
setproxyconnect(bool sproxy)1719 void icqconf::setproxyconnect(bool sproxy) {
1720     proxyconnect = sproxy;
1721     setproxy();
1722 }
1723 
setproxyssl(bool sproxyssl)1724 void icqconf::setproxyssl(bool sproxyssl) {
1725     proxyssl = sproxyssl;
1726 }
1727 
setgroupmode(icqconf::groupmode amode)1728 void icqconf::setgroupmode(icqconf::groupmode amode) {
1729     fgroupmode = amode;
1730 }
1731 
setsortmode(icqconf::sortmode smode)1732 void icqconf::setsortmode(icqconf::sortmode smode) {
1733     fsortmode = smode;
1734     icqcontacts::setsortmode(smode);
1735 }
1736 
initmultiproto(bool p[],string buf,bool excludenochat)1737 void icqconf::initmultiproto(bool p[], string buf, bool excludenochat) {
1738     string w;
1739     protocolname pname;
1740 
1741     for(pname = icq; pname != protocolname_size; pname++)
1742 	p[pname] = buf.empty();
1743 
1744     while(!(w = getword(buf)).empty()) {
1745 	for(pname = icq; pname != protocolname_size; pname++) {
1746 	    if(getprotocolname(pname) == w) {
1747 		if(excludenochat) {
1748 		    p[pname] = !gethook(pname).getCapabs().count(hookcapab::nochat);
1749 		} else {
1750 		    p[pname] = true;
1751 		}
1752 		break;
1753 	    }
1754 	}
1755     }
1756 }
1757 
setbrowser(const string & abrowser)1758 void icqconf::setbrowser(const string &abrowser) {
1759   if (!abrowser.empty())
1760     browser = abrowser;
1761   else
1762     browser = "mozilla";
1763 }
1764 
setsmtphost(const string & asmtphost)1765 void icqconf::setsmtphost(const string &asmtphost) {
1766     int pos;
1767 
1768     smtphost = "";
1769     smtpport = 0;
1770 
1771     if(!asmtphost.empty()) {
1772 	if((pos = asmtphost.find(":")) != -1) {
1773 	    smtphost = asmtphost.substr(0, pos);
1774 	    smtpport = atol(asmtphost.substr(pos+1).c_str());
1775 	} else {
1776 	    smtphost = asmtphost;
1777 	    smtpport = 25;
1778 	}
1779     }
1780 
1781     if(smtphost.empty() || !smtpport) {
1782 	smtphost = getsmtphost();
1783 	smtpport = getsmtpport();
1784     }
1785 }
1786 
sethttpproxyhost(const string & ahttpproxyhost)1787 void icqconf::sethttpproxyhost(const string &ahttpproxyhost) {
1788     int pos, posn;
1789 
1790     httpproxyhost = "";
1791     httpproxyport = 0;
1792     httpproxyuser = "";
1793     httpproxypasswd = "";
1794 
1795     if(!ahttpproxyhost.empty()) {
1796 	if((pos = ahttpproxyhost.find(":")) != -1) {
1797 	    if ((posn = ahttpproxyhost.find("@")) != -1) {
1798 		httpproxyuser = ahttpproxyhost.substr(0, pos);
1799 		httpproxypasswd = ahttpproxyhost.substr(pos+1, posn-pos-1);
1800 		if((pos = ahttpproxyhost.find(":", posn)) != -1) {
1801 		    httpproxyhost = ahttpproxyhost.substr(posn+1, pos-posn-1);
1802 		    httpproxyport = atol(ahttpproxyhost.substr(pos+1).c_str());
1803 		}
1804 	    } else {
1805 		httpproxyhost = ahttpproxyhost.substr(0, pos);
1806 		httpproxyport = atol(ahttpproxyhost.substr(pos+1).c_str());
1807 	    }
1808 	} else {
1809 	    httpproxyhost = ahttpproxyhost;
1810 	    httpproxyport = 8080;
1811 	}
1812     }
1813 
1814     setproxy();
1815 }
1816 
getbrowser() const1817 string icqconf::getbrowser() const {
1818   return browser.empty() ? "mozilla" : browser;
1819 }
1820 
getsmtphost() const1821 string icqconf::getsmtphost() const {
1822     return smtphost.empty() ? "localhost" : smtphost;
1823 }
1824 
getsmtpport() const1825 unsigned int icqconf::getsmtpport() const {
1826     return smtpport ? smtpport : 25;
1827 }
1828 
gethttpproxyhost() const1829 string icqconf::gethttpproxyhost() const {
1830     return httpproxyhost;
1831 }
1832 
gethttpproxyport() const1833 unsigned int icqconf::gethttpproxyport() const {
1834     return httpproxyport ? httpproxyport : 8080;
1835 }
1836 
gethttpproxyuser() const1837 string icqconf::gethttpproxyuser() const {
1838     return httpproxyuser;
1839 }
1840 
gethttpproxypasswd() const1841 string icqconf::gethttpproxypasswd() const {
1842     return httpproxypasswd;
1843 }
1844 
checkdiskspace()1845 void icqconf::checkdiskspace() {
1846     fenoughdiskspace = true;
1847 
1848 #if !(defined(__sun__) || defined(__NetBSD__) || defined(__sgi__))
1849     struct statfs st;
1850     if(!statfs(conf->getdirname().c_str(), &st)) {
1851 #else
1852     struct statvfs st;
1853     if(!statvfs(conf->getdirname().c_str(), &st)) {
1854 #endif
1855 	fenoughdiskspace = ((double) st.f_bavail) * st.f_bsize >= 10240;
1856     }
1857 }
1858 
1859 void icqconf::setcharsets(const string &from, const string &to) {
1860     fromcharset = from;
1861     tocharset = to;
1862 }
1863 
1864 const char *icqconf::getconvertfrom(protocolname pname) const {
1865     if(pname != protocolname_size && !getcpconvert(pname)) return "iso-8859-1";
1866     return fromcharset.c_str();
1867 }
1868 
1869 const char *icqconf::getconvertto(protocolname pname) const {
1870     if(pname != protocolname_size && !getcpconvert(pname)) return "iso-8859-1";
1871     return tocharset.c_str();
1872 }
1873 
1874 // ----------------------------------------------------------------------------
1875 
1876 icqconf::imaccount::imaccount() {
1877     uin = port = 0;
1878     pname = infocard;
1879 }
1880 
1881 icqconf::imaccount::imaccount(protocolname apname) {
1882     uin = port = 0;
1883     pname = apname;
1884 }
1885 
1886 bool icqconf::imaccount::empty() const {
1887     return !uin && nickname.empty();
1888 }
1889 
1890 void icqconf::imaccount::write(ofstream &f) {
1891     string prefix = conf->getprotocolname(pname) + "_";
1892     map<string, string>::iterator ia;
1893 
1894     f << endl;
1895     if(!nickname.empty()) f << prefix << "nick\t" << nickname << endl;
1896     if(uin) f << prefix << "uin\t" << uin << endl;
1897     if(conf->getsavepwd()) f << prefix << "pass\t" << password << endl;
1898     if(!server.empty()) {
1899 	f << prefix << "server\t" << server;
1900 	if(port) f << ":" << port;
1901 	f << endl;
1902     }
1903 
1904     for(ia = additional.begin(); ia != additional.end(); ++ia)
1905 	if(!ia->first.empty() && !ia->second.empty())
1906 	    f << prefix << ia->first << "\t" << ia->second << endl;
1907 }
1908 
1909 void icqconf::imaccount::read(const string &spec) {
1910     int pos = spec.find("_");
1911     string spname, buf;
1912 
1913     if(pos != -1) {
1914 	buf = spec;
1915 	spname = getword(buf.erase(0, pos+1));
1916 
1917 	if(spname == "nick") nickname = buf; else
1918 	if(spname == "uin") uin = strtoul(buf.c_str(), 0, 0); else
1919 	if(spname == "pass") password = buf; else
1920 	if(spname == "server") {
1921 	    if((pos = buf.find(":")) != -1) {
1922 		server = buf.substr(0, pos);
1923 		port = strtoul(buf.substr(pos+1).c_str(), 0, 0);
1924 	    } else {
1925 		server = buf;
1926 	    }
1927 
1928 	    if(pname == icq)
1929 	    if(server == "icq.mirabilis.com")
1930 		server = "";
1931 
1932 	    if(pname == yahoo)
1933 	    if(server == "scs.yahoo.com")
1934 		server = "";
1935 
1936 	} else {
1937 	    additional[spname] = buf;
1938 	}
1939     }
1940 }
1941 
1942 bool icqconf::imaccount::operator == (protocolname apname) const {
1943     return pname == apname;
1944 }
1945 
1946 bool icqconf::imaccount::operator != (protocolname apname) const {
1947     return pname != apname;
1948 }
1949