jabberd2  2.2.17
mod_help.c
Go to the documentation of this file.
1 /*
2  * jabberd - Jabber Open Source Server
3  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
4  * Ryan Eatmon, Robert Norris
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
19  */
20 
21 /* for strndup */
22 #define _GNU_SOURCE
23 #include <string.h>
24 #include "sm.h"
25 
33 /* XEP-0157 serverinfo fields */
34 static const char *_serverinfo_fields[] = {
35  "abuse-addresses",
36  "admin-addresses",
37  "feedback-addresses",
38  "sales-addresses",
39  "security-addresses",
40  "support-addresses",
41  NULL
42 };
43 
45 {
46  module_t mod = mi->mod;
47  jid_t all, msg, jid, smjid;
48  int subj, subjectl;
49  char *org_subject;
50  char *subject;
51  char *resource = (char *) mod->private;
52 
53  smjid = jid_new(jid_user(pkt->to), -1);
54  jid_reset_components(smjid, smjid->node, smjid->domain, resource);
55 
56  /* answer to probes and subscription requests */
57  if(pkt->type == pkt_PRESENCE_PROBE || pkt->type == pkt_S10N) {
58  log_debug(ZONE, "answering presence probe/sub from %s with /help resource", jid_full(pkt->from));
59 
60  /* send presence */
61  pkt_router(pkt_create(mod->mm->sm, "presence", NULL, jid_user(pkt->from), jid_full(smjid)));
62  }
63 
64  jid_free(smjid);
65 
66  /* we want messages addressed to the sm itself or /help resource */
67  if(!(pkt->type & pkt_MESSAGE) || (pkt->to->resource[0] != '\0' && strcmp(pkt->to->resource, "help")))
68  return mod_PASS;
69 
70  log_debug(ZONE, "help message from %s", jid_full(pkt->from));
71 
72  all = xhash_get(mod->mm->sm->acls, "all");
73  msg = xhash_get(mod->mm->sm->acls, "messages");
74 
75  nad_set_attr(pkt->nad, 1, -1, "type", NULL, 0);
76  subj = nad_find_elem(pkt->nad, 1, NAD_ENS(pkt->nad, 1), "subject", 1);
77  if(subj >= 0 && NAD_CDATA_L(pkt->nad, subj) > 0)
78  {
79  org_subject = strndup(NAD_CDATA(pkt->nad, subj), NAD_CDATA_L(pkt->nad, subj));
80  } else {
81  org_subject = "(none)";
82  }
83  subjectl = strlen(org_subject) + strlen(jid_full(pkt->from)) + 8;
84  subject = (char *) malloc(sizeof(char) * subjectl);
85  snprintf(subject, subjectl, "Fwd[%s]: %s", jid_full(pkt->from), org_subject);
86  if(subj >= 0 && NAD_CDATA_L(pkt->nad, subj) > 0)
87  {
88  free(org_subject);
89  nad_drop_elem(pkt->nad, subj);
90  }
91  nad_insert_elem(pkt->nad, 1, NAD_ENS(pkt->nad, 1), "subject", subject);
92 
93  for(jid = all; jid != NULL; jid = jid->next)
94  {
95  if (jid_compare_full(pkt->from, jid) == 0) {
96  /* make a copy of the nad so it can be dumped to a string */
97  nad_t copy = nad_copy(pkt->nad);
98  char * xml;
99  int len;
100  if (!copy) {
101  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));
102  continue;
103  }
104  nad_print(copy, 0, &xml, &len);
105  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);
106  nad_free(copy);
107  continue;
108  }
109  log_debug(ZONE, "resending to %s", jid_full(jid));
110  pkt_router(pkt_dup(pkt, jid_full(jid), jid_user(pkt->to)));
111  }
112 
113  for(jid = msg; jid != NULL; jid = jid->next)
114  if(!jid_search(all, jid))
115  {
116  log_debug(ZONE, "resending to %s", jid_full(jid));
117  pkt_router(pkt_dup(pkt, jid_full(jid), jid_user(pkt->to)));
118  }
119 
120  /* !!! autoreply */
121 
122  free(subject);
123  pkt_free(pkt);
124 
125  return mod_HANDLED;
126 }
127 
129 {
130  module_t mod = mi->mod;
131  int ns, i, n;
132  config_elem_t elem;
133  char confelem[64];
134 
135  log_debug(ZONE, "in mod_help disco-extend");
136 
137  if(config_get(mod->mm->sm->config, "discovery.serverinfo") == NULL)
138  return;
139 
140  ns = nad_add_namespace(pkt->nad, uri_XDATA, NULL);
141  /* there may be several XDATA siblings, so need to enforce the NS */
142  pkt->nad->scope = ns;
143 
144  nad_append_elem(pkt->nad, ns, "x", 3);
145  nad_append_attr(pkt->nad, -1, "type", "result");
146  /* hidden form type field*/
147  nad_append_elem(pkt->nad, -1, "field", 4);
148  nad_append_attr(pkt->nad, -1, "var", "FORM_TYPE");
149  nad_append_attr(pkt->nad, -1, "type", "hidden");
150  nad_append_elem(pkt->nad, -1, "value", 5);
152 
153  /* loop over serverinfo fields */
154  for(i = 0; _serverinfo_fields[i]; i++) {
155  snprintf(confelem, 64, "discovery.serverinfo.%s.value", _serverinfo_fields[i]);
156  elem = config_get(mod->mm->sm->config, confelem);
157 
158  if(elem != NULL) {
159  nad_append_elem(pkt->nad, -1, "field", 4);
160  nad_append_attr(pkt->nad, -1, "var", _serverinfo_fields[i]);
161 
162  for(n = 0; n < elem->nvalues; n++) {
163  log_debug(ZONE, "adding %s: %s", confelem, elem->values[n]);
164  nad_append_elem(pkt->nad, -1, "value", 5);
165  nad_append_cdata(pkt->nad, elem->values[n], strlen(elem->values[n]), 6);
166  }
167  }
168  }
169 }
170 
172  module_t mod = mi->mod;
173 
174  if(mod->init) return 0;
175 
176  /* store /help resource for use when answering probes */
177  mod->private = "help";
178 
179  mod->pkt_sm = _help_pkt_sm;
181  /* module data is static so nothing to free */
182  /* mod->free = _help_free; */
183 
184  return 0;
185 }