/* always returns number of bytes written or that would have been * written if the buffer was large enough * return values < 0 indicate some error occurred, * and return values > buflen indicate buffer was not large enough */ static int _render_stanza_recursive(xmpp_stanza_t *stanza, char * const buf, size_t const buflen) { char *ptr = buf; size_t left = buflen; int ret, written; xmpp_stanza_t *child; hash_iterator_t *iter; const char *key; char *tmp; written = 0; if (stanza->type == XMPP_STANZA_UNKNOWN) return XMPP_EINVOP; if (stanza->type == XMPP_STANZA_TEXT) { if (!stanza->data) return XMPP_EINVOP; tmp = _escape_xml(stanza->ctx, stanza->data); if (tmp == NULL) return XMPP_EMEM; ret = xmpp_snprintf(ptr, left, "%s", tmp); xmpp_free(stanza->ctx, tmp); if (ret < 0) return XMPP_EMEM; _render_update(&written, buflen, ret, &left, &ptr); } else { /* stanza->type == XMPP_STANZA_TAG */ if (!stanza->data) return XMPP_EINVOP; /* write beginning of tag and attributes */ ret = xmpp_snprintf(ptr, left, "<%s", stanza->data); if (ret < 0) return XMPP_EMEM; _render_update(&written, buflen, ret, &left, &ptr); if (stanza->attributes && hash_num_keys(stanza->attributes) > 0) { iter = hash_iter_new(stanza->attributes); while ((key = hash_iter_next(iter))) { if (!strcmp(key, "xmlns")) { /* don't output namespace if parent stanza is the same */ if (stanza->parent && stanza->parent->attributes && hash_get(stanza->parent->attributes, key) && !strcmp((char*)hash_get(stanza->attributes, key), (char*)hash_get(stanza->parent->attributes, key))) continue; /* or if this is the stream namespace */ if (!stanza->parent && !strcmp((char*)hash_get(stanza->attributes, key), XMPP_NS_CLIENT)) continue; } tmp = _escape_xml(stanza->ctx, (char *)hash_get(stanza->attributes, key)); if (tmp == NULL) return XMPP_EMEM; ret = xmpp_snprintf(ptr, left, " %s=\"%s\"", key, tmp); xmpp_free(stanza->ctx, tmp); if (ret < 0) return XMPP_EMEM; _render_update(&written, buflen, ret, &left, &ptr); } hash_iter_release(iter); } if (!stanza->children) { /* write end if singleton tag */ ret = xmpp_snprintf(ptr, left, "/>"); if (ret < 0) return XMPP_EMEM; _render_update(&written, buflen, ret, &left, &ptr); } else { /* this stanza has child stanzas */ /* write end of start tag */ ret = xmpp_snprintf(ptr, left, ">"); if (ret < 0) return XMPP_EMEM; _render_update(&written, buflen, ret, &left, &ptr); /* iterate and recurse over child stanzas */ child = stanza->children; while (child) { ret = _render_stanza_recursive(child, ptr, left); if (ret < 0) return ret; _render_update(&written, buflen, ret, &left, &ptr); child = child->next; } /* write end tag */ ret = xmpp_snprintf(ptr, left, "</%s>", stanza->data); if (ret < 0) return XMPP_EMEM; _render_update(&written, buflen, ret, &left, &ptr); } } return written; }
static PyObject* escape_xml(PyObject* self, PyObject *args) { return _escape_xml(self, args, escapes); }
static PyObject* escape_xml_cdata(PyObject* self, PyObject *args) { return _escape_xml(self, args, escapes_cdata); }
int _recurse_jsonObjectToXML(const jsonObject* obj, growing_buffer* res_xml) { char * hint = NULL; if (obj->classname) hint = strdup(obj->classname); if(obj->type == JSON_NULL) { if (hint) buffer_fadd(res_xml, "<null class_hint=\"%s\"/>",hint); else buffer_add(res_xml, "<null/>"); } else if(obj->type == JSON_BOOL) { const char* bool_val; if (obj->value.b) bool_val = "true"; else bool_val = "false"; if (hint) buffer_fadd(res_xml, "<boolean value=\"%s\" class_hint=\"%s\"/>", bool_val, hint); else buffer_fadd(res_xml, "<boolean value=\"%s\"/>", bool_val); } else if (obj->type == JSON_STRING) { if (hint) { char * t = _escape_xml(jsonObjectGetString(obj)); buffer_fadd(res_xml,"<string class_hint=\"%s\">%s</string>", hint, t); free(t); } else { char * t = _escape_xml(jsonObjectGetString(obj)); buffer_fadd(res_xml,"<string>%s</string>", t); free(t); } } else if(obj->type == JSON_NUMBER) { double x = jsonObjectGetNumber(obj); if (hint) { if (x == (int)x) buffer_fadd(res_xml,"<number class_hint=\"%s\">%d</number>", hint, (int)x); else buffer_fadd(res_xml,"<number class_hint=\"%s\">%lf</number>", hint, x); } else { if (x == (int)x) buffer_fadd(res_xml,"<number>%d</number>", (int)x); else buffer_fadd(res_xml,"<number>%lf</number>", x); } } else if (obj->type == JSON_ARRAY) { if (hint) buffer_fadd(res_xml,"<array class_hint=\"%s\">", hint); else buffer_add(res_xml,"<array>"); int i; for ( i = 0; i!= obj->size; i++ ) _recurse_jsonObjectToXML(jsonObjectGetIndex(obj,i), res_xml); buffer_add(res_xml,"</array>"); } else if (obj->type == JSON_HASH) { if (hint) buffer_fadd(res_xml,"<object class_hint=\"%s\">", hint); else buffer_add(res_xml,"<object>"); jsonIterator* itr = jsonNewIterator(obj); const jsonObject* tmp; while( (tmp = jsonIteratorNext(itr)) ) { buffer_fadd(res_xml,"<element key=\"%s\">",itr->key); _recurse_jsonObjectToXML(tmp, res_xml); buffer_add(res_xml,"</element>"); } jsonIteratorFree(itr); buffer_add(res_xml,"</object>"); } if (hint) free(hint); return 1; }