messagingapp/msgutils/unidatautils/unidatamodel/src/ConformanceChecker.cpp
changeset 25 84d9eb65b26f
equal deleted inserted replaced
23:238255e8b033 25:84d9eb65b26f
       
     1 /*
       
     2 * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "ConformanceChecker.h"
       
    22 
       
    23 #include <gmxmldocument.h>
       
    24 #include <gmxmlelement.h>
       
    25 
       
    26 #include "smilliterals.h"
       
    27 
       
    28 // ============================ MEMBER FUNCTIONS ===============================
       
    29 
       
    30 
       
    31 // -----------------------------------------------------------------------------
       
    32 // CConformanceChecker::NewL
       
    33 // Two-phased constructor.
       
    34 // -----------------------------------------------------------------------------
       
    35 //
       
    36 EXPORT_C
       
    37 CConformanceChecker* CConformanceChecker::NewL()
       
    38     {
       
    39     CConformanceChecker* self = new( ELeave ) CConformanceChecker;
       
    40     return self;
       
    41     }
       
    42 
       
    43 
       
    44 // Destructor
       
    45 CConformanceChecker::~CConformanceChecker()
       
    46     {
       
    47     }
       
    48 
       
    49 
       
    50 //
       
    51 // ----------------------------------------------------------
       
    52 // CConformanceChecker::Check(CMDXMLDocument* aXmldoc)
       
    53 //
       
    54 // Checks if the DOM tree's content is legacy content or not.
       
    55 // ----------------------------------------------------------
       
    56 //
       
    57 
       
    58 TBool CConformanceChecker::Check(CMDXMLDocument* aXmldoc, TMmsSmilVersion aVersion, TInt aFlags)
       
    59 	{
       
    60 	//Initializing the flags according to the CF document version
       
    61 	switch ( aVersion )
       
    62 		{
       
    63 		case EMmsSmil_v2_0:
       
    64 			iFlags = 0;
       
    65 			break;
       
    66 		case EMmsSmil_v3_0: //Not implemented yet
       
    67 			return EFalse;
       
    68 		default:
       
    69 			iFlags = 0;
       
    70 		}
       
    71 	//Combine the implicit flags  with the explicitly specified flags
       
    72 	iFlags=iFlags | aFlags;
       
    73 
       
    74 	if (!aXmldoc) return EFalse;
       
    75 
       
    76 	CMDXMLElement* root = aXmldoc->DocumentElement();
       
    77 	if (!root) return EFalse;
       
    78 
       
    79 	CMDXMLNode* smil = NULL;
       
    80 	CMDXMLNode* head = NULL;
       
    81 	CMDXMLNode* body = NULL;
       
    82 
       
    83 	CMDXMLNode* node = root->FirstChild();
       
    84 	while (node && node->NodeName() != KSmilTag)
       
    85 		{
       
    86 		node=node->NextSibling();
       
    87 		}
       
    88 
       
    89 	if ( node ) smil = node;
       
    90 	else return EFalse;
       
    91 
       
    92 	node = smil->FirstChild();
       
    93 	while (node && node->NodeType() != CMDXMLNode::EElementNode)
       
    94 		{
       
    95 		node = node->NextSibling();
       
    96 		}
       
    97 
       
    98 	if (node && node->NodeName() == KHeadTag)
       
    99 		{
       
   100 		head = node;
       
   101 		if (!CheckHeadStructure(head))
       
   102 			return EFalse;
       
   103 		//Going forward in the DOM to find next element
       
   104 		node = head->NextSibling();
       
   105 		while (node && node->NodeType() != CMDXMLNode::EElementNode)
       
   106 			{
       
   107 			node = node->NextSibling();
       
   108 			}
       
   109 		}
       
   110 	if (node && node->NodeName() == KBodyTag)
       
   111 		{
       
   112 		body = node;
       
   113 		if (!CheckBodyStructure(body))
       
   114 			return EFalse;
       
   115 		}
       
   116 	else if ( node ) return EFalse; //there is some other element (not head or body in the smil element)
       
   117 	//Checking the head content
       
   118 	if ( head )
       
   119 		{
       
   120 		node = head->FirstChild();
       
   121 		}
       
   122 	else
       
   123 		{
       
   124 		node = NULL;
       
   125 		}
       
   126 
       
   127 	while (node && node->NodeName() != KLayoutTag)
       
   128 		{
       
   129 		node = node->NextSibling();
       
   130 		}
       
   131 	//Checking the content of the layout
       
   132 	if (!CheckLayoutContent(node))
       
   133 		return EFalse;
       
   134 	//Checking the body content
       
   135 	if (!CheckBodyContent(body))
       
   136 		return EFalse;
       
   137 
       
   138 	return ETrue;
       
   139 	} //End of Check()
       
   140 
       
   141 //
       
   142 // ----------------------------------------------------------
       
   143 // CConformanceChecker::CheckHeadStructure(CMDXMLNode* aHead)
       
   144 //
       
   145 // Checks the structure of the head element: allowed to contain only layout and meta element
       
   146 // ----------------------------------------------------------
       
   147 //
       
   148 
       
   149 TBool CConformanceChecker::CheckHeadStructure(CMDXMLNode* aHead)
       
   150 	{
       
   151 	//Checking that the head has only layout and meta element
       
   152 	if (!aHead)
       
   153 		{
       
   154 		return ETrue;
       
   155 		}
       
   156 	CMDXMLNode* node = aHead->FirstChild();
       
   157 	while (node)
       
   158 		{
       
   159 		if (node->NodeType() == CMDXMLNode::EElementNode
       
   160 			&& node->NodeName() != KLayoutTag
       
   161 			&& node->NodeName() != KMetaTag)
       
   162 			{
       
   163 			return EFalse;
       
   164 			}
       
   165 		else
       
   166 			{
       
   167 			node = node->NextSibling();
       
   168 			}
       
   169 		}
       
   170 	return ETrue;
       
   171 	}
       
   172 
       
   173 //
       
   174 // ----------------------------------------------------------
       
   175 // CConformanceChecker::CheckBodyStructure(CMDXMLNode* aBody)
       
   176 //
       
   177 // Checks the structure of the body element: allowed to contain only par elements
       
   178 //											(one including seq element right after the body is allowed)
       
   179 // ----------------------------------------------------------
       
   180 //
       
   181 TBool CConformanceChecker::CheckBodyStructure(CMDXMLNode* aBody)
       
   182 	{
       
   183 	//Checking that the body has only par elements
       
   184 	if (!aBody)
       
   185 		{
       
   186 		return ETrue;
       
   187 		}
       
   188 	CMDXMLNode* node = aBody->FirstChild();
       
   189 	while (node && node->NodeType() != CMDXMLNode::EElementNode)
       
   190 		{
       
   191 		node = node->NextSibling();
       
   192 		}
       
   193 
       
   194 	//One seq element right after the body is allowed if EAllowSeqTag is set
       
   195 	if ((iFlags & EAllowSeqTag)!=0 && node && node->NodeName() == KSeqTag)
       
   196 		{
       
   197 		if (node->NextSibling())
       
   198 			{
       
   199 			return EFalse;
       
   200 			}
       
   201 		else
       
   202 			{
       
   203 			node = node->FirstChild();
       
   204 			}
       
   205 		}
       
   206 	while (node)
       
   207 		{
       
   208 		if (node->NodeType() == CMDXMLNode::EElementNode && node->NodeName() != KParTag)
       
   209 			{
       
   210 			return EFalse;
       
   211 			}
       
   212 		else
       
   213 			{
       
   214 			node = node->NextSibling();
       
   215 			}
       
   216 		}
       
   217 	return ETrue;
       
   218 	}
       
   219 
       
   220 //
       
   221 // ----------------------------------------------------------
       
   222 // CConformanceChecker::CheckLayoutContent(CMDXMLNode* aLayout)
       
   223 //
       
   224 // Checks the content of the layout element
       
   225 //			- root-layout and max. 2 region elements are allowed
       
   226 //			- checks the width/height values for root-layout (pixel is allowed)
       
   227 //			- checks the width/height/top/left values for region
       
   228 //			  if EAllowMixedRegionDimensions is not set no mixed pixel/percent allowed
       
   229 // ----------------------------------------------------------
       
   230 //
       
   231 
       
   232 TBool CConformanceChecker::CheckLayoutContent(CMDXMLNode* aLayout)
       
   233 	{
       
   234 	TInt rl_nr = 0;
       
   235 	TInt r_nr = 0;
       
   236 	if (!aLayout)
       
   237 		{
       
   238 		return ETrue;
       
   239 		}
       
   240 	CMDXMLNode* node = aLayout->FirstChild();
       
   241 	TBool foundImage = EFalse;
       
   242 	TBool foundText = EFalse;
       
   243 	while (node)
       
   244 		{
       
   245 		if (node->NodeType() == CMDXMLNode::EElementNode)
       
   246 			{
       
   247 			if (node->NodeName() == KRootLayoutTag)
       
   248 				{
       
   249 				if (++rl_nr > 1)
       
   250 					return EFalse;
       
   251 				//Check the attributes
       
   252 				CMDXMLElement* elem = static_cast<CMDXMLElement*>(node);
       
   253 				TInt n = elem->NumAttributes();
       
   254 				for (TInt i = 0; i < n; ++i)
       
   255 					{
       
   256 					TPtrC name, value;
       
   257 					elem->AttributeDetails(i,name,value);
       
   258 					if	( (iFlags & EAllowAllAttributes) == 0 &&
       
   259 						name != KWidthAttr && name != KHeightAttr )
       
   260 						{
       
   261 						return EFalse;
       
   262 						}
       
   263 					if (name == KWidthAttr || name == KHeightAttr)
       
   264 						{
       
   265 						TBool pixel = EFalse;  // WB!
       
   266 						TBool percent = EFalse;
       
   267 						if (!CheckMixedRegionAttribute(value,percent,pixel))
       
   268 							{
       
   269 							return EFalse;
       
   270 							}
       
   271 						}
       
   272 					}
       
   273 				}
       
   274 			else if (node->NodeName() == KRegionTag)
       
   275 				{
       
   276 				if (++r_nr > 2)
       
   277 					{
       
   278 					return EFalse;
       
   279 					}
       
   280 				//Check the attributes
       
   281 				TBool foundPixel = EFalse;
       
   282 				TBool foundPercent = EFalse;
       
   283 
       
   284 				CMDXMLElement* elem = static_cast<CMDXMLElement*>(node);
       
   285 				TInt n = elem->NumAttributes();
       
   286 				for (TInt i = 0; i < n; ++i)
       
   287 					{
       
   288 					TPtrC name, value;
       
   289 					elem->AttributeDetails(i,name,value);
       
   290 
       
   291 					if ((iFlags & EAllowAllAttributes) == 0 && name != KIdAttr
       
   292 						&& name != KWidthAttr && name != KHeightAttr
       
   293 						&& name != KFitAttr && name != KLeftAttr && name != KTopAttr)
       
   294 						{
       
   295 						return EFalse;
       
   296 						}
       
   297 					if ((iFlags & EAllowMixedRegionDimensions)==0 &&
       
   298 						(name == KWidthAttr || name == KHeightAttr
       
   299 						|| name == KTopAttr || name == KLeftAttr)
       
   300 						&& !CheckMixedRegionAttribute(value,foundPercent,foundPixel))
       
   301 						{
       
   302 						return EFalse;
       
   303 						}
       
   304 					if ((iFlags & EAllowAnyRegionNames)==0 && name == KIdAttr
       
   305 						&& !CheckRegionNames(value,foundImage,foundText))
       
   306 						{
       
   307 						return EFalse;
       
   308 						}
       
   309 
       
   310 					}//for
       
   311 				}
       
   312 			else
       
   313 				{
       
   314 				return EFalse;
       
   315 				}
       
   316 
       
   317 			}
       
   318 		node = node->NextSibling();
       
   319 		}//while
       
   320 	return ETrue;
       
   321 	}
       
   322 
       
   323 //
       
   324 // ----------------------------------------------------------
       
   325 // CConformanceChecker::CheckMixedRegionAttribute
       
   326 // Checks if the given value is ending with percent or pixel
       
   327 // and if this is conforming to the values of aPixel, aPercent.
       
   328 // Returns true - if the value is not mixed
       
   329 //		   false - if mixed
       
   330 // ----------------------------------------------------------
       
   331 //
       
   332 TBool CConformanceChecker::CheckMixedRegionAttribute(TDesC& aValue,
       
   333 													 TBool& aPercent, TBool& aPixel) const
       
   334 	{
       
   335 	TInt valueLength = aValue.Length();
       
   336 	TInt j = 0;
       
   337 	TBool success = ETrue;
       
   338 	while (j < valueLength && static_cast<TChar>(aValue[j]).IsDigit())
       
   339 		{
       
   340 		j++;
       
   341 		}
       
   342 	HBufC* ending = aValue.Right(valueLength-j).Alloc();
       
   343 	if (!ending)
       
   344 		{
       
   345 		success = EFalse;
       
   346 		}
       
   347 	else
       
   348 		{
       
   349 		TPtr endingPtr = ending -> Des();
       
   350 		endingPtr.LowerCase();
       
   351 		endingPtr.TrimRight();
       
   352 		if (endingPtr==KPercent)
       
   353 			{
       
   354 			aPercent = ETrue;
       
   355 			if (aPixel)
       
   356 				{
       
   357 				success = EFalse;
       
   358 				}
       
   359 			}
       
   360 		else if (endingPtr==KNullDesC || endingPtr==KPx)
       
   361 			{
       
   362 			aPixel = ETrue;
       
   363 			if (aPercent)
       
   364 				{
       
   365 				success = EFalse;
       
   366 				}
       
   367 			}
       
   368 		else
       
   369 			success = EFalse; //Cannot be other then pixel or percent
       
   370 		}
       
   371 	delete ending;
       
   372 	return success;
       
   373 	}
       
   374 
       
   375 
       
   376 //
       
   377 // ----------------------------------------------------------
       
   378 // CConformanceChecker::CheckRegionNames
       
   379 // Checks if the given value is exactly "Image" or "Text" and if it
       
   380 // is duplicated (checking the transmitted boolean parameters).
       
   381 // Returns true - if the value is "Image" or "Text" and it's not duplicated
       
   382 //		   false - otherwise
       
   383 // ----------------------------------------------------------
       
   384 //
       
   385 TBool CConformanceChecker::CheckRegionNames(TDesC& aValue,
       
   386 											TBool& aFoundImage, TBool& aFoundText) const
       
   387 {
       
   388 	if (aValue == KImage)
       
   389 		{
       
   390 		if (aFoundImage)
       
   391 			{
       
   392 			return EFalse;
       
   393 			}
       
   394 		else
       
   395 			{
       
   396 			aFoundImage = ETrue;
       
   397 			}
       
   398 		}
       
   399 	else if (aValue == KText)
       
   400 		{
       
   401 		if (aFoundText)
       
   402 			{
       
   403 			return EFalse;
       
   404 			}
       
   405 		else
       
   406 			{
       
   407 			aFoundText = ETrue;
       
   408 			}
       
   409 		}
       
   410 	else
       
   411 		{
       
   412 		return EFalse;
       
   413 		}
       
   414 	return ETrue;
       
   415 }
       
   416 
       
   417 //
       
   418 // ----------------------------------------------------------
       
   419 // CConformanceChecker::CheckBodyContent(CMDXMLNode* aBody)
       
   420 //
       
   421 // Checks the content of the body element
       
   422 // ----------------------------------------------------------
       
   423 //
       
   424 TBool CConformanceChecker::CheckBodyContent(CMDXMLNode* aBody)
       
   425 	{
       
   426 	if (!aBody)
       
   427 		{
       
   428 		return ETrue;
       
   429 		}
       
   430 	CMDXMLNode* node = aBody->FirstChild();
       
   431 	//One seq element right after the body is allowed if EAllowSeqTag is set
       
   432 	if ((iFlags & EAllowSeqTag)!=0 && node && node->NodeName() == KSeqTag)
       
   433 		{
       
   434 		node = node->FirstChild();
       
   435 		}
       
   436 	while (node)
       
   437 		{
       
   438 		if (node->NodeName() == KParTag)
       
   439 			{
       
   440 			//Checking the attributes of par element
       
   441 			//only dur is allowed, dur='indefinite' illegal
       
   442 			//checking dur is in ms
       
   443 			CMDXMLElement* elem = static_cast<CMDXMLElement*>(node);
       
   444 			if (elem->NumAttributes() > 1 && (iFlags & EAllowAllAttributes) == 0)
       
   445 				{
       
   446 				return EFalse;
       
   447 				}
       
   448 			for (TInt i = 0; i < elem->NumAttributes(); ++i)
       
   449 				{
       
   450 				TPtrC name, value;
       
   451 				elem->AttributeDetails(i,name,value);
       
   452 
       
   453 				if (name == KDurAttr && value == KIndefiniteVal)
       
   454 					{
       
   455 					return EFalse;
       
   456 					}
       
   457 				if ((iFlags & EAllowAllAttributes) == 0 && (name != KDurAttr ))
       
   458 					{
       
   459 					return EFalse;
       
   460 					}
       
   461 				if (name == KDurAttr && (iFlags & EAllowNonMilliseconds) == 0
       
   462 					&& !IsInMilliseconds(value))
       
   463 					{
       
   464 					return EFalse;
       
   465 					}
       
   466 
       
   467 				}
       
   468 			if (!CheckParContent(node))
       
   469 				return EFalse;
       
   470 			}
       
   471 		node = node->NextSibling();
       
   472 		}
       
   473 	return ETrue;
       
   474 	}
       
   475 
       
   476 
       
   477 //
       
   478 // ----------------------------------------------------------
       
   479 // CConformanceChecker::CheckParContent(CMDXMLNode* aPar)
       
   480 //
       
   481 // Checks the content of the par element
       
   482 // ----------------------------------------------------------
       
   483 //
       
   484 
       
   485 TBool CConformanceChecker::CheckParContent(CMDXMLNode* aPar)
       
   486 	{
       
   487 	if (!aPar)
       
   488 		{
       
   489 		return ETrue;
       
   490 		}
       
   491 	TBool hasImage=EFalse;
       
   492 	TBool hasText=EFalse;
       
   493 	TBool hasAudio=EFalse;
       
   494 	TBool hasRef=EFalse;
       
   495 	TBool hasVideo=EFalse;
       
   496 
       
   497 	RArray<TPtrC> regionNames;
       
   498 	CMDXMLNode* innernode = aPar->FirstChild();
       
   499 	TBool legacy = ETrue;
       
   500 	while (legacy && innernode)
       
   501 		{
       
   502 		if (innernode->NodeType() == CMDXMLNode::EElementNode)
       
   503 			{
       
   504 			//Checking one type of media per par element
       
   505 			if (innernode->NodeName() == KImageTag)
       
   506 				if (hasImage)
       
   507 					{
       
   508 					legacy = EFalse;
       
   509 					}
       
   510 				else
       
   511 					{
       
   512 					hasImage = ETrue;
       
   513 					}
       
   514 			else if (innernode->NodeName() == KTextTag)
       
   515 				if (hasText)
       
   516 					{
       
   517 					legacy = EFalse;
       
   518 					}
       
   519 				else
       
   520 					{
       
   521 					hasText = ETrue;
       
   522 					}
       
   523 			else if (innernode->NodeName() == KAudioTag)
       
   524 				if (hasAudio)
       
   525 					{
       
   526 					legacy = EFalse;
       
   527 					}
       
   528 				else
       
   529 					{
       
   530 					hasAudio = ETrue;
       
   531 					}
       
   532 			else if (innernode->NodeName() == KRefTag)
       
   533 				if (hasRef)
       
   534 					{
       
   535 					legacy = EFalse;
       
   536 					}
       
   537 				else
       
   538 					{
       
   539 					hasRef = ETrue;
       
   540 					}
       
   541 			else if (innernode->NodeName() == KVideoTag)
       
   542 				if ((iFlags & EAllowVideoTag) == 0)
       
   543 					{
       
   544 					legacy = EFalse;
       
   545 					}
       
   546 				else
       
   547 					{
       
   548 					if (hasVideo)
       
   549 						{
       
   550 						legacy = EFalse;
       
   551 						}
       
   552 					else
       
   553 						{
       
   554 						hasVideo=ETrue;
       
   555 						}
       
   556 					}
       
   557 			else legacy = EFalse; //No other elements are allowed then img,text, audio, ref, video
       
   558 				//Check attributes
       
   559 			CMDXMLElement* elem = static_cast<CMDXMLElement*>(innernode);
       
   560 			TInt n = elem->NumAttributes();
       
   561 			for (TInt i = 0; legacy && (i < n); ++i)
       
   562 				{
       
   563 				TPtrC name, value;
       
   564 				elem->AttributeDetails(i,name,value);
       
   565 				//Check one region is used only once per par element
       
   566 				if (name == KRegionAttr)
       
   567 					{
       
   568 					if ((iFlags & EAllowAnyRegionNames) == 0
       
   569 						&& value != KImage && value != KText)
       
   570 						{
       
   571 						legacy = EFalse;
       
   572 						}
       
   573 					TInt nr = regionNames.Count();
       
   574 					TInt j = 0;
       
   575 					while (j < nr && legacy)
       
   576 						{
       
   577 						if (regionNames[j]==value)
       
   578 							{
       
   579 							legacy = EFalse;
       
   580 							}
       
   581 						else
       
   582 							{
       
   583 							++j;
       
   584 							}
       
   585 						}
       
   586 					if (legacy)
       
   587 						{
       
   588 						regionNames.Append(value);
       
   589 						if (regionNames.Count()>2)
       
   590 							{
       
   591 							legacy = EFalse;
       
   592 							}
       
   593 						}
       
   594 
       
   595 					}
       
   596 				else if ((iFlags & EAllowAllAttributes) == 0 && name != KSrcAttr
       
   597 					&& name != KAltAttr && name != KBeginAttr && name != KEndAttr)
       
   598 					{
       
   599 					legacy = EFalse;
       
   600 					}
       
   601 					//checking the src attribute
       
   602 				if (name == KSrcAttr && (iFlags & EAllowNonUsAscii) == 0)
       
   603 					{
       
   604 					TInt valueLength=value.Length();
       
   605 					for (TInt i = 0; legacy && (i < valueLength); ++i)
       
   606 						{
       
   607 						TInt v = value[i];
       
   608 						if (v < KUSAsciiMinCode || v > KUSAsciiMaxCode)
       
   609 							{
       
   610 							legacy = EFalse;
       
   611 							}
       
   612 						}
       
   613 					}
       
   614 				//checking begin and end in ms
       
   615 				if ((name == KBeginAttr || name == KEndAttr)
       
   616 					&& (iFlags & EAllowNonMilliseconds) == 0
       
   617 					&& !IsInMilliseconds(value))
       
   618 					{
       
   619 						legacy = EFalse;
       
   620 					}
       
   621 				}//for
       
   622 			}
       
   623 		innernode = innernode->NextSibling();
       
   624 		} //while
       
   625     regionNames.Close();
       
   626 	return legacy;
       
   627 	}
       
   628 
       
   629 //
       
   630 // ----------------------------------------------------------
       
   631 // CConformanceChecker::IsInMilliseconds(TDesC aValue);
       
   632 //
       
   633 // Checks if  aValue is ending with 'ms'
       
   634 // ----------------------------------------------------------
       
   635 //
       
   636 
       
   637 TBool CConformanceChecker::IsInMilliseconds(TDesC& aValue) const
       
   638 	{
       
   639 	TBuf<2> ending;
       
   640 	TInt j = 0;
       
   641 	TInt n = aValue.Length();
       
   642 	TInt trimmedEndingLength = 2;
       
   643 	//Processing till all the white spaces are eliminated from the end
       
   644 	do
       
   645 	{
       
   646 	j+=2-trimmedEndingLength;
       
   647 	if (n>=j+2)
       
   648 		ending = aValue.Mid(n-2-j,2);
       
   649 	ending.TrimRight();
       
   650 	trimmedEndingLength = ending.Length();
       
   651 	}
       
   652 	while (trimmedEndingLength!=2 && n>j+2);
       
   653 	ending.LowerCase();
       
   654 	if (ending != KMs) return EFalse;
       
   655 	return ETrue;
       
   656 	}
       
   657 
       
   658 //  End of File