📄 wml_compiler.c
字号:
break; } /* * If node is an element with content, it will need an end tag after it's * children. The status for it is returned by parse_element. */ switch (status) { case 0: if (node->children != NULL) if (parse_node(node->children, wbxml) == -1) return -1; break; case 1: if (node->children != NULL) if (parse_node(node->children, wbxml) == -1) return -1; parse_st_end(wbxml); break; case -1: /* Something went wrong in the parsing. */ return -1; default: error(0, "WML compiler: undefined return value in a parse function."); return -1; break; } if (node->next != NULL) if (parse_node(node->next, wbxml) == -1) return -1; return 0;}/* * parse_document - the parsing function for the document node. * The function outputs the WBXML version, WML public id and the * character set values into start of the wbxml. */static int parse_document(xmlDocPtr document, Octstr *charset, wml_binary_t **wbxml, Octstr *version){ xmlNodePtr node; Octstr *externalID = NULL; long i; if (document == NULL) { error(0, "WML compiler: XML parsing failed, no parsed document."); error(0, "Most probably an error in the WML source."); return -1; } /* Return WBXML version dependent on device given Encoding-Version */ if (version == NULL) { (*wbxml)->wbxml_version = 0x01; /* WBXML Version number 1.1 */ info(0, "WBXML: No wbxml version given, assuming 1.1"); } else { for (i = 0; i < NUMBER_OF_WBXML_VERSION; i++) { if (octstr_compare(version, octstr_imm(wbxml_version[i].string)) == 0) { (*wbxml)->wbxml_version = wbxml_version[i].value; debug("parse_document",0,"WBXML: Encoding with wbxml version <%s>", octstr_get_cstr(version)); break; } } if (i == NUMBER_OF_WBXML_VERSION) { (*wbxml)->wbxml_version = 0x01; /* WBXML Version number 1.1 */ warning(0, "WBXML: Unknown wbxml version, assuming 1.1 (<%s> is unknown)", octstr_get_cstr(version)); } } /* Return WML Version dependent on xml ExternalID string */ if ((document->intSubset != NULL) && (document->intSubset->ExternalID != NULL)) externalID = octstr_create(document->intSubset->ExternalID); if (externalID == NULL) { (*wbxml)->wml_public_id = 0x04; /* WML 1.1 Public ID */ warning(0, "WBXML: WML without ExternalID, assuming 1.1"); } else { for (i = 0; i < NUMBER_OF_WML_EXTERNALID; i++) { if (octstr_compare(externalID, octstr_imm(wml_externalid[i].string)) == 0) { (*wbxml)->wml_public_id = wml_externalid[i].value; debug("parse_document",0,"WBXML: WML with ExternalID <%s>", octstr_get_cstr(externalID)); break; } } if (i == NUMBER_OF_WML_EXTERNALID) { (*wbxml)->wml_public_id = 0x04; /* WML 1.1 Public ID */ warning(0, "WBXML: WML with unknown ExternalID, assuming 1.1 " "(<%s> is unknown)", octstr_get_cstr(externalID)); } } octstr_destroy(externalID); (*wbxml)->string_table_length = 0x00; /* String table length=0 */ /* * Make sure we set the charset encoding right. If none is given * then set UTF-8 as default. */ (*wbxml)->character_set = charset ? parse_charset(charset) : parse_charset(octstr_imm("UTF-8")); node = xmlDocGetRootElement(document); string_table_build(node, wbxml); return parse_node(node, wbxml);}/* * parse_element - the parsing function for an element node. * The element tag is encoded into one octet hexadecimal value, * if possible. Otherwise it is encoded as text. If the element * needs an end tag, the function returns 1, for no end tag 0 * and -1 for an error. */static int parse_element(xmlNodePtr node, wml_binary_t **wbxml){ int add_end_tag = 0; unsigned char wbxml_hex = 0, status_bits; xmlAttrPtr attribute; Octstr *name; wml_hash_t *element; name = octstr_create(node->name); /* Check, if the tag can be found from the code page. */ if ((element = dict_get(wml_elements_dict, name)) != NULL) { wbxml_hex = element->binary; /* A conformance patch: no do-elements of same name in a card or template. An extremely ugly patch. --tuo */ if (wbxml_hex == 0x27 || /* Card */ wbxml_hex == 0x3B) /* Template */ if (check_do_elements(node) == -1) { add_end_tag = -1; error(0, "WML compiler: Two or more do elements with same" " name in a card or template element."); } /* A conformance patch: if variable in setvar has a bad name, it's ignored. */ if (wbxml_hex == 0x3E) /* Setvar */ if (check_variable_name(node) == FAILED) { octstr_destroy(name); return add_end_tag; } if ((status_bits = element_check_content(node)) > 0) { wbxml_hex = wbxml_hex | status_bits; /* If this node has children, the end tag must be added after them. */ if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT) add_end_tag = 1; } output_st_char(wbxml_hex, wbxml); } else { /* The tag was not on the code page, it has to be encoded as a string. */ wbxml_hex = WBXML_LITERAL; if ((status_bits = element_check_content(node)) > 0) { wbxml_hex = wbxml_hex | status_bits; /* If this node has children, the end tag must be added after them. */ if ((status_bits & WBXML_CONTENT_BIT) == WBXML_CONTENT_BIT) add_end_tag = 1; } output_st_char(wbxml_hex, wbxml); octstr_append_uintvar((*wbxml)->wbxml_string,string_table_add(octstr_duplicate(name), wbxml)); warning(0, "WML compiler: Unknown tag in WML source: <%s>", octstr_get_cstr(name)); } /* Encode the attribute list for this node and add end tag after the list. */ if(node->properties != NULL) { attribute = node->properties; while (attribute != NULL) { parse_attribute(attribute, wbxml); attribute = attribute->next; } parse_st_end(wbxml); } octstr_destroy(name); return add_end_tag;}/* * parse_attribute - the parsing function for attributes. The function * encodes the attribute (and probably start of the value) as a one * hexadecimal octet. The value (or the rest of it) is coded as a string * maybe using predefined attribute value tokens to reduce the length * of the output. Returns 0 for success, -1 for error. */static int parse_attribute(xmlAttrPtr attr, wml_binary_t **wbxml){ int status = 0; int coded_length = 0; unsigned char wbxml_hex = 0x00; wml_hash_t *hit = NULL; wml_attribute_t *attribute = NULL; Octstr *name = NULL, *pattern = NULL, *p = NULL; name = octstr_create(attr->name); if (attr->children != NULL) pattern = create_octstr_from_node(attr->children); else pattern = NULL; /* Check if the attribute is found on the code page. */ if ((attribute = dict_get(wml_attributes_dict, name)) != NULL) { if (attr->children == NULL || (hit = list_search(attribute->value_list, (void *)pattern, hash_cmp)) == NULL) { if(attribute->binary == 0x00) { warning(0, "WML compiler: can't compile attribute %s%s%s%s", octstr_get_cstr(attribute->attribute), (attr->children != NULL ? "=\"": ""), (attr->children != NULL ? octstr_get_cstr(pattern) : ""), (attr->children != NULL ? "\"": "")); wbxml_hex = WBXML_LITERAL; output_st_char(wbxml_hex, wbxml); output_st_char(string_table_add(octstr_duplicate(name), wbxml), wbxml); } else { wbxml_hex = attribute->binary; output_st_char(wbxml_hex, wbxml); } } else if (hit->binary) { wbxml_hex = hit->binary; coded_length = octstr_len(hit->item); output_st_char(wbxml_hex, wbxml); } else status = -1; } else { /* The attribute was not on the code page, it has to be encoded as a string. */ wbxml_hex = WBXML_LITERAL; output_st_char(wbxml_hex, wbxml); octstr_append_uintvar((*wbxml)->wbxml_string,string_table_add(octstr_duplicate(name), wbxml)); warning(0, "WML compiler: Unknown attribute in WML source: <%s>", octstr_get_cstr(name)); } if (status >= 0) { var_esc_t default_esc; default_esc = (octstr_str_compare (name, "href") == 0) ? ESC : NOESC; /* The rest of the attribute is coded as a inline string. */ if (pattern != NULL && coded_length < (int) octstr_len(pattern)) { if (coded_length == 0) p = create_octstr_from_node(attr->children); else p = octstr_copy(pattern, coded_length, octstr_len(pattern) - coded_length); if (check_if_url(wbxml_hex)) status = parse_attr_value(p, wml_URL_values_list, wbxml, attr->doc->charset, default_esc); else status = parse_attr_value(p, wml_attr_values_list, wbxml, attr->doc->charset, default_esc); if (status != 0) error(0, "WML compiler: could not output attribute " "value as a string."); octstr_destroy(p); } } /* Memory cleanup. */ octstr_destroy(name); if (pattern != NULL) octstr_destroy(pattern); return status;}/* * parse_attr_value - parses an attributes value using WML value codes. */static int parse_attr_value(Octstr *attr_value, List *tokens, wml_binary_t **wbxml, int charset, var_esc_t default_esc){ int i, pos, wbxml_hex; wml_hash_t *temp = NULL; Octstr *cut_text = NULL; char *tmp; /* * Beware that libxml2 does internal encoding in UTF-8 while parsing. * So if our original WML source had a different encoding set, we have * to transcode at least here. Only transcode if target encoding differs * from libxml2's internal encoding (UTF-8). */ tmp = (char*) xmlGetCharEncodingName(charset); if (charset != XML_CHAR_ENCODING_UTF8 && charset_convert(attr_value, "UTF-8", tmp) != 0) { error(0, "Failed to convert XML attribute value from charset " "<%s> to <%s>, will leave as is.", "UTF-8", tmp ? tmp : "(undef)"); } /* * The attribute value is search for text strings that can be replaced * with one byte codes. Note that the algorith is not foolproof; seaching * is done in an order and the text before first hit is not checked for * those tokens that are after the hit in the order. Most likely it would * be waste of time anyway. String table is not used here, since at least * Nokia 7110 doesn't seem to understand string table references here. */ /* A fast patch to allow reserved names to be variable names. May produce a little longer binary at some points. --tuo */ if (octstr_search_char(attr_value, '$', 0) >= 0) { if (parse_st_octet_string(attr_value, 0, default_esc, wbxml) != 0) return -1; } else { for (i = 0; i < list_len(tokens); i++) { temp = list_get(tokens, i); pos = octstr_search(attr_value, temp->item, 0); switch (pos) { case -1: break; case 0: wbxml_hex = temp->binary; output_st_char(wbxml_hex, wbxml); octstr_delete(attr_value, 0, octstr_len(temp->item)); break; default: /* * There is some text before the first hit, that has to * be handled too. */ gw_assert(pos <= octstr_len(attr_value)); cut_text = octstr_copy(attr_value, 0, pos); if (parse_st_octet_string(cut_text, 0, default_esc, wbxml) != 0) return -1; octstr_destroy(cut_text); wbxml_hex = temp->binary; output_st_char(wbxml_hex, wbxml); octstr_delete(attr_value, 0, pos + octstr_len(temp->item)); break; } } /* * If no hits, then the attr_value is handled as a normal text, * otherwise the remaining part is searched for other hits too. */ if ((int) octstr_len(attr_value) > 0) { if (i < list_len(tokens)) parse_attr_value(attr_value, tokens, wbxml, charset, default_esc); else if (parse_st_octet_string(attr_value, 0, default_esc, wbxml) != 0) return -1; } } return 0;}/* * parse_st_end - adds end tag to an element. */static void parse_st_end(wml_binary_t **wbxml){ output_st_char(WBXML_END, wbxml);}/* * parse_text - a text string parsing function. * This function parses a text node. */static int parse_text(xmlNodePtr node, wml_binary_t **wbxml){ int ret; Octstr *temp; char* tmp; temp = create_octstr_from_node(node); /* returns string in UTF-8 */ /* * Beware that libxml2 does internal encoding in UTF-8 while parsing. * So if our original WML source had a different encoding set, we have * to transcode at least here. Only transcode if target encoding differs * from libxml2's internal encoding (UTF-8). */ tmp = (char*) xmlGetCharEncodingName(node->doc->charset); if (node->doc->charset != XML_CHAR_ENCODING_UTF8 && charset_convert(temp, "UTF-8", tmp) != 0) { error(0, "Failed to convert XML text entity from charset " "<%s> to <%s>, will leave as is.", "UTF-8", tmp ? tmp : "(undef)"); } octstr_shrink_blanks(temp); if (!check_if_emphasis(node->prev) && !check_if_emphasis(node->next)) octstr_strip_blanks(temp); if (octstr_len(temp) == 0) ret = 0; else ret = parse_st_octet_string(temp, 0, NOESC, wbxml); /* Memory cleanup. */ octstr_destroy(temp); return ret;}/* * parse_cdata - a cdata section parsing function. * This function parses a cdata section that is outputted into the binary * "as is". */static int parse_cdata(xmlNodePtr node, wml_binary_t **wbxml){ int ret = 0; Octstr *temp; temp = create_octstr_from_node(node); parse_st_octet_string(temp, 1, NOESC, wbxml); /* Memory cleanup. */ octstr_destroy(temp); return ret;}/* * parse_variable - a variable parsing function. * Arguments: * - text: the octet string containing a variable * - start: the starting position of the variable not including * trailing & * Returns: lenth of the variable for success, -1 for failure, 0 for * variable syntax error, when it will be ignored. * Parsed variable is returned as an octet string in Octstr **output. */static int parse_variable(Octstr *text, int start, var_esc_t default_esc, Octstr **output, wml_binary_t **wbxml){ var_esc_t esc; int ret; Octstr *variable; variable = get_variable(text, start + 1); octstr_truncate(*output, 0); if (variable == NULL) return 0; if (octstr_get_char(variable, 0) == '$') { octstr_append_char(*output, '$'); octstr_destroy(variable); ret = 2; } else { if (octstr_get_char(text, start + 1) == '(') ret = octstr_len(variable) + 3; else ret = octstr_len(variable) + 1; if ((esc = check_variable_syntax(variable, default_esc)) != FAILED) output_variable(variable, output, esc, wbxml); else octstr_destroy(variable); } return ret;}/* * get_variable - get the variable name from text. * Octstr *text contains the text with a variable name starting at point * int start. */static Octstr *get_variable(Octstr *text, int start){ Octstr *var = NULL; long end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -