/* * Glue code between climm and it's ICQv8 protocol code. * * climm Copyright (C) © 2001-2007 Rüdiger Kuhlmann * * climm is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 dated June, 1991. * * climm is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public * License for more details. * * In addition, as a special exception permission is granted to link the * code of this release of climm with the OpenSSL project's "OpenSSL" * library, and distribute the linked executables. You must obey the GNU * General Public License in all respects for all of the code used other * than "OpenSSL". If you modify this file, you may extend this exception * to your version of the file, but you are not obligated to do so. If you * do not wish to do so, delete this exception statement from your version * of this file. * * You should have received a copy of the GNU General Public License * along with this package; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * $Id$ */ #include "climm.h" #include "contact.h" #include "connection.h" #include "oscar_snac.h" #include "oscar_roster.h" #include "oscar_contact.h" #include "preferences.h" #include "im_icq8.h" static void IMRosterCancel (Event *event) { if (event->data) OscarRosterD (event->data); event->data = NULL; EventD (event); } static RosterEntry *IMRosterGroup (Roster *roster, UWORD id) { RosterEntry *re; for (re = roster->groups; re; re = re->next) if (re->tag == id) return re; return NULL; } static Contact *IMRosterCheckCont (Server *serv, RosterEntry *rc) { Contact *cont; if (!serv || !rc) return NULL; cont = ContactScreen (serv, rc->name); if (!cont) return NULL; if (rc->type == roster_normal) { OptSetVal (&cont->copts, CO_ISSBL, 1); if (rc->reqauth) OptSetVal (&cont->copts, CO_ASK_SBL, 1); else { OptSetVal (&cont->copts, CO_FROM_SBL, 1); OptSetVal (&cont->copts, CO_TO_SBL, 1); } } ContactIDSet (cont, rc->type, rc->id, rc->tag); return cont; } static ContactGroup *IMRosterCheckGroup (Server *serv, RosterEntry *rg) { ContactGroup *cg, *tcg; if (!serv || !rg) return NULL; cg = ContactGroupFind (serv, 0, rg->name); if (!cg) cg = ContactGroupFind (serv, rg->tag, NULL); if (!cg) return NULL; OptSetVal (&cg->copts, CO_ISSBL, 1); cg->id = 0; if ((tcg = ContactGroupFind (serv, rg->tag, NULL))) { OptSetVal (&cg->copts, CO_ISSBL, 0); tcg->id = 0; } cg->id = rg->tag; return cg; } static void IMRosterDoDelete (Event *event) { Roster *roster = event->data; RosterEntry *re; Server *serv = event->conn->serv; if (!roster) return; if (roster->delname) { for (re = roster->groups; re; re = re->next) if (!strcmp (re->name, roster->delname) || (re->nick && !strcmp (re->nick, roster->delname))) SnacCliRosterentrydelete (serv, re); for (re = roster->ignore; re; re = re->next) if (!strcmp (re->name, roster->delname) || (re->nick && !strcmp (re->nick, roster->delname))) SnacCliRosterentrydelete (serv, re); for (re = roster->invisible; re; re = re->next) if (!strcmp (re->name, roster->delname) || (re->nick && !strcmp (re->nick, roster->delname))) SnacCliRosterentrydelete (serv, re); for (re = roster->visible; re; re = re->next) if (!strcmp (re->name, roster->delname) || (re->nick && !strcmp (re->nick, roster->delname))) SnacCliRosterentrydelete (serv, re); for (re = roster->normal; re; re = re->next) if (!strcmp (re->name, roster->delname) || (re->nick && !strcmp (re->nick, roster->delname))) SnacCliRosterentrydelete (serv, re); for (re = roster->generic; re; re = re->next) if (!strcmp (re->name, roster->delname) || (re->nick && !strcmp (re->nick, roster->delname))) SnacCliRosterentrydelete (serv, re); } else { for (re = roster->groups; re; re = re->next) if (re->tag == roster->deltag && re->id == roster->delid) SnacCliRosterentrydelete (serv, re); for (re = roster->ignore; re; re = re->next) if (re->tag == roster->deltag && re->id == roster->delid) SnacCliRosterentrydelete (serv, re); for (re = roster->invisible; re; re = re->next) if (re->tag == roster->deltag && re->id == roster->delid) SnacCliRosterentrydelete (serv, re); for (re = roster->visible; re; re = re->next) if (re->tag == roster->deltag && re->id == roster->delid) SnacCliRosterentrydelete (serv, re); for (re = roster->normal; re; re = re->next) if (re->tag == roster->deltag && re->id == roster->delid) SnacCliRosterentrydelete (serv, re); for (re = roster->generic; re; re = re->next) if (re->tag == roster->deltag && re->id == roster->delid) SnacCliRosterentrydelete (serv, re); } IMRosterCancel (event); } static void IMRosterShow (Event *event) { Roster *roster = event->data; RosterEntry *rg, *rc; Server *serv = event->conn->serv; Contact *cont = NULL; int cnt_groups = 0, cnt_ignored = 0, cnt_hidden = 0, cnt_intimate = 0, cnt_normal = 0; if (!roster) return; rl_printf (i18n (2535, "Groups:\n")); for (rg = roster->groups; rg; rg = rg->next) { IMRosterCheckGroup (serv, rg); if (prG->verbose) rl_printf (" %6d", rg->tag); rl_printf (" %s%s%s\n", COLCONTACT, rg && rg->name ? rg->name : "", COLNONE); cnt_groups++; } rl_printf (i18n (2473, "Normal contacts:\n")); for (rc = roster->normal; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); if (prG->verbose) rl_printf (" %6d", rc->tag); rl_printf (" %s%-25s%s %s%15s%s", COLCONTACT, rg && rg->name ? rg->name : "", COLNONE, COLCONTACT, rc->name, COLNONE); if (prG->verbose) rl_printf (" %6d", rc->id); rl_printf (" %s%s%s\n", COLCONTACT, rc->nick ? rc->nick : "", COLNONE); if (cont) cnt_normal++; } rl_printf (i18n (2471, "Ignored contacts:\n")); for (rc = roster->ignore; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); if (prG->verbose) rl_printf (" %6d", rc->tag); rl_printf (" %s%-25s%s %s%15s%s", COLCONTACT, rg && rg->name ? rg->name : "", COLNONE, COLCONTACT, rc->name, COLNONE); if (prG->verbose) rl_printf (" %6d", rc->id); rl_printf (" %s%s%s\n", COLCONTACT, rc->nick ? rc->nick : "", COLNONE); if (cont) cnt_ignored++; } rl_printf (i18n (2472, "Hidden-from contacts:\n")); for (rc = roster->invisible; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); if (prG->verbose) rl_printf (" %6d", rc->tag); rl_printf (" %s%-25s%s %s%15s%s", COLCONTACT, rg && rg->name ? rg->name : "", COLNONE, COLCONTACT, rc->name, COLNONE); if (prG->verbose) rl_printf (" %6d", rc->id); rl_printf (" %s%s%s\n", COLCONTACT, rc->nick ? rc->nick : "", COLNONE); if (cont) cnt_hidden++; } rl_printf (i18n (2474, "Intimate contacts:\n")); for (rc = roster->visible; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); if (prG->verbose) rl_printf (" %6d", rc->tag); rl_printf (" %s%-25s%s %s%15s%s", COLCONTACT, rg && rg->name ? rg->name : "", COLNONE, COLCONTACT, rc->name, COLNONE); if (prG->verbose) rl_printf (" %6d", rc->id); rl_printf (" %s%s%s\n", COLCONTACT, rc->nick ? rc->nick : "", COLNONE); if (cont) cnt_intimate++; } IMRosterCancel (event); rl_printf (i18n (2475, "Showed %d contact groups, alltogether %d contacts, %d ignored, %d hidden, %d intimate.\n"), cnt_groups, cnt_ignored + cnt_hidden + cnt_intimate + cnt_normal, cnt_ignored, cnt_hidden, cnt_intimate); } static void IMRosterDownCont (Server *serv, Roster *roster, ContactGroup *cg, RosterEntry *rc, int *pcnt, int *pmod, char force, UDWORD flag) { ContactGroup *tcg = NULL; Contact *cont; RosterEntry *rg; char mod = 0; char cnt = 0; rg = IMRosterGroup (roster, rc->tag); cont = IMRosterCheckCont (serv, rc); rl_printf (" %s%-25s%s %s%15s%s %s%s%s\n", COLCONTACT, rg && rg->name ? rg->name : "", COLNONE, COLCONTACT, rc->name, COLNONE, COLCONTACT, rc->nick ? rc->nick : "", COLNONE); if (!cont) return; if (!cont->group) { ContactCreate (serv, cont); ContactAdd (cg, cont); OptSetVal (&cont->copts, CO_IGNORE, flag == CO_IGNORE); OptSetVal (&cont->copts, CO_HIDEFROM, flag == CO_HIDEFROM); OptSetVal (&cont->copts, CO_INTIMATE, flag == CO_INTIMATE); mod = cnt = 1; (*pcnt)++; } else if (force) { if (ContactPrefVal (cont, CO_LOCAL)) { OptSetVal (&cont->copts, CO_LOCAL, 0); mod = 1; } if (ContactPrefVal (cont, CO_IGNORE) != (flag == CO_IGNORE)) { OptSetVal (&cont->copts, CO_IGNORE, flag == CO_IGNORE); mod = 1; } if (ContactPrefVal (cont, CO_HIDEFROM) != (flag == CO_HIDEFROM)) { OptSetVal (&cont->copts, CO_HIDEFROM, flag == CO_HIDEFROM); mod = 1; } if (ContactPrefVal (cont, CO_INTIMATE) != (flag == CO_INTIMATE)) { OptSetVal (&cont->copts, CO_INTIMATE, flag == CO_INTIMATE); mod = 1; } } if (rg) tcg = IMRosterCheckGroup (serv, rg); if (tcg && !ContactHas (tcg, cont) && (force || cont->group == serv->contacts)) { ContactAdd (tcg, cont); cont->group = tcg; mod = 1; } ContactAddAlias (cont, rc->name); if (rc->nick && strcmp (rc->nick, rc->name) && !ContactFindAlias (cont, rc->nick)) { ContactAddAlias (cont, rc->nick); mod = 1; } if (mod && !cnt) (*pmod)++; } static void IMRosterAdddown (Event *event) { Roster *roster = event->data; RosterEntry *rg, *rc; Server *serv = event->conn->serv; ContactGroup *cg; int cnt_groups = 0, cnt_ignored = 0, cnt_hidden = 0, cnt_intimate = 0, cnt_normal = 0; int mod_groups = 0, mod_ignored = 0, mod_hidden = 0, mod_intimate = 0, mod_normal = 0; if (!roster) return; for (rg = roster->groups; rg; rg = rg->next) { cg = IMRosterCheckGroup (serv, rg); if (!cg) { cg = ContactGroupC (serv, rg->tag, rg->name); OptSetVal (&cg->copts, CO_ISSBL, 1); rl_printf (i18n (2737, "Added contact group %s (#%d).\n"), rg->name, rg->tag); cnt_groups++; } else if (cg && strcmp (rg->name, cg->name)) { s_repl (&cg->name, rg->name); mod_groups++; } } cg = ContactGroupC (NULL, 0, ""); rl_printf (i18n (2473, "Normal contacts:\n")); for (rc = roster->normal; rc; rc = rc->next) IMRosterDownCont (serv, roster, cg, rc, &cnt_normal, &mod_normal, FALSE, 0); rl_printf (i18n (2471, "Ignored contacts:\n")); for (rc = roster->ignore; rc; rc = rc->next) IMRosterDownCont (serv, roster, cg, rc, &cnt_ignored, &mod_ignored, FALSE, CO_IGNORE); rl_printf (i18n (2472, "Hidden-from contacts:\n")); for (rc = roster->invisible; rc; rc = rc->next) IMRosterDownCont (serv, roster, cg, rc, &cnt_hidden, &mod_hidden, FALSE, CO_HIDEFROM); rl_printf (i18n (2474, "Intimate contacts:\n")); for (rc = roster->visible; rc; rc = rc->next) IMRosterDownCont (serv, roster, cg, rc, &cnt_intimate, &mod_intimate, FALSE, CO_INTIMATE); /* if (ContactIndex (cg, 0)) */ /* SnacCliAddcontact (serv, NULL, cg); */ IMRosterCancel (event); rl_printf (i18n (2476, "Downloaded %d contact groups, alltogether %d contacts, %d ignored, %d hidden, %d intimate.\n"), cnt_groups, cnt_ignored + cnt_hidden + cnt_intimate + cnt_normal, cnt_ignored, cnt_hidden, cnt_intimate); rl_printf (i18n (2578, "Modified %d contact groups, alltogether %d contacts, %d ignored, %d hidden, %d intimate.\n"), mod_groups, mod_ignored + mod_hidden + mod_intimate + mod_normal, mod_ignored, mod_hidden, mod_intimate); } static void IMRosterOverwritedown (Event *event) { Roster *roster = event->data; RosterEntry *rg, *rc; Server *serv = event->conn->serv; ContactGroup *cg; int cnt_groups = 0, cnt_ignored = 0, cnt_hidden = 0, cnt_intimate = 0, cnt_normal = 0; int mod_groups = 0, mod_ignored = 0, mod_hidden = 0, mod_intimate = 0, mod_normal = 0; if (!roster) return; for (rg = roster->groups; rg; rg = rg->next) { cg = IMRosterCheckGroup (serv, rg); if (!cg) { cg = ContactGroupC (serv, rg->tag, rg->name); OptSetVal (&cg->copts, CO_ISSBL, 1); rl_printf (i18n (2737, "Added contact group %s (#%d).\n"), rg->name, rg->tag); cnt_groups++; } else if (strcmp (rg->name, cg->name)) { s_repl (&cg->name, rg->name); mod_groups++; } } cg = ContactGroupC (NULL, 0, ""); rl_printf (i18n (2473, "Normal contacts:\n")); for (rc = roster->normal; rc; rc = rc->next) IMRosterDownCont (serv, roster, cg, rc, &cnt_intimate, &mod_intimate, TRUE, 0); rl_printf (i18n (2471, "Ignored contacts:\n")); for (rc = roster->ignore; rc; rc = rc->next) IMRosterDownCont (serv, roster, cg, rc, &cnt_ignored, &mod_ignored, TRUE, CO_IGNORE); rl_printf (i18n (2472, "Hidden-from contacts:\n")); for (rc = roster->invisible; rc; rc = rc->next) IMRosterDownCont (serv, roster, cg, rc, &cnt_hidden, &mod_hidden, TRUE, CO_HIDEFROM); rl_printf (i18n (2474, "Intimate contacts:\n")); for (rc = roster->visible; rc; rc = rc->next) IMRosterDownCont (serv, roster, cg, rc, &cnt_normal, &mod_normal, TRUE, CO_INTIMATE); /* if (ContactIndex (cg, 0)) */ /* SnacCliAddcontact (serv, NULL, cg); */ IMRosterCancel (event); rl_printf (i18n (2476, "Downloaded %d contact groups, alltogether %d contacts, %d ignored, %d hidden, %d intimate.\n"), cnt_groups, cnt_ignored + cnt_hidden + cnt_intimate + cnt_normal, cnt_ignored, cnt_hidden, cnt_intimate); rl_printf (i18n (2578, "Modified %d contact groups, alltogether %d contacts, %d ignored, %d hidden, %d intimate.\n"), mod_groups, mod_ignored + mod_hidden + mod_intimate + mod_normal, mod_ignored, mod_hidden, mod_intimate); } static void IMRosterAddup (Event *event) { Roster *roster = event->data; RosterEntry *rg, *rc; Server *serv = event->conn->serv; ContactGroup *cg, *tcg; Contact *cont; int i, cnt_groups = 0, cnt_normal = 0; if (!roster) return; for (rg = roster->groups; rg; rg = rg->next) cg = IMRosterCheckGroup (serv, rg); for (i = 0; (cg = ContactGroupIndex (i)); i++) if (cg->serv == serv && !ContactGroupPrefVal (cg, CO_ISSBL)) if (ContactGroupPrefVal (cg, CO_WANTSBL)) { cnt_groups++; SnacCliRosteraddgroup (serv, cg, 3); } for (rc = roster->ignore; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); } for (rc = roster->invisible; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); } cg = ContactGroupC (NULL, 0, ""); for (rc = roster->normal; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); tcg = IMRosterCheckGroup (serv, rg); if (tcg && cont->group && tcg != cont->group && tcg == cont->group->serv->contacts) ContactAdd (cg, cont); } SnacCliRosterbulkmove (serv, cg, 3); ContactGroupD (cg); for (rc = roster->visible; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); } cg = ContactGroupC (NULL, 0, ""); for (i = 0; (cont = ContactIndex (serv->contacts, i)); i++) if (!ContactPrefVal (cont, CO_ISSBL)) if (ContactPrefVal (cont, CO_WANTSBL) && !ContactPrefVal (cont, CO_IGNORE) && cnt_normal < 25) { cnt_normal++; OptSetVal (&cont->copts, CO_ASK_SBL, 1); OptSetVal (&cont->copts, CO_TO_SBL, 0); OptSetVal (&cont->copts, CO_FROM_SBL, 0); ContactAdd (cg, cont); } if (ContactIndex (cg, 0)) SnacCliRosterbulkadd (serv, cg); IMRosterCancel (event); rl_printf (i18n (2477, "Uploading %d contact groups and %d contacts.\n"), cnt_groups, cnt_normal); } static void IMRosterDiff (Event *event) { Roster *roster = event->data; RosterEntry *rg, *rc; Server *serv = event->conn->serv; ContactGroup *cg, *tcg; Contact *cont; int i, cnt_more = 0, cnt_auto = 0; int cnt_groups = 0, cnt_ignored = 0, cnt_hidden = 0, cnt_intimate = 0, cnt_normal = 0; if (!roster) return; for (rg = roster->groups; rg; rg = rg->next) { cg = IMRosterCheckGroup (serv, rg); if (!cg) { rl_printf (i18n (2694, "Group %s (#%d) exists only on the server.\n"), rg->name, rg->id); cnt_groups++; } else if (cg && strcmp (rg->name, cg->name)) { rl_printf (i18n (2695, "Group %s (#%d) on the server is group %s (#%d) locally.\n"), rg->name, rg->id, cg->name, cg->id); cnt_groups++; } } for (i = 0; (cg = ContactGroupIndex (i)); i++) if (cg->serv == serv && !ContactGroupPrefVal (cg, CO_ISSBL)) { rl_printf (i18n (2696, "Group %s (#%d) exists only locally.\n"), cg->name, cg->id); cnt_groups++; } for (rc = roster->ignore; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); if (!cont || !cont->group || (!ContactPrefVal (cont, CO_IGNORE) && ContactPrefVal (cont, CO_WANTSBL))) { rl_printf (i18n (2697, "Contact %s/%s exists only on the server as ignored (#%d).\n"), rc->name, rc->nick ? rc->nick : rc->name, rc->id); cnt_ignored++; } } for (rc = roster->invisible; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); if (!cont || !cont->group) { rl_printf (i18n (2698, "Contact %s/%s exists only on the server as invisible (#%d).\n"), rc->name, rc->nick ? rc->nick : rc->name, rc->id); cnt_hidden++; } else if (!ContactPrefVal (cont, CO_HIDEFROM) && ContactPrefVal (cont, CO_WANTSBL)) { rl_printf (i18n (2699, "Contact %s/%s is invisible (#%d) on the server, but locally (#%d) normal.\n"), rc->name, cont->screen, rc->id, ContactID (cont, roster_normal)->id); cnt_hidden++; } } for (rc = roster->visible; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); if (!cont || !cont->group) { rl_printf (i18n (2700, "Contact %s/%s exists only on the server as visible (#%d).\n"), rc->name, rc->nick ? rc->nick : rc->name, rc->id); cnt_intimate++; } else if (!ContactPrefVal (cont, CO_INTIMATE) && ContactPrefVal (cont, CO_WANTSBL)) { rl_printf (i18n (2701, "Contact %s/%s is visible (#%d) on the server, but locally (#%d) normal.\n"), rc->name, cont->screen, rc->id, ContactID (cont, roster_normal)->id); cnt_intimate++; } } for (rc = roster->normal; rc; rc = rc->next) { cont = IMRosterCheckCont (serv, rc); rg = IMRosterGroup (roster, rc->tag); if (!cont || !cont->group) { rl_printf (i18n (2702, "Contact %s/%s exists only on the server (#%d).\n"), rc->name, rc->nick ? rc->nick : rc->name, rc->id); cnt_normal++; continue; } if (!ContactPrefVal (cont, CO_WANTSBL)) continue; if (strcmp (rc->name, cont->screen)) { rl_printf (i18n (2703, "Contact %s (#%d) is screen name %s (#%d) locally. Huh??\n"), rc->name, rc->id, cont->screen, ContactID (cont, roster_normal)->id); cnt_normal++; } if (strcmp (rc->nick ? rc->nick : rc->name, cont->nick)) { rl_printf (i18n (2704, "Contact %s is %s (#%d) on the server and %s (#%d) locally.\n"), cont->screen, rc->nick ? rc->nick : rc->name, rc->id, cont->nick, ContactID (cont, roster_normal)->id); cnt_normal++; } if (ContactPrefVal (cont, CO_HIDEFROM) && !ContactID (cont, roster_invisible)->issbl) { rl_printf (i18n (2705, "Contact %s/%s is normal (#%d) on the server, but invisible (#%d,#%d) locally.\n"), cont->screen, cont->nick, rc->id, ContactID (cont, roster_normal)->id, ContactID (cont, roster_invisible)->id); cnt_hidden++; } if (ContactPrefVal (cont, CO_INTIMATE) && !ContactID (cont, roster_visible)->issbl) { rl_printf (i18n (2706, "Contact %s/%s is normal (#%d) on the server, but visible (#%d,#%d) locally.\n"), cont->screen, cont->nick, rc->id, ContactID (cont, roster_normal)->id, ContactID (cont, roster_visible)->id); cnt_intimate++; } if (ContactPrefVal (cont, CO_IGNORE) && !ContactID (cont, roster_ignore)->issbl) { rl_printf (i18n (2710, "Contact %s/%s is normal (#%d) on the server, but ignored (#%d,#%d) locally.\n"), cont->screen, cont->nick, rc->id, ContactID (cont, roster_normal)->id, ContactID (cont, roster_ignore)->id); cnt_ignored++; } if (rg->tag != cont->group->id) { tcg = IMRosterCheckGroup (serv, rg); if (tcg && cont->group && tcg != cont->group && tcg == cont->group->serv->contacts) cnt_auto++; rl_printf (i18n (2707, "Contact %s/%s (#%d) is in group %s (#%d) on the server, but in group %s (#%d) locally.\n"), cont->screen, cont->nick, rc->id, rg && rg->name ? rg->name : "?", rg->tag, cont->group == serv->contacts ? "(none)" : cont->group->name, cont->group->id); cnt_normal++; } } for (i = 0; (cont = ContactIndex (serv->contacts, i)); i++) if (ContactPrefVal (cont, CO_WANTSBL) && (!ContactID (cont, roster_normal)->issbl || !ContactPrefVal (cont, CO_ISSBL))) { rl_printf (i18n (2708, "Contact %s/%s (#%d) exists only locally.\n"), cont->screen, cont->nick, ContactID (cont, roster_normal)->id); cnt_more++; } IMRosterCancel (event); rl_printf (i18n (2491, "Differences in %d contact groups, alltogether %d contacts, %d ignored, %d hidden, %d intimate, %d local.\n"), cnt_groups, cnt_ignored + cnt_hidden + cnt_intimate + cnt_normal + cnt_more, cnt_ignored, cnt_hidden, cnt_intimate, cnt_more); if (prG->autoupdate == 5) { if (cnt_more || cnt_auto) IMRoster (serv, IMROSTER_UPLOAD); else prG->autoupdate++; } } UBYTE IMDeleteID (Server *serv, int tag, int id, const char *name) { Roster *roster; roster = OscarRosterC (); roster->deltag = tag; roster->delid = id; roster->delname = name ? strdup (name) : NULL; QueueEnqueueData2 (serv->conn, QUEUE_REQUEST_ROSTER, SnacCliCheckroster (serv), 900, roster, IMRosterDoDelete, IMRosterCancel); return RET_OK; } UBYTE IMRoster (Server *serv, int mode) { ContactGroup *cg; ContactIDs *ids; Contact *cont; int i; for (i = 0, cg = serv->contacts; (cont = ContactIndex (cg, i)); i++) { OptSetVal(&cont->copts, CO_ISSBL, 0); OptSetVal(&cont->copts, CO_TO_SBL, 0); OptSetVal(&cont->copts, CO_FROM_SBL, 0); OptSetVal(&cont->copts, CO_ASK_SBL, 0); for (ids = cont->ids; ids; ids = ids->next) ids->issbl = 0; } for (i = 0; (cg = ContactGroupIndex (i)); i++) if (cg->serv == serv) OptSetVal (&cg->copts, CO_ISSBL, 0); switch (mode) { case IMROSTER_IMPORT: QueueEnqueueData2 (serv->conn, QUEUE_REQUEST_ROSTER, SnacCliCheckroster (serv), 900, NULL, IMRosterOverwritedown, IMRosterCancel); break; case IMROSTER_DOWNLOAD: QueueEnqueueData2 (serv->conn, QUEUE_REQUEST_ROSTER, SnacCliCheckroster (serv), 900, NULL, IMRosterAdddown, IMRosterCancel); break; case IMROSTER_EXPORT: case IMROSTER_UPLOAD: QueueEnqueueData2 (serv->conn, QUEUE_REQUEST_ROSTER, SnacCliCheckroster (serv), 900, NULL, IMRosterAddup, IMRosterCancel); break; case IMROSTER_DIFF: QueueEnqueueData2 (serv->conn, QUEUE_REQUEST_ROSTER, SnacCliCheckroster (serv), 900, NULL, IMRosterDiff, IMRosterCancel); break; case IMROSTER_SYNC: case IMROSTER_SHOW: QueueEnqueueData2 (serv->conn, QUEUE_REQUEST_ROSTER, SnacCliCheckroster (serv), 900, NULL, IMRosterShow, IMRosterCancel); return RET_OK; } return RET_DEFER; }