jabberd2
2.2.16
|
00001 /* 00002 * jabberd - Jabber Open Source Server 00003 * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, 00004 * Ryan Eatmon, Robert Norris 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA 00019 */ 00020 00021 /* for strndup */ 00022 #define _GNU_SOURCE 00023 #include <string.h> 00024 #include "sm.h" 00025 00033 /* XEP-0157 serverinfo fields */ 00034 static const char *_serverinfo_fields[] = { 00035 "abuse-addresses", 00036 "admin-addresses", 00037 "feedback-addresses", 00038 "sales-addresses", 00039 "security-addresses", 00040 "support-addresses", 00041 NULL 00042 }; 00043 00044 static mod_ret_t _help_pkt_sm(mod_instance_t mi, pkt_t pkt) 00045 { 00046 module_t mod = mi->mod; 00047 jid_t all, msg, jid, smjid; 00048 int subj, subjectl; 00049 char *org_subject; 00050 char *subject; 00051 char *resource = (char *) mod->private; 00052 00053 smjid = jid_new(jid_user(pkt->to), -1); 00054 jid_reset_components(smjid, smjid->node, smjid->domain, resource); 00055 00056 /* answer to probes and subscription requests */ 00057 if(pkt->type == pkt_PRESENCE_PROBE || pkt->type == pkt_S10N) { 00058 log_debug(ZONE, "answering presence probe/sub from %s with /help resource", jid_full(pkt->from)); 00059 00060 /* send presence */ 00061 pkt_router(pkt_create(mod->mm->sm, "presence", NULL, jid_user(pkt->from), jid_full(smjid))); 00062 } 00063 00064 jid_free(smjid); 00065 00066 /* we want messages addressed to the sm itself or /help resource */ 00067 if(!(pkt->type & pkt_MESSAGE) || (pkt->to->resource[0] != '\0' && strcmp(pkt->to->resource, "help"))) 00068 return mod_PASS; 00069 00070 log_debug(ZONE, "help message from %s", jid_full(pkt->from)); 00071 00072 all = xhash_get(mod->mm->sm->acls, "all"); 00073 msg = xhash_get(mod->mm->sm->acls, "messages"); 00074 00075 nad_set_attr(pkt->nad, 1, -1, "type", NULL, 0); 00076 subj = nad_find_elem(pkt->nad, 1, NAD_ENS(pkt->nad, 1), "subject", 1); 00077 if(subj >= 0 && NAD_CDATA_L(pkt->nad, subj) > 0) 00078 { 00079 org_subject = strndup(NAD_CDATA(pkt->nad, subj), NAD_CDATA_L(pkt->nad, subj)); 00080 } else { 00081 org_subject = "(none)"; 00082 } 00083 subjectl = strlen(org_subject) + strlen(jid_full(pkt->from)) + 8; 00084 subject = (char *) malloc(sizeof(char) * subjectl); 00085 snprintf(subject, subjectl, "Fwd[%s]: %s", jid_full(pkt->from), org_subject); 00086 if(subj >= 0 && NAD_CDATA_L(pkt->nad, subj) > 0) 00087 { 00088 free(org_subject); 00089 nad_drop_elem(pkt->nad, subj); 00090 } 00091 nad_insert_elem(pkt->nad, 1, NAD_ENS(pkt->nad, 1), "subject", subject); 00092 00093 for(jid = all; jid != NULL; jid = jid->next) 00094 { 00095 if (jid_compare_full(pkt->from, jid) == 0) { 00096 /* make a copy of the nad so it can be dumped to a string */ 00097 nad_t copy = nad_copy(pkt->nad); 00098 char * xml; 00099 int len; 00100 if (!copy) { 00101 log_write(mod->mm->sm->log, LOG_ERR, "%s:%d help admin %s is messaging sm for help! packet dropped. (unable to print packet - out of memory?)", ZONE, jid_full(jid)); 00102 continue; 00103 } 00104 nad_print(copy, 0, &xml, &len); 00105 log_write(mod->mm->sm->log, LOG_ERR, "%s:%d help admin %s is messaging sm for help! packet dropped: \"%.*s\"\n", ZONE, jid_full(jid), len, xml); 00106 nad_free(copy); 00107 continue; 00108 } 00109 log_debug(ZONE, "resending to %s", jid_full(jid)); 00110 pkt_router(pkt_dup(pkt, jid_full(jid), jid_user(pkt->to))); 00111 } 00112 00113 for(jid = msg; jid != NULL; jid = jid->next) 00114 if(!jid_search(all, jid)) 00115 { 00116 log_debug(ZONE, "resending to %s", jid_full(jid)); 00117 pkt_router(pkt_dup(pkt, jid_full(jid), jid_user(pkt->to))); 00118 } 00119 00120 /* !!! autoreply */ 00121 00122 free(subject); 00123 pkt_free(pkt); 00124 00125 return mod_HANDLED; 00126 } 00127 00128 static void _help_disco_extend(mod_instance_t mi, pkt_t pkt) 00129 { 00130 module_t mod = mi->mod; 00131 int ns, i, n; 00132 config_elem_t elem; 00133 char confelem[64]; 00134 00135 log_debug(ZONE, "in mod_help disco-extend"); 00136 00137 if(config_get(mod->mm->sm->config, "discovery.serverinfo") == NULL) 00138 return; 00139 00140 ns = nad_add_namespace(pkt->nad, uri_XDATA, NULL); 00141 /* there may be several XDATA siblings, so need to enforce the NS */ 00142 pkt->nad->scope = ns; 00143 00144 nad_append_elem(pkt->nad, ns, "x", 3); 00145 nad_append_attr(pkt->nad, -1, "type", "result"); 00146 /* hidden form type field*/ 00147 nad_append_elem(pkt->nad, -1, "field", 4); 00148 nad_append_attr(pkt->nad, -1, "var", "FORM_TYPE"); 00149 nad_append_attr(pkt->nad, -1, "type", "hidden"); 00150 nad_append_elem(pkt->nad, -1, "value", 5); 00151 nad_append_cdata(pkt->nad, uri_SERVERINFO, strlen(uri_SERVERINFO), 6); 00152 00153 /* loop over serverinfo fields */ 00154 for(i = 0; _serverinfo_fields[i]; i++) { 00155 snprintf(confelem, 64, "discovery.serverinfo.%s.value", _serverinfo_fields[i]); 00156 elem = config_get(mod->mm->sm->config, confelem); 00157 00158 if(elem != NULL) { 00159 nad_append_elem(pkt->nad, -1, "field", 4); 00160 nad_append_attr(pkt->nad, -1, "var", _serverinfo_fields[i]); 00161 00162 for(n = 0; n < elem->nvalues; n++) { 00163 log_debug(ZONE, "adding %s: %s", confelem, elem->values[n]); 00164 nad_append_elem(pkt->nad, -1, "value", 5); 00165 nad_append_cdata(pkt->nad, elem->values[n], strlen(elem->values[n]), 6); 00166 } 00167 } 00168 } 00169 } 00170 00171 DLLEXPORT int module_init(mod_instance_t mi, char *arg) { 00172 module_t mod = mi->mod; 00173 00174 if(mod->init) return 0; 00175 00176 /* store /help resource for use when answering probes */ 00177 mod->private = "help"; 00178 00179 mod->pkt_sm = _help_pkt_sm; 00180 mod->disco_extend = _help_disco_extend; 00181 /* module data is static so nothing to free */ 00182 /* mod->free = _help_free; */ 00183 00184 return 0; 00185 }