static mod_ret_t _iq_private_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) { module_t mod = mi->mod; int ns, elem, target, targetns; st_ret_t ret; char filter[4096]; os_t os; os_object_t o; nad_t nad; pkt_t result; sess_t sscan; /* only handle private sets and gets */ if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_PRIVATE) return mod_PASS; /* we're only interested in no to, to our host, or to us */ if(pkt->to != NULL && jid_compare_user(sess->jid, pkt->to) != 0 && strcmp(sess->jid->domain, jid_user(pkt->to)) != 0) return mod_PASS; ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVATE, NULL); elem = nad_find_elem(pkt->nad, 1, ns, "query", 1); /* find the first child */ target = elem + 1; while(target < pkt->nad->ecur) { if(pkt->nad->elems[target].depth > pkt->nad->elems[elem].depth) break; target++; } /* not found, so we're done */ if(target == pkt->nad->ecur) return -stanza_err_BAD_REQUEST; /* find the target namespace */ targetns = NAD_ENS(pkt->nad, target); /* gotta have a namespace */ if(targetns < 0) { log_debug(ZONE, "no namespace specified"); return -stanza_err_BAD_REQUEST; } log_debug(ZONE, "processing private request for %.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns)); /* get */ if(pkt->type == pkt_IQ) { #ifdef ENABLE_EXPERIMENTAL /* remember that this resource requested the namespace */ if(sess->module_data[mod->index] == NULL) { /* create new hash if necesary */ sess->module_data[mod->index] = xhash_new(101); pool_cleanup(sess->p, (void (*))(void *) xhash_free, sess->module_data[mod->index]); } xhash_put(sess->module_data[mod->index], pstrdupx(sess->p, NAD_NURI(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns)), (void *) 1); #endif snprintf(filter, 4096, "(ns=%i:%.*s)", NAD_NURI_L(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns)); ret = storage_get(sess->user->sm->st, "private", jid_user(sess->jid), filter, &os); switch(ret) { case st_SUCCESS: if(os_iter_first(os)) { o = os_iter_object(os); if(os_object_get_nad(os, o, "xml", &nad)) { result = pkt_new(sess->user->sm, nad_copy(nad)); if(result != NULL) { nad_set_attr(result->nad, 1, -1, "type", "result", 6); pkt_id(pkt, result); pkt_sess(result, sess); pkt_free(pkt); os_free(os); return mod_HANDLED; } } } os_free(os); /* drop through */ log_debug(ZONE, "storage_get succeeded, but couldn't make packet, faking st_NOTFOUND"); case st_NOTFOUND: log_debug(ZONE, "namespace not found, returning"); /* * !!! really, we should just return a 404. 1.4 just slaps a * result on the packet and sends it back. hurrah for * legacy namespaces. */ nad_set_attr(pkt->nad, 1, -1, "type", "result", 6); pkt_sess(pkt_tofrom(pkt), sess); return mod_HANDLED; case st_FAILED: return -stanza_err_INTERNAL_SERVER_ERROR; case st_NOTIMPL: return -stanza_err_FEATURE_NOT_IMPLEMENTED; } } os = os_new(); o = os_object_new(os); snprintf(filter, 4096, "%.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns)); os_object_put(o, "ns", filter, os_type_STRING); os_object_put(o, "xml", pkt->nad, os_type_NAD); snprintf(filter, 4096, "(ns=%i:%.*s)", NAD_NURI_L(pkt->nad, targetns), NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns)); ret = storage_replace(sess->user->sm->st, "private", jid_user(sess->jid), filter, os); os_free(os); switch(ret) { case st_FAILED: return -stanza_err_INTERNAL_SERVER_ERROR; case st_NOTIMPL: return -stanza_err_FEATURE_NOT_IMPLEMENTED; default: /* create result packet */ result = pkt_create(sess->user->sm, "iq", "result", NULL, NULL); pkt_id(pkt, result); /* and flush it to the session */ pkt_sess(result, sess); #ifdef ENABLE_EXPERIMENTAL /* push it to all resources that read this xmlns item */ snprintf(filter, 4096, "%.*s", NAD_NURI_L(pkt->nad, targetns), NAD_NURI(pkt->nad, targetns)); for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next) { /* skip our resource and those that didn't read any private-storage */ if(sscan == sess || sscan->module_data[mod->index] == NULL) continue; /* check whether namespace was read */ if(xhash_get(sscan->module_data[mod->index], filter)) { result = pkt_dup(pkt, jid_full(sscan->jid), NULL); if(result->from != NULL) { jid_free(result->from); nad_set_attr(result->nad, 1, -1, "from", NULL, 0); } pkt_id_new(result); pkt_sess(result, sscan); } } #endif /* finally free the packet */ pkt_free(pkt); return mod_HANDLED; } /* we never get here */ return 0; }
static mod_ret_t _vacation_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) { module_t mod = mi->mod; vacation_t v = sess->user->module_data[mod->index]; int ns, start, end, msg; char dt[30]; pkt_t res; os_t os; os_object_t o; /* we only want to play with vacation iq packets */ if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_VACATION) return mod_PASS; /* if it has a to, throw it out */ if(pkt->to != NULL) return -stanza_err_BAD_REQUEST; /* get */ if(pkt->type == pkt_IQ) { if(v->msg == NULL) { res = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL); pkt_id(pkt, res); pkt_free(pkt); pkt_sess(res, sess); return mod_HANDLED; } ns = nad_find_scoped_namespace(pkt->nad, uri_VACATION, NULL); if(v->start != 0) { datetime_out(v->start, dt_DATETIME, dt, 30); nad_insert_elem(pkt->nad, 2, ns, "start", dt); } else nad_insert_elem(pkt->nad, 2, ns, "start", NULL); if(v->end != 0) { datetime_out(v->end, dt_DATETIME, dt, 30); nad_insert_elem(pkt->nad, 2, ns, "end", dt); } else nad_insert_elem(pkt->nad, 2, ns, "end", NULL); nad_insert_elem(pkt->nad, 2, ns, "message", v->msg); pkt_tofrom(pkt); nad_set_attr(pkt->nad, 1, -1, "type", "result", 6); pkt_sess(pkt, sess); return mod_HANDLED; } /* set */ ns = nad_find_scoped_namespace(pkt->nad, uri_VACATION, NULL); start = nad_find_elem(pkt->nad, 2, ns, "start", 1); end = nad_find_elem(pkt->nad, 2, ns, "end", 1); msg = nad_find_elem(pkt->nad, 2, ns, "message", 1); if(start < 0 || end < 0 || msg < 0) { /* forget */ if(v->msg != NULL) { free(v->msg); v->msg = NULL; } v->start = 0; v->end = 0; storage_delete(mi->sm->st, "vacation-settings", jid_user(sess->jid), NULL); res = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL); pkt_id(pkt, res); pkt_free(pkt); pkt_sess(res, sess); return mod_HANDLED; } if(NAD_CDATA_L(pkt->nad, start) > 0) { strncpy(dt, NAD_CDATA(pkt->nad, start), (30 < NAD_CDATA_L(pkt->nad, start) ? 30 : NAD_CDATA_L(pkt->nad, start))); v->start = datetime_in(dt); } else v->start = 0; if(NAD_CDATA_L(pkt->nad, end) > 0) { strncpy(dt, NAD_CDATA(pkt->nad, end), (30 < NAD_CDATA_L(pkt->nad, end) ? 30 : NAD_CDATA_L(pkt->nad, end))); v->end = datetime_in(dt); } else v->end = 0; v->msg = (char *) malloc(sizeof(char) * (NAD_CDATA_L(pkt->nad, msg) + 1)); strncpy(v->msg, NAD_CDATA(pkt->nad, msg), NAD_CDATA_L(pkt->nad, msg)); v->msg[NAD_CDATA_L(pkt->nad, msg)] = '\0'; os = os_new(); o = os_object_new(os); os_object_put(o, "start", &v->start, os_type_INTEGER); os_object_put(o, "end", &v->end, os_type_INTEGER); os_object_put(o, "message", v->msg, os_type_STRING); if(storage_replace(mod->mm->sm->st, "vacation-settings", jid_user(sess->user->jid), NULL, os) != st_SUCCESS) { free(v->msg); v->msg = NULL; v->start = 0; v->end = 0; return -stanza_err_INTERNAL_SERVER_ERROR; } res = pkt_create(mod->mm->sm, "iq", "result", NULL, NULL); pkt_id(pkt, res); pkt_free(pkt); pkt_sess(res, sess); return mod_HANDLED; }