⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_announce.c

📁 这是一个完全开放的
💻 C
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, *                    Ryan Eatmon, Robert Norris * * This program 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; either version 2 of the License, or * (at your option) any later version. * * This program 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA */#include "sm.h"/** @file sm/mod_announce.c  * @brief announce (broadcast) messages  * @author Robert Norris  * $Date: 2004/11/13 16:08:33 $  * $Revision: 1.17.2.3 $  *//* * message to host/announce goes to all online sessions and to offline users next time they connect * message to host/announce/online goes to all online sessions */typedef struct moddata_st {    nad_t       nad;    int         loaded;    time_t      t;    os_t        tos;    int         index;} *moddata_t;static void _announce_load(module_t mod, moddata_t data) {    st_ret_t ret;    os_t os;    os_object_t o;    os_type_t ot;    nad_t nad;    int ns, elem, attr;    char timestamp[18], telem[5];    struct tm tm;    /* struct tm can vary in size depending on platform */    memset(&tm, 0, sizeof(struct tm));    data->loaded = 1;        /* load the current message */    if((ret = storage_get(mod->mm->sm->st, "motd-message", mod->mm->sm->id, NULL, &os)) == st_SUCCESS) {        os_iter_first(os);        o = os_iter_object(os);        if(os_object_get(os, o, "xml", (void **) &nad, os_type_NAD, &ot)) {            /* Copy the nad, as the original is freed when the os is freed below */            data->nad = nad_copy(nad);            if((ns = nad_find_scoped_namespace(data->nad, uri_DELAY, NULL)) >= 0 &&               (elem = nad_find_elem(data->nad, 1, ns, "x", 1)) >= 0 &&               (attr = nad_find_attr(data->nad, elem, -1, "stamp", NULL)) >= 0) {                snprintf(timestamp, 18, "%.*s", NAD_AVAL_L(data->nad, attr), NAD_AVAL(data->nad, attr));                /* year */                telem[0] = timestamp[0];                telem[1] = timestamp[1];                telem[2] = timestamp[2];                telem[3] = timestamp[3];                telem[4] = '\0';                tm.tm_year = atoi(telem) - 1900;                /* month */                telem[0] = timestamp[4];                telem[1] = timestamp[5];                telem[2] = '\0';                tm.tm_mon = atoi(telem) - 1;                /* day */                telem[0] = timestamp[6];                telem[1] = timestamp[7];                tm.tm_mday = atoi(telem);                /* hour */                telem[0] = timestamp[9];                telem[1] = timestamp[10];                tm.tm_hour = atoi(telem);                /* minute */                telem[0] = timestamp[12];                telem[1] = timestamp[13];                tm.tm_min = atoi(telem);                /* second */                telem[0] = timestamp[15];                telem[1] = timestamp[16];                tm.tm_sec = atoi(telem);                            data->t = mktime(&tm);            }        }        os_free(os);    }    if(data->tos != NULL)        os_free(data->tos);    data->tos = os_new();    os_object_put(os_object_new(data->tos), "time", &data->t, os_type_INTEGER);}static mod_ret_t _announce_in_sess(mod_instance_t mi, sess_t sess, pkt_t pkt) {    module_t mod = mi->mod;    moddata_t data = (moddata_t) mod->private;    time_t t;    nad_t nad;    pkt_t motd;    os_t os;    os_object_t o;    os_type_t ot;    /* try to load data if we haven't yet */    if(data->nad == NULL) {        if(data->loaded)            return mod_PASS;        /* nothing to give them */        _announce_load(mod, data);        if(data->nad == NULL)            return mod_PASS;    }    /* if they're becoming available for the first time */    if(pkt->type == pkt_PRESENCE && pkt->to == NULL && sess->user->top == NULL) {        /* load the time of the last motd they got */        if((time_t) sess->user->module_data[mod->index] == 0 &&           storage_get(sess->user->sm->st, "motd-times", jid_user(sess->jid), NULL, &os) == st_SUCCESS) {            os_iter_first(os);            o = os_iter_object(os);            os_object_get(os, o, "time", (void **) &t, os_type_INTEGER, &ot);            sess->user->module_data[mod->index] = (void *) t;            os_free(os);        }        /* they've seen this one */        if((time_t) sess->user->module_data[mod->index] >= data->t)            return mod_PASS;        /* a-delivering we go */        log_debug(ZONE, "delivering stored motd to %s", jid_full(sess->jid));        nad = nad_copy(data->nad);        nad_set_attr(nad, 1, -1, "to", jid_full(sess->jid), strlen(jid_full(sess->jid)));        nad_set_attr(nad, 1, -1, "from", mod->mm->sm->id, strlen(mod->mm->sm->id));        motd = pkt_new(mod->mm->sm, nad);        if(motd == NULL) {            log_debug(ZONE, "invalid stored motd, not delivering");            nad_free(nad);        } else            pkt_router(motd);        sess->user->module_data[mod->index] = (void *) data->t;        storage_replace(sess->user->sm->st, "motd-times", jid_user(sess->jid), NULL, data->tos);    }    return mod_PASS;}static void _announce_broadcast_user(xht users, const char *key, void *val, void *arg) {    user_t user = (user_t) val;    moddata_t data = (moddata_t) arg;    sess_t sess;    nad_t nad;    for(sess = user->sessions; sess != NULL; sess = sess->next) {        if((!sess->available && !sess->invisible) || sess->pri < 0)            continue;        log_debug(ZONE, "resending to '%s'", jid_full(sess->jid));        nad = nad_copy(data->nad);        nad_set_attr(nad, 1, -1, "to", jid_full(sess->jid), strlen(jid_full(sess->jid)));        nad_set_attr(nad, 1, -1, "from", user->sm->id, strlen(user->sm->id));        pkt_router(pkt_new(user->sm, nad));        sess->user->module_data[data->index] = (void *) data->t;        storage_replace(sess->user->sm->st, "motd-times", jid_user(sess->jid), NULL, data->tos);    }}static mod_ret_t _announce_pkt_sm(mod_instance_t mi, pkt_t pkt) {    module_t mod = mi->mod;    moddata_t data = (moddata_t) mod->private;    pkt_t store;    nad_t nad;    time_t t;    os_t os;    os_object_t o;    st_ret_t ret;    /* time of this packet */    t = time(NULL);    /* we want messages addressed to /announce */    if(pkt->type != pkt_MESSAGE || strlen(pkt->to->resource) < 8 || strncmp(pkt->to->resource, "announce", 8) != 0)        return mod_PASS;        /* make sure they're allowed */    if(!aci_check(mod->mm->sm->acls, "broadcast", pkt->from)) {        log_debug(ZONE, "not allowing broadcast from %s", jid_full(pkt->from));        return -stanza_err_FORBIDDEN;    }    if(pkt->to->resource[8] == '\0') {        log_debug(ZONE, "storing message for announce later");        store = pkt_dup(pkt, NULL, NULL);        pkt_delay(store, t, mod->mm->sm->id);        /* prepare for storage */        os = os_new();        o = os_object_new(os);        os_object_put(o, "xml", store->nad, os_type_NAD);        /* store it */        ret = storage_replace(mod->mm->sm->st, "motd-message", mod->mm->sm->id, NULL, os);        os_free(os);        switch(ret) {            case st_FAILED:                pkt_free(store);                return -stanza_err_INTERNAL_SERVER_ERROR;            case st_NOTIMPL:                pkt_free(store);                return -stanza_err_FEATURE_NOT_IMPLEMENTED;            default:                break;        }        /* replace our local copy */        if(data->nad != NULL)            nad_free(data->nad);        data->nad = store->nad;        store->nad = NULL;        pkt_free(store);        /* update timestamp */        data->t = t;        if(data->tos != NULL)            os_free(data->tos);        data->tos = os_new();        os_object_put(os_object_new(data->tos), "time", &t, os_type_INTEGER);    }    else if(strcmp(&(pkt->to->resource[8]), "/online") != 0) {        log_debug(ZONE, "unknown announce resource '%s'", pkt->to->resource);        pkt_free(pkt);        return mod_HANDLED;    }    log_debug(ZONE, "broadcasting message to all sessions");    /* hack */    nad = data->nad;    data->nad = pkt->nad;    xhash_walk(mod->mm->sm->users, _announce_broadcast_user, (void *) data);    data->nad = nad;    /* done */    pkt_free(pkt);    return mod_HANDLED;}static void _announce_user_delete(mod_instance_t mi, jid_t jid) {    log_debug(ZONE, "deleting motd time for %s", jid_user(jid));    storage_delete(mi->sm->st, "motd-times", jid_user(jid), NULL);}static void _announce_free(module_t mod) {    moddata_t data = (moddata_t) mod->private;    if(data->nad != NULL) nad_free(data->nad);    if(data->tos != NULL) os_free(data->tos);    free(data);}int announce_init(mod_instance_t mi) {    module_t mod = mi->mod;    moddata_t data;    if(mod->init) return 0;    data = (moddata_t) malloc(sizeof(struct moddata_st));    memset(data, 0, sizeof(struct moddata_st));    mod->private = (void *) data;    data->index = mod->index;    mod->in_sess = _announce_in_sess;    mod->pkt_sm = _announce_pkt_sm;    mod->user_delete = _announce_user_delete;    mod->free = _announce_free;    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -