📄 mod_filter.c
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL"). You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/. * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights * * Portions created by or assigned to Jabber.com, Inc. are * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. * * Acknowledgements * * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. * * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above. If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL. If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL. * * * --------------------------------------------------------------------------*/#include "jsm.h"/** mod_filter.c: it's alive! it now handles all functions that used to be handled by mod_offline.c mod_filter supports the following conditions: unavailable - matches when you aren't online from - matches if the sender is the same as the cdata in the <from/> tag resource - matches YOUR resource subject - matches the subject of the message body - matches the body of the message show - matches your <show/> in presence type - matches the type='' attrib and the following Actions: offline - stores the message offline forward - forwards the message to another jid reply - sends back an auto-reply message to the sender continue - continues processing of other rules settype - change the incoming message type you may specify any number of conditions/actions, if there are more than one condition, ALL conditions must match for the rule to match, and ALL the listed actions will be taken. rules are checked in order, stopping when a match is found, unless a <continue/> flag is in place example rule: <rule> <unavailable/> <offline/> <reply>I'm not available right now</reply> <forward>tsbandit@jabber.org</forward> </rule>*//* mod_filter must go first in module ordering *//* basic principle of mod_filter * each user has their own filter * each filter contains zero or more rules * each rule contains one or more conditions and one or more actions * some conditions/actions may contain text to limit it further * first matching condition is applied and processing quits (unless an action is continue) * processed in order from client * NO ACTION IMPLIES DROP * FUTURE CONDITIONS: type, time, size * FUTURE ACTIONS: edit,error,settype */xmlnode mod_filter__default = NULL;jsmi mod_filter__jsmi = NULL;#define MOD_FILTER_MAX_SIZE 100typedef struct action_struct { pool p; int is_match, has_action; int offline, reply, settype, cont, error; jid forward; mapi m;} _action, *action;/* get the user's filter rules */xmlnode mod_filter_get(udata u){ xmlnode ret; /* get the existing rules */ ret = xdb_get(u->si->xc, u->id, NS_FILTER); if(ret == NULL) { ret = xmlnode_new_tag("query"); xmlnode_put_attrib(ret, "xmlns", NS_FILTER); } return ret;}void mod_filter_action_offline(mapi m, xmlnode rule){ xmlnode cur; /* look for event messages */ for(cur = xmlnode_get_firstchild(m->packet->x); cur != NULL; cur = xmlnode_get_nextsibling(cur)) if(NSCHECK(cur, NS_EVENT)) { if(xmlnode_get_tag(cur, "id") != NULL) return; /* bah, we don't want to store events offline (XXX: do we?) */ if(xmlnode_get_tag(cur, "offline") != NULL) break; /* cur remaining set is the flag */ } log_debug("mod_filter","storing message for %s offline.",m->user->user); jutil_delay(m->packet->x,"Offline Storage"); if(xdb_act(m->si->xc, m->user->id, NS_OFFLINE, "insert", NULL, m->packet->x)) return; if(cur != NULL) { /* if there was an offline event to be sent, send it for gosh sakes! */ xmlnode cur2; jutil_tofrom(m->packet->x); /* erease everything else in the message */ for(cur2 = xmlnode_get_firstchild(m->packet->x); cur2 != NULL; cur2 = xmlnode_get_nextsibling(cur2)) if(cur2 != cur) xmlnode_hide(cur2); /* erase any other events */ for(cur2 = xmlnode_get_firstchild(cur); cur2 != NULL; cur2 = xmlnode_get_nextsibling(cur2)) xmlnode_hide(cur2); /* fill it in and send it on */ xmlnode_insert_tag(cur,"offline"); xmlnode_insert_cdata(xmlnode_insert_tag(cur,"id"),xmlnode_get_attrib(m->packet->x,"id"), -1); js_deliver(m->si, jpacket_reset(m->packet)); }}void mod_filter_action_reply(mapi m,xmlnode rule){ char *reply=xmlnode_get_tag_data(rule,"reply"); xmlnode x = xmlnode_get_tag(m->packet->x, "x?xmlns=jabber:x:envelope"); int has_envelope = 0; /* check for infinite loops */ if(x != NULL) { xmlnode cur = xmlnode_get_tag(x, "forwardedby"); has_envelope = 1; for(; cur != NULL; cur = xmlnode_get_nextsibling(cur)) { if(xmlnode_get_type(cur) != NTYPE_TAG) continue; if(j_strcmp(xmlnode_get_name(cur), "forwardedby") == 0) { char *fb = xmlnode_get_attrib(cur, "jid"); jid j = jid_new(m->packet->p, fb); if(jid_cmpx(j, m->packet->to, JID_USER | JID_SERVER) == 0) { x = xmlnode_dup(m->packet->x); xmlnode_put_attrib(x, "to", jid_full(j)); xmlnode_put_attrib(x, "from", jid_full(m->packet->to)); deliver_fail(dpacket_new(x), "Replying would result in infinite loop"); return; } } } } if(!has_envelope) xmlnode_put_attrib(x = xmlnode_insert_tag(m->packet->x, "x"), "xmlns", "jabber:x:envelope"); xmlnode_put_attrib(xmlnode_insert_tag(x, "forwardedby"), "jid", jid_full(m->packet->to)); xmlnode_put_attrib(xmlnode_insert_tag(x, "from"), "jid", jid_full(m->packet->to)); xmlnode_put_attrib(xmlnode_insert_tag(x, "to"), "jid", jid_full(m->packet->from)); if(jid_cmpx(m->packet->to, m->packet->from, JID_USER | JID_SERVER) == 0) { /* special case, we sent a msg to ourselves */ /* try to find a session to deliver to... */ session s = js_session_get(m->user, m->packet->to->resource); s = s ? s : js_session_primary(m->user); s = s ? s : m->s; if(s == NULL) { /* can't find a deliverable session, store offline */ mod_filter_action_offline(m, rule); return; } /* just deliver to the session */ x = xmlnode_dup(m->packet->x); jutil_tofrom(x); if(xmlnode_get_tag(x, "body") != NULL) xmlnode_hide(xmlnode_get_tag(x, "body")); if(reply != NULL) xmlnode_insert_cdata(xmlnode_insert_tag(x, "body"), reply, -1); js_session_to(s, jpacket_new(x)); return; } x = xmlnode_dup(m->packet->x); jutil_tofrom(x); if(xmlnode_get_tag(x, "body") != NULL) xmlnode_hide(xmlnode_get_tag(x, "body")); if(reply != NULL) xmlnode_insert_cdata(xmlnode_insert_tag(x, "body"), reply, -1); deliver(dpacket_new(x),m->si->i);}void mod_filter_action_error(mapi m,xmlnode rule){ xmlnode err = xmlnode_get_tag(rule, "error"); log_debug(ZONE,"sending an error reply"); if(err != NULL) { xmlnode_insert_tag_node(m->packet->x, err); xmlnode_put_attrib(m->packet->x, "type", "error"); jpacket_reset(m->packet); } mod_filter_action_reply(m, rule);}void mod_filter_action_forward(mapi m,xmlnode rule,jid j){ int has_envelope=0; jid cur; xmlnode x=xmlnode_get_tag(m->packet->x,"x?xmlns=jabber:x:envelope"); /* check for infinite loops... */ if(x!=NULL) { xmlnode cur=xmlnode_get_tag(x,"forwardedby"); has_envelope=1; for(;cur!=NULL;cur=xmlnode_get_nextsibling(cur)) { if(xmlnode_get_type(cur) != NTYPE_TAG) continue; if(j_strcmp(xmlnode_get_name(cur),"forwardedby")==0) { char *fb=xmlnode_get_attrib(cur,"jid"); jid j=jid_new(m->packet->p,fb); if( ( j != NULL ) && ( jid_cmpx(j,m->packet->to,JID_USER|JID_SERVER)==0 ) ) { x=xmlnode_dup(m->packet->x); xmlnode_put_attrib(x,"to",jid_full(j)); xmlnode_put_attrib(x,"from",jid_full(m->packet->to)); deliver_fail(dpacket_new(x),"Forwarding would result in infinite loop"); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -