jabberd2
2.2.16
|
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 }