WBXML_DECLARE(WBXMLError) wbxml_buffer_encode_base64(WBXMLBuffer *buffer) { WB_UTINY *result = NULL; WBXMLError ret = WBXML_OK; if ( (buffer == NULL) || (buffer->is_static) ) { return WBXML_ERROR_INTERNAL; } if ((result = wbxml_base64_encode((const WB_UTINY *) wbxml_buffer_get_cstr(buffer), wbxml_buffer_len(buffer))) == NULL) { return WBXML_ERROR_B64_ENC; } /* Reset buffer */ wbxml_buffer_delete(buffer, 0, wbxml_buffer_len(buffer)); /* Set data */ if (!wbxml_buffer_append_cstr(buffer, result)) { ret = WBXML_ERROR_NOT_ENOUGH_MEMORY; } wbxml_free(result); return ret; }
WBXML_DECLARE(void) wbxml_buffer_strip_blanks(WBXMLBuffer *buffer) { WB_ULONG start = 0, end = 0, len = 0; WB_UTINY ch = 0; if ((buffer == NULL) || buffer->is_static) return; /* Remove whitespaces at beginning of buffer... */ while (wbxml_buffer_get_char(buffer, start, &ch) && isspace(ch) && start <= wbxml_buffer_len(buffer)) { start ++; } if (start > 0) wbxml_buffer_delete(buffer, 0, start); /* ... and at the end */ if ((len = wbxml_buffer_len(buffer)) > 0) { end = len = len - 1; while (wbxml_buffer_get_char(buffer, end, &ch) && isspace(ch)) { end--; } wbxml_buffer_delete(buffer, end + 1, len - end); } }
WBXML_DECLARE(WBXMLError) wbxml_buffer_decode_base64(WBXMLBuffer *buffer) { WB_UTINY *result = NULL; WB_LONG len = 0; WBXMLError ret = WBXML_OK; if ( (buffer == NULL) || (buffer->is_static) ) { return WBXML_ERROR_INTERNAL; } wbxml_buffer_no_spaces(buffer); if ((len = wbxml_base64_decode((const WB_UTINY *) wbxml_buffer_get_cstr(buffer), wbxml_buffer_len(buffer), &result)) <= 0) { return WBXML_ERROR_B64_DEC; } /* Reset buffer */ wbxml_buffer_delete(buffer, 0, wbxml_buffer_len(buffer)); /* Set binary data */ if (!wbxml_buffer_append_data(buffer, result, len)) { ret = WBXML_ERROR_NOT_ENOUGH_MEMORY; } wbxml_free(result); return ret; }
WBXML_DECLARE(WBXMLBuffer *) wbxml_buffer_duplicate(WBXMLBuffer *buff) { WBXMLBuffer *result = NULL; if (buff == NULL) return NULL; result = wbxml_buffer_create_real(wbxml_buffer_get_cstr(buff), wbxml_buffer_len(buff), wbxml_buffer_len(buff)); return result; }
WBXML_DECLARE(void) wbxml_buffer_remove_trailing_zeros(WBXMLBuffer **buffer) { WB_UTINY ch = 0; if ((buffer == NULL) || (*buffer == NULL)) return; while ((*buffer)->len > 0) { if (wbxml_buffer_get_char(*buffer, wbxml_buffer_len(*buffer) - 1, &ch) && (ch == '\0')) wbxml_buffer_delete(*buffer, wbxml_buffer_len(*buffer) - 1, 1); else return; } }
WBXML_DECLARE(WB_BOOL) wbxml_buffer_binary_to_hex(WBXMLBuffer *buffer, WB_BOOL uppercase) { WB_UTINY *hexits = NULL; WB_LONG i = 0; if ((buffer == NULL) || buffer->is_static) return FALSE; if (wbxml_buffer_len(buffer) == 0) return TRUE; hexits = (WB_UTINY *)(uppercase ? "0123456789ABCDEF" : "0123456789abcdef"); /* Grows the Buffer size by 2 */ grow_buff(buffer, buffer->len * 2); /* In-place modification must be done back-to-front to avoid * overwriting the data while we read it. Even the order of * the two assignments is important, to get i == 0 right. */ for (i = buffer->len - 1; i >= 0; i--) { buffer->data[i * 2 + 1] = hexits[buffer->data[i] % 16]; buffer->data[i * 2] = hexits[(buffer->data[i] / 16) & 0xf]; } buffer->len = buffer->len * 2; buffer->data[buffer->len] = '\0'; return TRUE; }
WBXML_DECLARE(void) wbxml_buffer_hex_to_binary(WBXMLBuffer *buffer) { WB_UTINY *p = NULL; WB_ULONG i = 0, len = 0; if ((buffer == NULL) || buffer->is_static) return; p = buffer->data; len = wbxml_buffer_len(buffer); /* Convert ascii data to binary values */ for (i = 0; i < len; i++, p++) { if (*p >= '0' && *p <= '9') *p -= '0'; else if (*p >= 'a' && *p <= 'f') *p = (WB_UTINY) (*p - 'a' + 10); else if (*p >= 'A' && *p <= 'F') *p = (WB_UTINY) (*p - 'A' + 10); else { /* Bad Bad ! There should be only digits in the buffer ! */ *p = 0; } } /* De-hexing will compress data by factor of 2 */ len = buffer->len / 2; for (i = 0; i < len; i++) buffer->data[i] = (WB_UTINY) (buffer->data[i * 2] * 16 | buffer->data[i * 2 + 1]); buffer->len = len; buffer->data[len] = '\0'; }
WBXML_DECLARE(void) wbxml_buffer_shrink_blanks(WBXMLBuffer *buffer) { WB_ULONG i = 0, j = 0, end = 0; WB_UTINY ch = 0; if ((buffer == NULL) || buffer->is_static) return; end = wbxml_buffer_len(buffer); for (i = 0; i < end; i++) { if (wbxml_buffer_get_char(buffer, i, &ch) && isspace(ch)) { /* Replace space by a whitespace */ if (ch != ' ') wbxml_buffer_set_char(buffer, i, ' '); /* Remove all following spaces */ j = i = i + 1; while (wbxml_buffer_get_char(buffer, j, &ch) && isspace(ch)) j++; if (j - i > 1) wbxml_buffer_delete(buffer, i, j - i); } } }
WBXML_DECLARE(WB_BOOL) wbxml_buffer_remove_trailing_zeros(WBXMLBuffer *buffer) { WB_UTINY ch = 0; if ((buffer == NULL) || (buffer->is_static)) return FALSE; while (buffer->len > 0) { if (wbxml_buffer_get_char(buffer, wbxml_buffer_len(buffer) - 1, &ch) && (ch == '\0')) wbxml_buffer_delete(buffer, wbxml_buffer_len(buffer) - 1, 1); else return TRUE; } return TRUE; }
WBXML_DECLARE(WB_BOOL) wbxml_buffer_append(WBXMLBuffer *dest, WBXMLBuffer *buff) { if ((dest == NULL) || dest->is_static) return FALSE; if (buff == NULL) return TRUE; return wbxml_buffer_append_data(dest, wbxml_buffer_get_cstr(buff), wbxml_buffer_len(buff)); }
WBXML_DECLARE(void) wbxml_buffer_no_spaces(WBXMLBuffer *buffer) { WB_ULONG i = 0, j = 0, end = 0; WB_UTINY ch = 0; if ((buffer == NULL) || buffer->is_static) return; while (i < wbxml_buffer_len(buffer)) { if (wbxml_buffer_get_char(buffer, i, &ch) && isspace(ch)) { wbxml_buffer_delete(buffer, i, 1); } else { i++; } } }
void wbxml_tree_clb_xml_end_element(void *ctx, const XML_Char *localName) { WBXMLTreeClbCtx *tree_ctx = (WBXMLTreeClbCtx *) ctx; WBXMLBuffer *content = NULL; WBXMLTreeNode *node = NULL; WBXMLError ret = WBXML_OK; WBXML_DEBUG((WBXML_PARSER, "Expat element end callback ('%s')", localName)); /* If the node is flagged as binary node * then the data is base64 encoded in the XML document * and the data must be decoded in one step. * Examples: Microsoft ActiveSync tags ConversationId or MIME */ node = tree_ctx->current; if (node && node->type == WBXML_TREE_ELEMENT_NODE && node->name->type == WBXML_VALUE_TOKEN && node->name->u.token->options & WBXML_TAG_OPTION_BINARY) { if (node->content == NULL) { WBXML_DEBUG((WBXML_PARSER, " Binary tag: No content => no conversion!")); } else { WBXML_DEBUG((WBXML_PARSER, " Binary tag: Convert base64 data")); ret = wbxml_buffer_decode_base64(node->content); if (ret != WBXML_OK) { WBXML_DEBUG((WBXML_PARSER, " Binary tag: Base64 decoder failed!")); tree_ctx->error = ret; } else { /* Add the buffer as a regular string node (since libwbxml doesn't * offer a way to specify an opaque data node). The WBXML * encoder is responsible for generating correct opaque data for * nodes like this. */ if (wbxml_tree_add_text(tree_ctx->tree, tree_ctx->current, (const WB_UTINY*)wbxml_buffer_get_cstr(node->content), wbxml_buffer_len(node->content)) == NULL) { WBXML_DEBUG((WBXML_PARSER, " Binary tag: Cannot add base64 decoded node!")); tree_ctx->error = WBXML_ERROR_INTERNAL; } } /* safe cleanup */ content = node->content; node->content = NULL; wbxml_buffer_destroy(content); } } if (tree_ctx->expat_utf16) { /** @todo Convert from UTF-16 to UTF-8 */ } /* Check for Error */ if (tree_ctx->error != WBXML_OK) return; /* Are we skipping a whole node ? */ if (tree_ctx->skip_lvl > 0) { if (tree_ctx->skip_lvl == 1) { /* End of skipped node */ #if defined( WBXML_SUPPORT_SYNCML ) if (WBXML_STRCMP(localName, "syncml:devinf:DevInf") == 0 || WBXML_STRCMP(localName, "syncml:dmddf1.2:MgmtTree") == 0) { /* definitions first ... or some compilers don't like it */ WBXMLBuffer *embed_doc = NULL; WBXMLTree *tree = NULL; const WBXMLLangEntry *lang; /* Get embedded DevInf or DM DDF Document */ embed_doc = wbxml_buffer_create(tree_ctx->input_buff + tree_ctx->skip_start, XML_GetCurrentByteIndex(tree_ctx->xml_parser) - tree_ctx->skip_start, XML_GetCurrentByteIndex(tree_ctx->xml_parser) - tree_ctx->skip_start + 10); if (embed_doc == NULL) { tree_ctx->error = WBXML_ERROR_NOT_ENOUGH_MEMORY; wbxml_buffer_destroy(embed_doc); return; } if (tree_ctx->expat_utf16) { /** @todo Convert from UTF-16 to UTF-8 */ } /* Check Buffer Creation and add the closing tag */ if ((WBXML_STRCMP(localName, "syncml:devinf:DevInf") == 0 && (!wbxml_buffer_append_cstr(embed_doc, "</DevInf>"))) || (WBXML_STRCMP(localName, "syncml:dmddf1.2:MgmtTree") == 0 && (!wbxml_buffer_append_cstr(embed_doc, "</MgmtTree>")))) { tree_ctx->error = WBXML_ERROR_NOT_ENOUGH_MEMORY; wbxml_buffer_destroy(embed_doc); return; } /* Add doctype to give the XML parser a chance */ if (WBXML_STRCMP(localName, "syncml:dmddf1.2:MgmtTree") == 0 && tree_ctx->tree->lang->langID != WBXML_LANG_SYNCML_SYNCML12) { tree_ctx->error = WBXML_ERROR_UNKNOWN_XML_LANGUAGE; wbxml_buffer_destroy(embed_doc); return; } switch(tree_ctx->tree->lang->langID) { case WBXML_LANG_SYNCML_SYNCML10: lang = wbxml_tables_get_table(WBXML_LANG_SYNCML_DEVINF10); break; case WBXML_LANG_SYNCML_SYNCML11: lang = wbxml_tables_get_table(WBXML_LANG_SYNCML_DEVINF11); break; case WBXML_LANG_SYNCML_SYNCML12: if (WBXML_STRCMP(localName, "syncml:dmddf1.2:MgmtTree") == 0) { lang = wbxml_tables_get_table(WBXML_LANG_SYNCML_DMDDF12); } else { lang = wbxml_tables_get_table(WBXML_LANG_SYNCML_DEVINF12); } break; default: tree_ctx->error = WBXML_ERROR_UNKNOWN_XML_LANGUAGE; wbxml_buffer_destroy(embed_doc); return; } assert (lang!= NULL); if (lang == NULL) { tree_ctx->error = WBXML_ERROR_UNKNOWN_XML_LANGUAGE; wbxml_buffer_destroy(embed_doc); return; } /* DOCTYPE in reverse order */ if (!wbxml_buffer_insert_cstr(embed_doc,(WB_UTINY *) "\">\n", 0) || /* > */ !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) lang->publicID->xmlDTD, 0) || /* DTD */ !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) "\" \"", 0) || /* DTD */ !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) lang->publicID->xmlPublicID, 0) || /* Public ID */ !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) " PUBLIC \"", 0) || /* PUBLIC " */ !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) lang->publicID->xmlRootElt, 0) || /* Root Element */ !wbxml_buffer_insert_cstr(embed_doc, (WB_UTINY *) "<!DOCTYPE ", 0)) /* <!DOCTYPE */ { tree_ctx->error = WBXML_ERROR_ENCODER_APPEND_DATA; wbxml_buffer_destroy(embed_doc); return; } WBXML_DEBUG((WBXML_PARSER, "\t Embedded Doc : '%s'", wbxml_buffer_get_cstr(embed_doc))); /* Parse 'DevInf' Document */ if ((ret = wbxml_tree_from_xml(wbxml_buffer_get_cstr(embed_doc), wbxml_buffer_len(embed_doc), &tree)) != WBXML_OK) { tree_ctx->error = ret; wbxml_buffer_destroy(embed_doc); return; } /* Add Tree Node */ tree_ctx->current = wbxml_tree_add_tree(tree_ctx->tree, tree_ctx->current, tree); if (tree_ctx->current == NULL) { tree_ctx->error = WBXML_ERROR_INTERNAL; wbxml_tree_destroy(tree); wbxml_buffer_destroy(embed_doc); return; } /* Clean-up */ wbxml_buffer_destroy(embed_doc); tree_ctx->skip_lvl = 0; } #endif /* WBXML_SUPPORT_SYNCML */ } else { tree_ctx->skip_lvl--; return; } } if (tree_ctx->current == NULL) { tree_ctx->error = WBXML_ERROR_INTERNAL; return; } if (tree_ctx->current->parent == NULL) { /* This must be the Root Element */ if (tree_ctx->current != tree_ctx->tree->root) { tree_ctx->error = WBXML_ERROR_INTERNAL; } } else { #if defined ( WBXML_SUPPORT_SYNCML ) /* Have we added a missing CDATA section ? * If so, we assume that now that we have reached an end of Element, * the CDATA section ended, and so we go back to parent. */ if ((tree_ctx->current != NULL) && (tree_ctx->current->type == WBXML_TREE_CDATA_NODE)) tree_ctx->current = tree_ctx->current->parent; #endif /* WBXML_SUPPORT_SYNCML */ /* Go back one step upper in the tree */ tree_ctx->current = tree_ctx->current->parent; } }