exip  Alpha 0.5.4
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
headerDecode.c
Go to the documentation of this file.
1 /*==================================================================*\
2 | EXIP - Embeddable EXI Processor in C |
3 |--------------------------------------------------------------------|
4 | This work is licensed under BSD 3-Clause License |
5 | The full license terms and conditions are located in LICENSE.txt |
6 \===================================================================*/
7 
18 #include "headerDecode.h"
19 #include "streamDecode.h"
20 #include "streamRead.h"
21 #include "contentHandler.h"
22 #include "memManagement.h"
23 #include "bodyDecode.h"
24 #include "grammars.h"
25 #include "EXIParser.h"
26 #include "sTables.h"
27 #include "stringManipulate.h"
28 #include "initSchemaInstance.h"
29 
31 extern const EXIPSchema ops_schema;
32 
33 // Content Handler API
34 static errorCode ops_fatalError(const errorCode code, const char* msg, void* app_data);
35 static errorCode ops_startDocument(void* app_data);
36 static errorCode ops_endDocument(void* app_data);
37 static errorCode ops_startElement(QName qname, void* app_data);
38 static errorCode ops_endElement(void* app_data);
39 static errorCode ops_attribute(QName qname, void* app_data);
40 static errorCode ops_stringData(const String value, void* app_data);
41 static errorCode ops_intData(Integer int_val, void* app_data);
42 static errorCode ops_boolData(boolean bool_val, void* app_data);
43 
45 {
49  unsigned char prevElementUriID;
50  unsigned char prevElementLnID;
51 };
52 
53 errorCode decodeHeader(EXIStream* strm, boolean outOfBandOpts)
54 {
55  errorCode tmp_err_code = EXIP_UNEXPECTED_ERROR;
56  unsigned int bits_val = 0;
57  boolean boolVal = FALSE;
58 
59  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">Start EXI header decoding\n"));
60  TRY(readBits(strm, 2, &bits_val));
61  if(bits_val == 2) // The header Distinguishing Bits i.e. no EXI Cookie
62  {
63  strm->header.has_cookie = 0;
64  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">No EXI cookie detected\n"));
65  }
66  else if(bits_val == 0)// ASCII code for $ = 00100100 (36)
67  {
68  TRY(readBits(strm, 6, &bits_val));
69  if(bits_val != 36)
71  TRY(readBits(strm, 8, &bits_val));
72  if(bits_val != 69) // ASCII code for E = 01000101 (69)
74  TRY(readBits(strm, 8, &bits_val));
75  if(bits_val != 88) // ASCII code for X = 01011000 (88)
77  TRY(readBits(strm, 8, &bits_val));
78  if(bits_val != 73) // ASCII code for I = 01001001 (73)
80 
81  strm->header.has_cookie = 1;
82  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">EXI cookie detected\n"));
83  TRY(readBits(strm, 2, &bits_val));
84  if(bits_val != 2) // The header Distinguishing Bits are required
86  }
87  else
88  {
90  }
91 
92  // Read the Presence Bit for EXI Options
93  TRY(readNextBit(strm, &boolVal));
94 
95  if(boolVal == TRUE) // There are EXI options
96  {
97  strm->header.has_options = TRUE;
98  // validation checks. If the options are included then
99  // they cannot be set by an out-of-band mechanism.
100  // If out-of-band options are set -
101  // rise a warning and overwrite them.
102  // Only the options from the header will be used
103  if(outOfBandOpts == TRUE)
104  {
105  DEBUG_MSG(WARNING, DEBUG_CONTENT_IO, (">Ignored out-of-band set EXI options\n"));
106  makeDefaultOpts(&strm->header.opts);
107  }
108  }
109  else // Out-of-band set EXI options
110  {
111  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">No EXI options field in the header\n"));
112  strm->header.has_options = FALSE;
113  if(outOfBandOpts == FALSE)
114  {
115  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">No EXI options in the header and no out-of-band options specified. \n"));
117  }
118  }
119 
120  // Read the Version type
121  TRY(readNextBit(strm, &boolVal));
122 
123  strm->header.is_preview_version = boolVal;
124  strm->header.version_number = 1;
125 
126  do
127  {
128  TRY(readBits(strm, 4, &bits_val));
129  strm->header.version_number += bits_val;
130  if(bits_val < 15)
131  break;
132  } while(1);
133 
134  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">EXI version: %d\n", strm->header.version_number));
135 
136  if(strm->header.has_options == 1)
137  {
138  Parser optionsParser;
139  struct ops_AppData appD;
140 
141  TRY(initParser(&optionsParser, strm->buffer, &appD));
142 
143  optionsParser.strm.context.bitPointer = strm->context.bitPointer;
144  optionsParser.strm.context.bufferIndx = strm->context.bufferIndx;
145  optionsParser.strm.gStack = NULL;
146 
147  makeDefaultOpts(&optionsParser.strm.header.opts);
148  SET_STRICT(optionsParser.strm.header.opts.enumOpt);
149 
150  optionsParser.handler.fatalError = ops_fatalError;
151  optionsParser.handler.error = ops_fatalError;
152  optionsParser.handler.startDocument = ops_startDocument;
153  optionsParser.handler.endDocument = ops_endDocument;
154  optionsParser.handler.startElement = ops_startElement;
155  optionsParser.handler.attribute = ops_attribute;
156  optionsParser.handler.stringData = ops_stringData;
157  optionsParser.handler.endElement = ops_endElement;
158  optionsParser.handler.intData = ops_intData;
159  optionsParser.handler.booleanData = ops_boolData;
160 
161  appD.o_strm = &optionsParser.strm;
162  appD.parsed_ops = &strm->header.opts;
163  appD.prevElementLnID = 0;
164  appD.prevElementUriID = 0;
165  appD.permanentAllocList = &strm->memList;
166 
167  TRY_CATCH(setSchema(&optionsParser, (EXIPSchema*) &ops_schema), destroyParser(&optionsParser));
168  TRY_CATCH(createValueTable(&optionsParser.strm.valueTable), destroyParser(&optionsParser));
169 
170  while(tmp_err_code == EXIP_OK)
171  {
172  tmp_err_code = parseNext(&optionsParser);
173  }
174 
175  destroyParser(&optionsParser);
176 
177  if(tmp_err_code != EXIP_PARSING_COMPLETE)
178  return tmp_err_code;
179 
180  strm->buffer.bufContent = optionsParser.strm.buffer.bufContent;
181  strm->context.bitPointer = optionsParser.strm.context.bitPointer;
182  strm->context.bufferIndx = optionsParser.strm.context.bufferIndx;
183 
184  if(WITH_COMPRESSION(strm->header.opts.enumOpt) ||
186  {
187  // Padding bits
188  if(strm->context.bitPointer != 0)
189  {
190  strm->context.bitPointer = 0;
191  strm->context.bufferIndx += 1;
192  }
193  }
194  }
195 
196  return checkOptionValues(&strm->header.opts);
197 }
198 
199 static errorCode ops_fatalError(const errorCode code, const char* msg, void* app_data)
200 {
201  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Error during parsing of the EXI Options\n"));
202  return EXIP_HANDLER_STOP;
203 }
204 
205 static errorCode ops_startDocument(void* app_data)
206 {
207  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">Start parsing the EXI Options\n"));
208  return EXIP_OK;
209 }
210 
211 static errorCode ops_endDocument(void* app_data)
212 {
213  DEBUG_MSG(INFO, DEBUG_CONTENT_IO, (">Complete parsing the EXI Options\n"));
214  return EXIP_OK;
215 }
216 
217 static errorCode ops_startElement(QName qname, void* app_data)
218 {
219  struct ops_AppData* o_appD = (struct ops_AppData*) app_data;
220 
221  if(o_appD->o_strm->gStack->currQNameID.uriId == 4) // URI == http://www.w3.org/2009/exi
222  {
223  o_appD->prevElementUriID = 4;
224 
225  switch(o_appD->o_strm->gStack->currQNameID.lnId)
226  {
227  case 33: // strict
228  SET_STRICT(o_appD->parsed_ops->enumOpt);
229  o_appD->prevElementLnID = 33;
230  break;
231  case 31: // schemaId
232  o_appD->prevElementLnID = 31;
234  break;
235  case 7: // compression
237  o_appD->prevElementLnID = 7;
238  break;
239  case 14: // fragment
240  SET_FRAGMENT(o_appD->parsed_ops->enumOpt);
241  o_appD->prevElementLnID = 14;
242  break;
243  case 13: // dtd
245  o_appD->prevElementLnID = 13;
246  break;
247  case 29: // prefixes
249  o_appD->prevElementLnID = 29;
250  break;
251  case 26: // lexicalValues
253  o_appD->prevElementLnID = 26;
254  break;
255  case 5: // comments
257  o_appD->prevElementLnID = 5;
258  break;
259  case 27: // pis
261  o_appD->prevElementLnID = 27;
262  break;
263  case 4: // alignment->byte
265  o_appD->prevElementLnID = 4;
266  break;
267  case 28: // alignment->pre-compress
269  o_appD->prevElementLnID = 28;
270  break;
271  case 32: // selfContained
273  o_appD->prevElementLnID = 32;
274  break;
275  case 8: // datatypeRepresentationMap
276  o_appD->prevElementLnID = 8;
277  break;
278  case 36: // uncommon
279  o_appD->prevElementLnID = 36;
280  break;
281  }
282  }
283  else // URI != http://www.w3.org/2009/exi
284  {
285  // The previous element should be either uncommon or datatypeRepresentationMap otherwise it is an error
286  // These are the only places where <any> element is allowed
287  if(o_appD->prevElementUriID != 4 || o_appD->prevElementLnID != 36 || o_appD->prevElementLnID != 8)
288  {
289  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Wrong namespace in the EXI Options\n"));
290  return EXIP_HANDLER_STOP;
291  }
292 
293  // Handle here the user defined meta-data that follows! http://www.w3.org/TR/2011/REC-exi-20110310/#key-userMetaData
294  }
295 
296  return EXIP_OK;
297 }
298 
299 static errorCode ops_endElement(void* app_data)
300 {
301  return EXIP_OK;
302 }
303 
304 static errorCode ops_attribute(QName qname, void* app_data)
305 {
306  struct ops_AppData* o_appD = (struct ops_AppData*) app_data;
307 
308  if(o_appD->prevElementUriID == 4) // URI == http://www.w3.org/2009/exi
309  {
310  if(o_appD->prevElementLnID != 31) // schemaId
311  {
312  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Corrupt EXI Options\n"));
313  return EXIP_HANDLER_STOP;
314  }
315  else
316  {
318  {
320  }
321  else
322  {
323  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Corrupt EXI Options\n"));
324  return EXIP_HANDLER_STOP;
325  }
326  }
327  }
328  else
329  {
330  // Handle here the user defined meta-data that follows! http://www.w3.org/TR/2011/REC-exi-20110310/#key-userMetaData
331  }
332 
333  return EXIP_OK;
334 }
335 
336 static errorCode ops_stringData(const String value, void* app_data)
337 {
338  struct ops_AppData* o_appD = (struct ops_AppData*) app_data;
339 
340  if(o_appD->prevElementUriID == 4) // URI == http://www.w3.org/2009/exi
341  {
342  if(o_appD->prevElementLnID != 31) // schemaId
343  {
344  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Corrupt EXI Options\n"));
345  return EXIP_HANDLER_STOP;
346  }
347  else
348  {
349  if(isStringEmpty(&value))
350  {
352  }
353  else
354  {
356  if(cloneStringManaged(&value, &o_appD->parsed_ops->schemaID, o_appD->permanentAllocList) != EXIP_OK)
357  {
358  DEBUG_MSG(ERROR, DEBUG_CONTENT_IO, (">Memory error\n"));
359  return EXIP_HANDLER_STOP;
360  }
361  }
362  }
363  }
364  else
365  {
366  // Handle here the user defined meta-data that follows! http://www.w3.org/TR/2011/REC-exi-20110310/#key-userMetaData
367  }
368 
369  return EXIP_OK;
370 }
371 
372 static errorCode ops_intData(Integer int_val, void* app_data)
373 {
374  struct ops_AppData* o_appD = (struct ops_AppData*) app_data;
375 
376  switch(o_appD->o_strm->gStack->currQNameID.lnId)
377  {
378  case 37: // valueMaxLength
379  o_appD->parsed_ops->valueMaxLength = (unsigned int) int_val;
380  break;
381  case 38: // valuePartitionCapacity
382  o_appD->parsed_ops->valuePartitionCapacity = (unsigned int) int_val;
383  break;
384  case 2: // blockSize
385  o_appD->parsed_ops->blockSize = (unsigned int) int_val;
386  break;
387  }
388  return EXIP_OK;
389 }
390 
391 static errorCode ops_boolData(boolean bool_val, void* app_data)
392 {
393  struct ops_AppData* o_appD = (struct ops_AppData*) app_data;
394 
395  if(o_appD->parsed_ops->schemaIDMode == SCHEMA_ID_NIL) // xsi:nil attribute
396  {
397  if(bool_val == FALSE)
399  }
400  else
401  {
402  // Handle here the user defined meta-data that follows! http://www.w3.org/TR/2011/REC-exi-20110310/#key-userMetaData
403  }
404 
405  return EXIP_OK;
406 }