Logo Search packages:      
Sourcecode: jabberd2 version File versions  Download package

static mod_ret_t _privacy_in_sess ( mod_instance_t  mi,
sess_t  sess,
pkt_t  pkt 
) [static]

list management requests

Definition at line 585 of file mod_privacy.c.

References _privacy_lists_result_builder(), _privacy_result_builder(), zebra_st::def, module_st::index, sess_st::jid, user_st::jid, zebra_st::lists, module_st::mm, mod_instance_st::mod, mod_HANDLED, mod_PASS, sess_st::module_data, user_st::module_data, pkt_st::nad, sess_st::next, pkt_st::ns, os_free(), os_new(), os_object_new(), os_object_put(), os_type_BOOLEAN, os_type_INTEGER, os_type_STRING, sm_st::pc, pkt_id(), pkt_IQ, pkt_IQ_SET, user_st::sessions, pkt_st::sm, mm_st::sm, sm_st::st, st_SUCCESS, storage_delete(), storage_replace(), pkt_st::to, pkt_st::type, and sess_st::user.

                                                                             {
    module_t mod = mi->mod;
    int ns, query, list, name, active, def, item, type, value, action, order;
    char corder[14], str[256], filter[1024];
    zebra_t z;
    zebra_list_t zlist, old;
    pool p;
    zebra_item_t zitem, scan;
    sess_t sscan;
    pkt_t result;
    os_t os;
    os_object_t o;
    st_ret_t ret;

    /* we only want to play with iq:privacy packets */
    if((pkt->type != pkt_IQ && pkt->type != pkt_IQ_SET) || pkt->ns != ns_PRIVACY)
        return mod_PASS;

    /* if it has a to, throw it out */
    if(pkt->to != NULL)
        return -stanza_err_BAD_REQUEST;

    /* find the query */
    ns = nad_find_scoped_namespace(pkt->nad, uri_PRIVACY, NULL);
    query = nad_find_elem(pkt->nad, 1, ns, "query", 1);
    if(query < 0)
        return -stanza_err_BAD_REQUEST;

    /* get our lists */
    z = (zebra_t) sess->user->module_data[mod->index];

    /* update lists or set the active list */
    if(pkt->type == pkt_IQ_SET) {
        /* find out what we're doing */
        list = nad_find_elem(pkt->nad, query, ns, "list", 1);
        active = nad_find_elem(pkt->nad, query, ns, "active", 1);
        def = nad_find_elem(pkt->nad, query, ns, "default", 1);
        
        /* we need something to do, but we can't do it all at once */
        if((list < 0 && active < 0 && def < 0) || (list >= 0 && (active >=0 || def >= 0)))
            return -stanza_err_BAD_REQUEST;

        /* loop over any/all lists and store them */
        if(list >= 0) {
            /* only allowed to change one list at a time */
            if(nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0) {
                /* hack the error in */
                pkt_error(pkt, stanza_err_BAD_REQUEST);

                pkt_sess(pkt, sess);
                return mod_HANDLED;
            }

            /* get the list name */
            name = nad_find_attr(pkt->nad, list, -1, "name", NULL);
            if(name < 0) {
                log_debug(ZONE, "no list name specified, failing request");
                return -stanza_err_BAD_REQUEST;
            }

            snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name));
            str[255] = '\0';

            log_debug(ZONE, "updating list %s", str);

            /* make a new one */
            p = pool_new();

            zlist = (zebra_list_t) pmalloco(p, sizeof(struct zebra_list_st));

            zlist->p = p;
            zlist->name = pstrdup(p, str);

            os = os_new();

            /* loop over the items */
            item = nad_find_elem(pkt->nad, list, ns, "item", 1);
            while(item >= 0) {
                /* extract things */
                type = nad_find_attr(pkt->nad, item, -1, "type", 0);
                value = nad_find_attr(pkt->nad, item, -1, "value", 0);
                action = nad_find_attr(pkt->nad, item, -1, "action", 0);
                order = nad_find_attr(pkt->nad, item, -1, "order", 0);

                /* sanity */
                if(action < 0 || order < 0 || (type >= 0 && value < 0)) {
                    pool_free(p);
                    os_free(os);
                    return -stanza_err_BAD_REQUEST;
                }

                /* new item */
                zitem = (zebra_item_t) pmalloco(p, sizeof(struct zebra_item_st));

                /* have to store it too */
                o = os_object_new(os);
                os_object_put(o, "list", zlist->name, os_type_STRING);

                /* type & value */
                if(type >= 0) {
                    if(NAD_AVAL_L(pkt->nad, type) == 3 && strncmp("jid", NAD_AVAL(pkt->nad, type), 3) == 0) {
                        zitem->type = zebra_JID;

                        zitem->jid = jid_new(mod->mm->sm->pc, NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value));
                        if(zitem->jid == NULL) {
                            log_debug(ZONE, "invalid jid '%.*s', failing request", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value));
                            pool_free(p);
                            os_free(os);
                            return -stanza_err_BAD_REQUEST;
                        }

                        pool_cleanup(p, free, zitem->jid);

                        log_debug(ZONE, "jid item with value '%s'", jid_full(zitem->jid));

                        os_object_put(o, "type", "jid", os_type_STRING);
                        os_object_put(o, "value", jid_full(zitem->jid), os_type_STRING);
                    }

                    else if(NAD_AVAL_L(pkt->nad, type) == 5 && strncmp("group", NAD_AVAL(pkt->nad, type), 5) == 0) {
                        zitem->type = zebra_GROUP;

                        zitem->group = pstrdupx(zlist->p, NAD_AVAL(pkt->nad, value), NAD_AVAL_L(pkt->nad, value));

                        /* !!! check if the group exists */

                        log_debug(ZONE, "group item with value '%s'", zitem->group);

                        os_object_put(o, "type", "group", os_type_STRING);
                        os_object_put(o, "value", zitem->group, os_type_STRING);
                    }

                    else if(NAD_AVAL_L(pkt->nad, type) == 12 && strncmp("subscription", NAD_AVAL(pkt->nad, type), 12) == 0) {
                        zitem->type = zebra_S10N;

                        os_object_put(o, "type", "subscription", os_type_STRING);

                        if(NAD_AVAL_L(pkt->nad, value) == 2 && strncmp("to", NAD_AVAL(pkt->nad, value), 2) == 0) {
                            zitem->to = 1;
                            os_object_put(o, "value", "to", os_type_STRING);
                        } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("from", NAD_AVAL(pkt->nad, value), 4) == 0) {
                            zitem->from = 1;
                            os_object_put(o, "value", "from", os_type_STRING);
                        } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("both", NAD_AVAL(pkt->nad, value), 4) == 0) {
                            zitem->to = zitem->from = 1;
                            os_object_put(o, "value", "both", os_type_STRING);
                        } else if(NAD_AVAL_L(pkt->nad, value) == 4 && strncmp("none", NAD_AVAL(pkt->nad, value), 4) == 0)
                            os_object_put(o, "value", "none", os_type_STRING);
                        else {
                            log_debug(ZONE, "invalid value '%.*s' on s10n item, failing request", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value));
                            pool_free(p);
                            os_free(os);
                            return -stanza_err_BAD_REQUEST;
                        }

                        log_debug(ZONE, "s10n item with value '%.*s' (to %d from %d)", NAD_AVAL_L(pkt->nad, value), NAD_AVAL(pkt->nad, value), zitem->to, zitem->from);
                    }
                }

                /* action */
                if(NAD_AVAL_L(pkt->nad, action) == 4 && strncmp("deny", NAD_AVAL(pkt->nad, action), 4) == 0) {
                    zitem->deny = 1;
                    log_debug(ZONE, "deny rule");
                } else if(NAD_AVAL_L(pkt->nad, action) == 5 && strncmp("allow", NAD_AVAL(pkt->nad, action), 5) == 0) {
                    zitem->deny = 0;
                    log_debug(ZONE, "allow rule");
                } else {
                    log_debug(ZONE, "unknown action '%.*s', failing request", NAD_AVAL_L(pkt->nad, action), NAD_AVAL(pkt->nad, action));
                    pool_free(p);
                    os_free(os);
                    return -stanza_err_BAD_REQUEST;
                }

                os_object_put(o, "deny", &zitem->deny, os_type_BOOLEAN);

                /* order */
                snprintf(corder, 14, "%.*s", NAD_AVAL_L(pkt->nad, order), NAD_AVAL(pkt->nad, order));
                corder[13] = '\0';
                zitem->order = atoi(corder);

                os_object_put(o, "order", &zitem->order, os_type_INTEGER);

                /* block types */
                if(nad_find_elem(pkt->nad, item, ns, "message", 1) >= 0)
                    zitem->block |= block_MESSAGE;
                if(nad_find_elem(pkt->nad, item, ns, "presence-in", 1) >= 0)
                    zitem->block |= block_PRES_IN;
                if(nad_find_elem(pkt->nad, item, ns, "presence-out", 1) >= 0)
                    zitem->block |= block_PRES_OUT;
                if(nad_find_elem(pkt->nad, item, ns, "iq", 1) >= 0)
                    zitem->block |= block_IQ;

                os_object_put(o, "block", &zitem->block, os_type_INTEGER);

                /* insert it */
                for(scan = zlist->items; scan != NULL; scan = scan->next)
                    if(zitem->order < scan->order)
                        break;
            
                /* we're >= everyone, add us to the end */
                if(scan == NULL) {
                    if(zlist->last == NULL)
                        zlist->items = zlist->last = zitem;
                    else {
                        zlist->last->next = zitem;
                        zitem->prev = zlist->last;
                        zlist->last = zitem;
                    }
                }
            
                /* insert just before scan */
                else {
                    if(zlist->items == scan) {
                        zitem->next = zlist->items;
                        zlist->items = zitem;
                        scan->prev = zitem;
                    } else {
                        zitem->next = scan;
                        zitem->prev = scan->prev;
                        scan->prev->next = zitem;
                        scan->prev = zitem;
                    }
                }

                /* next item */
                item = nad_find_elem(pkt->nad, item, ns, "item", 0);
            }

            /* write the whole list out */
            sprintf(filter, "(list=%i:%s)", strlen(zlist->name), zlist->name);

            ret = storage_replace(mod->mm->sm->st, "privacy-items", jid_user(sess->user->jid), filter, os);
            os_free(os);

            /* failed! */
            if(ret != st_SUCCESS) {
                pool_free(zlist->p);
                return -stanza_err_INTERNAL_SERVER_ERROR;
            }

            /* old list pointer */
            old = xhash_get(z->lists, zlist->name);

            /* removed list */
            if(zlist->items == NULL) {
                log_debug(ZONE, "removed list %s", zlist->name);
                xhash_zap(z->lists, zlist->name);
                pool_free(zlist->p);
                if(old != NULL) pool_free(old->p);
                zlist = NULL;
            } else {
                log_debug(ZONE, "updated list %s", zlist->name);
                xhash_put(z->lists, zlist->name, (void *) zlist);
                if(old != NULL) pool_free(old->p);
            }

            /* if this was a new list, then noone has it active yet */
            if(old != NULL) {

                /* relink */
                log_debug(ZONE, "relinking sessions");

                /* loop through sessions, relink */
                for(sscan = sess->user->sessions; sscan != NULL; sscan = sscan->next)
                    if(sscan->module_data[mod->index] == old) {
                        sscan->module_data[mod->index] = (void *) zlist;
                        log_debug(ZONE, "session '%s' now has active list '%s'", jid_full(sscan->jid), (zlist != NULL) ? zlist->name : "(NONE)");
                    }

                /* default list */
                if(z->def == old) {
                    z->def = zlist;

                    if(zlist == NULL) {
                        storage_delete(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL);
                        log_debug(ZONE, "removed default list");
                    }

                    else {
                        os = os_new();
                        o = os_object_new(os);

                        os_object_put(o, "default", zlist->name, os_type_STRING);

                        storage_replace(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL, os);

                        os_free(os);

                        log_debug(ZONE, "default list is now '%s'", (zlist != NULL) ? zlist->name : "(NONE)");
                    }
                }
            }
        }

        /* set the active list */
        if(active >= 0) {
            name = nad_find_attr(pkt->nad, active, -1, "name", NULL);
            if(name < 0) {
                /* no name, no active list */
                log_debug(ZONE, "clearing active list for session '%s'", jid_full(sess->jid));
                sess->module_data[mod->index] = NULL;
            }

            else {
                snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name));
                str[255] = '\0';

                zlist = xhash_get(z->lists, str);
                if(zlist == NULL) {
                    log_debug(ZONE, "request to make list '%s' active, but there's no such list", str);

                    /* hack the error in */
                    pkt_error(pkt, stanza_err_ITEM_NOT_FOUND);

                    pkt_sess(pkt, sess);
                    return mod_HANDLED;
                }

                sess->module_data[mod->index] = zlist;

                log_debug(ZONE, "session '%s' now has active list '%s'", jid_full(sess->jid), str);
            }
        }

        /* set the default list */
        if(def >= 0) {
            name = nad_find_attr(pkt->nad, def, -1, "name", NULL);
            if(name < 0) {
                /* no name, no default list */
                log_debug(ZONE, "clearing default list for '%s'", jid_user(sess->user->jid));
                z->def = NULL;
            }

            else {
                snprintf(str, 256, "%.*s", NAD_AVAL_L(pkt->nad, name), NAD_AVAL(pkt->nad, name));
                str[255] = '\0';

                zlist = xhash_get(z->lists, str);
                if(zlist == NULL) {
                    log_debug(ZONE, "request to make list '%s' default, but there's no such list");

                    /* hack the error in */
                    pkt_error(pkt, stanza_err_ITEM_NOT_FOUND);

                    pkt_sess(pkt, sess);
                    return mod_HANDLED;
                }

                z->def = zlist;

                os = os_new();
                o = os_object_new(os);

                os_object_put(o, "default", zlist->name, os_type_STRING);

                storage_replace(mod->mm->sm->st, "privacy-default", jid_user(sess->user->jid), NULL, os);

                os_free(os);

                log_debug(ZONE, "'%s' now has default list '%s'", jid_user(sess->user->jid), str);
            }
        }

        /* done, let them know */
        result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);

        pkt_id(pkt, result);

        /* done with this */
        pkt_free(pkt);

        /* give it to the session */
        pkt_sess(result, sess);

        /* all done */
        return mod_HANDLED;
    }

    /* its a get */

    /* only allowed to request one list, if any */
    list = nad_find_elem(pkt->nad, query, ns, "list", 1);
    if(list >= 0 && nad_find_elem(pkt->nad, list, ns, "list", 0) >= 0) {
        /* hack the error in */
        pkt_error(pkt, stanza_err_BAD_REQUEST);

        pkt_sess(pkt, sess);
        return mod_HANDLED;
    }

    result = pkt_create(pkt->sm, "iq", "result", NULL, NULL);

    pkt_id(pkt, result);

    ns = nad_add_namespace(result->nad, uri_PRIVACY, NULL);
    query = nad_insert_elem(result->nad, 1, ns, "query", NULL);

    /* just do one */
    if(list >= 0) {
      name = nad_find_attr(pkt->nad, list, -1, "name", NULL);

      zlist = xhash_getx(z->lists, NAD_AVAL(pkt->nad, name), NAD_AVAL_L(pkt->nad, name));
      if(zlist == NULL) {
            /* hack the error in */
            pkt_error(pkt, stanza_err_ITEM_NOT_FOUND);

            pkt_sess(pkt, sess);
            return mod_HANDLED;
        }

        _privacy_result_builder(z->lists, zlist->name, (void *) zlist, (void *) result);
    }

    else {
        /* walk the list hash and add the lists in */
        xhash_walk(z->lists, _privacy_lists_result_builder, (void *) result);
    }

    /* tell them about current active and default list if they asked for everything */
    if(list < 0) {
        /* active */
        if(sess->module_data[mod->index] != NULL) {
            active = nad_insert_elem(result->nad, query, ns, "active", NULL);
            nad_set_attr(result->nad, active, -1, "name", ((zebra_list_t) sess->module_data[mod->index])->name, 0);
        }

        /* and the default list */
        if(z->def != NULL) {
            def = nad_insert_elem(result->nad, query, ns, "default", NULL);
            nad_set_attr(result->nad, def, -1, "name", z->def->name, 0);
        }
    }

    /* give it to the session */
    pkt_sess(result, sess);

    /* done with this */
    pkt_free(pkt);

    /* all done */
    return mod_HANDLED;
}


Generated by  Doxygen 1.6.0   Back to index