browserutilities/feedsengine/FeedsServer/FeedHandler/src/FeedParser.cpp
changeset 0 dd21522fd290
child 25 0ed94ceaa377
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2005 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 the License "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:  Parser "base" class.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <TInternetDate.h>
       
    20 
       
    21 #include "FeedParser.h"
       
    22 #include "FeedParserObserver.h"
       
    23 #include "LeakTracker.h"
       
    24 #include "XmlUtils.h"
       
    25 
       
    26 
       
    27 _LIT8(KUrlStr, "url");
       
    28 
       
    29 // -----------------------------------------------------------------------------
       
    30 // CFeedParser::CFeedParser
       
    31 // C++ default constructor can NOT contain any code, that
       
    32 // might leave.
       
    33 // -----------------------------------------------------------------------------
       
    34 //
       
    35 CFeedParser::CFeedParser(CXmlUtils& aXmlUtils):
       
    36         iFeedMappings(3), iItemMappings(3), iXmlUtils(aXmlUtils)
       
    37     {
       
    38     }
       
    39 
       
    40 
       
    41 // -----------------------------------------------------------------------------
       
    42 // CFeedParser::~CFeedParser
       
    43 // Deconstructor.
       
    44 // -----------------------------------------------------------------------------
       
    45 //
       
    46 CFeedParser::~CFeedParser()
       
    47     {
       
    48     iFeedMappings.Close();
       
    49     iItemMappings.Close();
       
    50     }
       
    51         
       
    52         
       
    53 // -----------------------------------------------------------------------------
       
    54 // CFeedParser::AddFeedMappingL
       
    55 //
       
    56 // Add a feed ElementHandler mapping.  See AddMappingL.
       
    57 // -----------------------------------------------------------------------------
       
    58 //
       
    59 void CFeedParser::AddFeedMappingL(const TDesC8& aNamespace, const TDesC8& aElementName,
       
    60         TInt aValueId, ElementHandlerFunctionL aHandler)
       
    61     {
       
    62     AddMappingL(iFeedMappings, aNamespace, aElementName, aValueId, aHandler);
       
    63     }
       
    64 
       
    65 
       
    66 // -----------------------------------------------------------------------------
       
    67 // CFeedParser::HandleFeedChildL
       
    68 //
       
    69 // Process a child of a feed element.  See HandleChildL
       
    70 // -----------------------------------------------------------------------------
       
    71 //
       
    72 void CFeedParser::HandleFeedChildL(TXmlEngElement aNode, 
       
    73         MFeedParserObserver& aObserver) const
       
    74     {
       
    75     HandleChildL(iFeedMappings, aNode, aObserver);
       
    76     }
       
    77     
       
    78     
       
    79 // -----------------------------------------------------------------------------
       
    80 // CFeedParser::AddItemMappingL
       
    81 //
       
    82 // Add an item ElementHandler mapping.  See AddMappingL.
       
    83 // -----------------------------------------------------------------------------
       
    84 //
       
    85 void CFeedParser::AddItemMappingL(const TDesC8& aNamespace, const TDesC8& aElementName,
       
    86         TInt aValueId, ElementHandlerFunctionL aHandler)
       
    87     {
       
    88     AddMappingL(iItemMappings, aNamespace, aElementName, aValueId, aHandler);
       
    89     }
       
    90 
       
    91 
       
    92 // -----------------------------------------------------------------------------
       
    93 // CFeedParser::HandleItemChildL
       
    94 //
       
    95 // Process a child of a item element.   See HandleChildL
       
    96 // -----------------------------------------------------------------------------
       
    97 //
       
    98 void CFeedParser::HandleItemChildL(TXmlEngElement aNode, 
       
    99         MFeedParserObserver& aObserver) const
       
   100     {
       
   101     HandleChildL(iItemMappings, aNode, aObserver);
       
   102     }
       
   103     
       
   104     
       
   105 // -----------------------------------------------------------------------------
       
   106 // CFeedParser::ElementHandlerCDataL
       
   107 //
       
   108 // An ElementHandler function that extracts the value from the 
       
   109 // child text nodes.
       
   110 // -----------------------------------------------------------------------------
       
   111 //
       
   112 void CFeedParser::ElementHandlerCDataL(const CFeedParser& /*aParser*/, CXmlUtils& aXmlUtils, 
       
   113         TXmlEngElement aNode, TInt aValueId, MFeedParserObserver& aObserver)
       
   114     {
       
   115     TDesC*  ucs2Des = NULL;
       
   116 
       
   117     // Get the text.
       
   118     ucs2Des = aXmlUtils.ExtractTextL(aNode);
       
   119     if ((ucs2Des == NULL) || (ucs2Des->Length() == 0))
       
   120         {
       
   121         delete ucs2Des;
       
   122         return;
       
   123         }
       
   124 
       
   125     // Set the value
       
   126     CleanupStack::PushL(ucs2Des);
       
   127     aObserver.AddAttributeL(aValueId, *ucs2Des);
       
   128     CleanupStack::PopAndDestroy(ucs2Des);
       
   129     }
       
   130 
       
   131 
       
   132 // -----------------------------------------------------------------------------
       
   133 // CFeedParser::ElementHandlerTextL
       
   134 //
       
   135 // An ElementHandler function that extracts the value from the 
       
   136 // child text nodes then resolves any html entities and removes any markup.
       
   137 // -----------------------------------------------------------------------------
       
   138 //
       
   139 void CFeedParser::ElementHandlerTextL(const CFeedParser& /*aParser*/, CXmlUtils& aXmlUtils, 
       
   140         TXmlEngElement aNode, TInt aValueId, MFeedParserObserver& aObserver)
       
   141     {
       
   142     HBufC*  ucs2Des = NULL;
       
   143 
       
   144     // Get the text.
       
   145     ucs2Des = aXmlUtils.ExtractTextL(aNode);
       
   146     if ((ucs2Des == NULL) || (ucs2Des->Length() == 0))
       
   147         {
       
   148         delete ucs2Des;
       
   149         return;
       
   150         }
       
   151 
       
   152     // Clean it up.
       
   153     TPtr  ptr(ucs2Des->Des());
       
   154     
       
   155     CleanupStack::PushL(ucs2Des);
       
   156     (void) aXmlUtils.CleanupMarkupL(ptr, 0);
       
   157 
       
   158     // Set the value
       
   159     if (ucs2Des->Length() > 0)
       
   160         {        
       
   161         aObserver.AddAttributeL(aValueId, *ucs2Des);
       
   162         }
       
   163         
       
   164     CleanupStack::PopAndDestroy(ucs2Des);
       
   165     }
       
   166 
       
   167 
       
   168 // -----------------------------------------------------------------------------
       
   169 // CFeedParser::ElementHandlerUrlChildL
       
   170 //
       
   171 // An ElementHandler function that extracts the value from a child
       
   172 // url element.  If the element doesn't contain any elements and it contains
       
   173 // text it is extracted instead.
       
   174 // -----------------------------------------------------------------------------
       
   175 //
       
   176 void CFeedParser::ElementHandlerUrlChildL(const CFeedParser& aParser, CXmlUtils& aXmlUtils, 
       
   177         TXmlEngElement aNode, TInt aValueId, MFeedParserObserver& aObserver)
       
   178     {
       
   179     TXmlEngElement  urlNode = NULL;
       
   180     
       
   181     // Get the url element.
       
   182     urlNode = aXmlUtils.GetFirstNamedChild(aNode, KUrlStr());
       
   183 
       
   184     // If it doesn't have a url child and it has no children at all just 
       
   185     // extract the url from the node's text.
       
   186     if ((urlNode.IsNull()) && (!urlNode.HasChildNodes()))
       
   187         {
       
   188         urlNode = aNode;
       
   189         }
       
   190 
       
   191     // Extracts the value url.
       
   192     ElementHandlerUrlL(aParser, aXmlUtils, urlNode, aValueId, aObserver);
       
   193     }
       
   194 
       
   195 
       
   196 // -----------------------------------------------------------------------------
       
   197 // CFeedParser::ElementHandlerUrlL
       
   198 //
       
   199 // An ElementHandler function that extracts the value from the 
       
   200 // child text nodes.  It further performs url related clean up.
       
   201 // -----------------------------------------------------------------------------
       
   202 //
       
   203 void CFeedParser::ElementHandlerUrlL(const CFeedParser& /*aParser*/, CXmlUtils& aXmlUtils, 
       
   204         TXmlEngElement aNode,  TInt aValueId, MFeedParserObserver& aObserver)
       
   205     {
       
   206     TDesC*  ucs2Des = NULL;
       
   207 
       
   208     // Get the text.
       
   209     ucs2Des = aXmlUtils.ExtractTextL(aNode);
       
   210     if ((ucs2Des == NULL) || (ucs2Des->Length() == 0))
       
   211         {
       
   212         delete ucs2Des;
       
   213         return;
       
   214         }
       
   215 
       
   216     CleanupStack::PushL(ucs2Des);
       
   217 
       
   218     // Clean up the url.
       
   219     TPtr ptr(const_cast<TUint16*>(ucs2Des->Ptr()), ucs2Des->Length());
       
   220     aXmlUtils.CleanupUrlL(ptr);
       
   221 
       
   222     // TODO: Resolve the href using feed url (the feed's url can be stored in CFeedParser).
       
   223 
       
   224     // Set the value
       
   225     aObserver.AddAttributeL(aValueId, *ucs2Des);
       
   226     CleanupStack::PopAndDestroy(ucs2Des);
       
   227     }
       
   228 
       
   229 
       
   230 // -----------------------------------------------------------------------------
       
   231 // CFeedParser::ElementHandlerDateL
       
   232 //
       
   233 // An ElementHandler function that extracts the date from the 
       
   234 // child text nodes.  It can handle date formats defined in RFC 3339, RFC 822,
       
   235 // RFC 1123, RFC 850, and RFC 1036
       
   236 // -----------------------------------------------------------------------------
       
   237 //
       
   238 void CFeedParser::ElementHandlerDateL(const CFeedParser& /*aParser*/, 
       
   239         CXmlUtils& /*aXmlUtils*/, TXmlEngElement aNode,  TInt aValueId, MFeedParserObserver& aObserver)
       
   240     {
       
   241     TTime    date;
       
   242     TBool    dateSet = EFalse;
       
   243     RBuf8    rbuf;
       
   244 
       
   245     // Get the text.
       
   246     aNode.WholeTextContentsCopyL( rbuf );
       
   247     if ( rbuf.Length() == 0 )
       
   248         {
       
   249         rbuf.Close();
       
   250         return;
       
   251         }
       
   252     rbuf.CleanupClosePushL();
       
   253 
       
   254     // Try to handle the date with TInternetDate first.
       
   255     TInternetDate  internetData;
       
   256     
       
   257     TRAPD(err, internetData.SetDateL( rbuf ));
       
   258     if (err == KErrNone)
       
   259         {
       
   260         date = internetData.DateTime();
       
   261         dateSet = ETrue;
       
   262         }
       
   263     
       
   264     // Otherwise if that didn't work then try to interpret it as a RFC 3339 date.
       
   265     else if (err == KErrCorrupt)
       
   266         {
       
   267         TRAP(err, ParseRFC3339L( rbuf, date ));
       
   268         if (err == KErrNone)
       
   269             {
       
   270             dateSet = ETrue;
       
   271             }
       
   272         }
       
   273     
       
   274     // Set the value
       
   275     if (dateSet)
       
   276         {        
       
   277         TBuf16<25>  str;
       
   278         
       
   279         str.Format(_L("%Ld"), date.Int64());
       
   280         aObserver.AddAttributeL(aValueId, str);
       
   281         }
       
   282         
       
   283     CleanupStack::PopAndDestroy( /*rbuf*/ );
       
   284     }
       
   285 
       
   286 
       
   287 // -----------------------------------------------------------------------------
       
   288 // CFeedParser::AddMappingL
       
   289 //
       
   290 // Makes a mapping between an element's namespance and name with the normalized
       
   291 // value-id (i.e. title or description) and a function which extracts out
       
   292 // relevant data and applies it to a provided ValueHolder using the value-id 
       
   293 // (see HandleChildL).
       
   294 // -----------------------------------------------------------------------------
       
   295 //
       
   296 void CFeedParser::AddMappingL(RArray<ElementHandlerMapEntry>& aMappings, 
       
   297         const TDesC8& aNamespace, const TDesC8& aElementName, TInt aValueId, 
       
   298         ElementHandlerFunctionL aHandler)
       
   299     {
       
   300     ElementHandlerMapEntry  entry;
       
   301 
       
   302     // Init the entry.
       
   303     entry.iElementNamespace.Set(aNamespace);
       
   304     entry.iElementName.Set(aElementName);
       
   305     entry.iValueId = aValueId;
       
   306     entry.iElementHandlerL = aHandler;
       
   307     
       
   308     // Append the entry.
       
   309     User::LeaveIfError(aMappings.Append(entry));
       
   310     }
       
   311 
       
   312 
       
   313 // -----------------------------------------------------------------------------
       
   314 // CFeedParser::HandleChildL
       
   315 //
       
   316 // Using the mapping defined by calls to AddMappingL it passes aNode, 
       
   317 // aValueHolder and associated value-id to the associated function.  The method
       
   318 // does what is needed to extract the relevant values from the node and applies
       
   319 // them on aValueHolder (using the normalized value-id).
       
   320 // -----------------------------------------------------------------------------
       
   321 //
       
   322 void CFeedParser::HandleChildL(const RArray<ElementHandlerMapEntry>& aMappings, 
       
   323         TXmlEngElement aNode, MFeedParserObserver& aObserver) const
       
   324     {
       
   325     // Find the corresponding entry in the map.
       
   326     for (TInt i = 0; i < aMappings.Count(); i++)
       
   327         {
       
   328         // Call the ElementHandler.
       
   329         if (iXmlUtils.IsNamed(aNode, aMappings[i].iElementNamespace, 
       
   330                 aMappings[i].iElementName))
       
   331             {
       
   332             (aMappings[i].iElementHandlerL)(*this, iXmlUtils, aNode, 
       
   333                     aMappings[i].iValueId, aObserver);            
       
   334             break;
       
   335             }
       
   336         }
       
   337     }
       
   338     
       
   339     
       
   340 // -----------------------------------------------------------------------------
       
   341 // CFeedParser::RFC3339DateL
       
   342 //
       
   343 // Converts the given RFC 3339 date into a TTime.
       
   344 // RFC 3339 format (examples): YYYY-MM-DDTHH:MM:SS.FFZ, 
       
   345 // YYYY-MM-DDTHH:MM:SS.FF+HH:MM or YYYY-MM-DDTHH:MM:SS.FF-HH:MM
       
   346 // -----------------------------------------------------------------------------
       
   347 //
       
   348 void CFeedParser::ParseRFC3339L(const TDesC8& aDateStr, TTime& aDate)
       
   349     {
       
   350     enum TPart  {EYear, EMonth, EDay, EHour, EMin, ESec, EMicro, EZoneHour, EZoneMin, ENone};
       
   351 
       
   352     TDateTime  dateTime;
       
   353     TInt       num;
       
   354     TBuf<30>   timeStr;
       
   355     TBuf<30>   zoneHour;
       
   356     TBuf<30>   zoneMin;
       
   357     TPart      part = EYear;
       
   358     TInt       zone = 0;
       
   359     
       
   360     timeStr.Zero();
       
   361     
       
   362     if (aDateStr.Length() > 30)
       
   363         {
       
   364         User::Leave(KErrCorrupt);
       
   365         }
       
   366         
       
   367     for (TInt i = 0; i < aDateStr.Length(); i++)
       
   368         {
       
   369         TChar  c(aDateStr[i]);
       
   370         
       
   371         // Extract the year.
       
   372         if (part == EYear)
       
   373             {
       
   374             if (c.IsDigit())
       
   375                 {
       
   376                 timeStr.Append(c);
       
   377                 }
       
   378             else if (c == '-')
       
   379                 {
       
   380                 // If timeStr.Length() equals 2 then get the current
       
   381                 // year and use the first two digits to set the four digit year.
       
   382                 if (timeStr.Length() == 2)
       
   383                     {
       
   384                     TTime    now;
       
   385                     TInt     year;
       
   386                     TBuf<4>  yearStr;
       
   387                     
       
   388                     now.UniversalTime();
       
   389                     year = now.DateTime().Year();
       
   390                     yearStr.AppendNum(year);
       
   391                     
       
   392                     timeStr.Insert(0, yearStr.Left(1));
       
   393                     timeStr.Insert(1, yearStr.Mid(1, 1));
       
   394                     }
       
   395 
       
   396                 TLex16 lex(timeStr);                
       
   397                 
       
   398                 lex.Val(num);
       
   399                 User::LeaveIfError(dateTime.SetYear(num));
       
   400                 timeStr.Zero();
       
   401             
       
   402                 part = EMonth;
       
   403                 }
       
   404             else
       
   405                 {
       
   406                 User::Leave(KErrCorrupt);
       
   407                 }
       
   408             }
       
   409             
       
   410         // Extract the month.
       
   411         else if (part == EMonth)
       
   412             {
       
   413             if (c.IsDigit())
       
   414                 {
       
   415                 timeStr.Append(c);
       
   416                 }
       
   417             else if (c == '-')
       
   418                 {
       
   419                 TLex16  lex(timeStr);
       
   420                 TMonth  month = EJanuary;
       
   421                 
       
   422                 lex.Val(num);
       
   423                 
       
   424                 // Convert num to the month enum.
       
   425                 switch (num)
       
   426                     {
       
   427                     case 1:
       
   428                         month = EJanuary;
       
   429                         break;
       
   430                     case 2:
       
   431                         month = EFebruary;
       
   432                         break;
       
   433                     case 3:
       
   434                         month = EMarch;
       
   435                         break;
       
   436                     case 4:
       
   437                         month = EApril;
       
   438                         break;
       
   439                     case 5:
       
   440                         month = EMay;
       
   441                         break;
       
   442                     case 6:
       
   443                         month = EJune;
       
   444                         break;
       
   445                     case 7:
       
   446                         month = EJuly;
       
   447                         break;
       
   448                     case 8:
       
   449                         month = EAugust;
       
   450                         break;
       
   451                     case 9:
       
   452                         month = ESeptember;
       
   453                         break;
       
   454                     case 10:
       
   455                         month = EOctober;
       
   456                         break;
       
   457                     case 11:
       
   458                         month = ENovember;
       
   459                         break;
       
   460                     case 12:
       
   461                         month = EDecember;
       
   462                         break;
       
   463                     default:
       
   464                         User::Leave(KErrCorrupt);
       
   465                         break;
       
   466                     }
       
   467                     
       
   468                 User::LeaveIfError(dateTime.SetMonth(month));
       
   469                 timeStr.Zero();
       
   470             
       
   471                 part = EDay;
       
   472                 }
       
   473             else
       
   474                 {
       
   475                 User::Leave(KErrCorrupt);
       
   476                 }
       
   477             }
       
   478             
       
   479         // Extract the day.
       
   480         else if (part == EDay)
       
   481             {
       
   482             if (c.IsDigit())
       
   483                 {
       
   484                 timeStr.Append(c);
       
   485                 }
       
   486             else if ((c == 'T') || (c == 't'))
       
   487                 {
       
   488                 TLex16 lex(timeStr);
       
   489                 
       
   490                 lex.Val(num);
       
   491                 // Day is zero based for some odd reason...
       
   492                 User::LeaveIfError(dateTime.SetDay(num - 1));
       
   493                 timeStr.Zero();
       
   494             
       
   495                 part = EHour;
       
   496                 }
       
   497             else
       
   498                 {
       
   499                 User::Leave(KErrCorrupt);
       
   500                 }
       
   501             }
       
   502             
       
   503         // Extract the hour.
       
   504         else if (part == EHour)
       
   505             {
       
   506             if (c.IsDigit())
       
   507                 {
       
   508                 timeStr.Append(c);
       
   509                 }
       
   510             else if (c == ':')
       
   511                 {
       
   512                 TLex16 lex(timeStr);
       
   513                 
       
   514                 lex.Val(num);
       
   515                 User::LeaveIfError(dateTime.SetHour(num));
       
   516                 timeStr.Zero();
       
   517             
       
   518                 part = EMin;
       
   519                 }
       
   520             else
       
   521                 {
       
   522                 User::Leave(KErrCorrupt);
       
   523                 }
       
   524             }
       
   525             
       
   526         // Extract the min.
       
   527         else if (part == EMin)
       
   528             {
       
   529             if (c.IsDigit())
       
   530                 {
       
   531                 timeStr.Append(c);
       
   532                 }
       
   533             else if (c == ':')
       
   534                 {
       
   535                 TLex16 lex(timeStr);
       
   536                 
       
   537                 lex.Val(num);
       
   538                 User::LeaveIfError(dateTime.SetMinute(num));
       
   539                 timeStr.Zero();
       
   540             
       
   541                 part = ESec;
       
   542                 }
       
   543             else
       
   544                 {
       
   545                 User::Leave(KErrCorrupt);
       
   546                 }
       
   547             }
       
   548             
       
   549             
       
   550         // Extract the sec.
       
   551         else if (part == ESec)
       
   552             {
       
   553             if (c.IsDigit())
       
   554                 {
       
   555                 timeStr.Append(c);
       
   556                 }
       
   557             else if (c == '.')
       
   558                 {
       
   559                 TLex16 lex(timeStr);
       
   560                 
       
   561                 lex.Val(num);
       
   562                 User::LeaveIfError(dateTime.SetSecond(num));
       
   563                 timeStr.Zero();
       
   564             
       
   565                 part = EMicro;
       
   566                 }
       
   567             else if ((c == 'Z') || (c == 'z'))
       
   568                 {
       
   569                 TLex16 lex(timeStr);
       
   570                 
       
   571                 lex.Val(num);
       
   572                 User::LeaveIfError(dateTime.SetSecond(num));
       
   573                 timeStr.Zero();
       
   574             
       
   575                 zone = 0;
       
   576                 part = ENone;
       
   577                 }
       
   578             else if (c == '+')
       
   579                 {
       
   580                 TLex16 lex(timeStr);
       
   581                 
       
   582                 lex.Val(num);
       
   583                 User::LeaveIfError(dateTime.SetSecond(num));
       
   584                 timeStr.Zero();
       
   585             
       
   586                 zone = 1;
       
   587                 part = EZoneHour;
       
   588                 }
       
   589             else if (c == '-')
       
   590                 {
       
   591                 TLex16 lex(timeStr);
       
   592                 
       
   593                 lex.Val(num);
       
   594                 User::LeaveIfError(dateTime.SetSecond(num));
       
   595                 timeStr.Zero();
       
   596             
       
   597                 zone = -1;
       
   598                 part = EZoneHour;
       
   599                 }
       
   600             else
       
   601                 {
       
   602                 User::Leave(KErrCorrupt);
       
   603                 }
       
   604             }
       
   605             
       
   606         // Ignore the micro-sec.
       
   607         else if (part == EMicro)
       
   608             {
       
   609             if (c.IsDigit())
       
   610                 {
       
   611                 // Ignore microseconds.
       
   612                 }
       
   613             else if ((c == 'Z') || (c == 'z'))
       
   614                 {
       
   615                 zone = 0;
       
   616                 part = ENone;
       
   617                 }
       
   618             else if (c == '+')
       
   619                 {
       
   620                 zone = 1;
       
   621                 part = EZoneHour;
       
   622                 }
       
   623             else if (c == '-')
       
   624                 {
       
   625                 zone = -1;
       
   626                 part = EZoneHour;
       
   627                 }
       
   628             else
       
   629                 {
       
   630                 User::Leave(KErrCorrupt);
       
   631                 }
       
   632             }
       
   633             
       
   634         // Extract the hour.
       
   635         else if (part == EZoneHour)
       
   636             {
       
   637             if (c.IsDigit())
       
   638                 {
       
   639                 zoneHour.Append(c);
       
   640                 }
       
   641             else if (c == ':')
       
   642                 {
       
   643                 part = EZoneMin;
       
   644                 }
       
   645             else
       
   646                 {
       
   647                 User::Leave(KErrCorrupt);
       
   648                 }
       
   649             }
       
   650             
       
   651         // Extract the min.
       
   652         else if (part == EZoneMin)
       
   653             {
       
   654             if (c.IsDigit())
       
   655                 {
       
   656                 zoneMin.Append(c);
       
   657                 }
       
   658             else
       
   659                 {
       
   660                 User::Leave(KErrCorrupt);
       
   661                 }
       
   662             }
       
   663             
       
   664         else
       
   665             {
       
   666             User::Leave(KErrCorrupt);
       
   667             }
       
   668         }
       
   669 
       
   670     // Handle the common date only format (i.e. YYYY-MM-DD).
       
   671     if ((part == EDay) && ((aDateStr.Length() == 10) || (aDateStr.Length() == 8)))
       
   672         {
       
   673         TLex16 lex(timeStr);
       
   674         
       
   675         lex.Val(num);
       
   676         
       
   677         // Day is zero based for some odd reason...
       
   678         User::LeaveIfError(dateTime.SetDay(num - 1));
       
   679         }
       
   680     
       
   681     // Convert timeStr into a TTime.
       
   682     aDate = dateTime;
       
   683 
       
   684     // Adjust the aDate to UTC.
       
   685     if (zone != 0)
       
   686         {
       
   687         TLex16 zHoursLex(zoneHour);
       
   688         TLex16 zMinLex(zoneMin);
       
   689         TInt  zHours;
       
   690         TInt  zMins;
       
   691         
       
   692         // Get the offset.
       
   693         zHoursLex.Val(zHours); 
       
   694         zMinLex.Val(zMins); 
       
   695         
       
   696         // Adjust it back to UTC.
       
   697         if (zone > 0)
       
   698             {
       
   699             aDate -= TTimeIntervalHours(zHours);
       
   700             aDate -= TTimeIntervalMinutes(zMins);
       
   701             }
       
   702             
       
   703         // Otherwise adjust it forward to UTC.
       
   704         else
       
   705             {
       
   706             aDate += TTimeIntervalHours(zHours);
       
   707             aDate += TTimeIntervalMinutes(zMins);
       
   708             }
       
   709         }
       
   710     }
       
   711