version 1.1.2.1, 2003/07/16 21:45:25
|
version 1.32, 2008/01/08 20:15:10
|
|
|
//%///////////////////////////////////////////////////////////////////////////// |
//%2006//////////////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM, |
// Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development |
// The Open Group, Tivoli Systems |
// Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. |
|
// Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.; |
|
// IBM Corp.; EMC Corporation, The Open Group. |
|
// Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.; |
|
// IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; VERITAS Software Corporation; The Open Group. |
|
// Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.; |
|
// EMC Corporation; Symantec Corporation; The Open Group. |
// | // |
// Permission is hereby granted, free of charge, to any person obtaining a copy | // Permission is hereby granted, free of charge, to any person obtaining a copy |
// of this software and associated documentation files (the "Software"), to | // of this software and associated documentation files (the "Software"), to |
|
|
// | // |
//============================================================================== | //============================================================================== |
// | // |
// Author: Humberto Rivero (hurivero@us.ibm.com) |
|
// |
|
// Modified By: |
|
// |
|
//%///////////////////////////////////////////////////////////////////////////// | //%///////////////////////////////////////////////////////////////////////////// |
| |
#include <Pegasus/Common/LanguageParser.h> | #include <Pegasus/Common/LanguageParser.h> |
#include <Pegasus/Common/InternalException.h> | #include <Pegasus/Common/InternalException.h> |
#include <Pegasus/Common/Tracer.h> | #include <Pegasus/Common/Tracer.h> |
|
#include <Pegasus/Common/MessageLoader.h> |
#include <cstring> | #include <cstring> |
| |
//PEGASUS_USING_STD; |
#ifdef PEGASUS_HAS_ICU |
|
# include <unicode/locid.h> |
|
#endif |
|
|
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
const LanguageParser LanguageParser::EMPTY = LanguageParser(); |
static char LANGUAGE_TAG_SEPARATOR_CHAR = '-'; |
|
static char LOCALE_ID_SEPARATOR_CHAR = '_'; |
| |
void LanguageParser::parseHdr(Array<String> &values, String & hdr){ |
AcceptLanguageList LanguageParser::parseAcceptLanguageHeader( |
// look for ',' which designates distict (Accept/Content)-Language fields |
const String& acceptLanguageHeader) |
// the form: [languagetag, languagetag, languagetag] so whitespace removal |
{ |
// may be necessary. |
PEG_METHOD_ENTER(TRC_L10N, "LanguageParser::parseAcceptLanguageHeader"); |
// then store them in the array |
|
PEG_METHOD_ENTER(TRC_L10N, "LanguageParser::parseHdr"); |
AcceptLanguageList acceptLanguages; |
Uint32 i = 0; |
|
while( i != PEG_NOT_FOUND ){ |
try |
i = hdr.find(","); |
{ |
if( i != PEG_NOT_FOUND ){ |
Array<String> languageElements; |
values.append(hdr.subString(0,i)); |
LanguageParser::_parseLanguageHeader( |
while(hdr[i+1] == ' ') i++; // get rid of whitespace after "," |
acceptLanguageHeader, |
hdr = hdr.subString(i+1); |
languageElements); |
} |
|
else{ // only one field, build an object with it |
for (Uint32 i = 0; i < languageElements.size(); i++) |
values.append(hdr); |
{ |
|
String languageTagString; |
|
Real32 qualityValue; |
|
LanguageParser::_parseAcceptLanguageElement( |
|
languageElements[i], languageTagString, qualityValue); |
|
acceptLanguages.insert( |
|
LanguageTag(languageTagString), qualityValue); |
|
} |
|
} |
|
catch (Exception& e) |
|
{ |
|
throw InvalidAcceptLanguageHeader(e.getMessage()); |
|
} |
|
|
|
PEG_METHOD_EXIT(); |
|
return acceptLanguages; |
|
} |
|
|
|
ContentLanguageList LanguageParser::parseContentLanguageHeader( |
|
const String& contentLanguageHeader) |
|
{ |
|
PEG_METHOD_ENTER(TRC_L10N, "LanguageParser::parseContentLanguageHeader"); |
|
|
|
ContentLanguageList contentLanguages; |
|
|
|
try |
|
{ |
|
Array<String> languageElements; |
|
LanguageParser::_parseLanguageHeader( |
|
contentLanguageHeader, |
|
languageElements); |
|
|
|
for (Uint32 i = 0; i < languageElements.size(); i++) |
|
{ |
|
contentLanguages.append(LanguageTag(languageElements[i])); |
|
} |
} | } |
|
catch (Exception& e) |
|
{ |
|
throw InvalidContentLanguageHeader(e.getMessage()); |
} | } |
|
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
|
return contentLanguages; |
} | } |
| |
Real32 LanguageParser::parseAcceptLanguageValue(String &language_tag, String & hdr){ |
void LanguageParser::parseLanguageTag( |
// look for ';' in hdr, that means we have a quality value to capture |
const String& languageTagString, |
// if not, we only have a language |
String& language, |
|
String& country, |
// if hdr begins with "x-" then we have a non-IANA (private) language tag |
String& variant) |
PEG_METHOD_ENTER(TRC_L10N, "LanguageParser::parseAcceptLanguageValue"); |
{ |
Uint32 i; |
PEG_METHOD_ENTER(TRC_L10N, "LanguageParser::parseLanguageTag"); |
Boolean validate_length = true; |
|
if((( i = hdr.find("x-")) != PEG_NOT_FOUND ) && (i == 0)){ |
language.clear(); |
hdr = convertPrivateLanguageTag(hdr); |
country.clear(); |
validate_length = false; |
variant.clear(); |
} |
|
|
if (languageTagString == "*") |
// get rid of any beginning or trailing whitespaces |
{ |
Uint32 j; |
// Parsing and validation is complete |
while( (j = hdr.find(" ")) != PEG_NOT_FOUND ){ |
PEG_METHOD_EXIT(); |
hdr.remove(j,1); |
return; |
} |
|
|
|
Real32 quality = 1; |
|
i = hdr.find(";"); |
|
if(i != PEG_NOT_FOUND){ // extract and store language and quality |
|
if(isValid(hdr.subString(0,i), validate_length)){ |
|
language_tag = hdr.subString(0,i); |
|
hdr.remove(0,i+3); // remove everything but the quality value |
|
} |
|
else{ |
|
throw InvalidAcceptLanguageHeader( |
|
"AcceptLanguage contains too many characters or non-alpha characters"); |
|
} |
|
//validate quality |
|
quality = atof(hdr.getCString()); |
|
if(quality > 1.0 || quality < 0.0){ |
|
throw InvalidAcceptLanguageHeader( |
|
"AcceptLanguage contains an invalid quality value"); |
|
} | } |
|
|
|
Boolean isStandardFormat = true; // RFC 3066 (ISO 639, ISO 3166) |
|
Array<String> subtags; |
|
|
|
_parseLanguageSubtags(subtags, languageTagString); |
|
|
|
// _parseLanguageSubtags() always returns at least one subtag. |
|
PEGASUS_ASSERT(subtags.size() > 0); |
|
|
|
// Validate the primary subtag. |
|
// Given a languageTagString "en-US-mn" the language is "en". |
|
|
|
language = subtags[0]; |
|
|
|
if ((language == "i") || (language == "x")) |
|
{ |
|
// These primary tags are allowed, but are not ISO 639 compliant |
|
isStandardFormat = false; |
|
language.clear(); |
|
} |
|
else if ((language.size() != 2) && (language.size() != 3)) |
|
{ |
|
// Except for "i" and "x", primary tags must be 2 or 3 characters, |
|
// according to RFC 3066. |
|
MessageLoaderParms parms( |
|
"Common.LanguageParser.INVALID_LANGUAGE_TAG", |
|
"Invalid language tag \"$0\".", languageTagString); |
|
PEG_METHOD_EXIT(); |
|
// throw Exception(MessageLoader::getMessage(parms)); |
|
// do not localize message, requires a language tag for this |
|
// localization can cause recursion here |
|
throw Exception(parms.toString()); |
} | } |
else{ // extract and store language, quality defaults to 1.0 |
|
if(isValid(hdr, validate_length)) language_tag = hdr; |
if (subtags.size() == 1) |
else throw InvalidAcceptLanguageHeader( |
{ |
"AcceptLanguage contains too many characters or non-alpha characters"); |
// If only the primary subtag is present, we are done! |
|
PEG_METHOD_EXIT(); |
|
return; |
} | } |
| |
|
// Validate the second subtag. |
|
// Given a languageTagString "en-US-mn" the country is "US". |
|
|
|
if (subtags[1].size() == 1) |
|
{ |
|
// The second subtag may not be a single character according to |
|
// RFC 3066. |
|
MessageLoaderParms parms( |
|
"Common.LanguageParser.INVALID_LANGUAGE_TAG", |
|
"Invalid language tag \"$0\".", languageTagString); |
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return quality; |
// throw Exception(MessageLoader::getMessage(parms)); |
|
// do not localize message, requires a language tag for this |
|
// localization can cause recursion here |
|
throw Exception(parms.toString()); |
|
} |
|
|
|
if (isStandardFormat) |
|
{ |
|
Uint32 variantIndex = 1; |
|
|
|
if (subtags[1].size() == 2) |
|
{ |
|
country = subtags[1]; |
|
variantIndex = 2; |
} | } |
| |
String LanguageParser::parseContentLanguageValue(String & hdr){ |
Uint32 numSubtags = subtags.size(); |
// we are looking for the language part of the hdr only, |
|
// according to the RFC, there may be parenthesized strings |
if (variantIndex < numSubtags) |
// that describe the purpose of the language, we need to ignore those |
{ |
PEG_METHOD_ENTER(TRC_L10N, "LanguageParser::parseContentLanguageValue"); |
variant = subtags[variantIndex++]; |
String value = hdr; |
|
Uint32 i,j; |
while (variantIndex < numSubtags) |
while((i = value.find("(")) != PEG_NOT_FOUND){ // get rid of anything in parenthesis in hdr if found |
{ |
if((j = value.find(")")) != PEG_NOT_FOUND) |
variant.append(LANGUAGE_TAG_SEPARATOR_CHAR); |
value.remove(i, (j-i)+1); |
variant.append(subtags[variantIndex++]); |
else throw InvalidContentLanguageHeader( |
} |
"ContentLanguage does not contain terminating ) character"); |
|
} | } |
// get rid of any beginning or trailing whitespaces |
|
while( (i = value.find(" ")) != PEG_NOT_FOUND ){ |
|
value.remove(i,1); |
|
} | } |
if(!isValid(value)) throw InvalidContentLanguageHeader( |
|
"ContentLanguage contains too many characters or non-alpha characters"); |
|
PEG_METHOD_EXIT(); | PEG_METHOD_EXIT(); |
return value; |
|
} | } |
| |
String LanguageParser::getLanguage(String & language_tag){ |
void LanguageParser::validateQualityValue(Real32 quality) |
// given a language_tag: en-US-mn we want to return "en" |
{ |
Uint32 i; |
if ((quality > 1.0) || (quality < 0.0)) |
if((i = language_tag.find(findSeparator(language_tag.getCString()))) != PEG_NOT_FOUND) |
{ |
return language_tag.subString(0,i); |
MessageLoaderParms parms( |
return String(language_tag); |
"Common.LanguageParser.INVALID_QUALITY_VALUE", |
|
"AcceptLanguage contains an invalid quality value"); |
|
throw InvalidAcceptLanguageHeader(MessageLoader::getMessage(parms)); |
|
} |
} | } |
| |
String LanguageParser::getCountry(String & language_tag){ |
String LanguageParser::buildAcceptLanguageHeader( |
// given a language_tag: en-US-mn we want to return "US" |
const AcceptLanguageList& acceptLanguages) |
Uint32 i,j; |
{ |
if( (i = language_tag.find(findSeparator(language_tag.getCString()))) != PEG_NOT_FOUND ) |
String alString; |
if( (j = language_tag.find(i+1, findSeparator(language_tag.getCString()))) != PEG_NOT_FOUND ) |
Uint32 numAcceptLanguages = acceptLanguages.size(); |
return language_tag.subString(i+1, j-(i+1)); |
|
else |
for (Uint32 i = 0; i < numAcceptLanguages; i++) |
return language_tag.subString(i+1); |
{ |
return String::EMPTY; |
alString.append(acceptLanguages.getLanguageTag(i).toString()); |
|
|
|
Real32 q = acceptLanguages.getQualityValue(i); |
|
if (q != 1.0) |
|
{ |
|
char qValueString[6]; |
|
sprintf(qValueString, "%4.3f", q); |
|
alString.append(";q="); |
|
alString.append(qValueString); |
} | } |
| |
String LanguageParser::getVariant(String & language_tag){ |
if (i < numAcceptLanguages - 1) |
// given a language_tag: en-US-mn we want to return "mn" |
{ |
Uint32 i; |
alString.append(","); |
if( (i = language_tag.find(findSeparator(language_tag.getCString()))) != PEG_NOT_FOUND ) |
} |
if( (i = language_tag.find(i+1, findSeparator(language_tag.getCString()))) != PEG_NOT_FOUND ) |
|
return language_tag.subString(i+1); |
|
return String::EMPTY; |
|
} | } |
| |
void LanguageParser::parseLanguageSubtags(Array<String> &subtags, String language_tag){ |
return alString; |
PEG_METHOD_ENTER(TRC_L10N, "LanguageParser::parseLanguageSubtags"); |
} |
Uint32 i; |
|
char separator = findSeparator(language_tag.getCString()); |
String LanguageParser::buildContentLanguageHeader( |
while( (i = language_tag.find(Char16(separator))) != PEG_NOT_FOUND ){ |
const ContentLanguageList& contentLanguages) |
subtags.append(language_tag.subString(0,i)); |
{ |
language_tag.remove(0,i + 1); |
String clString; |
|
Uint32 numContentLanguages = contentLanguages.size(); |
|
|
|
for (Uint32 i = 0; i < numContentLanguages; i++) |
|
{ |
|
clString.append(contentLanguages.getLanguageTag(i).toString()); |
|
|
|
if (i < numContentLanguages - 1) |
|
{ |
|
clString.append(","); |
} | } |
if(language_tag.size() > 0) |
|
subtags.append(language_tag); |
|
PEG_METHOD_EXIT(); |
|
} | } |
| |
Boolean LanguageParser::isValid(String language_tag, Boolean validate_length){ |
return clString; |
//break the String down into parts(subtags), then validate each part |
} |
|
|
|
#ifdef PEGASUS_HAS_ICU |
|
String& LanguageParser::convertLocaleIdToLanguageTag(String& localeId) |
|
{ |
|
Uint32 index = 0; |
|
while ((index = localeId.find(index, LOCALE_ID_SEPARATOR_CHAR)) != |
|
PEG_NOT_FOUND) |
|
{ |
|
localeId[index] = LANGUAGE_TAG_SEPARATOR_CHAR; |
|
} |
|
return localeId; |
|
} |
|
#endif |
| |
if(language_tag == "*") return true; |
AcceptLanguageList LanguageParser::getDefaultAcceptLanguages() |
|
{ |
|
#if defined(PEGASUS_HAS_MESSAGES) && defined(PEGASUS_HAS_ICU) |
|
Locale default_loc = Locale::getDefault(); |
| |
Array<String> subtags; |
String localeId = default_loc.getName(); |
parseLanguageSubtags(subtags, language_tag); |
|
if(subtags.size() > 0){ |
try |
for(int i = 0; i < subtags.size(); i++){ |
{ |
//length should be 8 or less AND all characters should be A-Z or a-z |
return LanguageParser::parseAcceptLanguageHeader( |
if((validate_length && subtags[i].size() > 8) || !checkAlpha(subtags[i].getCString())) |
convertLocaleIdToLanguageTag(localeId)); |
return false; |
|
} | } |
|
catch (const InvalidAcceptLanguageHeader& e) |
|
{ |
|
Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE, |
|
"src.Server.cimserver.FAILED_TO_SET_PROCESS_LOCALE", |
|
"Cannot convert the system process locale into a valid " |
|
"Accept-Language format."); |
|
Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE, |
|
e.getMessage()); |
|
AcceptLanguageList al; |
|
al.insert(LanguageTag("*"), 1); |
|
return al; |
} | } |
else{ //nothing back from parseLanguageSubtags |
#else |
return false; |
return AcceptLanguageList(); |
|
#endif |
} | } |
return true; |
|
|
void LanguageParser::_parseLanguageHeader( |
|
const String& languageHeaderValue, |
|
Array<String>& languageElements) |
|
{ |
|
PEG_METHOD_ENTER(TRC_L10N, "LanguageParser::_parseLanguageHeader"); |
|
|
|
languageElements.clear(); |
|
String element; |
|
|
|
for (Uint32 i=0, len=languageHeaderValue.size(); i<len; i++) |
|
{ |
|
Char16 nextChar = languageHeaderValue[i]; |
|
|
|
if (isascii(nextChar) && isspace(nextChar)) |
|
{ |
|
// Ignore whitespace |
|
} |
|
else if (nextChar == '(') |
|
{ |
|
// Ignore comments |
|
while (i < len) |
|
{ |
|
// Search for the closing parenthesis |
|
if (languageHeaderValue[i] == ')') |
|
{ |
|
break; |
|
} |
|
|
|
// Skip over escape characters |
|
if (languageHeaderValue[i] == '\\') |
|
{ |
|
i++; |
|
} |
|
|
|
i++; |
|
} |
|
|
|
// Check for a missing closing parenthesis |
|
if (i >= len) |
|
{ |
|
MessageLoaderParms parms( |
|
"Common.LanguageParser.DOES_NOT_CONTAIN_TERMINATING", |
|
"Closing \")\" character is missing."); |
|
throw Exception(MessageLoader::getMessage(parms)); |
|
} |
|
} |
|
else if (nextChar == ',') |
|
{ |
|
// Check for the end of the element |
|
languageElements.append(element); |
|
element.clear(); |
|
} |
|
else |
|
{ |
|
// Unescape an escape character |
|
if ((nextChar == '\\') && (i < len-1)) |
|
{ |
|
nextChar = languageHeaderValue[++i]; |
|
} |
|
|
|
// Include this character in the value |
|
element.append(nextChar); |
|
} |
|
} |
|
|
|
// Include the last element in the languageElements array |
|
languageElements.append(element); |
|
|
|
PEG_METHOD_EXIT(); |
} | } |
| |
String LanguageParser::convertPrivateLanguageTag(String language_tag){ |
void LanguageParser::_parseAcceptLanguageElement( |
// figure out if its a unix style locale or windows locale |
const String& acceptLanguageElement, |
int i; |
String& languageTag, |
if(( i = language_tag.find("pegasus-")) != PEG_NOT_FOUND ){ |
Real32& quality) |
language_tag = language_tag.subString(i+5); // capture the remainder of the string |
{ |
return String(replaceSeparator(language_tag.getCString(), '-')); |
PEG_METHOD_ENTER(TRC_L10N, "LanguageParser::_parseAcceptLanguageElement"); |
} |
|
//else if( (i = language_tag.find("win-")) != PEG_NOT_FOUND ){ |
// look for ';' in acceptLanguageElement, that means we have a |
// return language_tag.subString(i+4); // capture the remainder of the string |
// quality value to capture. If not present, we only have a language tag. |
// call windows ID to ICU convert routine or locmap.c function here |
|
//} |
Uint32 semicolonIndex = acceptLanguageElement.find(";"); |
else{ |
if (semicolonIndex != PEG_NOT_FOUND) |
return language_tag; |
{ |
|
// Separate the language tag and quality value |
|
|
|
String qualityString = |
|
acceptLanguageElement.subString(semicolonIndex+1); |
|
languageTag = acceptLanguageElement.subString(0, semicolonIndex); |
|
|
|
// Parse the quality value |
|
|
|
char dummyChar; |
|
int scanfConversions = sscanf( |
|
qualityString.getCString(), |
|
"q=%f%c", &quality, &dummyChar); |
|
|
|
if ((scanfConversions != 1) || |
|
(qualityString.size() > 7)) |
|
{ |
|
MessageLoaderParms parms( |
|
"Common.LanguageParser.INVALID_QUALITY_VALUE", |
|
"AcceptLanguage contains an invalid quality value"); |
|
PEG_METHOD_EXIT(); |
|
throw Exception(MessageLoader::getMessage(parms)); |
} | } |
} | } |
|
else |
|
{ |
|
languageTag = acceptLanguageElement; |
|
quality = 1.0; |
|
} |
|
|
|
PEG_METHOD_EXIT(); |
|
} |
| |
Boolean LanguageParser::checkAlpha(CString _str){ |
void LanguageParser::_parseLanguageSubtags( |
for(int i = 0; i < strlen(_str); i++) |
Array<String>& subtags, |
if( !isalpha(_str[i]) ) |
const String& languageTagString) |
|
{ |
|
PEG_METHOD_ENTER(TRC_L10N, "LanguageParser::_parseLanguageSubtags"); |
|
|
|
// Parse the language tag into subtags |
|
|
|
Uint32 subtagIndex = 0; |
|
Uint32 separatorIndex; |
|
while ((separatorIndex = languageTagString.find( |
|
subtagIndex, LANGUAGE_TAG_SEPARATOR_CHAR)) != PEG_NOT_FOUND) |
|
{ |
|
subtags.append(languageTagString.subString( |
|
subtagIndex, separatorIndex - subtagIndex)); |
|
subtagIndex = separatorIndex + 1; |
|
} |
|
subtags.append(languageTagString.subString(subtagIndex)); |
|
|
|
// Validate the syntax of each of the subtags |
|
|
|
for (Uint32 i = 0, n = subtags.size(); i < n; i++) |
|
{ |
|
if (((i == 0) && !_isValidPrimarySubtagSyntax(subtags[i])) || |
|
((i > 0) && !_isValidSubtagSyntax(subtags[i]))) |
|
{ |
|
MessageLoaderParms parms( |
|
"Common.LanguageParser.MALFORMED_LANGUAGE_TAG", |
|
"Malformed language tag \"$0\".", languageTagString); |
|
PEG_METHOD_EXIT(); |
|
// throw Exception(MessageLoader::getMessage(parms)); |
|
// do not localize message, requires a language tag for this |
|
// localization can cause recursion here |
|
throw Exception(parms.toString()); |
|
} |
|
} |
|
|
|
PEG_METHOD_EXIT(); |
|
} |
|
|
|
Boolean LanguageParser::_isValidPrimarySubtagSyntax(const String& subtag) |
|
{ |
|
if ((subtag.size() == 0) || (subtag.size() > 8)) |
|
{ |
|
return false; |
|
} |
|
|
|
for (Uint32 i = 0, n = subtag.size(); i < n; i++) |
|
{ |
|
if (!(isascii(subtag[i]) && isalpha(subtag[i]))) |
|
{ |
return false; | return false; |
|
} |
|
} |
|
|
return true; | return true; |
} | } |
| |
char LanguageParser::findSeparator(CString _str){ |
Boolean LanguageParser::_isValidSubtagSyntax(const String& subtag) |
for(int i = 0; i < strlen(_str); i++) |
{ |
if(!isalnum(_str[i])) |
if ((subtag.size() == 0) || (subtag.size() > 8)) |
return _str[i]; |
{ |
return '\0'; |
return false; |
} | } |
| |
CString LanguageParser::replaceSeparator(CString _s, char new_sep){ |
for (Uint32 i = 0, n = subtag.size(); i < n; i++) |
char * _str = const_cast<char *>((const char*)_s); |
{ |
for(int i = 0; i < strlen(_str); i++) |
if (!(isascii(subtag[i]) && isalnum(subtag[i]))) |
_str[i] = (!isalnum(_str[i])) ? new_sep : _str[i]; |
{ |
return (String(_str)).getCString(); |
return false; |
|
} |
} | } |
| |
|
return true; |
|
} |
| |
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |