• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Esmertec AG.
3  * Copyright (C) 2007 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include "imps_encoder.h"
21 #include "csp13_hash.h"
22 
23 /* TODOs:
24  * - use string table?
25  * - move common WBXML routines to WbxmlEncoder
26  * - so called "token" based IMPS value encoding
27  */
28 
29 struct XmlnsPrefix {
30     const char * prefix;
31     int attrToken;
32 };
33 static const XmlnsPrefix csp13xmlns[] = {
34     { "http://www.wireless-village.org/CSP",        0x05 },
35     { "http://www.wireless-village.org/PA",         0x06 },
36     { "http://www.wireless-village.org/TRC",        0x07 },
37     { "http://www.openmobilealliance.org/DTD/WV-CSP",   0x08 },
38     { "http://www.openmobilealliance.org/DTD/WV-PA",    0x09 },
39     { "http://www.openmobilealliance.org/DTD/WV-TRC",   0x0a },
40     { "http://www.openmobilealliance.org/DTD/IMPS-CSP", 0x0b },
41     { "http://www.openmobilealliance.org/DTD/IMPS-PA",  0x0c },
42     { "http://www.openmobilealliance.org/DTD/IMPS-TRC", 0x0d },
43 };
44 
isDatetimeElement(const char * name)45 static bool isDatetimeElement(const char *name)
46 {
47     return (strcmp("DateTime", name) == 0 || strcmp("DeliveryTime", name) == 0);
48 }
49 
reset()50 void ImpsWbxmlEncoder::reset()
51 {
52     clearResult();
53 
54     mTagCodePage = 0;
55     mCurrElement.clear();
56     mDepth = 0;
57 }
58 
startElement(const char * name,const char ** atts)59 EncoderError ImpsWbxmlEncoder::startElement(const char *name, const char **atts)
60 {
61     if (name == NULL) {
62         return ERROR_INVALID_DATA;
63     }
64 
65     bool isUnknownTag = false;
66     int stag = csp13TagNameToKey(name);
67     if (stag == -1) {
68         stag = TOKEN_LITERAL;
69         isUnknownTag = true;
70     }
71     mDepth++;
72     mCurrElement = name;
73 
74     if (((stag >> 8) & 0xff) != mTagCodePage) {
75         // SWITCH_PAGE
76         mTagCodePage = (stag >> 8) & 0xff;
77         appendResult(TOKEN_SWITCH_PAGE);
78         appendResult(mTagCodePage);
79     }
80     stag &= 0xff;
81     stag |= 0x40;       // TODO: assuming we always have content
82 
83     if (atts && atts[0]) {
84         stag |= 0x80;   // has attribute
85     }
86     appendResult(stag);
87 
88     if (isUnknownTag) {
89         int index = appendToStringTable(name);
90         encodeMbuint(index);
91     }
92     if (stag & 0x80) {
93         for (size_t i = 0; atts[i]; i += 2) {
94             EncoderError err = encodeAttrib(atts[i], atts[i + 1]);
95             if (err != NO_ERROR) {
96                 return err;
97             }
98         }
99         appendResult(TOKEN_END);
100     }
101     return NO_ERROR;
102 }
103 
characters(const char * chars,int len)104 EncoderError ImpsWbxmlEncoder::characters(const char *chars, int len)
105 {
106     if (chars == NULL || len < 0) {
107         return ERROR_INVALID_DATA;
108     }
109     if (!len) {
110         return NO_ERROR;
111     }
112     while (len && isXmlWhitespace(*chars)) {
113         chars++;
114         len--;
115     }
116     while (len && isXmlWhitespace(chars[len - 1])) {
117         len--;
118     }
119     if (!len) {
120         return NO_ERROR;
121     }
122 
123     if (csp13IsIntegerTag(mCurrElement.c_str())) {
124         return encodeInteger(chars, len);
125     } else if (isDatetimeElement(mCurrElement.c_str())) {
126         return encodeDatetime(chars, len);
127     } else {
128         return encodeString(chars, len);
129     }
130 }
131 
opaque(const char * chars,int len)132 EncoderError ImpsWbxmlEncoder::opaque(const char *chars, int len)
133 {
134     if (chars == NULL || len < 0) {
135         return ERROR_INVALID_DATA;
136     }
137     if (!len) {
138         return NO_ERROR;
139     }
140     appendResult(TOKEN_OPAQUE);
141     encodeMbuint((uint32_t)len);
142     appendResult(chars, len);
143     return NO_ERROR;
144 }
145 
endElement()146 EncoderError ImpsWbxmlEncoder::endElement()
147 {
148     mDepth--;
149     if (mDepth < 0) {
150         return ERROR_INVALID_END_ELEMENT;
151     }
152     appendResult(TOKEN_END);
153     mCurrElement.clear();
154     if (mDepth == 0) {
155         sendResult();
156     }
157     return NO_ERROR;
158 }
159 
encodeString(const char * chars,int len)160 EncoderError ImpsWbxmlEncoder::encodeString(const char *chars, int len)
161 {
162     // FIXME: should match and replace based on tokens (words)
163     int token = csp13ValueTokenToKey(chars, len);
164     if (token == -1) {
165         encodeInlinedStr(chars, len);
166     } else {
167         appendResult(TOKEN_EXT_T_0);
168         encodeMbuint(token);
169     }
170     return NO_ERROR;
171 }
172 
encodeAttrib(const char * name,const char * value)173 EncoderError ImpsWbxmlEncoder::encodeAttrib(const char *name, const char *value)
174 {
175     // IMPS so far has only "xmlns" attribute.
176     // TODO: rewrite in a more generic way and move this to WbxmlEncoder
177     if (strcmp(name, "xmlns")) {
178         return ERROR_UNSUPPORTED_ATTR;
179     }
180     int valueLen = strlen(value);
181     size_t csp13xmlnsCount = sizeof(csp13xmlns) / sizeof(csp13xmlns[0]);
182     size_t i;
183     for (i = 0; i < csp13xmlnsCount; i++) {
184         const char * prefix = csp13xmlns[i].prefix;
185         int prefixLen = strlen(csp13xmlns[i].prefix);
186         if (strncmp(prefix, value, prefixLen) == 0) {
187             appendResult(csp13xmlns[i].attrToken);
188             if (valueLen > prefixLen) {
189                 encodeInlinedStr(value + prefixLen, valueLen - prefixLen);
190             }
191             return NO_ERROR;
192         }
193     }
194     if (i == csp13xmlnsCount) {
195         // not predefined attribute
196         appendResult(TOKEN_LITERAL);
197         int index = appendToStringTable(name);
198         encodeMbuint(index);
199     }
200     encodeInlinedStr(value, valueLen);
201     return NO_ERROR;
202 }
203