jabberd2
2.2.16
|
00001 /* 00002 * jabberd - Jabber Open Source Server 00003 * Copyright (c) 2002-2003 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 /* xdata, whee! */ 00022 00023 #include "util.h" 00024 00026 xdata_t xdata_new(xdata_type_t type, char *title, char *instructions) { 00027 pool_t p; 00028 xdata_t xd; 00029 00030 assert((int) type); 00031 00032 p = pool_new(); 00033 00034 xd = pmalloco(p, sizeof(struct _xdata_st)); 00035 00036 xd->p = p; 00037 00038 xd->type = type; 00039 00040 if(title != NULL) xd->title = pstrdup(xd->p, title); 00041 if(instructions != NULL) xd->instructions = pstrdup(xd->p, instructions); 00042 00043 log_debug(ZONE, "created new xd; title=%s, instructions=%s", title, instructions); 00044 00045 return xd; 00046 } 00047 00049 xdata_field_t xdata_field_new(xdata_t xd, xdata_field_type_t type, char *var, char *label, char *desc, int required) { 00050 xdata_field_t xdf; 00051 00052 assert((int) (xd != NULL)); 00053 assert((int) type); 00054 assert((int) (var != NULL)); 00055 00056 xdf = pmalloco(xd->p, sizeof(struct _xdata_field_st)); 00057 00058 xdf->p = xd->p; 00059 00060 xdf->type = type; 00061 00062 xdf->var = pstrdup(xdf->p, var); 00063 00064 if(label != NULL) xdf->label = pstrdup(xdf->p, label); 00065 if(desc != NULL) xdf->desc = pstrdup(xdf->p, desc); 00066 00067 xdf->required = required; 00068 00069 return xdf; 00070 } 00071 00073 xdata_item_t xdata_item_new(xdata_t xd) { 00074 xdata_item_t xdi; 00075 00076 assert((int) (xd != NULL)); 00077 00078 xdi = pmalloco(xd->p, sizeof(struct _xdata_item_st)); 00079 00080 xdi->p = xd->p; 00081 00082 return xdi; 00083 } 00084 00086 void xdata_add_field(xdata_t xd, xdata_field_t xdf) { 00087 assert((int) (xd != NULL)); 00088 assert((int) (xdf != NULL)); 00089 00090 if(xd->fields == NULL) 00091 xd->fields = xd->flast = xdf; 00092 else { 00093 xd->flast->next = xdf; 00094 xd->flast = xdf; 00095 } 00096 } 00097 00098 void xdata_add_rfield(xdata_t xd, xdata_field_t xdf) { 00099 assert((int) (xd != NULL)); 00100 assert((int) (xdf != NULL)); 00101 00102 if(xd->rfields == NULL) 00103 xd->rfields = xd->rflast = xdf; 00104 else { 00105 xd->rflast->next = xdf; 00106 xd->rflast = xdf; 00107 } 00108 } 00109 00110 void xdata_add_field_item(xdata_item_t xdi, xdata_field_t xdf) { 00111 assert((int) (xdi != NULL)); 00112 assert((int) (xdf != NULL)); 00113 00114 if(xdi->fields == NULL) 00115 xdi->fields = xdi->flast = xdf; 00116 else { 00117 xdi->flast->next = xdf; 00118 xdi->flast = xdf; 00119 } 00120 } 00121 00123 void xdata_add_item(xdata_t xd, xdata_item_t xdi) { 00124 assert((int) (xd != NULL)); 00125 assert((int) (xdi != NULL)); 00126 00127 if(xd->items == NULL) 00128 xd->items = xd->ilast = xdi; 00129 else { 00130 xd->ilast->next = xdi; 00131 xd->ilast = xdi; 00132 } 00133 } 00134 00136 static void xdata_option_new(xdata_field_t xdf, char *value, int lvalue, char *label, int llabel) { 00137 xdata_option_t xdo; 00138 00139 assert((int) (xdf != NULL)); 00140 assert((int) (value != NULL)); 00141 00142 xdo = pmalloco(xdf->p, sizeof(struct _xdata_option_st)); 00143 00144 xdo->p = xdf->p; 00145 00146 if(lvalue <= 0) lvalue = strlen(value); 00147 xdo->value = pstrdupx(xdo->p, value, lvalue); 00148 00149 if(label != NULL) { 00150 if(llabel <= 0) llabel = strlen(label); 00151 xdo->label = pstrdupx(xdo->p, label, llabel); 00152 } 00153 00154 xdf->olast->next = xdo; 00155 xdf->olast = xdo; 00156 if(xdf->options == NULL) xdf->options = xdo; 00157 } 00158 00160 void xdata_add_value(xdata_field_t xdf, char *value, int vlen) { 00161 int first = 0; 00162 00163 assert((int) (xdf != NULL)); 00164 assert((int) (value != NULL)); 00165 00166 if(vlen <= 0) vlen = strlen(value); 00167 00168 if(xdf->values == NULL) 00169 first = 1; 00170 00171 xdf->values = (char **) realloc(xdf->values, sizeof(char *) * (xdf->nvalues + 1)); 00172 xdf->values[xdf->nvalues] = pstrdupx(xdf->p, value, vlen); 00173 xdf->nvalues++; 00174 00175 if(first) 00176 pool_cleanup(xdf->p, free, xdf->values); 00177 } 00178 00180 static xdata_field_t _xdata_field_parse(xdata_t xd, nad_t nad, int root) { 00181 xdata_field_t xdf; 00182 int attr, elem, eval; 00183 00184 xdf = pmalloco(xd->p, sizeof(struct _xdata_field_st)); 00185 00186 xdf->p = xd->p; 00187 00188 attr = nad_find_attr(nad, root, -1, "var", NULL); 00189 if(attr >= 0) 00190 xdf->var = pstrdupx(xdf->p, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)); 00191 00192 attr = nad_find_attr(nad, root, -1, "label", NULL); 00193 if(attr >= 0) 00194 xdf->label = pstrdupx(xdf->p, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)); 00195 00196 attr = nad_find_attr(nad, root, -1, "desc", NULL); 00197 if(attr >= 0) 00198 xdf->desc = pstrdupx(xdf->p, NAD_AVAL(nad, attr), NAD_AVAL_L(nad, attr)); 00199 00200 if(nad_find_elem(nad, root, NAD_ENS(nad, root), "required", 1) >= 0) 00201 xdf->required = 1; 00202 00203 attr = nad_find_attr(nad, root, -1, "type", NULL); 00204 if(attr >= 0) { 00205 if(NAD_AVAL_L(nad, attr) == 7 && strncmp("boolean", NAD_AVAL(nad, attr), 7) == 0) 00206 xdf->type = xd_field_BOOLEAN; 00207 else if(NAD_AVAL_L(nad, attr) == 5 && strncmp("fixed", NAD_AVAL(nad, attr), 5) == 0) 00208 xdf->type = xd_field_FIXED; 00209 else if(NAD_AVAL_L(nad, attr) == 6 && strncmp("hidden", NAD_AVAL(nad, attr), 6) == 0) 00210 xdf->type = xd_field_HIDDEN; 00211 else if(NAD_AVAL_L(nad, attr) == 9 && strncmp("jid-multi", NAD_AVAL(nad, attr), 9) == 0) 00212 xdf->type = xd_field_JID_MULTI; 00213 else if(NAD_AVAL_L(nad, attr) == 10 && strncmp("jid-single", NAD_AVAL(nad, attr), 10) == 0) 00214 xdf->type = xd_field_JID_SINGLE; 00215 else if(NAD_AVAL_L(nad, attr) == 10 && strncmp("list-multi", NAD_AVAL(nad, attr), 10) == 0) 00216 xdf->type = xd_field_LIST_MULTI; 00217 else if(NAD_AVAL_L(nad, attr) == 11 && strncmp("list-single", NAD_AVAL(nad, attr), 11) == 0) 00218 xdf->type = xd_field_LIST_SINGLE; 00219 else if(NAD_AVAL_L(nad, attr) == 10 && strncmp("text-multi", NAD_AVAL(nad, attr), 10) == 0) 00220 xdf->type = xd_field_TEXT_MULTI; 00221 else if(NAD_AVAL_L(nad, attr) == 12 && strncmp("text-private", NAD_AVAL(nad, attr), 12) == 0) 00222 xdf->type = xd_field_TEXT_PRIVATE; 00223 else if(NAD_AVAL_L(nad, attr) == 11 && strncmp("text-single", NAD_AVAL(nad, attr), 11) == 0) 00224 xdf->type = xd_field_TEXT_SINGLE; 00225 else { 00226 log_debug(ZONE, "unknown field type '%.*s'", NAD_AVAL_L(nad, attr), NAD_AVAL(nad, attr)); 00227 return NULL; 00228 } 00229 } 00230 00231 elem = nad_find_elem(nad, root, NAD_ENS(nad, root), "value", 1); 00232 while(elem >= 0) { 00233 if(NAD_CDATA_L(nad, elem) <= 0) { 00234 log_debug(ZONE, "value element requires cdata"); 00235 return NULL; 00236 } 00237 00238 xdata_add_value(xdf, NAD_CDATA(nad, elem), NAD_CDATA_L(nad, elem)); 00239 00240 elem = nad_find_elem(nad, elem, NAD_ENS(nad, elem), "value", 0); 00241 } 00242 00243 elem = nad_find_elem(nad, root, NAD_ENS(nad, root), "options", 1); 00244 while(elem >= 0) { 00245 eval = nad_find_elem(nad, elem, NAD_ENS(nad, elem), "value", 1); 00246 if(eval < 0) { 00247 log_debug(ZONE, "option requires value subelement"); 00248 return NULL; 00249 } 00250 00251 if(NAD_CDATA_L(nad, eval) <= 0) { 00252 log_debug(ZONE, "value element requires cdata"); 00253 return NULL; 00254 } 00255 00256 attr = nad_find_attr(nad, elem, -1, "label", NULL); 00257 if(attr < 0) 00258 xdata_option_new(xdf, NAD_CDATA(nad, eval), NAD_CDATA_L(nad, eval), NAD_AVAL(nad, eval), NAD_AVAL_L(nad, eval)); 00259 else 00260 xdata_option_new(xdf, NAD_CDATA(nad, eval), NAD_CDATA_L(nad, eval), NULL, 0); 00261 00262 elem = nad_find_elem(nad, elem, NAD_ENS(nad, elem), "options", 0); 00263 } 00264 00265 return xdf; 00266 } 00267 00269 xdata_t xdata_parse(nad_t nad, int root) { 00270 xdata_t xd; 00271 int atype, elem, field; 00272 xdata_field_t xdf; 00273 00274 assert((int) (nad != NULL)); 00275 assert((int) (root >= 0)); 00276 00277 log_debug(ZONE, "building xd from nad"); 00278 00279 if(root >= nad->ecur || NAD_NURI_L(nad, NAD_ENS(nad, root)) != strlen(uri_XDATA) || strncmp(uri_XDATA, NAD_NURI(nad, NAD_ENS(nad, root)), strlen(uri_XDATA) != 0) || NAD_ENAME_L(nad, root) != 1 || (NAD_ENAME(nad, root))[0] != 'x') { 00280 log_debug(ZONE, "elem %d does not exist, or is not {x:data}x", root); 00281 return NULL; 00282 } 00283 00284 atype = nad_find_attr(nad, root, -1, "type", NULL); 00285 if(atype < 0) { 00286 log_debug(ZONE, "no type attribute"); 00287 return NULL; 00288 } 00289 00290 if(NAD_AVAL_L(nad, atype) == 4 && strncmp("form", NAD_AVAL(nad, atype), NAD_AVAL_L(nad, atype)) == 0) 00291 xd = xdata_new(xd_type_FORM, NULL, NULL); 00292 else if(NAD_AVAL_L(nad, atype) == 6 && strncmp("result", NAD_AVAL(nad, atype), NAD_AVAL_L(nad, atype)) == 0) 00293 xd = xdata_new(xd_type_RESULT, NULL, NULL); 00294 else if(NAD_AVAL_L(nad, atype) == 6 && strncmp("submit", NAD_AVAL(nad, atype), NAD_AVAL_L(nad, atype)) == 0) 00295 xd = xdata_new(xd_type_SUBMIT, NULL, NULL); 00296 else if(NAD_AVAL_L(nad, atype) == 6 && strncmp("cancel", NAD_AVAL(nad, atype), NAD_AVAL_L(nad, atype)) == 0) 00297 xd = xdata_new(xd_type_CANCEL, NULL, NULL); 00298 else { 00299 log_debug(ZONE, "unknown xd type %.*s", NAD_AVAL_L(nad, atype), NAD_AVAL(nad, atype)); 00300 return NULL; 00301 } 00302 00303 elem = nad_find_elem(nad, root, NAD_ENS(nad, root), "title", 1); 00304 if(elem < 0 || NAD_CDATA_L(nad, elem) <= 0) { 00305 log_debug(ZONE, "no cdata on x/title element"); 00306 pool_free(xd->p); 00307 return NULL; 00308 } 00309 00310 xd->title = pmalloco(xd->p, sizeof(char) * (NAD_CDATA_L(nad, elem) + 1)); 00311 strncpy(xd->title, NAD_CDATA(nad, elem), NAD_CDATA_L(nad, elem)); 00312 00313 elem = nad_find_elem(nad, root, NAD_ENS(nad, root), "instructions", 1); 00314 if(elem < 0 || NAD_CDATA_L(nad, elem) <= 0) { 00315 log_debug(ZONE, "no cdata on x/instructions element"); 00316 pool_free(xd->p); 00317 return NULL; 00318 } 00319 00320 xd->instructions = pstrdupx(xd->p, NAD_CDATA(nad, elem), NAD_CDATA_L(nad, elem)); 00321 00322 switch(xd->type) { 00323 case xd_type_FORM: 00324 case xd_type_SUBMIT: 00325 /* form and submit just have fields, one level */ 00326 field = nad_find_elem(nad, root, NAD_ENS(nad, root), "field", 1); 00327 while(field >= 0) { 00328 xdf = _xdata_field_parse(xd, nad, field); 00329 if(xdf == NULL) { 00330 log_debug(ZONE, "field parse failed"); 00331 pool_free(xd->p); 00332 return NULL; 00333 } 00334 00335 xdata_add_field(xd, xdf); 00336 00337 field = nad_find_elem(nad, field, NAD_ENS(nad, root), "field", 0); 00338 } 00339 00340 break; 00341 00342 case xd_type_RESULT: 00343 /* result has reported and item */ 00344 elem = nad_find_elem(nad, root, NAD_ENS(nad, root), "reported", 1); 00345 if(elem >= 0) { 00346 field = nad_find_elem(nad, elem, NAD_ENS(nad, root), "field", 1); 00347 while(field >= 0) { 00348 xdf = _xdata_field_parse(xd, nad, field); 00349 if(xdf == NULL) { 00350 log_debug(ZONE, "field parse failed"); 00351 pool_free(xd->p); 00352 return NULL; 00353 } 00354 00355 xdata_add_field(xd, xdf); 00356 00357 field = nad_find_elem(nad, field, NAD_ENS(nad, root), "field", 0); 00358 } 00359 } 00360 00361 elem = nad_find_elem(nad, root, NAD_ENS(nad, root), "item", 1); 00362 if(elem >= 0) { 00363 field = nad_find_elem(nad, elem, NAD_ENS(nad, root), "field", 1); 00364 while(field >= 0) { 00365 xdf = _xdata_field_parse(xd, nad, field); 00366 if(xdf == NULL) { 00367 log_debug(ZONE, "field parse failed"); 00368 pool_free(xd->p); 00369 return NULL; 00370 } 00371 00372 xdata_add_field(xd, xdf); 00373 00374 field = nad_find_elem(nad, field, NAD_ENS(nad, root), "field", 0); 00375 } 00376 } 00377 00378 break; 00379 00380 case xd_type_CANCEL: 00381 /* nothing to do with cancel, its all based on context */ 00382 break; 00383 00384 case xd_type_NONE: 00385 break; 00386 } 00387 00388 return xd; 00389 }