MHEG5  18.9.0
MHEG5 Documentation
mh5gate.c
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright © 2014 The DTVKit Open Software Foundation Ltd (www.dtvkit.org)
3  * Copyright © 2004 Ocean Blue Software Ltd
4  * Copyright © 2000 Koninklijke Philips Electronics N.V
5  *
6  * This file is part of a DTVKit Software Component
7  * You are permitted to copy, modify or distribute this file subject to the terms
8  * of the DTVKit 1.0 Licence which can be found in licence.txt or at www.dtvkit.org
9  *
10  * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
11  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES
12  * OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
13  *
14  * If you or your organisation is not a member of DTVKit then you have access
15  * to this orig code outside of the terms of the licence agreement
16  * and you are expected to delete this and any associated files immediately.
17  * Further information on DTVKit, membership and terms can be found at www.dtvkit.org
18  *******************************************************************************/
32 /*---includes for this file--------------------------------------------------*/
33 #include <string.h>
34 
35 #include "mh5base.h"
36 #include "mh5memory.h"
37 #include "mh5application.h"
38 #include "mh5debug.h"
39 #include "mh5profile.h"
40 #include "mh5gate.h"
41 #ifdef INCLUDE_IC
42 #include "mh5control.h"
43 #include "mh5support.h"
44 #endif
45 
46 /*---constant definitions for this file--------------------------------------*/
47 
48 
49 /*---local typedef structs for this file-------------------------------------*/
50 
51 
52 /*---local (static) variable declarations for this file----------------------*/
53 
54 static struct
55 {
56  const char *data;
57  int len;
58 } source_names[ORIGIN_MAX] = {
59  { "DSM:/", 5 },
60  { "CI:/", 4 },
61  { "hybrid:/", 8 },
62  { "http:/", 6 },
63  { "https:/", 7 },
64  { "dvb:/", 5 },
65  { "rec:/", 5 }
66 };
67 
68 /* Path from // to the active application - see UK1.05 section 8.3.3.3 */
69 static MHEG5String activeAppPath = { 0, NULL };
70 
71 /* Origin of the current orig - See UK1.05 section 6.2.4 */
72 #ifdef INCLUDE_IC
73 static E_FS_ORIGIN currentSource = ORIGIN_HYBRID;
74 #else
75 static E_FS_ORIGIN currentSource = ORIGIN_DSM;
76 #endif
77 
78 /*---local function definitions----------------------------------------------*/
79 
92 static void ResolveParentDir(MHEG5String *ref, MHEG5Int *parents)
93 {
94  MHEG5Int i, j, k;
95  enum
96  {
97  ST_START, ST_SEP, ST_FIRST_DOT, ST_SECOND_DOT
98  } state;
99 
100  *parents = 0;
101  state = ST_SEP;
102  j = 0;
103  for (i = 0, j = 0; i != ref->len; ++i, ++j)
104  {
105  ref->data[j] = ref->data[i];
106  switch (state)
107  {
108  case ST_START:
109  if (ref->data[i] == '/')
110  {
111  /* / */
112  state = ST_SEP;
113  }
114  break;
115 
116  case ST_SEP:
117  if (ref->data[i] == '.')
118  {
119  /* /. */
120  state = ST_FIRST_DOT;
121  }
122  else
123  {
124  /* /x */
125  state = ST_START;
126  }
127  break;
128 
129  case ST_FIRST_DOT:
130  if (ref->data[i] == '.')
131  {
132  /* /.. */
133  state = ST_SECOND_DOT;
134  }
135  else
136  {
137  /* /.x or /./ - no resolution */
138  state = ST_START;
139  }
140  break;
141 
142  case ST_SECOND_DOT:
143  if (ref->data[i] == '/')
144  {
145  /* /../ - find previous separator */
146  for (k = j - 4; k >= 0; --k)
147  {
148  if (ref->data[k] == '/')
149  {
150  break;
151  }
152  }
153  if (k >= 0)
154  {
155  if (memcmp(&ref->data[k], "/../", 4) == 0)
156  {
157  /* Previous path is also .. - no resolution */
158  ++(*parents);
159  }
160  else
161  {
162  /* /../ cancels the previous path */
163  j = k;
164  }
165  }
166  else
167  {
168  /* No previous path */
169  ++(*parents);
170  }
171  state = ST_SEP;
172  }
173  else
174  {
175  /* /..x */
176  state = ST_START;
177  }
178  }
179  }
180  ref->len = j;
181  ref->len -= 3 * *parents;
182  memmove(ref->data, ref->data + 3 * *parents, ref->len);
183 }
184 
185 /*---global function definitions---------------------------------------------*/
186 
193 {
194  if (origin < ORIGIN_MAX)
195  {
196  return source_names[origin].len + 1;
197  }
198  return 0;
199 }
200 
209 {
210  E_FS_ORIGIN i;
211  MHEG5Bool success;
212 
213  *offset = 0;
214  success = MHEG5FALSE;
215 
216  if (ref->len > 0)
217  {
218  if (ref->data[0] == '~')
219  {
220  /* Default orig */
221  #ifdef INCLUDE_IC
223  {
224  *orig = ORIGIN_HYBRID;
225  }
226  else
227  #endif
228  {
229  *orig = ORIGIN_DSM;
230  }
231  if (ref->len > 1 && ref->data[1] == '/')
232  {
233  *offset = 2; /* Skip the "~/" */
234  success = MHEG5TRUE;
235  }
236  }
237  else if (ref->data[0] == '/')
238  {
239  /* Empty orig. Use current orig */
240  *orig = currentSource;
241  *offset = 1; /* Skip the "/" */
242  success = MHEG5TRUE;
243  }
244  else
245  {
246  for (i = 0; i != ORIGIN_MAX; ++i)
247  {
248  if ((ref->len >= source_names[i].len) &&
249  (MHEG5strncmp(ref->data, source_names[i].data, source_names[i].len)) == 0)
250  {
251  *orig = i;
252  *offset = source_names[i].len;
253  success = MHEG5TRUE;
254  break;
255  }
256  }
257  }
258  }
259  return success;
260 }
261 
270 {
271  E_FS_ORIGIN origin;
272  return MHEG5convertGIDGetOrigin( inRef, &origin );
273 }
274 
283 {
284  MHEG5Bool success;
285  MHEG5String copy;
286  MHEG5String path;
287  MHEG5String out;
288  E_FS_ORIGIN orig;
289  MHEG5Int offset;
290  MHEG5Int parents;
291  MHEG5Bool root;
292  MHEG5Int app_dir_len;
293  MHEG5Int in_len;
294 
295  out.len = 0;
296  out.data = NULL;
297 
298  in_len = inRef->len;
299 
300  /* Find origin */
301  success = MHEG5ResolveOrigin(inRef, pOrigin, &offset);
302  orig = *pOrigin;
303  if (success)
304  {
305  /* Check whether the path starts from the root */
306  if (inRef->data[offset] == '/')
307  {
308  root = MHEG5TRUE;
309  offset++;
310  }
311  else
312  {
313  root = MHEG5FALSE;
314 
315  /* HTTP and HTTPS must be at root level. http:/xyz is not acceptable
316  * although DSM:/xyz or hybrid:/xyz are (18.3.2.3). Note that
317  * '/scene.mheg' is acceptable when the current orig is HTTP or HTTPS.
318  */
319  if ((offset >= 6) && (orig == ORIGIN_HTTP || orig == ORIGIN_HTTPS))
320  {
321  success = MHEG5FALSE;
322  }
323  }
324  }
325  if (success)
326  {
327  if (orig == ORIGIN_CI)
328  {
329  /* Remove trailing null-terminators */
330  while (in_len > 0 && inRef->data[in_len - 1] == '\0')
331  {
332  in_len--;
333  }
334  }
335  path.data = inRef->data + offset;
336  path.len = in_len - offset;
337  copy = MHEG5stringCopy(path);
338  if (copy.len > 0)
339  {
340  ResolveParentDir(&copy, &parents);
341  if (!root)
342  {
343  /* Not root - need to "append" to current working directory
344  * after resolving parent directory. For example, "appending"
345  * "../../x to DSM://a/b/c/d results in DSM://a/b/x.
346  */
347  app_dir_len = activeAppPath.len;
348  while (parents > 0)
349  {
350  while (app_dir_len > 0 &&
351  activeAppPath.data[app_dir_len - 1] != '/')
352  {
353  --app_dir_len;
354  }
355  if (app_dir_len > 0)
356  {
357  --app_dir_len;
358  }
359  --parents;
360  if (app_dir_len == 0 && parents > 0)
361  {
362  break;
363  }
364  }
365  if (parents == 0)
366  {
367  /* Root without parents */
368  out.len = source_names[orig].len + 1 + copy.len;
369  if (app_dir_len > 0)
370  {
371  out.len += app_dir_len + 1;
372  }
373  out.data = STR_DataAlloc( out.len );
374  if (out.data != NULL)
375  {
376  memcpy( out.data, source_names[orig].data, source_names[orig].len );
377  offset = source_names[orig].len;
378  out.data[offset++] = '/';
379  if (app_dir_len > 0)
380  {
381  /* Current working directory is valid, we have:
382  * "<orig>://" + "cur/work/dir" + "/path"
383  */
384  memcpy( out.data + offset, activeAppPath.data, app_dir_len );
385  offset += app_dir_len;
386  out.data[offset++] = '/';
387  }
388  /* else The substring from the current working directory
389  * is empty. This means that we have:
390  * "<orig>://" + "" + "/path", so one separator is redundant
391  */
392  memcpy( out.data + offset, copy.data, copy.len );
393  }
394  }
395  }
396  else if (parents == 0)
397  {
398  /* Root path, no parents */
399  out.len = source_names[orig].len + 1 + copy.len;
400  out.data = STR_DataAlloc( out.len );
401  if (out.data != NULL)
402  {
403  memcpy( out.data, source_names[orig].data, source_names[orig].len );
404  offset = source_names[orig].len;
405  out.data[offset++] = '/';
406  memcpy( out.data + offset, copy.data, copy.len );
407  }
408  }
409  else
410  {
411  /* invalid: root with parents (e.g. DSM://../x/y) */
412  }
413 
414  /* restore original length of string, so that STR_DataFree will find the original allocation */
415  copy.len = path.len;
416  }
417  else if (copy.len == 0 && root)
418  {
419  /* Root dir */
420  out.len = source_names[orig].len + 1;
421  out.data = STR_DataAlloc( out.len );
422  if (out.data != NULL)
423  {
424  memcpy( out.data, source_names[orig].data, source_names[orig].len );
425  offset = source_names[orig].len;
426  out.data[offset++] = '/';
427  }
428  }
429  /* Note: even zero length string gets an allocation */
430  MHEG5stringDestruct(&copy);
431  }
432 
433  return out;
434 }
435 
445 {
446  MHEG5String out;
447  MHEG5Int offset;
448  out.len = source_names[origin].len;
449  if (path.zptr != NULL)
450  {
451  if (path.zptr[0] != '/')
452  {
453  out.len++;
454  }
455  if (path.zptr[path.zlen-1] == '/')
456  {
457  out.len--;
458  }
459  out.len += path.zlen;
460  }
461  if (name.zptr != NULL)
462  {
463  if (name.zptr[0] != '/')
464  {
465  out.len++;
466  }
467  out.len += name.zlen;
468  }
469  out.data = STR_DataAlloc( out.len );
470  if (out.data == NULL)
471  {
472  TRACE(TERROR,("mem fail"))
473  out.len = 0;
474  }
475  else
476  {
477  memcpy( out.data, source_names[origin].data, source_names[origin].len );
478  offset = source_names[origin].len;
479  if (path.zptr != NULL)
480  {
481  if (path.zptr[0] != '/')
482  {
483  out.data[offset++] = '/';
484  }
485  if (path.zptr[path.zlen-1] == '/')
486  {
487  path.zlen--;
488  }
489  memcpy( out.data + offset, path.zptr, path.zlen );
490  offset += path.zlen;
491  }
492  if (name.zptr != NULL)
493  {
494  if (name.zptr[0] != '/')
495  {
496  out.data[offset++] = '/';
497  }
498  memcpy( out.data + offset, name.zptr, name.zlen );
499  offset += name.zlen;
500  }
501  assert(out.len == offset);
502  }
503  return out;
504 }
505 
518 {
519  MHEG5String path;
520  MHEG5Bool rc = MHEG5FALSE;
521 
522  assert( gref.len );
523  path = MHEG5convertGID((MHEG5String *)&gref);
524  if (path.len == gptr->groupName.len)
525  {
526  if (memcmp(path.data, gptr->groupName.data, gptr->groupName.len) == 0)
527  rc = MHEG5TRUE;
528  }
529  MHEG5stringDestruct(&path);
530  return rc;
531 }
532 
534 {
535  MHEG5String path1;
536  MHEG5String path2;
537  MHEG5Bool rc = MHEG5FALSE;
538 
539  assert( gref1.ptr.group != gref2.ptr.group );
540  if (gref1.len == 0)
541  {
542  if (gref2.len == 0)
543  {
544  rc = MHEG5TRUE;
545  }
546  else
547  {
548  rc = MHEG5sameGroup( gref1.ptr.group, gref2 );
549  }
550  }
551  else if (gref2.len == 0)
552  {
553  if (gref1.len == 0)
554  {
555  rc = MHEG5TRUE;
556  }
557  else
558  {
559  rc = MHEG5sameGroup( gref2.ptr.group, gref1 );
560  }
561  }
562  else
563  {
564  path1 = MHEG5convertGID((MHEG5String *)&gref1);
565  path2 = MHEG5convertGID((MHEG5String *)&gref2);
566  if ((path1.len == path2.len) &&
567  (memcmp(path1.data, path2.data, path1.len) == 0)
568  )
569  rc = MHEG5TRUE;
570  MHEG5stringDestruct(&path1);
571  MHEG5stringDestruct(&path2);
572  }
573  return rc;
574 }
575 
584 {
585  E_FS_ORIGIN i;
586  int firstByte;
587  int lastByte;
588 
589  /* free any old path */
590  if (activeAppPath.data != NULL)
591  {
592  STR_DataFree( activeAppPath.data, activeAppPath.len );
593  activeAppPath.len = 0;
594  activeAppPath.data = NULL;
595  }
596 
597  if (app_dir.len < 2)
598  {
599  ERROR_PRINT(("ERROR: MHEG5setWorkingDir - app_dir too short\n"));
600  }
601  else
602  {
603  for (i = 0; i != ORIGIN_MAX; ++i)
604  {
605  if ((app_dir.len >= source_names[i].len) &&
606  (MHEG5strncmp(app_dir.data, source_names[i].data, source_names[i].len)) == 0)
607  {
608  currentSource = i;
609  break;
610  }
611  }
612  if ( i == ORIGIN_MAX )
613  {
614  ERROR_PRINT(("ERROR: MHEG5setWorkingDir - unrecognised app_dir\n"));
615  #ifdef INCLUDE_IC
617  {
618  currentSource = ORIGIN_HYBRID;
619  }
620  else
621  #endif
622  {
623  currentSource = ORIGIN_DSM;
624  }
625  }
626 
627  /* Find the first character after the first ocurrence of "//" */
628  firstByte = 2;
629  while (firstByte < app_dir.len)
630  {
631  if ((app_dir.data[firstByte - 2] == '/') &&
632  (app_dir.data[firstByte - 1] == '/'))
633  {
634  break;
635  }
636  firstByte++;
637  }
638 
639  /* Strip off the file name leaving only the directory path - This is done by
640  * finding the last slash character
641  */
642  lastByte = app_dir.len - 2;
643  while ((lastByte > 0) && (app_dir.data[lastByte + 1] != '/'))
644  {
645  lastByte--;
646  }
647 
648  if (lastByte >= firstByte) /* is something to copy */
649  {
650  /* Calculate the number of bytes to copy */
651  activeAppPath.len = lastByte - firstByte + 1;
652  activeAppPath.data = STR_DataAlloc( activeAppPath.len );
653  if (activeAppPath.data == NULL)
654  {
655  activeAppPath.len = 0;
656  }
657  else
658  {
659  /* Copy the active application directory path */
660  memcpy( activeAppPath.data, app_dir.data + firstByte, activeAppPath.len );
661  }
662  }
663  }
664 }
665 
Implement MHEG5 engine control functions (i.e. start/stop etc)
Basis MHEG5 data types.
#define ORIGIN_MAX
Definition: mh5gate.h:41
const char * data
Definition: mh5gate.c:56
void MHEG5setWorkingDir(MHEG5String app_dir)
Set the working directory for the current application. This is used to resolve relative paths...
Definition: mh5gate.c:583
MHEG5String MHEG5CreateUrl(E_FS_ORIGIN origin, S_STRING path, S_STRING name)
Convert a group ID from a relative reference to an absolute reference. See UK1.05 section 8...
Definition: mh5gate.c:444
unsigned char * STR_DataAlloc(unsigned int size)
Definition: glue_memory.c:596
MHEG5Int MHEG5FullOriginLength(E_FS_ORIGIN origin)
Get length for origin (e.g. "DSM://" is 6)
Definition: mh5gate.c:192
union sMH5GroupRef::@5 ptr
U8BIT * zptr
Definition: dtvstring.h:31
MHEG5String MHEG5stringCopy(MHEG5String source)
<Function description>="">
Definition: mh5base.c:574
void MHEG5stringDestruct(MHEG5String *item)
Destruct a MHEG5String.
Definition: mh5base.c:686
long MHEG5Int
Definition: mh5base.h:73
This file defines the profile for the MHEG engine.
MHEG5Bool MHEG5sameGroups(MH5GroupRef gref1, MH5GroupRef gref2)
Compares two group ID strings to see whether they both reference the same group. Relative group ID st...
Definition: mh5gate.c:533
void STR_DataFree(unsigned char *data, unsigned int size)
Definition: glue_memory.c:668
Implement Functions to support Service Gateways. Functions for standarizing several GroupIDs like +DS...
short MHEG5Bool
Definition: mh5base.h:71
MHEG5Byte * data
Definition: mh5base.h:85
int len
Definition: mh5gate.c:57
#define MHEG5TRUE
Definition: mh5base.h:49
#define MHEG5strncmp(a, b, n)
Definition: mh5base.h:52
Implementation of the MHEG5 Application Class Defines a set of Ingredient objects, which are shared within an application scope. Base class: Group Subclasses: None Status: Concrete class.
Mheg5 logging and debug printing.
MHEG5String MHEG5convertGIDGetOrigin(MHEG5String *inRef, E_FS_ORIGIN *pOrigin)
Convert a group ID from a relative reference to an absolute reference. See UK1.05 section 8...
Definition: mh5gate.c:282
MHEG5Int len
Definition: mh5base.h:99
MHEG5String groupName
Definition: mh5group.h:53
redirection include
#define ERROR_PRINT(x)
Definition: mh5debug.h:76
MH5GroupPtr group
Definition: mh5base.h:103
MHEG5Bool MH5_SupportInteractionChannel(void)
Return whether Interaction channel is supported by current profile.
Definition: mh5support.c:423
MHEG5Int len
Definition: mh5base.h:84
U32BIT zlen
Definition: dtvstring.h:30
MHEG5String MHEG5convertGID(MHEG5String *inRef)
Convert a group ID from a relative reference to an absolute reference. See UK1.05 section 8...
Definition: mh5gate.c:269
E_FS_ORIGIN
Definition: mh5gate.h:48
MHEG5Bool MHEG5ResolveOrigin(MHEG5String *ref, E_FS_ORIGIN *orig, MHEG5Int *offset)
Resolve the orig of a reference.
Definition: mh5gate.c:208
MHEG5Bool MHEG5sameGroup(MH5GroupPtr gptr, MH5GroupRef gref)
Compares two group ID strings to see whether they both reference the same group. The first string is ...
Definition: mh5gate.c:517
#define MHEG5FALSE
Definition: mh5base.h:48
Engine support utility functions for MHEG5.
#define TRACE(t, x)
Definition: glue_debug.h:118