📄 mod_filter.c
字号:
if(cur_action->is_match||(type==NULL&&jpacket_subtype(m->packet)!=JPACKET__NONE)||(j_strcmp(type,xtype)!=0)) { log_debug2(ZONE, LOGT_DELIVER, "not a match"); if(cur==t)cur=xmlnode_get_nextsibling(cur); xmlnode_hide(t); continue; } if (cur==t) cur=xmlnode_get_nextsibling(cur); xmlnode_hide(t); cur_action->is_match=1; } if(!cur_action->is_match) break; log_debug2(ZONE, LOGT_DELIVER, "MATCH"); } else if(j_strcmp(xmlnode_get_name(cur),"settype")==0) { if(m->packet->type == JPACKET_IQ) break; cur_action->has_action=1; cur_action->settype=1; log_debug2(ZONE, LOGT_DELIVER, "settype: %s",xmlnode_get_data(cur)); cur=xmlnode_get_nextsibling(cur); } else if(j_strcmp(xmlnode_get_name(cur),"reply")==0) { if(m->packet->type == JPACKET_IQ) break; cur_action->has_action=1; cur_action->reply=1; log_debug2(ZONE, LOGT_DELIVER, "reply: %s",xmlnode_get_data(cur)); cur=xmlnode_get_nextsibling(cur); } else if(j_strcmp(xmlnode_get_name(cur),"forward")==0) { jid new=jid_new(p,xmlnode_get_data(cur)); if ( ! new ) { log_debug2(ZONE, LOGT_DELIVER, "Ignoring illegal forwarding address: %s", xmlnode_get_data(cur)); /* * NPS: * This if statement deals w/ the immediate case of * the jid specified in the rule is bogus (can't * be converted to a jid struct. However, it * does so by just ignoring that there ever was a * <forward> tag in the rule, which is probably * confusing to an end user. I'd like to see a * deliver_fail() call used, but util I have a chance * to figure out an appropriate way to use it, * this will have to do. */ } else { if(m->packet->type == JPACKET_IQ) break; cur_action->has_action=1; new->next=cur_action->forward; cur_action->forward=new; log_debug2(ZONE, LOGT_DELIVER, "forward: %s",xmlnode_get_data(cur)); } cur=xmlnode_get_nextsibling(cur); } else if(j_strcmp(xmlnode_get_name(cur),"offline")==0) { if(m->packet->type == JPACKET_IQ) break; cur_action->has_action=1; cur_action->offline=1; log_debug2(ZONE, LOGT_DELIVER, "offline storage"); cur=xmlnode_get_nextsibling(cur); } else if(j_strcmp(xmlnode_get_name(cur),"continue")==0) { cur_action->has_action=1; cur_action->cont=1; log_debug2(ZONE, LOGT_DELIVER, "continue processing"); cur=xmlnode_get_nextsibling(cur); } else if(j_strcmp(xmlnode_get_name(cur), "error") == 0) { cur_action->has_action = 1; cur_action->error = 1; log_debug2(ZONE, LOGT_DELIVER, "reply with error"); cur = xmlnode_get_nextsibling(cur); } else { /* we don't know this tag.. how did we get here then?? */ cur=xmlnode_get_nextsibling(cur); } } if(!cur_action->is_match) { memset(cur_action,0,sizeof(_action)); continue; } if(cur_action->reply) mod_filter_action_reply(m,rules); if(cur_action->error) mod_filter_action_error(m, rules); if(cur_action->settype) mod_filter_action_settype(m,rules); if(cur_action->forward!=NULL) mod_filter_action_forward(m,rules,cur_action->forward); if(cur_action->offline) mod_filter_action_offline(m,rules); if(cur_action->cont) { /* continue processing rules */ memset(cur_action,0,sizeof(_action)); continue; } else break; } xmlnode_free(container); if(cur_action->has_action) { xmlnode_free(jp->x); pool_free(p); return M_HANDLED; } else { pool_free(p); return M_PASS; } /* it will never get to this point, but just becuase... */ return M_PASS;}/** * handle packets sent by the user to configure his filter. * * This is used to get the current filter or update the filter definition by the user * * @param m the mapi_struct containing the request * @param arg unused/ignored * @return M_IGNORE if not an iq stanza, M_HANDLED if the packet has been fully handled, M_PASS else */mreturn mod_filter_iq(mapi m, void *arg) { xmlnode opts, cur; int max_rule_size; pool p; /* we only care for iq stanzas */ if (m->packet->type != JPACKET_IQ) { return M_IGNORE; } /* we only care for packets in the jabber:iq:filter namespace sent to the user himself */ if(!NSCHECK(m->packet->iq, NS_FILTER) || m->packet->to != NULL) { return M_PASS; } log_debug2(ZONE, LOGT_DELIVER, "FILTER RULE SET: iq %s", xmlnode2str(m->packet->x)); max_rule_size = j_atoi(xmlnode_get_tag_data(js_config(m->si, "filter"), "max_size"), MOD_FILTER_MAX_SIZE); switch(jpacket_subtype(m->packet)) { case JPACKET__SET: /* check packet max size, and validity */ log_debug2(ZONE, LOGT_DELIVER, "FILTER RULE SET: rule max size %d: %s", max_rule_size, xmlnode2str(m->packet->x)); p = pool_new(); for(cur = xmlnode_get_firstchild(m->packet->iq); cur != NULL; cur = xmlnode_get_nextsibling(cur)) { xmlnode tag; if(xmlnode_get_type(cur) != NTYPE_TAG) continue; max_rule_size--; log_debug2(ZONE, LOGT_DELIVER, "only %d left..", max_rule_size); if(max_rule_size <= 0 || j_strcmp(xmlnode_get_name(cur), "rule") != 0) { /* invalid tag used */ jutil_iqresult(m->packet->x); xmlnode_put_attrib(m->packet->x, "type", "error"); xmlnode_put_attrib(xmlnode_insert_tag(m->packet->x, "error"), "code", "406"); xmlnode_insert_cdata(xmlnode_get_tag(m->packet->x, "error"), "Invalid rule, check rule size and tags", -1); xmlnode_hide(m->packet->iq); jpacket_reset(m->packet); js_session_to(m->s, m->packet); pool_free(p); return M_HANDLED; } for(tag = xmlnode_get_firstchild(cur); tag != NULL; tag = xmlnode_get_nextsibling(tag)) { char *c, *a; xmlnode config; if(xmlnode_get_type(tag) != NTYPE_TAG) continue; config = js_config(m->si, "filter"); config = xmlnode_get_tag(config, "allow"); /* if ns is used, offline, reply and settype cannot be used */ if(j_strcmp(xmlnode_get_name(tag), "ns") == 0 && (xmlnode_get_tag(tag->parent, "offline") != NULL || xmlnode_get_tag(tag->parent, "reply") == 0 || xmlnode_get_tag(tag->parent, "settype") == 0)) { jutil_iqresult(m->packet->x); xmlnode_put_attrib(m->packet->x, "type", "error"); xmlnode_put_attrib(xmlnode_insert_tag(m->packet->x, "error"), "code", "406"); xmlnode_insert_cdata(xmlnode_get_tag(m->packet->x, "error"), spools(p, "ns tag cannot be used this way", p), -1); xmlnode_hide(m->packet->iq); jpacket_reset(m->packet); js_session_to(m->s, m->packet); pool_free(p); return M_HANDLED; } c = spools(p, "conditions/", xmlnode_get_name(tag), p); a = spools(p, "actions/", xmlnode_get_name(tag), p); if(xmlnode_get_tag(config, c) == NULL && xmlnode_get_tag(config, a) == NULL) { /* invalid tag used */ jutil_iqresult(m->packet->x); xmlnode_put_attrib(m->packet->x, "type", "error"); xmlnode_put_attrib(xmlnode_insert_tag(m->packet->x, "error"), "code", "406"); xmlnode_insert_cdata(xmlnode_get_tag(m->packet->x, "error"), spools(p, "tag type '", xmlnode_get_name(tag), "' can not be used on this server", p), -1); xmlnode_hide(m->packet->iq); jpacket_reset(m->packet); js_session_to(m->s, m->packet); pool_free(p); return M_HANDLED; } } } pool_free(p); xdb_set(m->si->xc, m->user->id, NS_FILTER, m->packet->iq); jutil_iqresult(m->packet->x); xmlnode_hide(m->packet->iq); jpacket_reset(m->packet); js_session_to(m->s, m->packet); break; case JPACKET__GET: opts = mod_filter_get(m->user); xmlnode_put_attrib(m->packet->x, "type", "result"); xmlnode_insert_node(m->packet->iq, xmlnode_get_firstchild(opts)); jpacket_reset(m->packet); js_session_to(m->s, m->packet); xmlnode_free(opts); break; default: xmlnode_free(m->packet->x); } return M_HANDLED;}/** * sets up the per-session listeners * * register mod_filter_out as callback for packets the user sends * * @param m the mapi_struct containing the session creation event * @param arg unused/ignored * @return always M_PASS */mreturn mod_filter_session(mapi m, void *arg) { js_mapi_session(es_OUT, m->s, mod_filter_iq, NULL); return M_PASS;}/** * frees allocated memory on session manager shutdown * * @param m the mapi_struct containing the shutdown event * @param arg pointer to the xmlnode that contains the default rule * @return always M_PASS */mreturn mod_filter_shutdown(mapi m, void *arg) { if (arg != NULL) { xmlnode_free((xmlnode)arg); } return M_PASS;}/** * init mod_filter, register callbacks in the Jabber session manager and load the configuration (default rules) * * register mod_filter_handler as callback for the e_DELIVER event * register mod_filter_session as callback to be notified about newly created sessions * register mod_filter_shutdown as callback for session manager shutdown * * @param si jsmi_struct containing Jabber session manager instance-local data */void mod_filter(jsmi si) { xmlnode rule, mod_filter__default; /* setup the default built-in rule */ rule = js_config(si, "filter"); rule = xmlnode_get_tag(rule, "default"); mod_filter__default = xmlnode_new_tag("query"); xmlnode_put_attrib(mod_filter__default, "xmlns", NS_FILTER); xmlnode_insert_node(mod_filter__default, xmlnode_get_firstchild(rule)); log_debug2(ZONE, LOGT_INIT, "mod_filter startup up... default server rule: %s", xmlnode2str(mod_filter__default)); log_warn(NULL, "using mod_filter in jsm is depricated. It can produce endless looping messages if an other entity is auto-replying as well without support for jabber:x:envelope. mod_filter uses the undocumented jabber:x:envelope namespace instead of JEP-0131."); js_mapi_register(si, e_DELIVER, mod_filter_handler, mod_filter__default); js_mapi_register(si, e_SESSION, mod_filter_session, NULL); js_mapi_register(si, e_SHUTDOWN, mod_filter_shutdown, mod_filter__default);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -