voipplugins/dhcppositionprovider/src/dhcpocationinformationparser.cpp
branchRCL_3
changeset 22 d38647835c2e
parent 0 a4daefaec16c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/voipplugins/dhcppositionprovider/src/dhcpocationinformationparser.cpp	Wed Sep 01 12:29:57 2010 +0100
@@ -0,0 +1,885 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Parses location information from DHCP message to LCI
+*
+*/
+
+
+#include <e32math.h>
+#include "dhcplocationinformationparser.h"
+#include "dhcppsylogging.h"
+
+// Dynamic Host Configuration Protocol (DHCPv4 and DHCPv6) Option for Civic
+// Addresses Configuration Information
+// draft-ietf-geopriv-dhcp-civil-09
+
+// Civic Address CAtypes
+const TUint8 KDhcpState = 1;
+const TUint8 KDhcpCounty = 2;
+const TUint8 KDhcpCity = 3;
+const TUint8 KDhcpBorough = 4;
+const TUint8 KDhcpBlock = 5;
+const TUint8 KDhcpGroupOfStreets = 6;
+
+// Civic Address Additional CAtypes
+// const TUint8 KLanguage = 0;
+const TUint8 KDhcpLeadingStreetDirection = 16;
+const TUint8 KDhcpTrailingStreetDirection = 17;
+const TUint8 KDhcpStreetSuffix = 18;
+const TUint8 KDhcpHouseNumber = 19;
+const TUint8 KDhcpHouseNumberSuffix = 20;
+const TUint8 KDhcpVanityAddress = 21;
+const TUint8 KDhcpAdditionalLocationInformation = 22;
+const TUint8 KDhcpName = 23;
+const TUint8 KDhcpPostalCode = 24;
+const TUint8 KDhcpFloor = 27;
+const TUint8 KDchpCASeat = 33;
+
+// XML civilLoc elements
+_LIT8( KDhcpCountry, "country" );
+_LIT8( KDhcpA1, "A1" );     // state
+_LIT8( KDhcpA2, "A2" );     // county
+_LIT8( KDhcpA3, "A3" );     // city
+_LIT8( KDhcpA4, "A4" );     // borough
+_LIT8( KDhcpA5, "A5" );     // block
+_LIT8( KDhcpA6, "A6" );     // street
+_LIT8( KDhcpPRD, "PRD" );   // leading street direction
+_LIT8( KDhcpPOD, "POD" );   // trailing street direction
+_LIT8( KDhcpSTS, "STS" );   // street suffix
+_LIT8( KDhcpHNO, "HNO" );   // house number
+_LIT8( KDhcpHNS, "HNS" );   // house number suffix
+_LIT8( KDhcpLMK, "LMK" );   // landmark or vanity address
+_LIT8( KDhcpLOC, "LOC" );   // additional location information
+_LIT8( KDhcpNAM, "NAM" );   // name
+_LIT8( KDhcpPC, "PC" );     // postal code
+_LIT8( KDhcpFLR, "FLR" );   // floor
+_LIT8( KDhcpSEAT, "SEAT" ); // seat
+
+
+// XML message parsing
+
+// General
+_LIT8( KOpenBracket, "<" );
+_LIT8( KCloseBracket, ">" );
+_LIT8( KForwardSlash, "/" );
+_LIT8( KQuotationMark, "\"" );
+_LIT8( KColon, ":" );
+_LIT8( KSpaceChar, " " );
+_LIT8( KHyphen, "-" );
+
+// XML (RFC 4119)
+_LIT8( KXMLBegin, "?xml version=\"1.0\" encoding=\"UTF-8\"?" );
+_LIT8( KPresence, "presence" );
+_LIT8( KTuple, "tuple" );
+_LIT8( KStatus, "status" );
+_LIT8( KTimeStamp, "<timestamp>" );
+_LIT8( KTimeStampEnd, "</timestamp>" );
+_LIT8( KXmlnsNamespace, " xmlns=\"urn:ietf:params:xml:ns:pidf\"" );
+_LIT8( KId, " id=\"" );
+_LIT8( KTupleId1, "tuple1" );
+_LIT8( KT, "T" );
+_LIT8( KZ, "Z" );
+
+// gp namespace (RFC 4119)
+_LIT8( KGpNamespace, " xmlns:gp=\"urn:ietf:params:xml:ns:pidf:geopriv10\"" );
+_LIT8( KGp, "<gp:" );
+_LIT8( KGpEnd, "</gp:" );
+_LIT8( KGeopriv, "geopriv" );
+_LIT8( KLocationInfo, "location-info" );
+_LIT8( KUsageRules, "usage-rules" );
+_LIT8( KRetransmissionAllowed, "retransmission-allowed" );
+_LIT8( KRetentionExpiry, "retention-expiry" );
+_LIT8( KMethod, "method" );
+_LIT8( KNo, "no" );
+_LIT8( KDhcp, "DHCP" );
+
+// gml namespace (RFC 4119)
+_LIT8( KGmlNamespace,
+    " xmlns:gml=\"urn:opengis:specification:gml:schema-xsd:feature:v3.0\"" );
+_LIT8( KGml, "<gml:" );
+_LIT8( KGmlEnd, "</gml:" );
+_LIT8( KGmlId, " gml:id=\"" );
+_LIT8( KLocation, "location" );
+_LIT8( KPoint, "Point" );
+_LIT8( KCoordinates, "coordinates" );
+_LIT8( KPointId1, "point1" );
+_LIT8( KSrsName, " srsName=\"" );
+_LIT8( KNorth, "N" );
+_LIT8( KEast, "E" );
+_LIT8( KSouth, "S" );
+_LIT8( KWest, "W" );
+
+// Datum related (RFC 3825)
+_LIT8( KEpsg4269, "epsg:4269" ); // NAD83 (North American Datum 1983)
+_LIT8( KEpsg4326, "epsg:4326" ); // EPSG:4326 - WGS84 (World Geodesic Datum)
+
+// cl namespace (RFC 4119)
+_LIT8( KClNamespace,
+    " xmlns:cl=\" urn:ietf:params:xml:ns:pidf:geopriv10:civicLoc\"" );
+_LIT8( KCl, "<cl:" );
+_LIT8( KClEnd, "</cl:" );
+_LIT8( KCivicAddress, "civicAddress" );
+
+// Other constants
+const TUint8 KDhcpMinAsciiValue = 0x1f;
+const TUint8 KDhcpMaxAsciiValue = 0x7f;
+const TReal KDhcp25BitDivisor = 0x2000000;          // 33554432dec;
+
+// ---------------------------------------------------------------------------
+// Default constructor
+// ---------------------------------------------------------------------------
+//
+TDhcpLocationInformationParser::TDhcpLocationInformationParser()
+    {
+    iTimeStamp.HomeTime();
+    }
+
+// ---------------------------------------------------------------------------
+// Parse XML description, geoConf or civic address, of the location
+// information. RFC 4119
+// ---------------------------------------------------------------------------
+//
+void TDhcpLocationInformationParser::ParseLocationInformation(
+    const TDesC8& aInput, const TParsingType aParsingType, TDes8& aOutput )
+    {
+    TRACESTRING( "TLocationInformationParser::ParseLocationInformation" );
+
+    // XML
+    aOutput.Append( KOpenBracket );
+    aOutput.Append( KXMLBegin );
+    aOutput.Append( KCloseBracket );
+
+    // presence
+    aOutput.Append( KOpenBracket );
+    aOutput.Append( KPresence );
+    aOutput.Append( KXmlnsNamespace );
+    aOutput.Append( KGpNamespace );
+    if ( EDHCPCoordinates == aParsingType )
+        {
+        aOutput.Append( KGmlNamespace );
+        }
+    else // EDHCPCivicAddress
+        {
+        aOutput.Append( KClNamespace );
+        }
+
+    aOutput.Append( KCloseBracket );
+
+    // tuple
+    aOutput.Append( KOpenBracket );
+    aOutput.Append( KTuple );
+    aOutput.Append( KId );
+    aOutput.Append( KTupleId1 );
+    aOutput.Append( KQuotationMark );
+    aOutput.Append( KCloseBracket );
+
+    // timestamp
+    aOutput.Append( KTimeStamp );
+    ParseTimeStamp( aOutput );
+    aOutput.Append( KTimeStampEnd );
+
+    // status
+    aOutput.Append( KOpenBracket );
+    aOutput.Append( KStatus );
+    aOutput.Append( KCloseBracket );
+
+    // geopriv
+    aOutput.Append( KGp );
+    aOutput.Append( KGeopriv );
+    aOutput.Append( KCloseBracket );
+
+    // location-info
+    aOutput.Append( KGp );
+    aOutput.Append( KLocationInfo );
+    aOutput.Append( KCloseBracket );
+
+    if (aParsingType == EDHCPCoordinates)
+        {
+        // GML
+        aOutput.Append( KGml );
+        aOutput.Append( KLocation );
+        aOutput.Append( KCloseBracket );
+
+        // Point
+        aOutput.Append( KGml );
+        aOutput.Append( KPoint );
+        aOutput.Append( KGmlId );
+        aOutput.Append( KPointId1 );
+        aOutput.Append( KQuotationMark );
+        // srsName, i.e. datum
+        ParseDatum( aInput, aOutput ); // Ignore error
+        aOutput.Append( KCloseBracket );
+
+        // coordinates
+        aOutput.Append( KGml );
+        aOutput.Append( KCoordinates );
+        aOutput.Append( KCloseBracket );
+
+        // Parse coordinates
+        ParseLCI( aInput, aOutput );
+
+        // coordinates end
+        aOutput.Append( KGmlEnd );
+        aOutput.Append( KCoordinates );
+        aOutput.Append( KCloseBracket );
+
+        // Point end
+        aOutput.Append( KGmlEnd );
+        aOutput.Append( KPoint );
+        aOutput.Append( KCloseBracket );
+
+        // GML end
+        aOutput.Append( KGmlEnd );
+        aOutput.Append( KLocation );
+        aOutput.Append( KCloseBracket );
+        }
+    else // EDHCPCivicAddress
+        {
+        // civicAddress
+        aOutput.Append( KCl );
+        aOutput.Append( KCivicAddress );
+        aOutput.Append( KCloseBracket );
+
+        // Parse civic address elements
+        ParseCivicAddressElements( aInput, aOutput );
+
+        // civicAddress end
+        aOutput.Append( KClEnd );
+        aOutput.Append( KCivicAddress );
+        aOutput.Append( KCloseBracket );
+        }
+
+    // location-info end
+    aOutput.Append( KGpEnd );
+    aOutput.Append( KLocationInfo );
+    aOutput.Append( KCloseBracket );
+
+    // usage-rules
+    aOutput.Append( KGp );
+    aOutput.Append( KUsageRules );
+    aOutput.Append( KCloseBracket );
+    // retransmission-allowed
+    aOutput.Append( KGp );
+    aOutput.Append( KRetransmissionAllowed );
+    aOutput.Append( KCloseBracket );
+    aOutput.Append( KNo );
+    aOutput.Append( KGpEnd );
+    aOutput.Append( KRetransmissionAllowed );
+    aOutput.Append( KCloseBracket );
+    // retention-expiry
+    aOutput.Append( KGp );
+    aOutput.Append( KRetentionExpiry );
+    aOutput.Append( KCloseBracket );
+    ParseRetentionExpiry( aOutput );
+    aOutput.Append( KGpEnd );
+    aOutput.Append( KRetentionExpiry );
+    aOutput.Append( KCloseBracket );
+    // method
+    aOutput.Append( KGp );
+    aOutput.Append( KMethod );
+    aOutput.Append( KCloseBracket );
+    aOutput.Append( KDhcp );
+    aOutput.Append( KGpEnd );
+    aOutput.Append( KMethod );
+    aOutput.Append( KCloseBracket );
+
+    // : provided-by
+
+    // usage-rules end
+    aOutput.Append( KGpEnd );
+    aOutput.Append( KUsageRules );
+    aOutput.Append( KCloseBracket );
+
+    // geopriv end
+    aOutput.Append( KGpEnd );
+    aOutput.Append( KGeopriv );
+    aOutput.Append( KCloseBracket );
+
+    // status end
+    aOutput.Append( KOpenBracket );
+    aOutput.Append( KForwardSlash );
+    aOutput.Append( KStatus );
+    aOutput.Append( KCloseBracket );
+
+    // tuple end
+    aOutput.Append( KOpenBracket );
+    aOutput.Append( KForwardSlash );
+    aOutput.Append( KTuple );
+    aOutput.Append( KCloseBracket );
+
+    // presence end
+    aOutput.Append( KOpenBracket );
+    aOutput.Append( KForwardSlash );
+    aOutput.Append( KPresence );
+    aOutput.Append( KCloseBracket );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Parses datum from the input
+// Datum usage: RFC 3825.
+// ---------------------------------------------------------------------------
+//
+TInt TDhcpLocationInformationParser::ParseDatum (const TDesC8& aInput, TDes8& aOutput )
+    {
+    TRACESTRING( "TLocationInformationParser::ParseDatum" );
+
+    if ( 16 > aInput.Length() )
+        {
+        return KErrNotFound;
+        }
+
+    // The LCI form is of fixed length (16 bytes). The last byte of the input
+    // contains the datum value.
+    switch ( ( TUint8 )aInput[ 15 ] )
+        {
+        case 1:
+            {
+            // WGS 84, 2D only (For 3D: WGS84 (Geographical 3D))
+            aOutput.Append( KSrsName );
+            aOutput.Append( KEpsg4326 );
+            aOutput.Append( KQuotationMark );
+            return KErrNone;
+            }
+        case 2:
+            {
+            // NAD83, 2D only (For 3D: NAD83 & NAVD88)
+            aOutput.Append( KSrsName );
+            aOutput.Append( KEpsg4269 );
+            aOutput.Append( KQuotationMark );
+            return KErrNone;
+            }
+        case 3:
+            {
+            // NAD83, 2D only (For 3D: NAD83 & MLLW)
+            aOutput.Append( KSrsName );
+            aOutput.Append( KEpsg4269 );
+            aOutput.Append( KQuotationMark );
+            return KErrNone;
+            }
+        default:
+            {
+            return KErrNotSupported;
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Parses the input to the LCI form
+// ---------------------------------------------------------------------------
+//
+void TDhcpLocationInformationParser::ParseLCI(
+    const TDesC8& aInput, TDes8& aOutput )
+    {
+    TRACESTRING( "TLocationInformationParser::ParseLCI" );
+
+    TLex8 input( aInput );
+
+    // Latitude
+
+    // Latitude resolution (6 bits)
+    TUint8 laRes = ( TUint8 )input.Peek();
+    laRes >>= 2;
+
+    // Latitude (9 bits integer, 25 bits fraction)
+    TUint16 laInt = ( TUint16 )input.Get();
+    laInt <<= 14;
+    laInt >>= 6;
+    laInt += ( TUint8 )input.Peek();
+    laInt >>= 1;
+
+    TUint32 laFra = ( TUint32 )input.Get();
+    laFra <<= 8;
+    laFra += ( TUint8 )input.Get();
+    laFra <<= 8;
+    laFra += ( TUint8 )input.Get();
+    laFra <<= 8;
+    laFra += ( TUint8 )input.Get();
+    laFra <<= 7;
+    laFra >>= 7;
+
+    ParseDMS( ETrue, laRes, laInt, laFra, aOutput );
+
+    aOutput.Append( KSpaceChar );
+
+    // Longitude
+
+    // Longitude resolution (6 bits)
+    TUint8 loRes = ( TUint8 )input.Peek();
+    loRes >>= 2;
+
+    // Longitude (9 bits integer, 25 bits fraction)
+    TUint16 loInt = ( TUint16 )input.Get();
+    loInt <<= 14;
+    loInt >>= 6;
+    loInt += ( TUint8 )input.Peek();
+    loInt >>= 1;
+
+    TUint32 loFra = ( TUint32 )input.Get();
+    loFra <<= 8;
+    loFra += ( TUint8 )input.Get();
+    loFra <<= 8;
+    loFra += ( TUint8 )input.Get();
+    loFra <<= 8;
+    loFra += ( TUint8 )input.Get();
+    loFra <<= 7;
+    loFra >>= 7;
+
+    ParseDMS( EFalse, loRes, loInt, loFra, aOutput );
+
+    // Altitude
+    if ( 15 <= aInput.Length() )
+        {
+        // AT (4 bits)
+        // 1 for meters, 2 for floors
+        TUint8 AT = ( TUint8 )input.Peek();
+        AT >>= 4;
+
+        // Altitude resolution (6 bits)
+        TUint16 altRes = ( TUint16 )input.Get();
+        altRes <<= 8;
+        altRes += ( TUint8 )input.Peek();
+        altRes >>= 6;
+
+        // Altitude (30 bits)
+        TUint32 alt = ( TUint32 )input.Get();
+        alt <<= 26;
+        alt >>= 18;
+        alt += ( TUint8 )input.Get();
+        alt <<= 8;
+        alt += ( TUint8 )input.Get();
+        alt <<= 8;
+        alt += ( TUint8 )input.Get();
+        alt <<= 8;
+
+        TRACESTRING2( "AT: %d", AT );
+        TRACESTRING2( "altRes: %d", altRes );
+        TRACESTRING2( "alt: %d", alt );
+        }
+
+    // No support for parsing altitude to XML yet
+    }
+
+
+// ---------------------------------------------------------------------------
+// Parses the input to the DMS coordinate form
+// ---------------------------------------------------------------------------
+//
+void TDhcpLocationInformationParser::ParseDMS(
+    TBool aIsLatitude,
+    TUint8 aResolution,
+    TUint16 aInteger,
+    TUint32 aFraction,
+    TDes8& aOutput )
+    {
+    TRACESTRING( "TLocationInformationParser::ParseDMS" );
+
+    TRACESTRING2( "aResolution: %d", aResolution );
+    TRACESTRING2( "aInteger: %d", aInteger );
+    TRACESTRING2( "aFraction: %d", aFraction );
+
+    // Check the first bit for sign
+    TUint16 sign = aInteger; // 9 bits
+    sign >>= 8;
+
+    // 2s complement
+    if ( sign )
+        {
+        aInteger = ~aInteger;
+        aInteger <<= 7;
+        aInteger >>= 7;
+        aFraction = ~aFraction;
+        aFraction <<= 7;
+        aFraction >>= 7;
+        }
+
+    // Apply resolution
+    if ( 9 < aResolution )
+        {
+        // Fractional part
+        aFraction >>= ( 34 - aResolution );
+        aFraction <<= ( 34 - aResolution );
+        }
+    else
+        {
+        // No fractional part
+        aFraction = 0;
+        // Integer part
+        aInteger >>= ( 9 - aResolution );
+        aInteger <<= ( 9 - aResolution );
+        }
+
+    // Fractional part
+    TReal minutes( 0.0 );
+    TReal seconds( 0.0 );
+    if ( aFraction )
+        {
+        TReal frac = ( TReal )aFraction / KDhcp25BitDivisor;
+        Math::Int( minutes, 60.0 * frac );
+        frac = 60.0 * frac - minutes;
+        Math::Int( seconds, 60.0 * frac );
+        }
+
+    // Parse the result
+    aOutput.AppendNum( aInteger );
+    aOutput.Append( KColon );
+    aOutput.AppendNum( ( TUint8 )minutes );
+    aOutput.Append( KColon );
+    aOutput.AppendNum( ( TUint8 )seconds );
+    if ( aIsLatitude )
+        {
+        if ( sign )
+            {
+            aOutput.Append( KSouth );
+            }
+        else
+            {
+            aOutput.Append( KNorth );
+            }
+        }
+    else
+        {
+        if ( sign )
+            {
+            aOutput.Append( KWest );
+            }
+        else
+            {
+            aOutput.Append( KEast );
+            }
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Parse XML description of civic address elements
+// Correspondence of tags can be found in Ch.3.4 Civic Address Components in
+// http://www.ietf.org/internet-drafts/draft-ietf-geopriv-dhcp-civil-09.txt
+// ---------------------------------------------------------------------------
+//
+void TDhcpLocationInformationParser::ParseCivicAddressElements(
+    const TDesC8& aInput, TDes8& aOutput )
+    {
+    TRACESTRING( "TLocationInformationParser::ParseCivicAddressElements" );
+
+    TLex8 input( aInput );
+
+    // Skip what
+    input.Inc();
+
+    // country code, two letters long
+    aOutput.Append( KCl );
+    aOutput.Append( KDhcpCountry );
+    aOutput.Append( KCloseBracket );
+    aOutput.Append( input.Get() );
+    aOutput.Append( input.Get() );
+    aOutput.Append( KClEnd );
+    aOutput.Append( KDhcpCountry );
+    aOutput.Append( KCloseBracket );
+
+    // civicAddress elements
+    while ( !input.Eos() )
+        {
+        TInt type = ( TUint8 )input.Get();
+        switch ( type )
+            {
+            case KDhcpState:
+                {
+                TRACESTRING( "KDhcpState" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpA1 );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpA1 );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpCounty:
+                {
+                TRACESTRING( "KDhcpCounty" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpA2 );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpA2 );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpCity:
+                {
+                TRACESTRING( "KDhcpCity" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpA3 );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpA3 );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpBorough:
+                {
+                TRACESTRING( "KDhcpBorough" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpA4 );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpA4 );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpBlock:
+                {
+                TRACESTRING( "KBlock" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpA5 );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpA5 );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpGroupOfStreets:
+                {
+                TRACESTRING( "KGroupOfStreets" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpA6 );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpA6 );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpLeadingStreetDirection:
+                {
+                TRACESTRING( "KLeadingStreetDirection" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpPRD );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpPRD );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpTrailingStreetDirection:
+                {
+                TRACESTRING( "KTrailingStreetDirection" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpPOD );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpPOD );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpStreetSuffix:
+                {
+                TRACESTRING( "KStreetSuffix" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpSTS );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpSTS );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpHouseNumber:
+                {
+                TRACESTRING( "KHouseNumber" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpHNO );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpHNO );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpHouseNumberSuffix:
+                {
+                TRACESTRING( "KHouseNumberSuffix" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpHNS );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpHNS );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpVanityAddress:
+                {
+                TRACESTRING( "KVanityAddress" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpLMK );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpLMK );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpAdditionalLocationInformation:
+                {
+                TRACESTRING( "KAdditionalLocationInformation" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpLOC );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpLOC );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpName:
+                {
+                TRACESTRING( "KName" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpNAM );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpNAM );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpPostalCode:
+                {
+                TRACESTRING( "KPostalCode" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpPC );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpPC );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDchpCASeat:
+                {
+                TRACESTRING( "KCASeat" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpSEAT );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpSEAT );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            case KDhcpFloor:
+                {
+                TRACESTRING( "KFloor" );
+                aOutput.Append( KCl );
+                aOutput.Append( KDhcpFLR );
+                aOutput.Append( KCloseBracket );
+                ExtractCivicAddressElement( input, aOutput );
+                aOutput.Append( KClEnd );
+                aOutput.Append( KDhcpFLR );
+                aOutput.Append( KCloseBracket );
+                break;
+                }
+            default:
+                {
+                TRACESTRING2( "Not a supported CAtype: %d", type );
+                input.Inc( ( TInt )input.Get() ); // Skip value
+                break;
+                }
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Extract a single civic address element from the input
+// ---------------------------------------------------------------------------
+//
+void TDhcpLocationInformationParser::ExtractCivicAddressElement(
+    TLex8& aInput, TDes8& aOutput )
+    {
+    TRACESTRING( "TLocationInformationParser::ExtractCivicAddressElement" );
+
+    // Extract data length
+    TInt length = ( TInt )aInput.Get();
+    // Extract data
+    while ( length )
+        {
+        if ( KDhcpMinAsciiValue < ( TUint8 )aInput.Peek() &&
+             KDhcpMaxAsciiValue > ( TUint8 )aInput.Peek() )
+            {
+            aOutput.Append( aInput.Get() );
+            }
+        length--;
+        }
+    }
+
+
+// ---------------------------------------------------------------------------
+// Parses the timestamp
+// ---------------------------------------------------------------------------
+//
+void TDhcpLocationInformationParser::ParseTimeStamp( TDes8& aTimeStamp )
+    {
+    TRACESTRING( "TLocationInformationParser::ParseTimeStamp" );
+
+    TDateTime timeStamp = iTimeStamp.DateTime();
+    aTimeStamp.AppendNum( timeStamp.Year() );
+    aTimeStamp.Append( KHyphen );
+    aTimeStamp.AppendNum( timeStamp.Month() + 1 );
+    aTimeStamp.Append( KHyphen );
+    aTimeStamp.AppendNum( timeStamp.Day() + 1 );
+    aTimeStamp.Append( KT );
+    aTimeStamp.AppendNum( timeStamp.Hour() );
+    aTimeStamp.Append( KColon );
+    aTimeStamp.AppendNum( timeStamp.Minute() );
+    aTimeStamp.Append( KColon );
+    aTimeStamp.AppendNum( timeStamp.Second() );
+    aTimeStamp.Append( KZ );
+    }
+
+// ---------------------------------------------------------------------------
+// Parses the retention expiry. It is the timestamp value plus one day
+// ---------------------------------------------------------------------------
+//
+void TDhcpLocationInformationParser::ParseRetentionExpiry( TDes8& aTargetBfr )
+    {
+    TRACESTRING( "TLocationInformationParser::ParseRetentionExpiry" );
+    // Define the retention-expiry
+    TTime expiryTime( iTimeStamp );
+    TTimeIntervalDays day( 1 );
+    expiryTime += day;
+    TDateTime retentionExpiry = expiryTime.DateTime();
+
+    // Parse the retention-expiry
+    aTargetBfr.AppendNum( retentionExpiry.Year() );
+    aTargetBfr.Append( KHyphen );
+    aTargetBfr.AppendNum( retentionExpiry.Month() + 1 );
+    aTargetBfr.Append( KHyphen );
+    aTargetBfr.AppendNum( retentionExpiry.Day() + 1 );
+    aTargetBfr.Append( KT );
+    aTargetBfr.AppendNum( retentionExpiry.Hour() );
+    aTargetBfr.Append( KColon );
+    aTargetBfr.AppendNum( retentionExpiry.Minute() );
+    aTargetBfr.Append( KColon );
+    aTargetBfr.AppendNum( retentionExpiry.Second() );
+    aTargetBfr.Append( KZ );
+    }