3 * centerim IM protocol abstraction class
4 * $Id: abstracthook.cc,v 1.58 2004/11/09 23:49:59 konst Exp $
6 * Copyright (C) 2001,2002,2003 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 "abstracthook.h"
28 #include "yahoohook.h"
31 #include "jabberhook.h"
36 #include "icqcontacts.h"
46 time_t timer_current
= time(0);
48 abstracthook::abstracthook(protocolname aproto
)
49 : proto(aproto
), searchdest(0)
52 abstracthook::~abstracthook() {
55 void abstracthook::init() {
58 void abstracthook::connect() {
61 void abstracthook::disconnect() {
64 void abstracthook::exectimers() {
67 void abstracthook::main() {
70 void abstracthook::setautostatus(imstatus st
) {
73 void abstracthook::restorestatus() {
74 setautostatus(manualstatus
);
77 void abstracthook::setstatus(imstatus st
) {
78 setautostatus(manualstatus
= st
);
80 for(protocolname pname
= icq
; pname
!= protocolname_size
; pname
++) {
81 if(&gethook(pname
) == this) {
82 conf
->savestatus(pname
, manualstatus
);
88 void abstracthook::getsockets(fd_set
&rfds
, fd_set
&wfds
, fd_set
&efds
, int &hsocket
) const {
91 bool abstracthook::isoursocket(fd_set
&rfds
, fd_set
&wfds
, fd_set
&efds
) const {
95 bool abstracthook::online() const {
99 bool abstracthook::logged() const {
103 bool abstracthook::isconnecting() const {
107 bool abstracthook::enabled() const {
111 bool abstracthook::send(const imevent
&ev
) {
115 void abstracthook::sendnewuser(const imcontact
&c
) {
118 imstatus
abstracthook::getstatus() const {
122 bool abstracthook::isdirectopen(const imcontact
&c
) const {
126 void abstracthook::removeuser(const imcontact
&ic
) {
129 void abstracthook::requestinfo(const imcontact
&c
) {
132 void abstracthook::lookup(const imsearchparams
¶ms
, verticalmenu
&dest
) {
135 void abstracthook::stoplookup() {
139 void abstracthook::requestawaymsg(const imcontact
&c
) {
142 void abstracthook::ouridchanged(const icqconf::imaccount
&ia
) {
145 void abstracthook::requestversion(const imcontact
&c
) {
148 void abstracthook::ping(const imcontact
&c
) {
151 bool abstracthook::knowntransfer(const imfile
&fr
) const {
155 void abstracthook::replytransfer(const imfile
&fr
, bool accept
, const string
&localpath
) {
158 void abstracthook::aborttransfer(const imfile
&fr
) {
161 void abstracthook::conferencecreate(const imcontact
&confid
,
162 const vector
<imcontact
> &lst
) {
165 vector
<string
> abstracthook::getservices(servicetype::enumeration st
) const {
166 return vector
<string
>();
169 vector
<pair
< string
, string
> > abstracthook::getsearchparameters(const string
&agentname
) const {
170 return vector
<pair
<string
, string
> >();
173 vector
<pair
<string
, string
> > abstracthook::getregparameters(const string
&agentname
) const {
174 return vector
<pair
<string
, string
> >();
177 void abstracthook::updatecontact(icqcontact
*c
) {
180 void abstracthook::renamegroup(const string
&oldname
, const string
&newname
) {
183 string
abstracthook::rushtmlconv(const string
&tdir
, const string
&text
, bool rus
) {
185 string r
= rus
? rusconv(tdir
, text
) : text
;
187 if(tdir
== "kw" || tdir
== "ku") {
189 while((pos
= r
.find_first_of("&<>", pos
)) != -1) {
192 if(r
.substr(pos
, 4) != "<"
193 && r
.substr(pos
, 4) != ">")
194 r
.replace(pos
, 1, "&");
196 case '<': r
.replace(pos
, 1, "<"); break;
197 case '>': r
.replace(pos
, 1, ">"); break;
202 } else if(tdir
== "wk" || tdir
== "uk") {
204 while((pos
= r
.find("&", pos
)) != -1) {
205 if(r
.substr(pos
+1, 4) == "amp;") r
.replace(pos
, 5, "&"); else
206 if(r
.substr(pos
+1, 3) == "lt;") r
.replace(pos
, 4, "<"); else
207 if(r
.substr(pos
+1, 3) == "gt;") r
.replace(pos
, 4, ">"); else
208 if(r
.substr(pos
+1, 5) == "#150;") r
.replace(pos
, 6, "-"); else
209 if(r
.substr(pos
+1, 5) == "#151;") r
.replace(pos
, 6, "--"); else
210 if(r
.substr(pos
+1, 5) == "#146;") r
.replace(pos
, 6, "`"); else
211 if(r
.substr(pos
+1, 4) == "#39;") r
.replace(pos
, 5, "'"); else
212 if(r
.substr(pos
+1, 6) == "#8211;") r
.replace(pos
, 7, "--"); else
213 if(r
.substr(pos
+1, 6) == "#8230;") r
.replace(pos
, 7, "..."); else
214 if(r
.substr(pos
+1, 7) == "hellip;") r
.replace(pos
, 8, "..."); else
215 if(r
.substr(pos
+1, 6) == "laquo;") r
.replace(pos
, 7, "<<"); else
216 if(r
.substr(pos
+1, 6) == "raquo;") r
.replace(pos
, 7, ">>"); else
217 if(r
.substr(pos
+1, 6) == "bdquo;") r
.replace(pos
, 7, "\""); else
218 if(r
.substr(pos
+1, 6) == "ldquo;") r
.replace(pos
, 7, "\""); else
219 if(r
.substr(pos
+1, 5) == "copy;") r
.replace(pos
, 8, "(c)"); else
220 if(r
.substr(pos
+1, 4) == "#13;") r
.replace(pos
, 5, "\r"); else
221 if(r
.substr(pos
+1, 4) == "#10;") r
.replace(pos
, 5, "\n");
229 string
abstracthook::ruscrlfconv(const string
&tdir
, const string
&text
) {
230 string r
= rusconv(tdir
, text
);
233 for(pos
= 0; (pos
= r
.find("\r")) != -1; pos
++) {
240 string
abstracthook::rusconv(const string
&tdir
, const string
&text
) {
243 if(!conf
->getcpconvert(proto
) && tdir
.find("u") == -1)
247 if(tdir
== "kw") r
= siconv(text
, conf
->getconvertto(proto
), conf
->getconvertfrom(proto
)); else
248 if(tdir
== "wk") r
= siconv(text
, conf
->getconvertfrom(proto
), conf
->getconvertto(proto
)); else
249 if(tdir
== "ku") r
= siconv(text
, conf
->getconvertto(proto
), "utf-8"); else
250 if(tdir
== "uk") r
= siconv(text
, "utf-8", conf
->getconvertto(proto
)); else
251 if(tdir
== "ck") r
= siconv(text
, "UCS-2BE", conf
->getconvertto(proto
)); else
256 static unsigned char kw
[] = {
257 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
258 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
259 160,161,162,184,164,165,166,167,168,169,170,171,172,173,174,175,
260 176,177,178,168,180,181,182,183,184,185,186,187,188,189,190,191,
261 254,224,225,246,228,229,244,227,245,232,233,234,235,236,237,238,
262 239,255,240,241,242,243,230,226,252,251,231,248,253,249,247,250,
263 222,192,193,214,196,197,212,195,213,200,201,202,203,204,205,206,
264 207,223,208,209,210,211,198,194,220,219,199,216,221,217,215,218
267 static unsigned char wk
[] = {
268 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
269 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
270 160,161,162,163,164,165,166,167,179,169,170,171,172,173,174,175,
271 176,177,178,179,180,181,182,183,163,185,186,187,188,189,190,191,
272 225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240,
273 242,243,244,245,230,232,227,254,251,253,255,249,248,252,224,241,
274 193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208,
275 210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209
279 string::const_iterator i
;
280 unsigned char *table
= 0;
282 if(tdir
== "kw") table
= kw
; else
283 if(tdir
== "wk") table
= wk
;
288 for(i
= text
.begin(); i
!= text
.end(); ++i
) {
289 c
= (unsigned char) *i
;
291 if(c
& 0200) c
= table
[c
& 0177];
300 string
abstracthook::getmd5(const string
&text
) {
302 md5_byte_t digest
[16];
307 md5_append(&state
, (md5_byte_t
*) text
.c_str(), text
.size());
308 md5_finish(&state
, digest
);
310 for(int i
= 0; i
< 16; i
++) {
311 sprintf(buf
, "%02x", digest
[i
]);
318 void abstracthook::requestfromfound(const imcontact
&ic
) {
319 vector
<icqcontact
*>::const_iterator ig
= foundguys
.begin();
321 while(ig
!= foundguys
.end()) {
322 if((*ig
)->getdesc() == ic
) {
323 icqcontact
*rc
= clist
.get(ic
);
324 if(!rc
) rc
= clist
.get(contactroot
);
326 rc
->setnick((*ig
)->getnick());
327 rc
->setbasicinfo((*ig
)->getbasicinfo());
328 rc
->setmoreinfo((*ig
)->getmoreinfo());
329 rc
->setworkinfo((*ig
)->getworkinfo());
330 rc
->setinterests((*ig
)->getinterests());
331 rc
->setbackground((*ig
)->getbackground());
332 rc
->setabout((*ig
)->getabout());
341 bool abstracthook::regconnect(const string
&aserv
) {
345 bool abstracthook::regattempt(unsigned int &auin
, const string
&apassword
, const string
&email
) {
349 void abstracthook::log(logevent ev
, ...) {
352 static map
<logevent
, string
> lst
;
355 lst
[logConnecting
] = _("connecting to the server");
356 lst
[logLogged
] = _("logged in");
357 lst
[logSearchFinished
] = _("search finished, %d found");
358 lst
[logPasswordChanged
] = _("password was changed successfully");
359 lst
[logDisconnected
] = _("disconnected");
360 lst
[logContactAdd
] = _("adding %s to the contacts");
361 lst
[logContactRemove
] = _("removing %s from the contacts");
362 lst
[logConfMembers
] = _("members list fetching finished, %d found");
366 vsnprintf(buf
, NOTIFBUF
, lst
[ev
].c_str(), ap
);
369 face
.log((string
) "+ [" + conf
->getprotocolname(proto
) + "] " + buf
);
370 face
.xtermtitle((string
) "[" + conf
->getprotocolname(proto
) + "] " + buf
);
373 const unsigned short abstracthook::Country_table_size
= 243;
375 const abstracthook::Country_struct
abstracthook::Country_table
[Country_table_size
] = {
376 { "Unspecified", 0 },
377 { "Afghanistan", 93 },
380 { "American Samoa", 684 },
388 { "Ascension Island", 247 },
390 { "Australian Antarctic Territory", 6721 },
392 { "Azerbaijan", 994 },
395 { "Bangladesh", 880 },
405 { "Bosnia and Herzegovina", 387 },
408 { "British Virgin Islands", 106 },
411 { "Burkina Faso", 226 },
416 { "Cape Verde Islands", 238 },
417 { "Cayman Islands", 108 },
418 { "Central African Republic", 236 },
422 { "Christmas Island", 672 },
423 { "Cocos-Keeling Islands", 6101 },
427 { "Cook Islands", 682 },
428 { "Costa Rica", 506 },
432 { "Czech Republic", 42 },
434 { "Diego Garcia", 246 },
437 { "Dominican Republic", 110 },
440 { "El Salvador", 503 },
441 { "Equatorial Guinea", 240 },
445 { "Faeroe Islands", 298 },
446 { "Falkland Islands", 500 },
447 { "Fiji Islands", 679 },
450 { "French Antilles", 5901 },
451 { "French Guiana", 594 },
452 { "French Polynesia", 689 },
458 { "Gibraltar", 350 },
460 { "Greenland", 299 },
462 { "Guadeloupe", 590 },
464 { "Guantanamo Bay", 5399 },
465 { "Guatemala", 502 },
467 { "Guinea-Bissau", 245 },
471 { "Hong Kong", 852 },
473 { "INMARSAT (Atlantic-East)", 871 },
474 { "INMARSAT (Atlantic-West)", 874 },
475 { "INMARSAT (Indian)", 873 },
476 { "INMARSAT (Pacific)", 872 },
481 { "International Freephone Service", 800 },
487 { "Ivory Coast", 225 },
491 { "Kazakhstan", 705 },
493 { "Kiribati Republic", 686 },
494 { "Korea (North)", 850 },
495 { "Korea (Republic of)", 82 },
497 { "Kyrgyz Republic", 706 },
504 { "Liechtenstein", 4101 },
505 { "Lithuania", 370 },
506 { "Luxembourg", 352 },
508 { "Madagascar", 261 },
514 { "Marshall Islands", 692 },
515 { "Martinique", 596 },
516 { "Mauritania", 222 },
517 { "Mauritius", 230 },
518 { "Mayotte Island", 269 },
520 { "Micronesia, Federated States of", 691 },
524 { "Montserrat", 113 },
526 { "Mozambique", 258 },
531 { "Netherlands Antilles", 599 },
532 { "Netherlands", 31 },
534 { "New Caledonia", 687 },
535 { "New Zealand", 64 },
536 { "Nicaragua", 505 },
540 { "Norfolk Island", 6722 },
546 { "Papua New Guinea", 675 },
549 { "Philippines", 63 },
552 { "Puerto Rico", 121 },
554 { "Republic of Macedonia", 389 },
555 { "Reunion Island", 262 },
557 { "Rota Island", 6701 },
560 { "Saint Lucia", 122 },
561 { "Saipan Island", 670 },
562 { "San Marino", 378 },
563 { "Sao Tome and Principe", 239 },
564 { "Saudi Arabia", 966 },
565 { "Senegal Republic", 221 },
566 { "Seychelle Islands", 248 },
567 { "Sierra Leone", 232 },
569 { "Slovak Republic", 4201 },
571 { "Solomon Islands", 677 },
573 { "South Africa", 27 },
576 { "St. Helena", 290 },
577 { "St. Kitts", 115 },
578 { "St. Pierre and Miquelon", 508 },
579 { "St. Vincent and the Grenadines", 116 },
582 { "Swaziland", 268 },
584 { "Switzerland", 41 },
586 { "Taiwan, Republic of China", 886 },
587 { "Tajikistan", 708 },
590 { "Tinian Island", 6702 },
594 { "Trinidad and Tobago", 117 },
597 { "Turkmenistan", 709 },
598 { "Turks and Caicos Islands", 118 },
603 { "United Arab Emirates", 971 },
604 { "United Kingdom", 44 },
605 { "United States Virgin Islands", 123 },
607 { "Uzbekistan", 711 },
609 { "Vatican City", 379 },
612 { "Wallis and Futuna Islands", 681 },
613 { "Western Samoa", 685 },
615 { "Yugoslavia", 381 },
622 string
abstracthook::getCountryIDtoString(unsigned short id
) {
623 for(int n
= 0; n
< Country_table_size
; ++n
) {
624 if(Country_table
[n
].code
== id
) {
625 return Country_table
[n
].name
;
629 return Country_table
[0].name
;
632 unsigned short abstracthook::getCountryByName(string name
) {
634 name
= up(leadcut(trailcut(name
)));
636 for(i
= 0; i
< Country_table_size
; i
++)
637 if(name
== up(Country_table
[i
].name
))
638 return Country_table
[i
].code
;
643 signed char abstracthook::getSystemTimezone() {
645 struct tm
*tzone
= localtime(&t
);
649 nTimezone
= -(tzone
->tm_gmtoff
);
652 nTimezone
= _timezone
;
654 nTimezone
= timezone
;
658 nTimezone
+= (tzone
->tm_isdst
== 1 ? 3600 : 0);
661 if(nTimezone
> 23) return 23-nTimezone
;
663 return (signed char) nTimezone
;
666 static const unsigned char Interests_table_size
= 51;
667 static const unsigned char Interests_offset
= 100;
669 static const char* const Interests_table
[Interests_table_size
] = {
708 "Finance and Corporate",
710 "Consumer Electronics",
714 "Household Products",
715 "Mail Order Catalog",
718 "Sporting and Athletics",
723 string
abstracthook::getInterestsIDtoString(unsigned char id
) {
724 if(id
-Interests_offset
>= 0 && id
-Interests_offset
< Interests_table_size
) {
725 return Interests_table
[id
-Interests_offset
];
731 static const unsigned short Background_table_size
= 8;
733 static const struct {
737 } Background_table
[Background_table_size
] = {
738 { "University", 303 },
739 { "High school", 301 },
741 { "Elementary School", 300 },
742 { "Millitary", 304 },
744 { "Past Organization", 306 },
745 { "Past Work Place", 305 }
749 string
abstracthook::getBackgroundIDtoString(unsigned short id
) {
750 for(int n
= 0; n
< Background_table_size
; ++n
) {
751 if(id
== Background_table
[n
].code
) {
752 return Background_table
[n
].name
;
759 string
abstracthook::getTimezoneIDtoString(signed char id
) {
760 if(id
> 24 || id
< -24) {
761 return "Unspecified";
764 snprintf(buf
, sizeof(buf
), "GMT %s%d:%s", id
> 0 ? "-" : "+", abs(id
/2), id
% 2 == 0 ? "00" : "30");
769 string
abstracthook::getTimezonetoLocaltime(signed char id
) {
772 if(id
<= 24 && id
>= -24) {
773 time_t rt
= time(0) + getSystemTimezone()*1800;
781 const unsigned char abstracthook::Language_table_size
= 60;
783 const char* const abstracthook::Language_table
[Language_table_size
] = {
846 string
abstracthook::getLanguageIDtoString(unsigned char id
) {
847 if (id
>= Language_table_size
) {
848 return Language_table
[0];
850 return Language_table
[id
];
854 // ----------------------------------------------------------------------------
856 abstracthook
&gethook(protocolname pname
) {
857 static abstracthook
abshook(infocard
);
861 case icq
: return ihook
;
864 case yahoo
: return yhook
;
867 case aim
: return ahook
;
870 case irc
: return irhook
;
873 case jabber
: return jhook
;
876 case rss
: return rhook
;
879 case livejournal
: return lhook
;
882 case gadu
: return ghook
;
885 case msn
: return mhook
;
892 struct tm
*maketm(int hour
, int minute
, int day
, int month
, int year
) {
893 static struct tm msgtm
;
894 memset(&msgtm
, 0, sizeof(msgtm
));
895 msgtm
.tm_min
= minute
;
896 msgtm
.tm_hour
= hour
;
898 msgtm
.tm_mon
= month
-1;
899 msgtm
.tm_year
= year
-1900;