jabberd2  2.2.16
sm/mod_template_roster.c
Go to the documentation of this file.
00001 /*
00002  * jabberd - Jabber Open Source Server
00003  * Copyright (c) 2002-2003 Jeremie Miller, Thomas Muldowney,
00004  *                         Ryan Eatmon, Robert Norris
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
00019  */
00020 
00021 #include "sm.h"
00022 
00030 /* user template - roster */
00031 
00032 typedef struct _template_roster_st {
00033     sm_t    sm;
00034     char    *filename;
00035     time_t  mtime;
00036     xht     items;
00037 } *template_roster_t;
00038 
00039 /* union for xhash_iter_get to comply with strict-alias rules for gcc3 */
00040 union xhashv
00041 {
00042   void **val;
00043   item_t *item_val;
00044 };
00045 
00046 static int _template_roster_reload(template_roster_t tr) {
00047     struct stat st;
00048     FILE *f;
00049     long size;
00050     char *buf;
00051     nad_t nad;
00052     int nitems, eitem, ajid, as10n, aname, egroup;
00053     item_t item;
00054 
00055     if(stat(tr->filename, &st) < 0) {
00056         log_write(tr->sm->log, LOG_ERR, "couldn't stat roster template %s: %s", tr->filename, strerror(errno));
00057         return 1;
00058     }
00059 
00060     if(st.st_mtime <= tr->mtime)
00061         return 0;
00062 
00063     tr->mtime = st.st_mtime;
00064 
00065     if(tr->items != NULL)
00066         xhash_free(tr->items);
00067 
00068     tr->items = xhash_new(101);
00069 
00070     f = fopen(tr->filename, "r");
00071     if(f == NULL) {
00072         log_write(tr->sm->log, LOG_ERR, "couldn't open roster template %s: %s", tr->filename, strerror(errno));
00073         return 1;
00074     }
00075 
00076     fseek(f, 0, SEEK_END);
00077     size = ftell(f);
00078     fseek(f, 0, SEEK_SET);
00079 
00080     buf = (char *) malloc(sizeof(char) * size);
00081 
00082     if (fread(buf, 1, size, f) != size || ferror(f)) {
00083         log_write(tr->sm->log, LOG_ERR, "couldn't read from roster template %s: %s", tr->filename, strerror(errno));
00084         free(buf);
00085         fclose(f);
00086         return 1;
00087     }
00088 
00089     fclose(f);
00090 
00091     nad = nad_parse(buf, size);
00092     if(nad == NULL) {
00093         log_write(tr->sm->log, LOG_ERR, "couldn't parse roster template");
00094         free(buf);
00095         return 1;
00096     }
00097 
00098     free(buf);
00099 
00100     if(nad->ecur < 2) {
00101         log_write(tr->sm->log, LOG_NOTICE, "roster template has no elements");
00102     }
00103 
00104     nitems = 0;
00105     eitem = nad_find_elem(nad, 0, NAD_ENS(nad, 0), "item", 1);
00106     while(eitem >= 0) {
00107         ajid = nad_find_attr(nad, eitem, -1, "jid", NULL);
00108         if(ajid < 0) {
00109             log_write(tr->sm->log, LOG_ERR, "roster template has item with no jid, skipping");
00110             continue;
00111         }
00112         
00113         item = (item_t) pmalloco(xhash_pool(tr->items), sizeof(struct item_st));
00114 
00115         item->jid = jid_new(NAD_AVAL(nad, ajid), NAD_AVAL_L(nad, ajid));
00116         if(item->jid == NULL) {
00117             log_write(tr->sm->log, LOG_ERR, "roster template has item with invalid jid, skipping");
00118             continue;
00119         }
00120         pool_cleanup(xhash_pool(tr->items), (void (*)(void *)) jid_free, item->jid);
00121 
00122         as10n = nad_find_attr(nad, eitem, -1, "subscription", NULL);
00123         if(as10n >= 0) {
00124             if(NAD_AVAL_L(nad, as10n) == 2 && strncmp("to", NAD_AVAL(nad, as10n), 2) == 0)
00125                 item->to = 1;
00126             else if(NAD_AVAL_L(nad, as10n) == 4 && strncmp("from", NAD_AVAL(nad, as10n), 4) == 0)
00127                 item->from = 1;
00128             else if(NAD_AVAL_L(nad, as10n) == 4 && strncmp("both", NAD_AVAL(nad, as10n), 4) == 0)
00129                 item->to = item->from = 1;
00130         }
00131 
00132         aname = nad_find_attr(nad, eitem, -1, "name", NULL);
00133         if(aname >= 0)
00134             item->name = pstrdupx(xhash_pool(tr->items), NAD_AVAL(nad, aname), NAD_AVAL_L(nad, aname));
00135 
00136         egroup = nad_find_elem(nad, eitem, NAD_ENS(nad, 0), "group", 1);
00137         while(egroup >= 0) {
00138             if(NAD_CDATA_L(nad, egroup) <= 0) {
00139                 log_write(tr->sm->log, LOG_ERR, "roster template has zero-length group, skipping");
00140                 continue;
00141             }
00142 
00143             item->groups = (char **) realloc(item->groups, sizeof(char *) * (item->ngroups + 1));
00144             item->groups[item->ngroups] = pstrdupx(xhash_pool(tr->items), NAD_CDATA(nad, egroup), NAD_CDATA_L(nad, egroup));
00145             item->ngroups++;
00146 
00147             egroup = nad_find_elem(nad, egroup, NAD_ENS(nad, 0), "group", 0);
00148         }
00149 
00150         if(item->groups != NULL)
00151             pool_cleanup(xhash_pool(tr->items), free, item->groups);
00152 
00153         xhash_put(tr->items, jid_full(item->jid), item);
00154 
00155         log_debug(ZONE, "loaded roster template item %s, %d groups", jid_full(item->jid), item->ngroups);
00156 
00157         nitems++;
00158         
00159         eitem = nad_find_elem(nad, eitem, NAD_ENS(nad, 0), "item", 0);
00160     }
00161 
00162     log_write(tr->sm->log, LOG_NOTICE, "loaded %d items from roster template", nitems);
00163 
00164     return 0;
00165 }
00166 
00168 static void _template_roster_save_item(sm_t sm, jid_t jid, item_t item) {
00169     os_t os;
00170     os_object_t o;
00171     char filter[4096];
00172     int i;
00173 
00174     log_debug(ZONE, "saving roster item %s for %s", jid_full(item->jid), jid_user(jid));
00175 
00176     os = os_new();
00177     o = os_object_new(os);
00178 
00179     os_object_put(o, "jid", jid_full(item->jid), os_type_STRING);
00180 
00181     if(item->name != NULL)
00182         os_object_put(o, "name", item->name, os_type_STRING);
00183 
00184     os_object_put(o, "to", &item->to, os_type_BOOLEAN);
00185     os_object_put(o, "from", &item->from, os_type_BOOLEAN);
00186     os_object_put(o, "ask", &item->ask, os_type_INTEGER);
00187 
00188     snprintf(filter, 4096, "(jid=%zu:%s)", strlen(jid_full(item->jid)), jid_full(item->jid));
00189 
00190     storage_replace(sm->st, "roster-items", jid_user(jid), filter, os);
00191 
00192     os_free(os);
00193 
00194     snprintf(filter, 4096, "(jid=%zu:%s)", strlen(jid_full(item->jid)), jid_full(item->jid));
00195 
00196     if(item->ngroups == 0) {
00197         storage_delete(sm->st, "roster-groups", jid_user(jid), filter);
00198         return;
00199     }
00200 
00201     os = os_new();
00202     
00203     for(i = 0; i < item->ngroups; i++) {
00204         o = os_object_new(os);
00205 
00206         os_object_put(o, "jid", jid_full(item->jid), os_type_STRING);
00207         os_object_put(o, "group", item->groups[i], os_type_STRING);
00208     }
00209 
00210     storage_replace(sm->st, "roster-groups", jid_user(jid), filter, os);
00211 
00212     os_free(os);
00213 }
00214 
00215 static int _template_roster_user_create(mod_instance_t mi, jid_t jid) {
00216     template_roster_t tr = (template_roster_t) mi->mod->private;
00217     item_t item;
00218     union xhashv xhv;
00219 
00220     if(_template_roster_reload(tr) != 0)
00221         return 0;
00222 
00223     log_debug(ZONE, "populating roster with items from template");
00224 
00225     if(xhash_iter_first(tr->items))
00226         do {
00227             xhv.item_val = &item;
00228             xhash_iter_get(tr->items, NULL, NULL, xhv.val);
00229 
00230             _template_roster_save_item(tr->sm, jid, item);
00231         } while(xhash_iter_next(tr->items));
00232 
00233     return 0;
00234 }
00235 
00236 static void _template_roster_free(module_t mod) {
00237     template_roster_t tr = (template_roster_t) mod->private;
00238 
00239     if(tr->items != NULL)
00240         xhash_free(tr->items);
00241 
00242     free(tr);
00243 }
00244 
00245 DLLEXPORT int module_init(mod_instance_t mi, char *arg) {
00246     module_t mod = mi->mod;
00247     char *filename;
00248     template_roster_t tr;
00249 
00250     if(mod->init) return 0;
00251 
00252     filename = config_get_one(mod->mm->sm->config, "user.template.roster", 0);
00253     if(filename == NULL)
00254         return 0;
00255 
00256     tr = (template_roster_t) calloc(1, sizeof(struct _template_roster_st));
00257 
00258     tr->sm = mod->mm->sm;
00259     tr->filename = filename;
00260 
00261     mod->private = tr;
00262 
00263     mod->user_create = _template_roster_user_create;
00264     mod->free = _template_roster_free;
00265 
00266     return 0;
00267 }