diff options
Diffstat (limited to 'indra/newview/llsyntaxid.cpp')
-rw-r--r-- | indra/newview/llsyntaxid.cpp | 292 |
1 files changed, 205 insertions, 87 deletions
diff --git a/indra/newview/llsyntaxid.cpp b/indra/newview/llsyntaxid.cpp index 94226b82b1..3ee9859ccd 100644 --- a/indra/newview/llsyntaxid.cpp +++ b/indra/newview/llsyntaxid.cpp @@ -34,7 +34,6 @@ #include "llsdserialize.h" #include "llsyntaxid.h" - //----------------------------------------------------------------------------- // fetchKeywordsFileResponder //----------------------------------------------------------------------------- @@ -50,6 +49,7 @@ void fetchKeywordsFileResponder::errorWithContent(U32 status, const std::string& reason, const LLSD& content) { + LLSyntaxIdLSL::sLoadFailed = true; LL_ERRS("SyntaxLSL") << "fetchKeywordsFileResponder error [status:" << status << "]: " << content @@ -58,8 +58,43 @@ void fetchKeywordsFileResponder::errorWithContent(U32 status, void fetchKeywordsFileResponder::result(const LLSD& content_ref) { - LLSyntaxIdLSL::setKeywordsXml(content_ref); + // Continue only if a valid LLSD object was returned. + if (content_ref.isMap()) + { + LL_DEBUGS("SyntaxLSL") + << "content_ref isMap so assuming valid XML." << LL_ENDL; + + if (LLSyntaxIdLSL::isSupportedVersion(content_ref)) + { + LL_INFOS("SyntaxLSL") + << "Supported verson of syntax file." << LL_ENDL; + + LLSyntaxIdLSL::setKeywordsXml(content_ref); + LLSyntaxIdLSL::sInitialised = true; + LLSyntaxIdLSL::sLoaded = true; + LLSyntaxIdLSL::sLoadFailed = false; + cacheFile(content_ref); + } + else + { + LLSyntaxIdLSL::sLoaded = false; + LLSyntaxIdLSL::sLoadFailed = true; + LL_WARNS("SyntaxLSL") + << "Unknown or unsupported version of syntax file." << LL_ENDL; + } + } + else + { + LLSyntaxIdLSL::sLoaded = false; + LLSyntaxIdLSL::sLoadFailed = true; + LL_ERRS("SyntaxLSL") + << "Syntax file '" << mFileSpec << "' contains invalid LLSD!" << LL_ENDL; + } +} + +void fetchKeywordsFileResponder::cacheFile(const LLSD& content_ref) +{ std::stringstream str; LLSDSerialize::toPrettyXML(content_ref, str); const std::string xml = str.str(); @@ -70,29 +105,45 @@ void fetchKeywordsFileResponder::result(const LLSD& content_ref) file.close(); LL_INFOS("SyntaxLSL") - << "Syntax file received, saving as: '" << mFileSpec << "'" << LL_ENDL; + << "Syntax file received, saving as: '" << mFileSpec << "'" << LL_ENDL; } //----------------------------------------------------------------------------- // LLSyntaxIdLSL //----------------------------------------------------------------------------- +const std::string LLSyntaxIdLSL::CAPABILITY_NAME = "LSLSyntax"; +const std::string LLSyntaxIdLSL::FILENAME_DEFAULT = "keywords_lsl_default.xml"; +const std::string LLSyntaxIdLSL::SIMULATOR_FEATURE = "LSLSyntaxId"; + +bool LLSyntaxIdLSL::sInitialised; +LLSD LLSyntaxIdLSL::sKeywordsXml; +bool LLSyntaxIdLSL::sLoaded; +bool LLSyntaxIdLSL::sLoadFailed; +bool LLSyntaxIdLSL::sVersionChanged; + /** * @brief LLSyntaxIdLSL constructor */ -LLSyntaxIdLSL::LLSyntaxIdLSL() : - // Move these to signature? - mFileNameDefault("keywords_lsl_default.xml"), - mSimulatorFeature("LSLSyntaxId"), - mCapabilityName("LSLSyntax"), - mCapabilityURL(""), +LLSyntaxIdLSL::LLSyntaxIdLSL(std::string filenameDefault, std::string simFeatureName, std::string capabilityName) : mFilePath(LL_PATH_APP_SETTINGS) { + mCapabilityName = capabilityName; + mFileNameCurrent = filenameDefault; + mFileNameDefault = filenameDefault; + mSimulatorFeature = simFeatureName; mSyntaxIdCurrent = LLUUID(); - mFileNameCurrent = mFileNameDefault; } -LLSD LLSyntaxIdLSL::sKeywordsXml; +LLSyntaxIdLSL::LLSyntaxIdLSL() : + mFilePath(LL_PATH_APP_SETTINGS) +{ + mCapabilityName = CAPABILITY_NAME; + mFileNameCurrent = FILENAME_DEFAULT; + mFileNameDefault = FILENAME_DEFAULT; + mSimulatorFeature = SIMULATOR_FEATURE; + mSyntaxIdCurrent = LLUUID(); +} std::string LLSyntaxIdLSL::buildFileNameNew() { @@ -113,14 +164,15 @@ std::string LLSyntaxIdLSL::buildFullFileSpec() //----------------------------------------------------------------------------- bool LLSyntaxIdLSL::checkSyntaxIdChanged() { - bool changed = false; + sVersionChanged = false; LLViewerRegion* region = gAgent.getRegion(); if (region) { if (!region->capabilitiesReceived()) { // Shouldn't be possible, but experience shows that it may be needed. - LL_WARNS("SyntaxLSL") + sLoadFailed = true; + LL_ERRS("SyntaxLSL") << "Region '" << region->getName() << "' has not received capabilities yet! Cannot process SyntaxId." << LL_ENDL; @@ -128,46 +180,60 @@ bool LLSyntaxIdLSL::checkSyntaxIdChanged() else { LLSD simFeatures; - std::string message; region->getSimulatorFeatures(simFeatures); - // get and check the hash - if (simFeatures.has("LSLSyntaxId")) + // Does the sim have the required feature + if (simFeatures.has(mSimulatorFeature)) { - mSyntaxIdNew = simFeatures["LSLSyntaxId"].asUUID(); + // get and check the hash + mSyntaxIdNew = simFeatures[mSimulatorFeature].asUUID(); mCapabilityURL = region->getCapability(mCapabilityName); if (mSyntaxIdCurrent != mSyntaxIdNew) { - message = "' it has LSLSyntaxId capability, and the new hash is '" - + mSyntaxIdNew.asString() + "'"; + LL_INFOS("SyntaxLSL") + << "It has LSLSyntaxId capability, and the new hash is '" + << mSyntaxIdNew.asString() << "'" << LL_ENDL; - changed = true; + sVersionChanged = true; } else { - message = "' it has the same LSLSyntaxId! Leaving hash as '" - + mSyntaxIdCurrent.asString() + "'"; + LL_INFOS("SyntaxLSL") + << "It has the same LSLSyntaxId! Leaving hash as '" + << mSyntaxIdCurrent.asString() << "'" << LL_ENDL; } } else { - if ( mSyntaxIdCurrent.isNull() ) + if ( mSyntaxIdCurrent.isNull() && isInitialised()) { - message = " it does not have LSLSyntaxId capability, remaining with default keywords file!"; + LL_INFOS("SyntaxLSL") + << "It does not have LSLSyntaxId capability, remaining with default keywords file!" + << LL_ENDL; } else { // The hash is set to NULL_KEY to indicate use of default keywords file mSyntaxIdNew = LLUUID(); - message = " it does not have LSLSyntaxId capability, using default keywords file!"; - changed = true; + LL_INFOS("SyntaxLSL") + << "It does not have LSLSyntaxId capability, using default keywords file!" + << LL_ENDL; + sVersionChanged = true; } } - LL_INFOS("SyntaxLSL") - << "Region is '" << region->getName() << message << LL_ENDL; } } - return changed; + return sVersionChanged; +} + +/** + * @brief LLSyntaxIdLSL::fetching + * If the XML has not loaded yet and it hasn't failed, then we're still fetching it. + * @return bool Whether the file fetch is still in process. + */ +bool LLSyntaxIdLSL::fetching() +{ + return !(sLoaded || sLoadFailed); } //----------------------------------------------------------------------------- @@ -175,79 +241,118 @@ bool LLSyntaxIdLSL::checkSyntaxIdChanged() //----------------------------------------------------------------------------- void LLSyntaxIdLSL::fetchKeywordsFile() { - if ( !mCapabilityURL.empty() ) - { - LLHTTPClient::get(mCapabilityURL, - new fetchKeywordsFileResponder(mFullFileSpec), - LLSD(), 30.f - ); - LL_INFOS("SyntaxLSL") - << "LSLSyntaxId capability URL is: " << mCapabilityURL - << ". Filename to use is: '" << mFullFileSpec << "'." - << LL_ENDL; - } - else - { - LL_ERRS("SyntaxLSL") - << "LSLSyntaxId capability URL is empty!!" << LL_ENDL; - } + LLHTTPClient::get(mCapabilityURL, + new fetchKeywordsFileResponder(mFullFileSpec), + LLSD(), 30.f + ); + LL_INFOS("SyntaxLSL") + << "LSLSyntaxId capability URL is: " << mCapabilityURL + << ". Filename to use is: '" << mFullFileSpec << "'." + << LL_ENDL; } +//----------------------------------------------------------------------------- +// initialise +//----------------------------------------------------------------------------- void LLSyntaxIdLSL::initialise() { mFileNameNew = mFileNameCurrent; mSyntaxIdNew = mSyntaxIdCurrent; + if (checkSyntaxIdChanged()) { - LL_INFOS("SyntaxLSL") - << "LSL version has changed, getting appropriate file." - << LL_ENDL; + sKeywordsXml = LLSD(); + sLoaded = sLoadFailed = false; - // Need a full spec regardless of file source, so build it now. - buildFullFileSpec(); - if ( !mSyntaxIdNew.isNull() ) + if (mSyntaxIdNew.isNull()) + { // Need to open the default + loadDefaultKeywordsIntoLLSD(); + } + else if (!mCapabilityURL.empty() ) { - if ( !gDirUtilp->fileExists(mFullFileSpec) ) - { // Does not exist, so fetch it from the capability - fetchKeywordsFile(); - LL_INFOS("SyntaxLSL") - << "File is not cached, we will try to download it!" - << LL_ENDL; + LL_INFOS("SyntaxLSL") + << "LSL version has changed, getting appropriate file." + << LL_ENDL; + + // Need a full spec regardless of file source, so build it now. + buildFullFileSpec(); + if ( !mSyntaxIdNew.isNull()) + { + if ( !gDirUtilp->fileExists(mFullFileSpec) ) + { // Does not exist, so fetch it from the capability + LL_INFOS("SyntaxLSL") + << "File is not cached, we will try to download it!" + << LL_ENDL; + fetchKeywordsFile(); + } + else + { + LL_INFOS("SyntaxLSL") + << "File is cached, no need to download!" + << LL_ENDL; + loadKeywordsIntoLLSD(); + } } else - { - LL_INFOS("SyntaxLSL") - << "File is cached, no need to download!" - << LL_ENDL; - loadKeywordsIntoLLSD(); + { // Need to open the default + loadDefaultKeywordsIntoLLSD(); } } else - { // Need to open the default - loadDefaultKeywordsIntoLLSD("LSLSyntaxId is null so we will use the default file!"); + { + sLoadFailed = true; + LL_ERRS("SyntaxLSL") + << "LSLSyntaxId capability URL is empty!!" << LL_ENDL; + loadDefaultKeywordsIntoLLSD(); } } - else if (sKeywordsXml.isDefined()) + else if (!isInitialised()) + { + loadDefaultKeywordsIntoLLSD(); + } + + mFileNameCurrent = mFileNameNew; + mSyntaxIdCurrent = mSyntaxIdNew; +} + +//----------------------------------------------------------------------------- +// isSupportedVersion +//----------------------------------------------------------------------------- +bool LLSyntaxIdLSL::isSupportedVersion(const LLSD& content) +{ + bool isValid = false; + /* + * If the schema used to store LSL keywords and hints changes, this value is incremented + * Note that it should _not_ be changed if the keywords and hints _content_ changes. + */ + const U32 LLSD_SYNTAX_LSL_VERSION_EXPECTED = 2; + const std::string LLSD_SYNTAX_LSL_VERSION_KEY("llsd-lsl-syntax-version"); + + if (content.has(LLSD_SYNTAX_LSL_VERSION_KEY)) { LL_INFOS("SyntaxLSL") - << "No change to Syntax! Nothing to see. Move along now!" - << LL_ENDL; + << "Syntax file version: " << content[LLSD_SYNTAX_LSL_VERSION_KEY].asString() << LL_ENDL; + + if (content[LLSD_SYNTAX_LSL_VERSION_KEY].asInteger() == LLSD_SYNTAX_LSL_VERSION_EXPECTED) + { + isValid = true; + } } else - { // Need to open the default - loadDefaultKeywordsIntoLLSD("LSLSyntaxId is null so we will use the default file!"); + { + LL_WARNS("SyntaxLSL") << "No version key available!" << LL_ENDL; } - mFileNameCurrent = mFileNameNew; - mSyntaxIdCurrent = mSyntaxIdNew; + return isValid; } //----------------------------------------------------------------------------- // loadDefaultKeywordsIntoLLSD() //----------------------------------------------------------------------------- -void LLSyntaxIdLSL::loadDefaultKeywordsIntoLLSD(const std::string message) +void LLSyntaxIdLSL::loadDefaultKeywordsIntoLLSD() { - LL_INFOS("SyntaxLSL") << message << LL_ENDL; + LL_INFOS("SyntaxLSL") + << "LSLSyntaxId is null so we will use the default file!" << LL_ENDL; mSyntaxIdNew = LLUUID(); buildFullFileSpec(); loadKeywordsIntoLLSD(); @@ -259,39 +364,52 @@ void LLSyntaxIdLSL::loadDefaultKeywordsIntoLLSD(const std::string message) /** * @brief Load xml serialised LLSD * @desc Opens the specified filespec and attempts to deserialise the - * contained data to the specified LLSD object. - * @return Returns boolean true/false indicating success or failure. + * contained data to the specified LLSD object. indicate success/failure with + * sLoaded/sLoadFailed members. */ -bool LLSyntaxIdLSL::loadKeywordsIntoLLSD() +void LLSyntaxIdLSL::loadKeywordsIntoLLSD() { LL_INFOS("SyntaxLSL") << "Trying to open cached or default keyword file ;-)" << LL_ENDL; - bool loaded = false; + // Is this the right thing to do, or should we leave the old content + // even if it isn't entirely accurate anymore? + sKeywordsXml = LLSD().emptyMap(); + LLSD content; llifstream file; file.open(mFullFileSpec); if (file.is_open()) { - loaded = (bool)LLSDSerialize::fromXML(content, file); - if (!loaded) + sLoaded = (bool)LLSDSerialize::fromXML(content, file); + if (!sLoaded) { - LL_ERRS("SyntaxLSL") << "Unable to deserialise file: " << mFullFileSpec << LL_ENDL; - - // Is this the right thing to do, or should we leave the old content - // even if it isn't entirely accurate anymore? - sKeywordsXml = LLSD().emptyMap(); + LL_ERRS("SyntaxLSL") + << "Unable to deserialise file: " + << mFullFileSpec << LL_ENDL; } else { - sKeywordsXml = content; - LL_INFOS("SyntaxLSL") << "Deserialised file: " << mFullFileSpec << LL_ENDL; + if (isSupportedVersion(content)) + { + sKeywordsXml = content; + sLoaded = true; + sInitialised = true; + LL_INFOS("SyntaxLSL") + << "Deserialised file: " << mFullFileSpec << LL_ENDL; + } + else + { + sLoaded = false; + LL_WARNS("SyntaxLSL") + << "Unknown or unsupported version of syntax file." << LL_ENDL; + } } } else { LL_ERRS("SyntaxLSL") << "Unable to open file: " << mFullFileSpec << LL_ENDL; } - return loaded; + sLoadFailed = !sLoaded; } |