jabberd2  2.2.16
sm/mod_help.c
Go to the documentation of this file.
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 }