First public contribution.
1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include <uriutilscommon.h>
19 #include <delimitedpathsegment8.h>
20 #include <delimitedquery8.h>
21 #include <escapeutils.h>
24 #include "UriUtilsInternal.h"
25 #include "TValidator.h"
28 _LIT8(KTransport, "transport");
30 _LIT8(KMethod, "method");
32 _LIT8(KMaddr, "maddr");
34 _LIT8(KExtension, "ext" );
35 _LIT8(KIsdnSubAddress, "isub" );
36 _LIT8(KContext, "phone-context" );
37 const TInt KMaxHostAddr = 255;
43 TValidatorBase::TValidatorBase(const TUriC8& aUri)
49 Checks the Uri to be valid.
50 If there is no valid Host, Port, userinfo, Path, Query or Fragment then the
51 return value indicates an appropriate invalid Component. else returns zero,
52 which indicates given uri is valid.
54 @return whether the Uri is Valid by returning zero or appropriate error value
57 TInt TValidatorBase::Validate()
61 return KUriUtilsErrInvalidHost;
66 return KUriUtilsErrInvalidPort;
69 if (!IsValidUserInfo())
71 return KUriUtilsErrInvalidUserInfo;
76 return KUriUtilsErrInvalidParam;
81 return KUriUtilsErrInvalidHeaders;
84 if (!IsValidFragment())
86 return KUriUtilsErrInvalidFragment;
93 Checks whether the given character is in Valid Set of characters.
94 @param aChar A Character needs to be checked against Set of characters.
95 @param aCharSet A set of Characters Descriptor.
96 @return returns ETrue if aChar is a Valid Character else returns EFalse.
98 TBool TValidatorBase::IsInCharSet(TText8 aChar, const TDesC8& aCharSet) const
100 for (TInt i = 0; i < aCharSet.Length(); i++)
102 if (aChar == aCharSet[i])
111 Checks whether the given descriptor is Valid or not.
112 @param aDes A Descriptor needs to be checked against Set of characters
113 defined in aCharTypes.
114 @param aCharTypes A set of Characters Descriptor.
115 @param aEscapeValid For the given aCharTypes whether the Escape encoded is valid
116 or not while Validating aDes, is specified by setting ETrue or EFalse
117 @return returns ETrue if aDes is a Valid descriptor else returns EFalse.
119 TBool TValidatorBase::IsValidCharacters(const TDesC8& aDes, TUint32 aCharTypes, TBool aEscapeValid) const
121 TInt len = aDes.Length();
122 for (TInt i=0; i < len; i++)
125 // check for and decode '%' encoded characters
126 if (aEscapeValid && ch == '%')
129 if (!EscapeUtils::IsEscapeTriple(aDes.Mid(i,3), hex))
131 // not a valid encoding
138 if ((aCharTypes & KCharSetNumber) && (ch >= '0' && ch <= '9'))
142 if ((aCharTypes & KCharSetLowerAlpha) && (ch >= 'a' && ch <= 'z'))
146 if ((aCharTypes & KCharSetUpperAlpha) && (ch >= 'A' && ch <= 'Z'))
150 if ((aCharTypes & KCharSetAlways) && IsInCharSet(ch, KAlwaysValidChars()))
154 if ((aCharTypes & KCharSetCommon) && IsInCharSet(ch, KCommonValidChars))
158 if ((aCharTypes & KCharSetUser) && IsInCharSet(ch, KValidUserChars))
162 if ((aCharTypes & KCharSetParam) && IsInCharSet(ch, KValidParamChars))
166 if ((aCharTypes & KCharSetHeader) && IsInCharSet(ch, KValidHeaderChars))
170 if ((aCharTypes & KCharSetSipMark) && IsInCharSet(ch, KUriAlwaysValidSipMarkChars))
175 if ((aCharTypes & KCharSetSipPwd) && IsInCharSet(ch, KUriValidSipPwdChars))
180 if ((aCharTypes & KCharSetSipTkn) && IsInCharSet(ch, KUriValidSipToken))
185 // character is not valid so exit
192 The meaning empty here is that the component is present but it's value is not present
193 This occures when the delimeter for a component is in the URI but there is
194 nothing in the URI after the delimeter. For example:
195 1. sip:loc.com - a URI with no port
196 2. sip:loc.com: - a URI with a port delimeter but no port value. The port is 'empty'.
197 3. sip:loc.com:1666 - a URI with a port
199 @param aDes A Descriptor.
200 @return ETrue or EFalse.
202 TBool TValidatorBase::IsEmpty(const TDesC8& aDes) const
204 TInt len = aDes.Length();
205 const TUint8* ptr = aDes.Ptr();
208 // An entry for this item has been created so the delimeter was encountered
209 // However, no value has been found. The item is empty
217 // Implementatin of support for Sip-Uris as specified in RFC 3261. //
223 TValidatorSip::TValidatorSip(const TUriC8& aUri)
224 : TValidatorBase(aUri)
229 Checks that a Host is in a valid form as specified in RFC 3261.
231 @return A boolean value of ETrue if uri contains valid Host,
232 EFalse if it does not.
234 TBool TValidatorSip::IsValidHost() const
236 const TDesC8& host = iUri.Extract(EUriHost);
237 if (host.Length() == 0)
242 // IPv4 and IPv6 hosts are validated so just check text hosts
243 if (UriUtils::HostType(host) == UriUtils::ETextHost && !IsTextHostValid(host))
251 Checks that a Port is in a valid form as specified in RFC 3261.
253 @return A boolean value of ETrue if uri contains valid Port,
254 EFalse if it does not.
256 TBool TValidatorSip::IsValidPort() const
258 const TDesC8& port = iUri.Extract(EUriPort);
263 return IsValidCharacters(port, KCharSetNumber);
267 Checks whether Userinfo contains valid characters in the sip-uri as specified in RFC 3261.
269 @param aUser The descriptor to be checked.
270 @return A boolean value of ETrue if uri contains valid Userinfo,
271 EFalse if it does not.
273 TBool TValidatorSip::IsValidUser(const TDesC8& aUser) const
275 return IsValidCharacters(aUser, KCharSetUserAll, ETrue);
279 Checks whether Password contains valid characters in the sip-uri as specified in RFC 3261.
281 @param aPassword The descriptor to be checked.
282 @return A boolean value of ETrue if uri contains valid Password,
283 EFalse if it does not.
285 TBool TValidatorSip::IsValidPassword(const TDesC8& aPassword) const
287 if (!aPassword.Length())
291 return IsValidCharacters(aPassword, KCharSetSipPassWord, ETrue);
295 Checks that a UserInfo is in a valid form as specified in RFC 3261.
297 @return A boolean value of ETrue if uri contains valid UserInfo,
298 EFalse if it does not.
300 TBool TValidatorSip::IsValidUserInfo() const
302 const TDesC8& userInfo = iUri.Extract(EUriUserinfo);
304 if (IsEmpty(userInfo))
306 // The '@' UserInfo sparator was found in the URI but no username/password
311 TInt separatorPos = userInfo.Locate(KUserPwdSeparator);
312 if (separatorPos != KErrNotFound)
314 // seperator found so there is a username and password
315 // the username is left of the separator
316 if (!IsValidUser(userInfo.Left(separatorPos)))
320 // the password is right of the separator
321 return IsValidPassword(userInfo.Right(userInfo.Length() - separatorPos-1));
324 // there is no password element
325 return IsValidUser(userInfo);
329 Checks whether any duplicate parameter names exist in the
330 whole path of the sip-uri.
332 @param aParamName The descriptor to be checked.
333 @param aParamList the path/parameter part of uri, which conatians all parameters and values.
334 @return A boolean value of ETrue if uri contains duplicate parameters,
335 EFalse if it does not.
337 TBool TValidatorSip::IsDuplicated(const TDesC8& aParamName, const TDelimitedParserBase8 aParamList) const
339 // roll back to the start of the lhs segment parser
340 while(aParamList.Dec() != KErrNotFound)
349 while( aParamList.GetNext(segment) == KErrNone )
351 GetNameValuePair(segment, name, value);
352 if (aParamName.CompareF(name) == 0)
358 // The parameter name appears more than once in the paramter list
366 Checks whether parameter contains valid characters in the sip-uri as specified in RFC 3261.
368 @param aParam The descriptor to be checked.
369 @return A boolean value of ETrue if uri contains valid parameter,
370 EFalse if it does not.
372 TBool TValidatorSip::IsValidParam(const TDesC8& aParam) const
374 return IsValidCharacters(aParam, KCharSetParamAll, ETrue);
378 Checks whether ParamSegment contains valid characters in
379 Parameter name and Parameter value as specified in RFC 3261.
381 @param aName The descriptor for parameter name to be checked as per RFC 3261.
382 @param aValue The descriptor for value to be checked as per RFC 3261.
383 @return A boolean value of ETrue if uri contains valid parameters and values,
384 EFalse if it does not.
386 TBool TValidatorSip::IsValidParamSegment(const TDesC8& aName, const TDesC8& aValue) const
388 if (!aName.Length() || !IsValidParam(aName) )
393 /**************************************************************************************************************
394 * As per RFC 3261 if the uri-parameter contains name as Tranport or User or Method then its Value must be *
395 * the characters as specified in Token. else if the name is Ttl then its value must lie in between 0 - 255. *
396 * else if the name is Maddr then its value must be a host, else if the name is lr then it must not conatin *
397 * any value, else it must be a other-parameter whose value must conatin the characters specified in paramchar.*
398 * As per INC 115503 and due to IOP issue Validation of lr paramater is not performed. *
399 ***************************************************************************************************************/
400 if ( ( (aName.CompareF(KTransport()) == 0 || aName.CompareF(KUser()) == 0 || aName.CompareF(KMethod()) == 0 )
401 && !IsValidParamToken(aValue) )
402 || ( aName.CompareF(KTtl()) == 0 && !IsValidParamTtl(aValue) )
403 || ( aName.CompareF(KMaddr()) == 0 && !IsValidParamMaddr(aValue) )
404 || ( aName.CompareF(KTransport()) != 0 && aName.CompareF(KUser()) != 0 && aName.CompareF(KMethod()) != 0 && aName.CompareF(KTtl()) != 0
405 && aName.CompareF(KMaddr()) != 0 && aName.CompareF(KLr()) != 0 && !IsValidParam(aValue))
415 Checks whether parameters "transport", "User" and "Method" contains valid characters in the
416 sip-uri as specified in RFC 3261.
418 @param aParam The descriptor to be checked.
419 @return A boolean value of ETrue if uri contains valid parameter,
420 EFalse if it does not.
422 TBool TValidatorSip::IsValidParamToken(const TDesC8& aParam) const
424 if (!aParam.Length())
428 return IsValidCharacters(aParam, KCharSetSipToken, EFalse);
432 Checks whether parameter "ttl" contains valid characters in the sip-uri as specified in RFC 3261.
435 @param aParam The descriptor to be checked.
436 @return A boolean value of ETrue if uri contains valid parameter,
437 EFalse if it does not.
439 TBool TValidatorSip::IsValidParamTtl(const TDesC8& aParam) const
441 if (!aParam.Length() || aParam.Length() > 3 || !IsValidCharacters(aParam, KCharSetNumber, EFalse) )
449 if( address > KMaxHostAddr )
458 Checks whether parameter "maddr" contains valid characters in the sip-uri as specified in RFC 3261.
460 @param aParam The descriptor to be checked.
461 @return A boolean value of ETrue if uri contains valid parameter,
462 EFalse if it does not.
464 TBool TValidatorSip::IsValidParamMaddr(const TDesC8& aParam) const
466 if (!aParam.Length() && UriUtils::HostType(aParam) == UriUtils::ETextHost && !IsTextHostValid(aParam))
474 Checks that a Path/uri-parameter is in a valid form as specified in RFC 3261.
476 @return A boolean value of ETrue if uri contains valid Path/uri-parameter,
477 EFalse if it does not.
479 TBool TValidatorSip::IsValidPath() const
481 const TDesC8& parameters = iUri.Extract(EUriPath);
482 TDelimitedPathSegmentParser8 parser;
483 parser.Parse(parameters);
485 // sip parameters should start with a ';'
486 if (parameters.Length() && parameters[0] != ';')
494 while( parser.GetNext(segment) == KErrNone )
496 GetNameValuePair(segment, name, value);
497 if (IsEmpty(value) || IsDuplicated(name, parser) || !IsValidParamSegment(name, value))
507 Checks whether Header contains valid characters as specified in RFC 3261.
509 @param aHeader The descriptor to be checked as per RFC 3261.
510 @return A boolean value of ETrue if uri contains valid Header,
511 EFalse if it does not.
513 TBool TValidatorSip::IsValidHeader(const TDesC8& aHeader) const
515 return IsValidCharacters(aHeader, KCharSetHeaderAll, ETrue);
519 Checks whether HeaderSegment contains valid name and values as specified in RFC 3261.
521 @param aName The descriptor for Header name to be checked as per RFC 3261.
522 @param aValue The descriptor for Header value to be checked as per RFC 3261.
523 @return A boolean value of ETrue if uri contains valid Header name and Header values,
524 EFalse if it does not.
526 TBool TValidatorSip::IsValidHeaderSegment(const TDesC8& aName, const TDesC8& aValue) const
528 if (!aName.Length() || !IsValidHeader(aName) || !IsValidHeader(aValue))
536 Checks that a Query/Header is in a valid form as specified in RFC 3261.
538 @return A boolean value of ETrue if uri contains valid Query/Header,
539 EFalse if it does not.
541 TBool TValidatorSip::IsValidQuery() const
543 const TDesC8& headers = iUri.Extract(EUriQuery);
544 if (IsEmpty(headers))
549 TDelimitedQueryParser8 parser;
550 parser.Parse(headers);
555 while( parser.GetNext(segment) == KErrNone )
557 // must be in the form name=value even if the value part is empty
558 if (segment.Locate(KEqualsSeparator) == KErrNotFound)
563 GetNameValuePair(segment, name, value);
564 if (IsDuplicated(name, parser) || !IsValidHeaderSegment(name, value))
573 Checks that a Fragment is in a valid form as specified in RFC 3261.
574 Infact, SIP URIs should not contain a fragment. It it contains a
575 fragment then it is not a valid fragment.
577 @return A boolean value of ETrue if uri contains valid Fragment,
578 EFalse if it does not.
580 TBool TValidatorSip::IsValidFragment() const
582 const TDesC8& frag = iUri.Extract(EUriFragment);
587 // SIP URIs should not contain a fragment
597 // Implementatin of partial support for tel-Uris specified in RFC 3966. //
598 // Parsing of phone number separators as specified in RFC 3966 //
599 // section 5 will not be supported. //
600 // The Implementation supports only of the form tel:36789017;isub=1411 //
601 // It does not support lexicographical order of parameters for Validation.//
606 @param aUri A reference to a parsed uri object.
608 TValidatorTel::TValidatorTel(const TUriC8& aUri)
609 : TValidatorBase(aUri)
614 Checks whether valid parameter names and values exist in the
615 whole path of the tel-uri.
617 @param aName The descriptor for parameter name to be checked as per RFC3966.
618 @param aValue The descriptor for value to be checked as per RFC3966.
619 @return A boolean value of ETrue if uri contains valid parameters and values,
620 EFalse if it does not.
622 TBool TValidatorTel::IsValidParamSegment(const TDesC8& aName, const TDesC8& aValue) const
624 //Validation of the Name
625 if (!aName.Length() || !IsValidCharacters(aName, KCharSetParamAll) )
629 //Validation of the Value based on ISDN, EXTN, Phone-context or any.
630 if( ( KIsdnSubAddress().CompareF(aName) == 0 && !IsValidCharacters(aValue, KCharSetParamAll, ETrue) ) ||
631 ( KExtension().CompareF(aName) == 0 && !IsValidCharacters(aValue, KCharSetNumber) ) ||
632 ( KContext().CompareF(aName) == 0 && !IsValidCharacters(aValue, KCharSetParamAll) ) ||
633 ( KIsdnSubAddress().CompareF(aName) != 0 &&
634 KExtension().CompareF(aName) != 0 &&
635 KContext().CompareF(aName) != 0 &&
636 !IsValidCharacters(aValue, KCharSetParamAll, ETrue) ) )
644 Checks whether any duplicate parameter names exist in the
645 whole path of the tel-uri, and also checks whether the both ISDN and EXTN
646 parameters exist in tel-uri.
648 @param aParamName The descriptor to be checked.
649 @param aParamList the path part of uri, which conatians all parameters and values.
650 @return A boolean value of ETrue if uri contains duplicate parameters or
651 both isdn and extn parameters exist, EFalse if it does not.
653 TBool TValidatorTel::IsDuplicated(const TDesC8& aParamName, const TDelimitedParserBase8 aParamList) const
655 // roll back to the start of the lhs segment parser
656 while(aParamList.Dec() != KErrNotFound)
660 aParamList.Inc(); //To exclude phone number from the list.
666 while( aParamList.GetNext(segment) == KErrNone )
668 GetNameValuePair(segment, name, value);
669 if (aParamName.CompareF(name) == 0)
675 // The parameter name appears more than once in the paramter list
678 if( ( KIsdnSubAddress().CompareF(aParamName) == 0 && KExtension().CompareF(name) == 0 ) ||
679 ( KExtension().CompareF(aParamName) == 0 && KIsdnSubAddress().CompareF(name) == 0 ) )
681 //Both ISDN and EXTN should not exist in Uri
690 Checks that a path is in a valid form
692 @return ETrue if the path is valid otherwise EFalse
694 TBool TValidatorTel::IsValidPath() const
696 const TDesC8& path = iUri.Extract(EUriPath);
697 //empty path is invalid
703 //Implementation of all the steps specified in section 2.5.2.2
704 //Validation of the path components of tel uri
706 TDelimitedPathSegmentParser8 parser;
709 // tel parameters should start with a '+' or 'digit'
711 if(! (ch == '+' || ch.IsDigit()) )
719 //First segemnt must be telephone number
720 if (parser.GetNext(segment) == KErrNone)
722 GetNameValuePair(segment, name, value);
723 //contains only digits
724 if(!IsValidCharacters(name.Mid(1), KCharSetNumber))
729 //Remainig all the segments
730 while( parser.GetNext(segment) == KErrNone )
732 GetNameValuePair(segment, name, value);
737 if ( IsEmpty(value) || IsDuplicated(name, parser) || !IsValidParamSegment(name, value) )
746 Checks that a host is in a valid form
748 @return ETrue. "tel" uri does not conatin host
750 TBool TValidatorTel::IsValidHost() const
757 Checks that a UserInfo is in a valid form
759 @return ETrue. "tel" uri does not conatin UserInfo
761 TBool TValidatorTel::IsValidUserInfo() const
768 Checks that a Port is in a valid form
770 @return ETrue. "tel" uri does not conatin Port
772 TBool TValidatorTel::IsValidPort() const
779 Checks that a Query is in a valid form
781 @return ETrue. "tel" uri does not conatin Query
783 TBool TValidatorTel::IsValidQuery() const
790 Checks that a Fragment is in a valid form
792 @return ETrue. "tel" uri does not conatin Fragment
794 TBool TValidatorTel::IsValidFragment() const