From e588d1f28419745ee1e1ee98dc1852e0364a4088 Mon Sep 17 00:00:00 2001 From: Christian Goetze Date: Wed, 1 Jul 2009 00:22:05 +0000 Subject: svn merge -r125825:125901 svn+ssh://svn.lindenlab.com/svn/user/cg/qar-1654 QAR-1654 merge completed. --- indra/llmessage/CMakeLists.txt | 2 + indra/llmessage/llcachename.cpp | 226 ++++++++++++++------- indra/llmessage/llcachename.h | 6 +- indra/llmessage/llhttpclientadapter.cpp | 2 +- indra/llmessage/llhttpclientadapter.h | 2 +- indra/llmessage/llhttpclientinterface.h | 2 +- indra/llmessage/llmessagesenderinterface.h | 2 +- indra/llmessage/llregionpresenceverifier.cpp | 86 ++++++-- indra/llmessage/llregionpresenceverifier.h | 39 ++-- indra/llmessage/llstoredmessage.cpp | 2 +- indra/llmessage/llstoredmessage.h | 2 +- indra/llmessage/llthrottle.cpp | 25 +++ indra/llmessage/llthrottle.h | 2 + indra/llmessage/llurlrequest.cpp | 54 +++-- indra/llmessage/llurlrequest.h | 8 + .../tests/llregionpresenceverifier_test.cpp | 111 ++++++++++ 16 files changed, 433 insertions(+), 138 deletions(-) create mode 100644 indra/llmessage/tests/llregionpresenceverifier_test.cpp (limited to 'indra/llmessage') diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 88f83ba78e..81e518cf6e 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -221,6 +221,7 @@ IF (NOT LINUX AND VIEWER) # llhttpclientadapter.cpp lltrustedmessageservice.cpp lltemplatemessagedispatcher.cpp + llregionpresenceverifier.cpp ) LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}") @@ -228,3 +229,4 @@ IF (NOT LINUX AND VIEWER) # Don't make llmessage depend on llsdmessage_test because ADD_COMM_BUILD_TEST depends on llmessage! # ADD_COMM_BUILD_TEST(llsdmessage "" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py") ENDIF (NOT LINUX AND VIEWER) + diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 799bc83e20..82186fc503 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -76,11 +76,13 @@ public: LLCacheNameEntry(); public: - bool mIsGroup; - U32 mCreateTime; // unix time_t - std::string mFirstName; - std::string mLastName; - std::string mGroupName; + bool isUnknown() { return (mFirstName.empty() + || mFirstName == std::string("(???)")); }; + + bool mIsGroup; // true if this is a group ID/name + U32 mCreateTime; // unix time_t + std::string mFirstName; // Doubles as the group name + std::string mLastName; // Will be "" for groups }; LLCacheNameEntry::LLCacheNameEntry() @@ -162,7 +164,7 @@ void ReplySender::send(const LLUUID& id, mMsg->addUUIDFast(_PREHASH_ID, id); if(mCurrIsGroup) { - mMsg->addStringFast(_PREHASH_GroupName, entry.mGroupName); + mMsg->addStringFast(_PREHASH_GroupName, entry.mFirstName); } else { @@ -222,6 +224,7 @@ public: void processPendingReplies(); void sendRequest(const char* msg_name, const AskQueue& queue); bool isRequestPending(const LLUUID& id); + void makeNameRequestForID(const LLUUID& id, bool isGroup, LLHost & fromHost); // Message system callbacks. void processUUIDRequest(LLMessageSystem* msg, bool isGroup); @@ -389,6 +392,7 @@ void LLCacheName::importFile(LLFILE* fp) entry->mCreateTime = create_time; entry->mFirstName = firstname; entry->mLastName = lastname; + //llinfos << "Adding entry from file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl; impl.mCache[id] = entry; count++; @@ -425,6 +429,7 @@ bool LLCacheName::importFile(std::istream& istr) entry->mCreateTime = ctime; entry->mFirstName = agent[FIRST].asString(); entry->mLastName = agent[LAST].asString(); + //llinfos << "Adding name entry from XML file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl; impl.mCache[id] = entry; ++count; @@ -445,7 +450,9 @@ bool LLCacheName::importFile(std::istream& istr) LLCacheNameEntry* entry = new LLCacheNameEntry(); entry->mIsGroup = true; entry->mCreateTime = ctime; - entry->mGroupName = group[NAME].asString(); + entry->mFirstName = group[NAME].asString(); + entry->mLastName = ""; + //llinfos << "Adding group entry from XML file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl; impl.mCache[id] = entry; ++count; } @@ -463,32 +470,32 @@ void LLCacheName::exportFile(std::ostream& ostr) // Only write entries for which we have valid data. LLCacheNameEntry* entry = iter->second; if(!entry - || (std::string::npos != entry->mFirstName.find('?')) - || (std::string::npos != entry->mGroupName.find('?'))) - { + || entry->isUnknown()) + { // No entry, or user or group name is unknown continue; } // store it LLUUID id = iter->first; std::string id_str = id.asString(); - if(!entry->mFirstName.empty() && !entry->mLastName.empty()) - { + if(entry->mIsGroup) + { // Save group name and ID + data[GROUPS][id_str][NAME] = entry->mFirstName; + data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime; + } + else if(!entry->mLastName.empty()) + { // Save user names and ID data[AGENTS][id_str][FIRST] = entry->mFirstName; data[AGENTS][id_str][LAST] = entry->mLastName; data[AGENTS][id_str][CTIME] = (S32)entry->mCreateTime; } - else if(entry->mIsGroup && !entry->mGroupName.empty()) - { - data[GROUPS][id_str][NAME] = entry->mGroupName; - data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime; - } } LLSDSerialize::toPrettyXML(data, ostr); } +// DO NOT CALL THIS FOR GROUP NAMES BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& last) { if(id.isNull()) @@ -511,11 +518,11 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las last.clear(); if (!impl.isRequestPending(id)) { + //llinfos << "**** adding name req for " << id << llendl; impl.mAskNameQueue.insert(id); } - return FALSE; } - + return FALSE; } BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname) @@ -535,7 +542,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group) } LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache,id); - if (entry && entry->mGroupName.empty()) + if (entry && entry->mFirstName.empty()) { // COUNTER-HACK to combat James' HACK in exportFile()... // this group name was loaded from a name cache that did not @@ -546,7 +553,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group) if (entry) { - group = entry->mGroupName; + group = entry->mFirstName; return TRUE; } else @@ -562,7 +569,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group) // TODO: Make the cache name callback take a SINGLE std::string, // not a separate first and last name. -void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data) +void LLCacheName::getNameFromUUID(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data) { if(id.isNull()) { @@ -573,15 +580,8 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id ); if (entry) { - // id found in map therefore we can call the callback immediately. - if (entry->mIsGroup) - { - callback(id, entry->mGroupName, "", entry->mIsGroup, user_data); - } - else - { - callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data); - } + // id found in map therefore we can call the callback immediately. mLastName will be empty for groups + callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data); } else { @@ -590,13 +590,17 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb { if (is_group) { + //llinfos << "Group queued for " << id << llendl; impl.mAskGroupQueue.insert(id); } else { + //llinfos << "Name queued for " << id << llendl; impl.mAskNameQueue.insert(id); } } + + // There may be multiple replies for the same ID request impl.mReplyQueue.push_back(PendingReply(id, callback, user_data)); } } @@ -661,7 +665,7 @@ void LLCacheName::dump() { llinfos << iter->first << " = (group) " - << entry->mGroupName + << entry->mFirstName << " @ " << entry->mCreateTime << llendl; } @@ -715,17 +719,7 @@ void LLCacheName::Impl::processPendingReplies() if (it->mCallback) { - if (!entry->mIsGroup) - { - (it->mCallback)(it->mID, - entry->mFirstName, entry->mLastName, - FALSE, it->mData); - } - else { - (it->mCallback)(it->mID, - entry->mGroupName, "", - TRUE, it->mData); - } + (it->mCallback)(it->mID, entry->mFirstName, entry->mLastName, entry->mIsGroup, it->mData); } } @@ -768,10 +762,12 @@ void LLCacheName::Impl::sendRequest( if(start_new_message) { start_new_message = false; + //llinfos << "newMessageFast : " << msg_name << llendl; mMsg->newMessageFast(msg_name); } mMsg->nextBlockFast(_PREHASH_UUIDNameBlock); mMsg->addUUIDFast(_PREHASH_ID, (*it)); + //llinfos << " asking for ID: " << (*it) << llendl; if(mMsg->isSendFullFast(_PREHASH_UUIDNameBlock)) { @@ -837,38 +833,102 @@ void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup) { if (isGroup != entry->mIsGroup) { - llwarns << "LLCacheName - Asked for " - << (isGroup ? "group" : "user") << " name, " - << "but found " - << (entry->mIsGroup ? "group" : "user") - << ": " << id << llendl; + if (entry->isUnknown()) + { + Cache::iterator doomediter = mCache.find(id); + if (doomediter != mCache.end()) + { // Kill existing unknown entry + llwarns << "LLCacheName - Asked for " + << (isGroup ? "group" : "user") << " name, " + << "but found unknown " + << (entry->mIsGroup ? "group" : "user") + << " entry for: " << id + << ", deleting bad entry" + << llendl; + + delete entry; + entry = NULL; + mCache.erase(doomediter); + + // Request it with (hopefully) the correct type + makeNameRequestForID(id,isGroup,fromHost); + } + } + else if (isGroup) + { + llwarns << "LLCacheName - Asked for group name, but found user: " + << id + << " named " + << entry->mFirstName << " " << entry->mLastName + << llendl; + } + else + { + llwarns << "LLCacheName - Asked for user name, but found group: " + << id + << " named " + << entry->mFirstName + << llendl; + } } else { // ...it's in the cache, so send it as the reply sender.send(id, *entry, fromHost); - } - } - else - { - if (!isRequestPending(id)) - { + + /* if (isGroup) { - mAskGroupQueue.insert(id); + llinfos << "Group ID " << id + << " name " << entry->mFirstName + << " was already in cache" << llendl; } else { - mAskNameQueue.insert(id); + llinfos << "Agent ID " << id + << " name " << entry->mFirstName << " " << entry->mLastName + << " was already in cache" << llendl; } + */ } - - mReplyQueue.push_back(PendingReply(id, fromHost)); + } + else + { /* + if (isGroup) + { + llinfos << "Group ID " << id << " is not in cache" << llendl; + } + else + { + llinfos << "Agent ID " << id << " is not in cache" << llendl; + } + */ + makeNameRequestForID(id,isGroup,fromHost); } } } +void LLCacheName::Impl::makeNameRequestForID(const LLUUID& id, bool isGroup, LLHost & fromHost) +{ + if (!isRequestPending(id)) + { + if (isGroup) + { + //llinfos << "Adding group request for " << id << llendl; + mAskGroupQueue.insert(id); + } + else + { + //llinfos << "Adding name request for " << id << llendl; + mAskNameQueue.insert(id); + } + } + + // There may be multiple replys for the same ID request + mReplyQueue.push_back(PendingReply(id, fromHost)); +} + void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup) { @@ -878,35 +938,53 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup) LLUUID id; msg->getUUIDFast(_PREHASH_UUIDNameBlock, _PREHASH_ID, id, i); LLCacheNameEntry* entry = get_ptr_in_map(mCache, id); + bool add_new_entry_to_cache = false; if (!entry) { entry = new LLCacheNameEntry; - mCache[id] = entry; + add_new_entry_to_cache = true; } + // Remove ID from pending queue mPendingQueue.erase(id); - entry->mIsGroup = isGroup; - entry->mCreateTime = (U32)time(NULL); - if (!isGroup) - { - msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, entry->mFirstName, i); - msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName, entry->mLastName, i); + std::string first_name; + std::string last_name; + if (isGroup) + { // Group + msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, first_name, i); + LLStringFn::replace_ascii_controlchars(first_name, LL_UNKNOWN_CHAR); } else - { // is group - msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, entry->mGroupName, i); - LLStringFn::replace_ascii_controlchars(entry->mGroupName, LL_UNKNOWN_CHAR); + { // User + msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, first_name, i); + msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName, last_name, i); } - - if (!isGroup) - { - notifyObservers(id, entry->mFirstName, entry->mLastName, FALSE); + + if (!add_new_entry_to_cache && + (entry->mFirstName != first_name || + entry->mLastName != last_name || + entry->mIsGroup != isGroup)) + { // Hmmm, we already had an different entry for this ID. Let's see what happened... + llwarns << "Replacing existing entry in name cache for id " << id + << " first name was " << entry->mFirstName << ", now " << first_name + << " last name was " << entry->mLastName << ", now " << last_name + << " group flag was " << (S32) entry->mIsGroup << ", now " << (S32) isGroup + << llendl; } - else + + entry->mFirstName = first_name; + entry->mLastName = last_name; + entry->mIsGroup = isGroup; + entry->mCreateTime = (U32)time(NULL); + + if (add_new_entry_to_cache) { - notifyObservers(id, entry->mGroupName, "", TRUE); + //llinfos << "Adding entry for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl; + mCache[id] = entry; } + + notifyObservers(id, entry->mFirstName, entry->mLastName, isGroup); } } diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index 2757b86a7c..bfa116ad4a 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -89,12 +89,8 @@ public: // If the data is currently available, may call the callback immediatly // otherwise, will request the data, and will call the callback when // available. There is no garuntee the callback will ever be called. - void get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL); + void getNameFromUUID(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL); - // LEGACY - void getName(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL) - { get(id, FALSE, callback, user_data); } - // This method needs to be called from time to time to send out // requests. void processPending(); diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp index bbb56960df..5236a52164 100644 --- a/indra/llmessage/llhttpclientadapter.cpp +++ b/indra/llmessage/llhttpclientadapter.cpp @@ -1,5 +1,5 @@ /** - * @file + * @file llhttpclientadapter.cpp * @brief * * $LicenseInfo:firstyear=2009&license=viewergpl$ diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h index d5f3aeaf2c..c489dca32d 100644 --- a/indra/llmessage/llhttpclientadapter.h +++ b/indra/llmessage/llhttpclientadapter.h @@ -1,5 +1,5 @@ /** - * @file + * @file llhttpclientadepter.h * @brief * * $LicenseInfo:firstyear=2008&license=viewergpl$ diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h index 1f13d46447..61826cc4b4 100644 --- a/indra/llmessage/llhttpclientinterface.h +++ b/indra/llmessage/llhttpclientinterface.h @@ -1,5 +1,5 @@ /** - * @file + * @file llhttpclientinterface.h * @brief * * $LicenseInfo:firstyear=2008&license=viewergpl$ diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h index 4082666339..d98d891563 100644 --- a/indra/llmessage/llmessagesenderinterface.h +++ b/indra/llmessage/llmessagesenderinterface.h @@ -1,5 +1,5 @@ /** - * @file + * @file llmessagesenderinterface.h * @brief * * $LicenseInfo:firstyear=2008&license=viewergpl$ diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp index 552cf4cbdb..08c12f90da 100644 --- a/indra/llmessage/llregionpresenceverifier.cpp +++ b/indra/llmessage/llregionpresenceverifier.cpp @@ -1,5 +1,5 @@ /** - * @file + * @file llregionpresenceverifier.cpp * @brief * * $LicenseInfo:firstyear=2008&license=viewergpl$ @@ -25,11 +25,40 @@ #include "net.h" #include "message.h" +namespace boost +{ + void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p) + { + ++p->mReferenceCount; + } + + void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p) + { + if(p && 0 == --p->mReferenceCount) + { + delete p; + } + } +}; -LLRegionPresenceVerifier::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data) +LLRegionPresenceVerifier::Response::~Response() { } +LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string& + uri, + ResponsePtr data, + S32 retry_count) : + mUri(uri), + mSharedData(data), + mRetryCount(retry_count) +{ +} + +//virtual +LLRegionPresenceVerifier::RegionResponder::~RegionResponder() +{ +} void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content) { @@ -42,26 +71,32 @@ void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content) std::stringstream uri; uri << "http://" << destination.getString() << "/state/basic/"; - mSharedData->getHttpClient().get(uri.str(), new VerifiedDestinationResponder(mSharedData, content)); + mSharedData->getHttpClient().get( + uri.str(), + new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount)); } -void LLRegionPresenceVerifier::RegionResponder::completed( - U32 status, - const std::string& reason, - const LLSD& content) +void LLRegionPresenceVerifier::RegionResponder::error(U32 status, + const std::string& reason) { - LLHTTPClient::Responder::completed(status, reason, content); - - mSharedData->onCompletedRegionRequest(); + // TODO: babbage: distinguish between region presence service and + // region verification errors? + mSharedData->onRegionVerificationFailed(); } - -LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(ResponsePtr data, const LLSD& content) : mSharedData(data), mContent(content) +LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content, + S32 retry_count): + mUri(uri), + mSharedData(data), + mContent(content), + mRetryCount(retry_count) { } - - +//virtual +LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder() +{ +} void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content) { @@ -76,13 +111,14 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& { mSharedData->onRegionVerified(mContent); } - else if (mSharedData->shouldRetry()) + else if (mRetryCount > 0) { retry(); } else { - llwarns << "Could not correctly look up region from region presence service. Region: " << mSharedData->getRegionUri() << llendl; + llwarns << "Simulator verification failed. Region: " << mUri << llendl; + mSharedData->onRegionVerificationFailed(); } } @@ -90,13 +126,21 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry() { LLSD headers; headers["Cache-Control"] = "no-cache, max-age=0"; - llinfos << "Requesting region information, get uncached for region " << mSharedData->getRegionUri() << llendl; - mSharedData->decrementRetries(); - mSharedData->getHttpClient().get(mSharedData->getRegionUri(), new RegionResponder(mSharedData), headers); + llinfos << "Requesting region information, get uncached for region " + << mUri << llendl; + --mRetryCount; + mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers); } void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason) { - retry(); + if(mRetryCount > 0) + { + retry(); + } + else + { + llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl; + mSharedData->onRegionVerificationFailed(); + } } - diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h index d1de608ec6..f11eeef50c 100644 --- a/indra/llmessage/llregionpresenceverifier.h +++ b/indra/llmessage/llregionpresenceverifier.h @@ -1,5 +1,5 @@ /** - * @file + * @file llregionpresenceverifier.cpp * @brief * * $LicenseInfo:firstyear=2008&license=viewergpl$ @@ -26,7 +26,7 @@ #include "llhttpclient.h" #include #include "llsd.h" -#include +#include class LLHTTPClientInterface; @@ -36,48 +36,57 @@ public: class Response { public: - virtual ~Response() {} + virtual ~Response() = 0; virtual bool checkValidity(const LLSD& content) const = 0; virtual void onRegionVerified(const LLSD& region_details) = 0; - - virtual void decrementRetries() = 0; + virtual void onRegionVerificationFailed() = 0; virtual LLHTTPClientInterface& getHttpClient() = 0; - virtual std::string getRegionUri() const = 0; - virtual bool shouldRetry() const = 0; - virtual void onCompletedRegionRequest() {} + public: /* but not really -- don't touch this */ + U32 mReferenceCount; }; - typedef boost::shared_ptr ResponsePtr; + typedef boost::intrusive_ptr ResponsePtr; class RegionResponder : public LLHTTPClient::Responder { public: - RegionResponder(ResponsePtr data); + RegionResponder(const std::string& uri, ResponsePtr data, + S32 retry_count); + virtual ~RegionResponder(); virtual void result(const LLSD& content); - virtual void completed( - U32 status, - const std::string& reason, - const LLSD& content); + virtual void error(U32 status, const std::string& reason); private: ResponsePtr mSharedData; + std::string mUri; + S32 mRetryCount; }; class VerifiedDestinationResponder : public LLHTTPClient::Responder { public: - VerifiedDestinationResponder(ResponsePtr data, const LLSD& content); + VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, + const LLSD& content, S32 retry_count); + virtual ~VerifiedDestinationResponder(); virtual void result(const LLSD& content); virtual void error(U32 status, const std::string& reason); + private: void retry(); ResponsePtr mSharedData; LLSD mContent; + std::string mUri; + S32 mRetryCount; }; }; +namespace boost +{ + void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p); + void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p); +}; #endif //LL_LLREGIONPRESENCEVERIFIER_H diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp index 615eff405d..da6d1c84a8 100644 --- a/indra/llmessage/llstoredmessage.cpp +++ b/indra/llmessage/llstoredmessage.cpp @@ -1,5 +1,5 @@ /** - * @file + * @file llstoredmessage.cpp * @brief * * $LicenseInfo:firstyear=2009&license=viewergpl$ diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h index e817f19bd2..6a27698b03 100644 --- a/indra/llmessage/llstoredmessage.h +++ b/indra/llmessage/llstoredmessage.h @@ -1,5 +1,5 @@ /** - * @file + * @file llstoredmessage.h * @brief * * $LicenseInfo:firstyear=2009&license=viewergpl$ diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp index 70279a3c62..0872efba50 100644 --- a/indra/llmessage/llthrottle.cpp +++ b/indra/llmessage/llthrottle.cpp @@ -265,6 +265,31 @@ BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec) return changed; } +// Return bits available in the channel +S32 LLThrottleGroup::getAvailable(S32 throttle_cat) +{ + S32 retval = 0; + + F32 category_bps = mCurrentBPS[throttle_cat]; + F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME; + + // use a temporary bits_available + // since we don't want to change mBitsAvailable every time + F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]); + F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time); + + if (bits_available >= lookahead_bits) + { + retval = (S32) gThrottleMaximumBPS[throttle_cat]; + } + else + { + retval = (S32) bits_available; + } + + return retval; +} + BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits) { diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h index 7d1679beb2..47a7c653b2 100644 --- a/indra/llmessage/llthrottle.h +++ b/indra/llmessage/llthrottle.h @@ -84,6 +84,8 @@ public: BOOL dynamicAdjust(); // Shift bandwidth from idle channels to busy channels, TRUE if adjustment occurred BOOL setNominalBPS(F32* throttle_vec); // TRUE if any value was different, resets adjustment system if was different + S32 getAvailable(S32 throttle_cat); // Return bits available in the channel + void packThrottle(LLDataPacker &dp) const; void unpackThrottle(LLDataPacker &dp); public: diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 3ab8057abb..81b7761ed5 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -51,6 +51,7 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499; * String constants */ const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri"); +const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes"); static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user); @@ -247,7 +248,29 @@ LLIOPipe::EStatus LLURLRequest::process_impl( PUMP_DEBUG; LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); //llinfos << "LLURLRequest::process_impl()" << llendl; - if(!buffer) return STATUS_ERROR; + if (!buffer) return STATUS_ERROR; + + // we're still waiting or prcessing, check how many + // bytes we have accumulated. + const S32 MIN_ACCUMULATION = 100000; + if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION)) + { + // This is a pretty sloppy calculation, but this + // tries to make the gross assumption that if data + // is coming in at 56kb/s, then this transfer will + // probably succeed. So, if we're accumlated + // 100,000 bytes (MIN_ACCUMULATION) then let's + // give this client another 2s to complete. + const F32 TIMEOUT_ADJUSTMENT = 2.0f; + mDetail->mByteAccumulator = 0; + pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT); + lldebugs << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << llendl; + if (mState == STATE_INITIALIZED) + { + llinfos << "LLURLRequest adjustTimeoutSeconds called during upload" << llendl; + } + } + switch(mState) { case STATE_INITIALIZED: @@ -286,27 +309,14 @@ LLIOPipe::EStatus LLURLRequest::process_impl( bool newmsg = mDetail->mCurlRequest->getResult(&result); if(!newmsg) { - // we're still waiting or prcessing, check how many - // bytes we have accumulated. - const S32 MIN_ACCUMULATION = 100000; - if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION)) - { - // This is a pretty sloppy calculation, but this - // tries to make the gross assumption that if data - // is coming in at 56kb/s, then this transfer will - // probably succeed. So, if we're accumlated - // 100,000 bytes (MIN_ACCUMULATION) then let's - // give this client another 2s to complete. - const F32 TIMEOUT_ADJUSTMENT = 2.0f; - mDetail->mByteAccumulator = 0; - pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT); - } - // keep processing break; } mState = STATE_HAVE_RESPONSE; + context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes; + context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes; + lldebugs << this << "Setting context to " << context << llendl; switch(result) { case CURLE_OK: @@ -353,10 +363,16 @@ LLIOPipe::EStatus LLURLRequest::process_impl( // we already stuffed everything into channel in in the curl // callback, so we are done. eos = true; + context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes; + context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes; + lldebugs << this << "Setting context to " << context << llendl; return STATUS_DONE; default: PUMP_DEBUG; + context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes; + context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes; + lldebugs << this << "Setting context to " << context << llendl; return STATUS_ERROR; } } @@ -369,6 +385,8 @@ void LLURLRequest::initialize() mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1); mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this); mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this); + mRequestTransferedBytes = 0; + mResponseTransferedBytes = 0; } bool LLURLRequest::configure() @@ -471,6 +489,7 @@ size_t LLURLRequest::downCallback( req->mDetail->mChannels.out(), (U8*)data, bytes); + req->mResponseTransferedBytes += bytes; req->mDetail->mByteAccumulator += bytes; return bytes; } @@ -494,6 +513,7 @@ size_t LLURLRequest::upCallback( req->mDetail->mLastRead, (U8*)data, bytes); + req->mRequestTransferedBytes += bytes; return bytes; } diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index 86ef71f085..cb3c466440 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -45,6 +45,12 @@ #include "llchainio.h" #include "llerror.h" + +extern const std::string CONTEXT_REQUEST; +extern const std::string CONTEXT_DEST_URI_SD_LABEL; +extern const std::string CONTEXT_RESPONSE; +extern const std::string CONTEXT_TRANSFERED_BYTES; + class LLURLRequestDetail; class LLURLRequestComplete; @@ -208,6 +214,8 @@ protected: ERequestAction mAction; LLURLRequestDetail* mDetail; LLIOPipe::ptr_t mCompletionCallback; + S32 mRequestTransferedBytes; + S32 mResponseTransferedBytes; private: /** diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp new file mode 100644 index 0000000000..b7602ef15c --- /dev/null +++ b/indra/llmessage/tests/llregionpresenceverifier_test.cpp @@ -0,0 +1,111 @@ +/** + * @file + * @brief + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2001-2008, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "../test/lltut.h" +#include "llregionpresenceverifier.h" +#include "llcurl_stub.cpp" +#include "llhost.cpp" +#include "net.cpp" +#include "lltesthttpclientadapter.cpp" + +class LLTestResponse : public LLRegionPresenceVerifier::Response +{ +public: + + virtual bool checkValidity(const LLSD& content) const + { + return true; + } + + virtual void onRegionVerified(const LLSD& region_details) + { + } + + virtual void onRegionVerificationFailed() + { + } + + virtual LLHTTPClientInterface& getHttpClient() + { + return mHttpInterface; + } + + LLTestHTTPClientAdapter mHttpInterface; +}; + +namespace tut +{ + struct LLRegionPresenceVerifierData + { + LLRegionPresenceVerifierData() : + mResponse(new LLTestResponse()), + mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse), + LLSD(), 3) + { + } + + LLTestResponse* mResponse; + LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder; + }; + + typedef test_group factory; + typedef factory::object object; +} + +namespace +{ + tut::factory tf("LLRegionPresenceVerifier test"); +} + +namespace tut +{ + // Test that VerifiedDestinationResponder does retry + // on error when shouldRetry returns true. + template<> template<> + void object::test<1>() + { + mResponder.error(500, "Internal server error"); + ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1); + } + + // Test that VerifiedDestinationResponder only retries + // on error until shouldRetry returns false. + template<> template<> + void object::test<2>() + { + mResponder.error(500, "Internal server error"); + mResponder.error(500, "Internal server error"); + mResponder.error(500, "Internal server error"); + mResponder.error(500, "Internal server error"); + ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3); + } +} + -- cgit v1.3 From c2e425e5395c1b1b43a2f477565e374d919f10ee Mon Sep 17 00:00:00 2001 From: Dave Hiller Date: Tue, 14 Jul 2009 16:52:40 +0000 Subject: QAR-1651 svn merge -r126784:126785 svn+ssh://svn.lindenlab.com/svn/linden/branches/mock-3 into trunk --- indra/cmake/GoogleMock.cmake | 27 ++++++++++++++ indra/cmake/LLAddBuildTest.cmake | 11 +++++- indra/llmessage/tests/llmockhttpclient.h | 61 ++++++++++++++++++++++++++++++++ indra/test/CMakeLists.txt | 17 ++++++--- indra/test/test.cpp | 6 ++++ install.xml | 33 +++++++++++++++++ 6 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 indra/cmake/GoogleMock.cmake create mode 100644 indra/llmessage/tests/llmockhttpclient.h (limited to 'indra/llmessage') diff --git a/indra/cmake/GoogleMock.cmake b/indra/cmake/GoogleMock.cmake new file mode 100644 index 0000000000..ca5a8034ba --- /dev/null +++ b/indra/cmake/GoogleMock.cmake @@ -0,0 +1,27 @@ +# -*- cmake -*- +include(Prebuilt) +include(Linking) + +use_prebuilt_binary(googlemock) + +set(GOOGLEMOCK_INCLUDE_DIRS + ${LIBS_PREBUILT_DIR}/include) + +if (LINUX) + set(GOOGLEMOCK_LIBRARIES + gmock + gtest) +elseif(WINDOWS) + set(GOOGLEMOCK_LIBRARIES + gmock) + set(GOOGLEMOCK_INCLUDE_DIRS + ${LIBS_PREBUILT_DIR}/include + ${LIBS_PREBUILT_DIR}/include/gmock + ${LIBS_PREBUILT_DIR}/include/gmock/boost/tr1/tr1) +elseif(DARWIN) + set(GOOGLEMOCK_LIBRARIES + gmock + gtest) +endif(LINUX) + + diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 4a61725e09..4da0824120 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -13,6 +13,8 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources) # # WARNING: do NOT modify this code without working with poppy or daveh - # there is another branch that will conflict heavily with any changes here. +INCLUDE(GoogleMock) + IF(LL_TEST_VERBOSE) MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}") @@ -32,8 +34,10 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources) ${LLMATH_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS} ${LIBS_OPEN_DIR}/test + ${GOOGLEMOCK_INCLUDE_DIRS} ) SET(alltest_LIBRARIES + ${GOOGLEMOCK_LIBRARIES} ${PTHREAD_LIBRARY} ${WINDOWS_LIBRARIES} ) @@ -42,6 +46,11 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources) ${CMAKE_SOURCE_DIR}/test/test.h ) + # Use the default flags + if (LINUX) + SET(CMAKE_EXE_LINKER_FLAGS "") + endif (LINUX) + # start the source test executable definitions SET(${project}_TEST_OUTPUT "") FOREACH (source ${sources}) @@ -84,9 +93,9 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources) MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}") ENDIF(LL_TEST_VERBOSE) + # Setup target ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES}) - # # Per-codefile additional / external project dep and lib dep property extraction # diff --git a/indra/llmessage/tests/llmockhttpclient.h b/indra/llmessage/tests/llmockhttpclient.h new file mode 100644 index 0000000000..0de8246446 --- /dev/null +++ b/indra/llmessage/tests/llmockhttpclient.h @@ -0,0 +1,61 @@ +/** + * @file + * @brief + * + * $LicenseInfo:firstyear=2008&license=internal$ + * + * Copyright (c) 2008, Linden Research, Inc. + * + * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of + * this source code is governed by the Linden Lab Source Code Disclosure + * Agreement ("Agreement") previously entered between you and Linden + * Lab. By accessing, using, copying, modifying or distributing this + * software, you acknowledge that you have been informed of your + * obligations under the Agreement and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +/* Macro Definitions */ +#ifndef LL_LLMOCKHTTPCLIENT_H +#define LL_LLMOCKHTTPCLIENT_H + +#include "linden_common.h" +#include "llhttpclientinterface.h" + +#include + +class LLMockHTTPClient : public LLHTTPClientInterface +{ +public: + MOCK_METHOD2(get, void(const std::string& url, LLCurl::ResponderPtr responder)); + MOCK_METHOD3(get, void(const std::string& url, LLCurl::ResponderPtr responder, const LLSD& headers)); + MOCK_METHOD3(put, void(const std::string& url, const LLSD& body, LLCurl::ResponderPtr responder)); +}; + +// A helper to match responder types +template +struct ResponderType +{ + bool operator()(LLCurl::ResponderPtr ptr) const + { + T* p = dynamic_cast(ptr.get()); + return p != NULL; + } +}; + +inline bool operator==(const LLSD& l, const LLSD& r) +{ + std::ostringstream ls, rs; + ls << l; + rs << r; + return ls.str() == rs.str(); + +} + + +#endif //LL_LLMOCKHTTPCLIENT_H + diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index 49a0a8f361..53109ca196 100644 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -14,6 +14,7 @@ include(LScript) include(Linking) include(Tut) include(Boost) +include(GoogleMock) include_directories( ${LLCOMMON_INCLUDE_DIRS} @@ -24,6 +25,7 @@ include_directories( ${LLVFS_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} + ${GOOGLEMOCK_INCLUDE_DIRS} ) set(test_SOURCE_FILES @@ -121,6 +123,7 @@ target_link_libraries(test ${LLXML_LIBRARIES} ${LSCRIPT_LIBRARIES} ${LLCOMMON_LIBRARIES} + ${GOOGLEMOCK_LIBRARIES} ${APRICONV_LIBRARIES} ${PTHREAD_LIBRARY} ${WINDOWS_LIBRARIES} @@ -137,12 +140,18 @@ endif (WINDOWS) get_target_property(TEST_EXE test LOCATION) +SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR}) + +SET(TEST_LD_CMD + ${CMAKE_COMMAND} + -DLD_LIBRARY_PATH=${ARCH_PREBUILT_DIRS}:/usr/lib + -DTEST_CMD:STRING="${TEST_CMD}" + -P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake + ) + add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt - COMMAND ${TEST_EXE} - ARGS - --output=${CMAKE_CURRENT_BINARY_DIR}/cpp_test_results.txt - --touch=${CMAKE_CURRENT_BINARY_DIR}/cpp_tests_ok.txt + COMMAND ${TEST_LD_CMD} DEPENDS test WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "C++ unit tests" diff --git a/indra/test/test.cpp b/indra/test/test.cpp index ba81c6e49e..c9e985c914 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -54,6 +54,9 @@ # include "ctype_workaround.h" #endif +#include +#include + namespace tut { std::string sSourceDir; @@ -238,6 +241,9 @@ void wouldHaveCrashed(const std::string& message) int main(int argc, char **argv) { + // The following line must be executed to initialize Google Mock + // (and Google Test) before running the tests. + ::testing::InitGoogleMock(&argc, argv); LLError::initForApplication("."); LLError::setFatalFunction(wouldHaveCrashed); LLError::setDefaultLevel(LLError::LEVEL_ERROR); diff --git a/install.xml b/install.xml index a0d53dbcc0..464df8f710 100644 --- a/install.xml +++ b/install.xml @@ -541,6 +541,39 @@ + googlemock + + copyright + Copyright 2008, Google Inc. + description + Google C++ Mocking Framework (or Google Mock for short) is a library for writing and using C++ mock classes. + license + bsd + packages + + darwin + + md5sum + 4863e9fea433d0a4be761ea5d3e8346a + url + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/googlemock-1.1.0-darwin-20090626.tar.bz2 + + linux + + md5sum + 877dabecf84339690191c6115c76366e + url + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/googlemock-1.1.0-linux32-20090527.tar.bz2 + + windows + + md5sum + be37695d9f26552aec81c8e97ded0212 + url + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/googlemock-1.1.0-windows-20090529.tar.bz2 + + + gstreamer license -- cgit v1.3 From d025b721e0d39f53ef796f9c9e28e94b6d1cea20 Mon Sep 17 00:00:00 2001 From: Christian Goetze Date: Wed, 15 Jul 2009 17:55:58 +0000 Subject: svn merge -r126867:127217 svn+ssh://svn.lindenlab.com/svn/user/cg/qar-1691 Effective merge: svn merge -r125827:127126 svn+ssh://svn.lindenlab.com/svn/linden/branches/server/server-1.27 QAR-1691 --- indra/llmessage/lliohttpserver.cpp | 14 +++++++--- indra/llmessage/llxfermanager.cpp | 36 +++++++++++++++----------- indra/llprimitive/llprimtexturelist.cpp | 5 ++-- indra/lscript/lscript_compile/lscript_tree.cpp | 17 ++++-------- 4 files changed, 38 insertions(+), 34 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 83dfa94f00..ce815cc85b 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -520,7 +520,7 @@ protected: * seek orfor string assignment. * @returns Returns true if a line was found. */ - bool readLine( + bool readHeaderLine( const LLChannelDescriptors& channels, buffer_ptr_t buffer, U8* dest, @@ -591,7 +591,7 @@ LLHTTPResponder::~LLHTTPResponder() //lldebugs << "destroying LLHTTPResponder" << llendl; } -bool LLHTTPResponder::readLine( +bool LLHTTPResponder::readHeaderLine( const LLChannelDescriptors& channels, buffer_ptr_t buffer, U8* dest, @@ -669,7 +669,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( #endif PUMP_DEBUG; - if(readLine(channels, buffer, (U8*)buf, len)) + if(readHeaderLine(channels, buffer, (U8*)buf, len)) { bool read_next_line = false; bool parse_all = true; @@ -733,7 +733,13 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( if(read_next_line) { len = HEADER_BUFFER_SIZE; - readLine(channels, buffer, (U8*)buf, len); + if (!readHeaderLine(channels, buffer, (U8*)buf, len)) + { + // Failed to read the header line, probably too long. + // readHeaderLine already marked the channel/buffer as bad. + keep_parsing = false; + break; + } } if(0 == len) { diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp index 08c9192c9f..209bdb2249 100644 --- a/indra/llmessage/llxfermanager.cpp +++ b/indra/llmessage/llxfermanager.cpp @@ -760,30 +760,36 @@ static bool remove_prefix(std::string& filename, const std::string& prefix) static bool verify_cache_filename(const std::string& filename) { //NOTE: This routine is only used to check file names that our own - // code places in the cache directory. As such, it can be limited - // to this very restrictive file name pattern. It does not need to - // handle other characters. - + // code places in the cache directory. As such, it can be limited + // to this very restrictive file name pattern. It does not need to + // handle other characters. The only known uses of this are (with examples): + // sim to sim object pass: fc0b72d8-9456-63d9-a802-a557ef847313.tmp + // sim to viewer mute list: mute_b78eacd0-1244-448e-93ca-28ede242f647.tmp + // sim to viewer task inventory: inventory_d8ab59d2-baf0-0e79-c4c2-a3f99b9fcf45.tmp + + //IMPORTANT: Do not broaden the filenames accepted by this routine + // without careful analysis. Anything allowed by this function can + // be downloaded by the viewer. + size_t len = filename.size(); - //const boost::regex expr("[a-zA-Z0-9][-_.a-zA-Z0-9]<0,49>"); - if (len < 1 || len > 50) - { + //const boost::regex expr("[0-9a-zA-Z_-]<1,46>\.tmp"); + if (len < 5 || len > 50) + { return false; } - for(unsigned i=0; i 0) - { - ok = '_'==c || '-'==c || '.'==c; - } + bool ok = isalnum(c) || '_'==c || '-'==c; if (!ok) { return false; } } - return true; + return filename[len-4] == '.' + && filename[len-3] == 't' + && filename[len-2] == 'm' + && filename[len-1] == 'p'; } void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/) diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index c1dde32993..b02d4c50bd 100644 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -134,13 +134,12 @@ S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te) { if (S32(index) >= mEntryList.size()) { - // TODO -- assert here S32 current_size = mEntryList.size(); - llerrs << "index = " << S32(index) << " current_size = " << current_size << llendl; + llwarns << "ignore copy of index = " << S32(index) << " into texture entry list of size = " << current_size << llendl; return TEM_CHANGE_NONE; } - // we're changing an existing entry + // we're changing an existing entry llassert(mEntryList[index]); delete (mEntryList[index]); if (&te) diff --git a/indra/lscript/lscript_compile/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp index a15f1fee11..7fa115bb20 100644 --- a/indra/lscript/lscript_compile/lscript_tree.cpp +++ b/indra/lscript/lscript_compile/lscript_tree.cpp @@ -8799,8 +8799,7 @@ void LLScriptIf::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass p } break; case LSCP_PRUNE: - prunearg = TRUE; - mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + prunearg = FALSE; break; case LSCP_TYPE: mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -8986,8 +8985,7 @@ void LLScriptFor::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePass } break; case LSCP_PRUNE: - prunearg = TRUE; - mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + prunearg = FALSE; break; case LSCP_TYPE: if(mSequence) @@ -9091,8 +9089,7 @@ void LLScriptDoWhile::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompileP } break; case LSCP_PRUNE: - prunearg = TRUE; - mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + prunearg = FALSE; break; case LSCP_TYPE: mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -9168,8 +9165,7 @@ void LLScriptWhile::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPTCompilePas } break; case LSCP_PRUNE: - prunearg = TRUE; - mStatement->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); + prunearg = FALSE; break; case LSCP_TYPE: mExpression->recurse(fp, tabs, tabsize, pass, ptype, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); @@ -10137,10 +10133,7 @@ void LLScriptGlobalFunctions::recurse(LLFILE *fp, S32 tabs, S32 tabsize, LSCRIPT mStatements->recurse(fp, tabs, tabsize, pass, LSPRUNE_GLOBAL_NON_VOIDS, prunearg, scope, type, basetype, count, chunk, heap, stacksize, entry, entrycount, NULL); if (!prunearg) { - if (!gErrorToText.getErrors()) // Hide this error when a state change has been made in a global function - { - gErrorToText.writeError(fp, this, LSERROR_NO_RETURN); - } + gErrorToText.writeError(fp, this, LSERROR_NO_RETURN); } } else -- cgit v1.3 From c15b6d7d40ac03957b417cbe0e67d9c1bfa7703f Mon Sep 17 00:00:00 2001 From: Christian Goetze Date: Thu, 16 Jul 2009 20:00:21 +0000 Subject: Make googlemock publicly available --- indra/llmessage/tests/llmockhttpclient.h | 2 +- install.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/tests/llmockhttpclient.h b/indra/llmessage/tests/llmockhttpclient.h index 0de8246446..2f55e97fcc 100644 --- a/indra/llmessage/tests/llmockhttpclient.h +++ b/indra/llmessage/tests/llmockhttpclient.h @@ -2,7 +2,7 @@ * @file * @brief * - * $LicenseInfo:firstyear=2008&license=internal$ + * $LicenseInfo:firstyear=2008&license=viewergpl$ * * Copyright (c) 2008, Linden Research, Inc. * diff --git a/install.xml b/install.xml index 464df8f710..b980028447 100644 --- a/install.xml +++ b/install.xml @@ -556,21 +556,21 @@ md5sum 4863e9fea433d0a4be761ea5d3e8346a url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/googlemock-1.1.0-darwin-20090626.tar.bz2 + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-darwin-20090626.tar.bz2 linux md5sum 877dabecf84339690191c6115c76366e url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/googlemock-1.1.0-linux32-20090527.tar.bz2 + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-linux32-20090527.tar.bz2 windows md5sum be37695d9f26552aec81c8e97ded0212 url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/googlemock-1.1.0-windows-20090529.tar.bz2 + http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/googlemock-1.1.0-windows-20090529.tar.bz2 -- cgit v1.3 From 17b9cda4325a035f00e077a6a8e33a8c4f2d5a89 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Fri, 24 Jul 2009 00:46:26 +0000 Subject: For QAR-1710 : Server merge for QAR-1594 QAR-1643 QAR-1644 - "AVP Changes [SIM]" svn merge -r 128022:128028 svn+ssh://svn.lindenlab.com/svn/linden/branches/avatar-pipeline/server__merge__trunk-r127980 to svn+ssh://svn.lindenlab.com/svn/linden/trunk This is the server-side merge for inventory links, folder links&types, and landmark&callingcard permissions. --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/llassettype.cpp | 340 ++++++++++++++++-------------- indra/llcommon/llassettype.h | 170 ++++++++------- indra/llcommon/lldictionary.h | 106 ++++++++++ indra/llcommon/stdenums.h | 3 +- indra/llinventory/llinventory.cpp | 54 ++++- indra/llinventory/llinventory.h | 26 ++- indra/llinventory/llinventorytype.cpp | 241 ++++++++++----------- indra/llinventory/llinventorytype.h | 10 +- indra/llinventory/llparcel.h | 4 +- indra/llinventory/llpermissions.cpp | 11 + indra/llinventory/llpermissions.h | 3 + indra/llmessage/lltransfersourceasset.cpp | 48 +++-- indra/llmessage/message_prehash.cpp | 1 + indra/llmessage/message_prehash.h | 1 + indra/newview/llinventorybridge.cpp | 9 +- indra/newview/llviewerinventory.cpp | 4 +- scripts/messages/message_template.msg | 18 ++ 18 files changed, 653 insertions(+), 397 deletions(-) create mode 100644 indra/llcommon/lldictionary.h (limited to 'indra/llmessage') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index beac8df636..7bfcd43684 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -99,6 +99,7 @@ set(llcommon_HEADER_FILES lldefs.h lldependencies.h lldepthstack.h + lldictionary.h lldlinked.h lldqueueptr.h llendianswizzle.h diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index cf3bf89b4f..b852e4c00f 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -33,145 +33,125 @@ #include "linden_common.h" #include "llassettype.h" +#include "lldictionary.h" +#include "llmemory.h" -#include "llstring.h" -#include "lltimer.h" +///---------------------------------------------------------------------------- +/// Class LLAssetType +///---------------------------------------------------------------------------- +struct AssetEntry : public LLDictionaryEntry +{ + AssetEntry(const char *desc_name, + const char *type_name, // 8 character limit! + const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one + const char *category_name, // used by llinventorymodel when creating new categories + EDragAndDropType dad_type, + bool can_link, // can you create a link to this type? + bool is_protected) // can the viewer change categories of this type? + : + LLDictionaryEntry(desc_name), + mTypeName(type_name), + mHumanName(human_name), + mCategoryName(category_name), + mDadType(dad_type), + mCanLink(can_link), + mIsProtected(is_protected) + { + llassert(strlen(mTypeName) <= 8); + } -// I added lookups for exact text of asset type enums in addition to the ones below, so shoot me. -Steve + const char *mTypeName; + const char *mHumanName; + const char *mCategoryName; + EDragAndDropType mDadType; + bool mCanLink; + bool mIsProtected; +}; -struct asset_info_t +class LLAssetDictionary : public LLSingleton, + public LLDictionary { - LLAssetType::EType type; - const char* desc; +public: + LLAssetDictionary(); }; -asset_info_t asset_types[] = +LLAssetDictionary::LLAssetDictionary() { - { LLAssetType::AT_TEXTURE, "TEXTURE" }, - { LLAssetType::AT_SOUND, "SOUND" }, - { LLAssetType::AT_CALLINGCARD, "CALLINGCARD" }, - { LLAssetType::AT_LANDMARK, "LANDMARK" }, - { LLAssetType::AT_SCRIPT, "SCRIPT" }, - { LLAssetType::AT_CLOTHING, "CLOTHING" }, - { LLAssetType::AT_OBJECT, "OBJECT" }, - { LLAssetType::AT_NOTECARD, "NOTECARD" }, - { LLAssetType::AT_CATEGORY, "CATEGORY" }, - { LLAssetType::AT_ROOT_CATEGORY, "ROOT_CATEGORY" }, - { LLAssetType::AT_LSL_TEXT, "LSL_TEXT" }, - { LLAssetType::AT_LSL_BYTECODE, "LSL_BYTECODE" }, - { LLAssetType::AT_TEXTURE_TGA, "TEXTURE_TGA" }, - { LLAssetType::AT_BODYPART, "BODYPART" }, - { LLAssetType::AT_TRASH, "TRASH" }, - { LLAssetType::AT_SNAPSHOT_CATEGORY, "SNAPSHOT_CATEGORY" }, - { LLAssetType::AT_LOST_AND_FOUND, "LOST_AND_FOUND" }, - { LLAssetType::AT_SOUND_WAV, "SOUND_WAV" }, - { LLAssetType::AT_IMAGE_TGA, "IMAGE_TGA" }, - { LLAssetType::AT_IMAGE_JPEG, "IMAGE_JPEG" }, - { LLAssetType::AT_ANIMATION, "ANIMATION" }, - { LLAssetType::AT_GESTURE, "GESTURE" }, - { LLAssetType::AT_SIMSTATE, "SIMSTATE" }, - { LLAssetType::AT_NONE, "NONE" }, + // DESCRIPTION TYPE NAME HUMAN NAME CATEGORY NAME DRAG&DROP CAN LINK? PROTECTED? + // |--------------------|-----------|-------------------|-------------------|---------------|-----------|-----------| + addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, FALSE, TRUE)); + addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, FALSE, TRUE)); + addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, FALSE, TRUE)); + addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, FALSE, TRUE)); + addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, FALSE, TRUE)); + addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING, TRUE, TRUE)); + addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT, TRUE, TRUE)); + addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, FALSE, TRUE)); + addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY, TRUE, TRUE)); + addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY, TRUE, TRUE)); + addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, FALSE, TRUE)); + addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, FALSE, TRUE)); + addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, FALSE, TRUE)); + addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART, TRUE, TRUE)); + addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE, FALSE, TRUE)); + addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE, FALSE, TRUE)); + addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE, FALSE, TRUE)); + addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, FALSE, TRUE)); + addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, FALSE, TRUE)); + addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, FALSE, TRUE)); + addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, FALSE, TRUE)); + addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, FALSE, TRUE)); + addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE, FALSE, TRUE)); + addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE, FALSE, TRUE)); + + addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", "Link", DAD_LINK, FALSE, TRUE)); + addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", "New Folder", DAD_LINK, FALSE, TRUE)); + + for (S32 ensemble_num = S32(LLAssetType::AT_FOLDER_ENSEMBLE_START); + ensemble_num <= S32(LLAssetType::AT_FOLDER_ENSEMBLE_END); + ensemble_num++) + { + addEntry(LLAssetType::EType(ensemble_num), new AssetEntry("ENSEMBLE", "ensemble", "ensemble", "New Folder", DAD_CATEGORY, TRUE, FALSE)); + } + + addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("CURRENT", "current", "current outfit", "Current Outfit", DAD_CATEGORY, FALSE, TRUE)); + addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", "Outfit", DAD_CATEGORY, TRUE, FALSE)); + addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", "My Outfits", DAD_CATEGORY, FALSE, TRUE)); + + addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE, FALSE, FALSE)); }; -LLAssetType::EType LLAssetType::getType(const std::string& sin) +// static +LLAssetType::EType LLAssetType::getType(const std::string& desc_name) { - std::string s = sin; + std::string s = desc_name; LLStringUtil::toUpper(s); - for (S32 idx = 0; ;idx++) - { - asset_info_t* info = asset_types + idx; - if (info->type == LLAssetType::AT_NONE) - break; - if (s == info->desc) - return info->type; - } - return LLAssetType::AT_NONE; + return LLAssetDictionary::getInstance()->lookup(s); } -std::string LLAssetType::getDesc(LLAssetType::EType type) +// static +const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type) { - for (S32 idx = 0; ;idx++) + const AssetEntry *entry = LLAssetDictionary::getInstance()->lookup(asset_type); + if (entry) + { + return entry->mName; + } + else { - asset_info_t* info = asset_types + idx; - if (type == info->type) - return info->desc; - if (info->type == LLAssetType::AT_NONE) - break; + static const std::string error_string = "BAD TYPE"; + return error_string; } - return "BAD TYPE"; } -//============================================================================ - -// The asset type names are limited to 8 characters. -// static -const char* LLAssetType::mAssetTypeNames[LLAssetType::AT_COUNT] = -{ - "texture", - "sound", - "callcard", - "landmark", - "script", - "clothing", - "object", - "notecard", - "category", - "root", - "lsltext", - "lslbyte", - "txtr_tga",// Intentionally spelled this way. Limited to eight characters. - "bodypart", - "trash", - "snapshot", - "lstndfnd", - "snd_wav", - "img_tga", - "jpeg", - "animatn", - "gesture", - "simstate" -}; - -// This table is meant for decoding to human readable form. Put any -// and as many printable characters you want in each one. -// See also llinventory.cpp INVENTORY_TYPE_HUMAN_NAMES -const char* LLAssetType::mAssetTypeHumanNames[LLAssetType::AT_COUNT] = -{ - "texture", - "sound", - "calling card", - "landmark", - "legacy script", - "clothing", - "object", - "note card", - "folder", - "root", - "lsl2 script", - "lsl bytecode", - "tga texture", - "body part", - "trash", - "snapshot", - "lost and found", - "sound", - "targa image", - "jpeg image", - "animation", - "gesture", - "simstate" -}; - -///---------------------------------------------------------------------------- -/// class LLAssetType -///---------------------------------------------------------------------------- - // static -const char* LLAssetType::lookup( LLAssetType::EType type ) +const char *LLAssetType::lookup(LLAssetType::EType asset_type) { - if( (type >= 0) && (type < AT_COUNT )) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - return mAssetTypeNames[ S32( type ) ]; + return entry->mTypeName; } else { @@ -180,30 +160,35 @@ const char* LLAssetType::lookup( LLAssetType::EType type ) } // static -LLAssetType::EType LLAssetType::lookup( const char* name ) +LLAssetType::EType LLAssetType::lookup(const char* name) { return lookup(ll_safe_string(name)); } -LLAssetType::EType LLAssetType::lookup( const std::string& name ) +LLAssetType::EType LLAssetType::lookup(const std::string& type_name) { - for( S32 i = 0; i < AT_COUNT; i++ ) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + for (LLAssetDictionary::const_iterator iter = dict->begin(); + iter != dict->end(); + iter++) { - if( name == mAssetTypeNames[i] ) + const AssetEntry *entry = iter->second; + if (type_name == entry->mTypeName) { - // match - return (EType)i; + return iter->first; } } return AT_NONE; } // static -const char* LLAssetType::lookupHumanReadable(LLAssetType::EType type) +const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type) { - if( (type >= 0) && (type < AT_COUNT )) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - return mAssetTypeHumanNames[S32(type)]; + return entry->mHumanName; } else { @@ -212,49 +197,94 @@ const char* LLAssetType::lookupHumanReadable(LLAssetType::EType type) } // static -LLAssetType::EType LLAssetType::lookupHumanReadable( const char* name ) +LLAssetType::EType LLAssetType::lookupHumanReadable(const char* name) { return lookupHumanReadable(ll_safe_string(name)); } -LLAssetType::EType LLAssetType::lookupHumanReadable( const std::string& name ) +LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_name) { - for( S32 i = 0; i < AT_COUNT; i++ ) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + for (LLAssetDictionary::const_iterator iter = dict->begin(); + iter != dict->end(); + iter++) { - if( name == mAssetTypeHumanNames[i] ) + const AssetEntry *entry = iter->second; + if (readable_name == entry->mHumanName) { - // match - return (EType)i; + return iter->first; } } return AT_NONE; } -EDragAndDropType LLAssetType::lookupDragAndDropType( EType asset ) +// static +const char *LLAssetType::lookupCategoryName(LLAssetType::EType asset_type) +{ + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) + { + return entry->mCategoryName; + } + else + { + return "New Folder"; + } +} + +// static +EDragAndDropType LLAssetType::lookupDragAndDropType(EType asset_type) +{ + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) + return entry->mDadType; + else + return DAD_NONE; +} + +// static +bool LLAssetType::lookupCanLink(EType asset_type) +{ + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) + { + return entry->mCanLink; + } + return false; +} + +// static +// Not adding this to dictionary since we probably will only have these two types +bool LLAssetType::lookupIsLinkType(EType asset_type) +{ + if (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER) + { + return true; + } + return false; +} + +// static +// Only ensembles and plain folders aren't protected. "Protected" means +// you can't change certain properties such as their type. +bool LLAssetType::lookupIsProtectedCategoryType(EType asset_type) { - switch( asset ) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - case AT_TEXTURE: return DAD_TEXTURE; - case AT_SOUND: return DAD_SOUND; - case AT_CALLINGCARD: return DAD_CALLINGCARD; - case AT_LANDMARK: return DAD_LANDMARK; - case AT_SCRIPT: return DAD_NONE; - case AT_CLOTHING: return DAD_CLOTHING; - case AT_OBJECT: return DAD_OBJECT; - case AT_NOTECARD: return DAD_NOTECARD; - case AT_CATEGORY: return DAD_CATEGORY; - case AT_ROOT_CATEGORY: return DAD_ROOT_CATEGORY; - case AT_LSL_TEXT: return DAD_SCRIPT; - case AT_BODYPART: return DAD_BODYPART; - case AT_ANIMATION: return DAD_ANIMATION; - case AT_GESTURE: return DAD_GESTURE; - default: return DAD_NONE; - }; + return entry->mIsProtected; + } + return true; } + // static. Generate a good default description -void LLAssetType::generateDescriptionFor(LLAssetType::EType type, - std::string& desc) +void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type, + std::string& description) { const S32 BUF_SIZE = 30; char time_str[BUF_SIZE]; /* Flawfinder: ignore */ @@ -262,6 +292,6 @@ void LLAssetType::generateDescriptionFor(LLAssetType::EType type, time(&now); memset(time_str, '\0', BUF_SIZE); strftime(time_str, BUF_SIZE - 1, "%Y-%m-%d %H:%M:%S ", localtime(&now)); - desc.assign(time_str); - desc.append(LLAssetType::lookupHumanReadable(type)); + description.assign(time_str); + description.append(LLAssetType::lookupHumanReadable(asset_type)); } diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 4077b8d2c1..5c30c8354f 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -30,8 +30,8 @@ * $/LicenseInfo$ */ -#ifndef LL_LLASSETTYPE -#define LL_LLASSETTYPE +#ifndef LL_LLASSETTYPE_H +#define LL_LLASSETTYPE_H #include @@ -42,137 +42,163 @@ class LLAssetType public: enum EType { - // Used for painting the faces of geometry. - // Stored in typical j2c stream format AT_TEXTURE = 0, + // Used for painting the faces of geometry. + // Stored in typical j2c stream format. - // Used to fill the aural spectrum. AT_SOUND = 1, + // Used to fill the aural spectrum. - // Links instant message access to the user on the card. eg, a - // card for yourself, a card for linden support, a card for - // the guy you were talking to in the coliseum. AT_CALLINGCARD = 2, + // Links instant message access to the user on the card. + // : E.G. A card for yourself, for linden support, for + // : the guy you were talking to in the coliseum. - // Links to places in the world with location and a screen - // shot or image saved. eg, home, linden headquarters, the - // coliseum, or destinations where we want to increase - // traffic. AT_LANDMARK = 3, + // Links to places in the world with location and a screen shot or image saved. + // : E.G. Home, linden headquarters, the coliseum, destinations where + // : we want to increase traffic. - // Valid scripts that can be attached to an object. eg. open a - // door, jump into the air. AT_SCRIPT = 4, + // Valid scripts that can be attached to an object. + // : E.G. Open a door, jump into the air. - // A collection of textures and parameters that can be worn - // by an avatar. AT_CLOTHING = 5, + // A collection of textures and parameters that can be worn by an avatar. - // Any combination of textures, sounds, and scripts that are - // associated with a fixed piece of geometry. eg, a hot tub, a - // house with working door. AT_OBJECT = 6, + // Any combination of textures, sounds, and scripts that are + // associated with a fixed piece of geometry. + // : E.G. A hot tub, a house with working door. - // Just text AT_NOTECARD = 7, + // Just text. - // A category holds a collection of inventory items. It's - // treated as an item in the inventory, and therefore needs a - // type. AT_CATEGORY = 8, + // Holds a collection of inventory items. + // It's treated as an item in the inventory and therefore needs a type. - // A root category is a user's root inventory category. We - // decided to expose it visually, so it seems logical to fold - // it into the asset types. AT_ROOT_CATEGORY = 9, + // A user's root inventory category. + // We decided to expose it visually, so it seems logical to fold + // it into the asset types. - // The LSL is the brand spanking new scripting language. We've - // split it into a text and bytecode representation. AT_LSL_TEXT = 10, AT_LSL_BYTECODE = 11, + // The LSL is the scripting language. + // We've split it into a text and bytecode representation. - // uncompressed TGA texture AT_TEXTURE_TGA = 12, + // Uncompressed TGA texture. - // A collection of textures and parameters that can be worn - // by an avatar. AT_BODYPART = 13, + // A collection of textures and parameters that can be worn by an avatar. - // This asset type is meant to only be used as a marker for a - // category preferred type. Using this, we can throw things in - // the trash before completely deleting. AT_TRASH = 14, + // Only to be used as a marker for a category preferred type. + // Using this, we can throw things in the trash before completely deleting. - // This is a marker for a folder meant for snapshots. No - // actual assets will be snapshots, though if there were, you - // could interpret them as textures. AT_SNAPSHOT_CATEGORY = 15, + // A marker for a folder meant for snapshots. + // No actual assets will be snapshots, though if there were, you + // could interpret them as textures. - // This is used to stuff lost&found items into AT_LOST_AND_FOUND = 16, + // Used to stuff lost&found items into. - // uncompressed sound AT_SOUND_WAV = 17, + // Uncompressed sound. - // uncompressed image, non-square, and not appropriate for use - // as a texture. AT_IMAGE_TGA = 18, + // Uncompressed image, non-square. + // Not appropriate for use as a texture. - // compressed image, non-square, and not appropriate for use - // as a texture. AT_IMAGE_JPEG = 19, + // Compressed image, non-square. + // Not appropriate for use as a texture. - // animation AT_ANIMATION = 20, + // Animation. - // gesture, sequence of animations, sounds, chat, wait steps AT_GESTURE = 21, + // Gesture, sequence of animations, sounds, chat, wait steps. - // simstate file AT_SIMSTATE = 22, + // Simstate file. - // +*********************************************+ - // | TO ADD AN ELEMENT TO THIS ENUM: | - // +*********************************************+ - // | 1. INSERT BEFORE AT_COUNT | - // | 2. INCREMENT AT_COUNT BY 1 | - // | 3. ADD TO LLAssetType::mAssetTypeNames | - // | 4. ADD TO LLAssetType::mAssetTypeHumanNames | - // +*********************************************+ + AT_FAVORITE = 23, + // favorite items - AT_COUNT = 23, + AT_LINK = 24, + // Inventory symbolic link + + AT_LINK_FOLDER = 25, + // Inventory folder link + + AT_FOLDER_ENSEMBLE_START = 26, + AT_FOLDER_ENSEMBLE_END = 45, + // This range is reserved for special clothing folder types. + + AT_CURRENT_OUTFIT = 46, + // Current outfit + + AT_OUTFIT = 47, + // Predefined outfit ("look") + + AT_MY_OUTFITS = 48, + // Folder that holds your outfits. + + + AT_COUNT = 49, + + // +*********************************************************+ + // | TO ADD AN ELEMENT TO THIS ENUM: | + // +*********************************************************+ + // | 1. INSERT BEFORE AT_COUNT | + // | 2. INCREMENT AT_COUNT BY 1 | + // | 3. ADD TO LLAssetDictionary in LLAssetType.cpp | + // | 3. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp | + // +*********************************************************+ AT_NONE = -1 }; // machine transation between type and strings - static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate - static EType lookup(const std::string& name); - static const char* lookup(EType type); + static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate + static EType lookup(const std::string& type_name); + static const char* lookup(EType asset_type); // translation from a type to a human readable form. - static EType lookupHumanReadable( const char* name ); // safe conversion to std::string, *TODO: deprecate - static EType lookupHumanReadable( const std::string& name ); - static const char* lookupHumanReadable(EType type); - - static EDragAndDropType lookupDragAndDropType( EType ); + static EType lookupHumanReadable(const char* desc_name); // safe conversion to std::string, *TODO: deprecate + static EType lookupHumanReadable(const std::string& readable_name); + static const char* lookupHumanReadable(EType asset_type); // Generate a good default description. You may want to add a verb // or agent name after this depending on your application. - static void generateDescriptionFor(LLAssetType::EType type, - std::string& desc); + static void generateDescriptionFor(LLAssetType::EType asset_type, + std::string& description); + + static EType getType(const std::string& desc_name); + static const std::string& getDesc(EType asset_type); + static EDragAndDropType lookupDragAndDropType(EType asset_type); + + static bool lookupCanLink(EType asset_type); + static bool lookupIsLinkType(EType asset_type); - static EType getType(const std::string& sin); - static std::string getDesc(EType type); + static const char* lookupCategoryName(EType asset_type); + static bool lookupIsProtectedCategoryType(EType asset_type); + + /* TODO: Change return types from "const char *" to "const std::string &". + This is fairly straightforward, but requires changing some calls to use .c_str(). + e.g.: + - fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); + + fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType).c_str()); + */ private: // don't instantiate or derive one of these objects LLAssetType( void ) {} ~LLAssetType( void ) {} - -private: - static const char* mAssetTypeNames[]; - static const char* mAssetTypeHumanNames[]; }; -#endif // LL_LLASSETTYPE +#endif // LL_LLASSETTYPE_H diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h new file mode 100644 index 0000000000..436b689ca6 --- /dev/null +++ b/indra/llcommon/lldictionary.h @@ -0,0 +1,106 @@ +/** + * @file lldictionary.h + * @brief Lldictionary class header file + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLDICTIONARY_H +#define LL_LLDICTIONARY_H + +#include + +struct LLDictionaryEntry +{ + LLDictionaryEntry(const std::string &name) : + mName(name) + { + mNameCapitalized = mName; + LLStringUtil::replaceChar(mNameCapitalized, '-', ' '); + LLStringUtil::replaceChar(mNameCapitalized, '_', ' '); + for (U32 i=0; i < mNameCapitalized.size(); i++) + { + if (i == 0 || mNameCapitalized[i-1] == ' ') // don't change ordering of this statement or crash + { + mNameCapitalized[i] = toupper(mNameCapitalized[i]); + } + } + } + virtual ~LLDictionaryEntry() {} + const std::string mName; + std::string mNameCapitalized; +}; + +template +class LLDictionary : public std::map +{ +public: + typedef std::map map_t; + typedef typename map_t::iterator iterator_t; + typedef typename map_t::const_iterator const_iterator_t; + + LLDictionary() {} + virtual ~LLDictionary() + { + for (iterator_t iter = map_t::begin(); iter != map_t::end(); ++iter) + delete (iter->second); + } + + const Entry *lookup(Index index) const + { + const_iterator_t dictionary_iter = map_t::find(index); + if (dictionary_iter == map_t::end()) return NULL; + return dictionary_iter->second; + } + const Index lookup(const std::string &name) const + { + for (const_iterator_t dictionary_iter = map_t::begin(); + dictionary_iter != map_t::end(); + dictionary_iter++) + { + const Entry *entry = dictionary_iter->second; + if (entry->mName == name) + { + return dictionary_iter->first; + } + } + llassert(false); + return Index(-1); + } + +protected: + void addEntry(Index index, Entry *entry) + { + if (lookup(index)) + { + llerrs << "Dictionary entry already added (attempted to add duplicate entry)" << llendl; + } + (*this)[index] = entry; + } +}; + +#endif // LL_LLDICTIONARY_H diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h index 41da51fce3..1a5678dde1 100644 --- a/indra/llcommon/stdenums.h +++ b/indra/llcommon/stdenums.h @@ -54,7 +54,8 @@ enum EDragAndDropType DAD_BODYPART = 11, DAD_ANIMATION = 12, DAD_GESTURE = 13, - DAD_COUNT = 14, // number of types in this enum + DAD_LINK = 14, + DAD_COUNT = 15, // number of types in this enum }; // Reasons for drags to be denied. diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 2823cf7be9..e45bb59881 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -126,6 +126,20 @@ const std::string& LLInventoryObject::getName() const return mName; } +// To bypass linked items, since llviewerinventory's getType +// will return the linked-to item's type instead of this object's type. +LLAssetType::EType LLInventoryObject::getActualType() const +{ + return mType; +} + +// See LLInventoryItem override. +// virtual +const LLUUID& LLInventoryObject::getLinkedUUID() const +{ + return mUUID; +} + LLAssetType::EType LLInventoryObject::getType() const { return mType; @@ -296,6 +310,7 @@ LLInventoryItem::LLInventoryItem( { LLStringUtil::replaceNonstandardASCII(mDescription, ' '); LLStringUtil::replaceChar(mDescription, '|', ' '); + mPermissions.initMasks(inv_type); } LLInventoryItem::LLInventoryItem() : @@ -333,6 +348,19 @@ void LLInventoryItem::copyItem(const LLInventoryItem* other) mCreationDate = other->mCreationDate; } +// If this is a linked item, then the UUID of the base object is +// this item's assetID. +// virtual +const LLUUID& LLInventoryItem::getLinkedUUID() const +{ + if (LLAssetType::lookupIsLinkType(getActualType())) + { + return mAssetUUID; + } + + return LLInventoryObject::getLinkedUUID(); +} + const LLPermissions& LLInventoryItem::getPermissions() const { return mPermissions; @@ -405,6 +433,9 @@ void LLInventoryItem::setDescription(const std::string& d) void LLInventoryItem::setPermissions(const LLPermissions& perm) { mPermissions = perm; + + // Override permissions to unrestricted if this is a landmark + mPermissions.initMasks(mInventoryType); } void LLInventoryItem::setInventoryType(LLInventoryType::EType inv_type) @@ -476,6 +507,7 @@ BOOL LLInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 mType = static_cast(type); msg->getS8(block, "InvType", type, block_num); mInventoryType = static_cast(type); + mPermissions.initMasks(mInventoryType); msg->getU32Fast(block, _PREHASH_Flags, mFlags, block_num); @@ -666,6 +698,9 @@ BOOL LLInventoryItem::importFile(LLFILE* fp) lldebugs << "Resetting inventory type for " << mUUID << llendl; mInventoryType = LLInventoryType::defaultForAssetType(mType); } + + mPermissions.initMasks(mInventoryType); + return success; } @@ -705,8 +740,8 @@ BOOL LLInventoryItem::exportFile(LLFILE* fp, BOOL include_asset_key) const fprintf(fp, "\t\tasset_id\t%s\n", uuid_str.c_str()); } fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - const char* inv_type_str = LLInventoryType::lookup(mInventoryType); - if(inv_type_str) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str); + const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); + if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str()); fprintf(fp, "\t\tflags\t%08x\n", mFlags); mSaleInfo.exportFile(fp); fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); @@ -869,6 +904,9 @@ BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream) lldebugs << "Resetting inventory type for " << mUUID << llendl; mInventoryType = LLInventoryType::defaultForAssetType(mType); } + + mPermissions.initMasks(mInventoryType); + return success; } @@ -908,8 +946,8 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu output_stream << "\t\tasset_id\t" << uuid_str << "\n"; } output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n"; - const char* inv_type_str = LLInventoryType::lookup(mInventoryType); - if(inv_type_str) + const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); + if(!inv_type_str.empty()) output_stream << "\t\tinv_type\t" << inv_type_str << "\n"; std::string buffer; buffer = llformat( "\t\tflags\t%08x\n", mFlags); @@ -951,8 +989,8 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const } sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType); sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType; - const char* inv_type_str = LLInventoryType::lookup(mInventoryType); - if(inv_type_str) + const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); + if(!inv_type_str.empty()) { sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str; } @@ -1091,6 +1129,8 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd) mInventoryType = LLInventoryType::defaultForAssetType(mType); } + mPermissions.initMasks(mInventoryType); + return true; fail: return false; @@ -1698,7 +1738,7 @@ LLSD ll_create_sd_from_inventory_category(LLPointer cat) rv[INV_PARENT_ID_LABEL] = cat->getParentUUID(); rv[INV_NAME_LABEL] = cat->getName(); rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(cat->getType()); - if(LLAssetType::AT_NONE != cat->getPreferredType()) + if(LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())) { rv[INV_PREFERRED_TYPE_LABEL] = LLAssetType::lookup(cat->getPreferredType()); diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index d34046c310..094aebe93b 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -91,8 +91,11 @@ public: // accessors virtual const LLUUID& getUUID() const; const LLUUID& getParentUUID() const; - const std::string& getName() const; - LLAssetType::EType getType() const; + virtual const LLUUID& getLinkedUUID() const; // get the inventoryID that this item points to, else this item's inventoryID + + virtual const std::string& getName() const; + virtual LLAssetType::EType getType() const; + LLAssetType::EType getActualType() const; // bypasses indirection for linked items // mutators - will not call updateServer(); void setUUID(const LLUUID& new_uuid); @@ -238,15 +241,16 @@ public: void generateUUID() { mUUID.generate(); } // accessors - const LLPermissions& getPermissions() const; - const LLUUID& getCreatorUUID() const; - const LLUUID& getAssetUUID() const; - const std::string& getDescription() const; - const LLSaleInfo& getSaleInfo() const; - LLInventoryType::EType getInventoryType() const; - U32 getFlags() const; - time_t getCreationDate() const; - U32 getCRC32() const; // really more of a checksum. + virtual const LLUUID& getLinkedUUID() const; + virtual const LLPermissions& getPermissions() const; + virtual const LLUUID& getCreatorUUID() const; + virtual const LLUUID& getAssetUUID() const; + virtual const std::string& getDescription() const; + virtual const LLSaleInfo& getSaleInfo() const; + virtual LLInventoryType::EType getInventoryType() const; + virtual U32 getFlags() const; + virtual time_t getCreationDate() const; + virtual U32 getCRC32() const; // really more of a checksum. // mutators - will not call updateServer(), and will never fail // (though it may correct to sane values) diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index a161a0ee00..866d6722a0 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -33,66 +33,72 @@ #include "linden_common.h" #include "llinventorytype.h" +#include "lldictionary.h" +#include "llmemory.h" + +static const std::string empty_string; ///---------------------------------------------------------------------------- /// Class LLInventoryType ///---------------------------------------------------------------------------- - -// Unlike asset type names, not limited to 8 characters. -// Need not match asset type names. -static const char* INVENTORY_TYPE_NAMES[LLInventoryType::IT_COUNT] = -{ - "texture", // 0 - "sound", - "callcard", - "landmark", - NULL, - NULL, // 5 - "object", - "notecard", - "category", - "root", - "script", // 10 - NULL, - NULL, - NULL, - NULL, - "snapshot", // 15 - NULL, - "attach", - "wearable", - "animation", - "gesture", // 20 +struct InventoryEntry : public LLDictionaryEntry +{ + InventoryEntry(const std::string &name, // unlike asset type names, not limited to 8 characters; need not match asset type names + const std::string &human_name, // for decoding to human readable form; put any and as many printable characters you want in each one. + int num_asset_types = 0, ...) + : + LLDictionaryEntry(name), + mHumanName(human_name) + { + va_list argp; + va_start(argp, num_asset_types); + // Read in local textures + for (U8 i=0; i < num_asset_types; i++) + { + LLAssetType::EType t = (LLAssetType::EType)va_arg(argp,int); + mAssetTypes.push_back(t); + } + } + + const std::string mHumanName; + typedef std::vector asset_vec_t; + asset_vec_t mAssetTypes; }; -// This table is meant for decoding to human readable form. Put any -// and as many printable characters you want in each one. -// See also LLAssetType::mAssetTypeHumanNames -static const char* INVENTORY_TYPE_HUMAN_NAMES[LLInventoryType::IT_COUNT] = -{ - "texture", // 0 - "sound", - "calling card", - "landmark", - NULL, - NULL, // 5 - "object", - "note card", - "folder", - "root", - "script", // 10 - NULL, - NULL, - NULL, - NULL, - "snapshot", // 15 - NULL, - "attachment", - "wearable", - "animation", - "gesture", // 20 +class LLInventoryDictionary : public LLSingleton, + public LLDictionary +{ +public: + LLInventoryDictionary(); }; +LLInventoryDictionary::LLInventoryDictionary() +{ + addEntry(LLInventoryType::IT_TEXTURE, new InventoryEntry("texture", "texture", 1, LLAssetType::AT_TEXTURE)); + addEntry(LLInventoryType::IT_SOUND, new InventoryEntry("sound", "sound", 1, LLAssetType::AT_SOUND)); + addEntry(LLInventoryType::IT_CALLINGCARD, new InventoryEntry("callcard", "calling card", 1, LLAssetType::AT_CALLINGCARD)); + addEntry(LLInventoryType::IT_LANDMARK, new InventoryEntry("landmark", "landmark", 1, LLAssetType::AT_LANDMARK)); + //addEntry(LLInventoryType::IT_SCRIPT, new InventoryEntry(NULL,NULL)); + //addEntry(LLInventoryType::IT_CLOTHING, new InventoryEntry(NULL,NULL)); + addEntry(LLInventoryType::IT_OBJECT, new InventoryEntry("object", "object", 1, LLAssetType::AT_OBJECT)); + addEntry(LLInventoryType::IT_NOTECARD, new InventoryEntry("notecard", "note card", 1, LLAssetType::AT_NOTECARD)); + addEntry(LLInventoryType::IT_CATEGORY, new InventoryEntry("category", "folder" )); + addEntry(LLInventoryType::IT_ROOT_CATEGORY, new InventoryEntry("root", "root" )); + addEntry(LLInventoryType::IT_LSL, new InventoryEntry("script", "script", 2, LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE)); + //addEntry(LLInventoryType::IT_LSL_BYTECODE, new InventoryEntry(NULL,NULL)); + //addEntry(LLInventoryType::IT_TEXTURE_TGA, new InventoryEntry(NULL,NULL)); + //addEntry(LLInventoryType::IT_BODYPART, new InventoryEntry(NULL,NULL)); + //addEntry(LLInventoryType::IT_TRASH, new InventoryEntry(NULL,NULL)); + addEntry(LLInventoryType::IT_SNAPSHOT, new InventoryEntry("snapshot", "snapshot", 1, LLAssetType::AT_TEXTURE)); + //addEntry(LLInventoryType::IT_LOST_AND_FOUND, new InventoryEntry(NULL,NULL, )); + addEntry(LLInventoryType::IT_ATTACHMENT, new InventoryEntry("attach", "attachment", 1, LLAssetType::AT_OBJECT)); + addEntry(LLInventoryType::IT_WEARABLE, new InventoryEntry("wearable", "wearable", 2, LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART)); + addEntry(LLInventoryType::IT_ANIMATION, new InventoryEntry("animation", "animation", 1, LLAssetType::AT_ANIMATION)); + addEntry(LLInventoryType::IT_GESTURE, new InventoryEntry("gesture", "gesture", 1, LLAssetType::AT_GESTURE)); + addEntry(LLInventoryType::IT_FAVORITE, new InventoryEntry("favorite", "favorite", 1, LLAssetType::AT_FAVORITE)); +} + + // Maps asset types to the default inventory type for that kind of asset. // Thus, "Lost and Found" is a "Category" static const LLInventoryType::EType @@ -120,76 +126,60 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = LLInventoryType::IT_NONE, // AT_IMAGE_JPEG LLInventoryType::IT_ANIMATION, // AT_ANIMATION LLInventoryType::IT_GESTURE, // AT_GESTURE -}; + LLInventoryType::IT_NONE, // AT_SIMSTATE + LLInventoryType::IT_FAVORITE, // AT_FAVORITE -static const int MAX_POSSIBLE_ASSET_TYPES = 2; -static const LLAssetType::EType -INVENTORY_TO_ASSET_TYPE[LLInventoryType::IT_COUNT][MAX_POSSIBLE_ASSET_TYPES] = -{ - { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_TEXTURE - { LLAssetType::AT_SOUND, LLAssetType::AT_NONE }, // IT_SOUND - { LLAssetType::AT_CALLINGCARD, LLAssetType::AT_NONE }, // IT_CALLINGCARD - { LLAssetType::AT_LANDMARK, LLAssetType::AT_NONE }, // IT_LANDMARK - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_OBJECT - { LLAssetType::AT_NOTECARD, LLAssetType::AT_NONE }, // IT_NOTECARD - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_CATEGORY - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_ROOT_CATEGORY - { LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE }, // IT_LSL - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_SNAPSHOT - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_ATTACHMENT - { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART }, // IT_WEARABLE - { LLAssetType::AT_ANIMATION, LLAssetType::AT_NONE }, // IT_ANIMATION - { LLAssetType::AT_GESTURE, LLAssetType::AT_NONE }, // IT_GESTURE + LLInventoryType::IT_NONE, // AT_LINK + LLInventoryType::IT_NONE, // AT_LINK_FOLDER + + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE + + LLInventoryType::IT_CATEGORY, // AT_CURRENT_OUTFIT + LLInventoryType::IT_CATEGORY, // AT_OUTFIT + LLInventoryType::IT_CATEGORY, // AT_MY_OUTFITS }; // static -const char* LLInventoryType::lookup(EType type) +const std::string &LLInventoryType::lookup(EType type) { - if((type >= 0) && (type < IT_COUNT)) - { - return INVENTORY_TYPE_NAMES[S32(type)]; - } - else - { - return NULL; - } + const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(type); + if (!entry) return empty_string; + return entry->mName; } // static LLInventoryType::EType LLInventoryType::lookup(const std::string& name) { - for(S32 i = 0; i < IT_COUNT; ++i) - { - if((INVENTORY_TYPE_NAMES[i]) - && (name == INVENTORY_TYPE_NAMES[i])) - { - // match - return (EType)i; - } - } - return IT_NONE; + return LLInventoryDictionary::getInstance()->lookup(name); } // XUI:translate // translation from a type to a human readable form. // static -const char* LLInventoryType::lookupHumanReadable(EType type) +const std::string &LLInventoryType::lookupHumanReadable(EType type) { - if((type >= 0) && (type < IT_COUNT)) - { - return INVENTORY_TYPE_HUMAN_NAMES[S32(type)]; - } - else - { - return NULL; - } + const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(type); + if (!entry) return empty_string; + return entry->mHumanName; } // return the default inventory for the given asset type. @@ -206,21 +196,36 @@ LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType a } } -bool inventory_and_asset_types_match( - LLInventoryType::EType inventory_type, - LLAssetType::EType asset_type) + +// add any types that we don't want the user to be able to change permissions on. +// static +bool LLInventoryType::cannotRestrictPermissions(LLInventoryType::EType type) { - bool rv = false; - if((inventory_type >= 0) && (inventory_type < LLInventoryType::IT_COUNT)) + switch(type) + { + case IT_CALLINGCARD: + case IT_LANDMARK: + return true; + default: + return false; + } +} + +bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type, + LLAssetType::EType asset_type) +{ + const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(inventory_type); + if (!entry) return false; + + for (InventoryEntry::asset_vec_t::const_iterator iter = entry->mAssetTypes.begin(); + iter != entry->mAssetTypes.end(); + iter++) { - for(S32 i = 0; i < MAX_POSSIBLE_ASSET_TYPES; ++i) + const LLAssetType::EType type = (*iter); + if(type == asset_type) { - if(INVENTORY_TO_ASSET_TYPE[inventory_type][i] == asset_type) - { - rv = true; - break; - } + return true; } } - return rv; + return false; } diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index d3effc0e6d..8961ff96e7 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -67,21 +67,25 @@ public: IT_WEARABLE = 18, IT_ANIMATION = 19, IT_GESTURE = 20, - IT_COUNT = 21, + IT_FAVORITE = 21, + IT_COUNT = 22, IT_NONE = -1 }; // machine transation between type and strings static EType lookup(const std::string& name); - static const char* lookup(EType type); + static const std::string &lookup(EType type); // translation from a type to a human readable form. - static const char* lookupHumanReadable(EType type); + static const std::string &lookupHumanReadable(EType type); // return the default inventory for the given asset type. static EType defaultForAssetType(LLAssetType::EType asset_type); + // true if this type cannot have restricted permissions. + static bool cannotRestrictPermissions(EType type); + private: // don't instantiate or derive one of these objects LLInventoryType( void ); diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 5ba32c0600..5a865d27ba 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -446,8 +446,10 @@ public: BOOL getAllowFly() const { return (mParcelFlags & PF_ALLOW_FLY) ? TRUE : FALSE; } + // Remove permission restrictions for creating landmarks. + // We should eventually remove this flag completely. BOOL getAllowLandmark() const - { return (mParcelFlags & PF_ALLOW_LANDMARK) ? TRUE : FALSE; } + { return TRUE; } BOOL getAllowGroupScripts() const { return (mParcelFlags & PF_ALLOW_GROUP_SCRIPTS) ? TRUE : FALSE; } diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index e4f8b0dffd..036231ccf8 100644 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -83,6 +83,17 @@ void LLPermissions::initMasks(PermissionMask base, PermissionMask owner, fix(); } +// ! BACKWARDS COMPATIBILITY ! Override masks for inventory types that +// no longer can have restricted permissions. This takes care of previous +// version landmarks that could have had no copy/mod/transfer bits set. +void LLPermissions::initMasks(LLInventoryType::EType type) +{ + if (LLInventoryType::cannotRestrictPermissions(type)) + { + initMasks(PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL, PERM_ALL); + } +} + BOOL LLPermissions::getOwnership(LLUUID& owner_id, BOOL& is_group_owned) const { if(mOwner.notNull()) diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h index 9280629e0c..f03045e265 100644 --- a/indra/llinventory/llpermissions.h +++ b/indra/llinventory/llpermissions.h @@ -38,6 +38,7 @@ #include "lluuid.h" #include "llxmlnode.h" #include "reflective.h" +#include "llinventorytype.h" // prototypes class LLMessageSystem; @@ -129,6 +130,8 @@ public: void initMasks(PermissionMask base, PermissionMask owner, PermissionMask everyone, PermissionMask group, PermissionMask next); + // adjust permissions based on inventory type. + void initMasks(LLInventoryType::EType type); // // ACCESSORS diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp index a4d59275b9..5a1cd95ffc 100644 --- a/indra/llmessage/lltransfersourceasset.cpp +++ b/indra/llmessage/lltransfersourceasset.cpp @@ -264,16 +264,17 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type) bool rv = false; switch(type) { - case LLAssetType::AT_SOUND: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - rv = true; - break; - default: - break; + case LLAssetType::AT_SOUND: + case LLAssetType::AT_LANDMARK: + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + case LLAssetType::AT_ANIMATION: + case LLAssetType::AT_GESTURE: + case LLAssetType::AT_FAVORITE: + rv = true; + break; + default: + break; } return rv; } @@ -284,18 +285,21 @@ bool is_asset_id_knowable(LLAssetType::EType type) bool rv = false; switch(type) { - case LLAssetType::AT_TEXTURE: - case LLAssetType::AT_SOUND: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_NOTECARD: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - rv = true; - break; - default: - break; + case LLAssetType::AT_TEXTURE: + case LLAssetType::AT_SOUND: + case LLAssetType::AT_LANDMARK: + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_NOTECARD: + case LLAssetType::AT_BODYPART: + case LLAssetType::AT_ANIMATION: + case LLAssetType::AT_GESTURE: + case LLAssetType::AT_FAVORITE: + case LLAssetType::AT_LINK: + case LLAssetType::AT_LINK_FOLDER: + rv = true; + break; + default: + break; } return rv; } diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 43b5f8e224..30af58e430 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -174,6 +174,7 @@ char* _PREHASH_UpdateInventoryItem = LLMessageStringTable::getInstance()->getStr char* _PREHASH_UpdateCreateInventoryItem = LLMessageStringTable::getInstance()->getString("UpdateCreateInventoryItem"); char* _PREHASH_MoveInventoryItem = LLMessageStringTable::getInstance()->getString("MoveInventoryItem"); char* _PREHASH_CopyInventoryItem = LLMessageStringTable::getInstance()->getString("CopyInventoryItem"); +char* _PREHASH_LinkInventoryItem = LLMessageStringTable::getInstance()->getString("LinkInventoryItem"); char* _PREHASH_RemoveInventoryItem = LLMessageStringTable::getInstance()->getString("RemoveInventoryItem"); char* _PREHASH_CreateInventoryItem = LLMessageStringTable::getInstance()->getString("CreateInventoryItem"); char* _PREHASH_PathTwistBegin = LLMessageStringTable::getInstance()->getString("PathTwistBegin"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index f8ef610408..e73ec3e5e1 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -174,6 +174,7 @@ extern char * _PREHASH_UpdateInventoryItem; extern char * _PREHASH_UpdateCreateInventoryItem; extern char * _PREHASH_MoveInventoryItem; extern char * _PREHASH_CopyInventoryItem; +extern char * _PREHASH_LinkInventoryItem; extern char * _PREHASH_RemoveInventoryItem; extern char * _PREHASH_CreateInventoryItem; extern char * _PREHASH_PathTwistBegin; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 5d09d8748f..d96bcf5bbf 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -602,13 +602,12 @@ void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, } -const char* safe_inv_type_lookup(LLInventoryType::EType inv_type) +const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type) { - const char* rv = LLInventoryType::lookup(inv_type); - if(!rv) + const std::string rv= LLInventoryType::lookup(inv_type); + if(rv.empty()) { - const char* INVALID_TYPE = ""; - rv = INVALID_TYPE; + return std::string(""); } return rv; } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index f47d0777b0..bad2e174c9 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -307,8 +307,8 @@ bool LLViewerInventoryItem::exportFileLocal(LLFILE* fp) const fprintf(fp, "\t\tparent_id\t%s\n", uuid_str.c_str()); mPermissions.exportFile(fp); fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - const char* inv_type_str = LLInventoryType::lookup(mInventoryType); - if(inv_type_str) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str); + const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); + if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str()); fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); fprintf(fp, "\t\tcreation_date\t%d\n", (S32) mCreationDate); fprintf(fp,"\t}\n"); diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index 23efd65c45..67233cbda0 100644 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -8945,3 +8945,21 @@ version 2.0 { CRC U32 } } } + +{ + LinkInventoryItem Low 426 NotTrusted Zerocoded + { + AgentData Single + { AgentID LLUUID } + { SessionID LLUUID } + } + { + InventoryData Variable + { CallbackID U32 } // Async Response + { FolderID LLUUID } + { OldItemID LLUUID } + { Name Variable 1 } + { AssetType U8 } + } +} + -- cgit v1.3 From 87776b19443030bece31c26290d1092bf6cbb3e6 Mon Sep 17 00:00:00 2001 From: Christian Goetze Date: Wed, 29 Jul 2009 22:16:52 +0000 Subject: svn merge -r128774:128808 svn+ssh://svn.lindenlab.com/svn/user/cg/qar-1737 effective merge: svn merge -r127126:128746 svn+ssh://svn.lindenlab.com/svn/linden/branches/server/server-1.27 --- indra/llinventory/llinventory.cpp | 33 +++++++ indra/llinventory/llinventory.h | 4 + indra/llmessage/llmail.cpp | 18 +++- indra/llprimitive/llprimitive.cpp | 187 +++++++++++++++++++++++++++++++++++++- 4 files changed, 238 insertions(+), 4 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index e45bb59881..76de357e2b 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -453,6 +453,39 @@ void LLInventoryItem::setCreationDate(time_t creation_date_utc) mCreationDate = creation_date_utc; } +void LLInventoryItem::accumulatePermissionSlamBits(const LLInventoryItem& old_item) +{ + // Remove any pre-existing II_FLAGS_PERM_OVERWRITE_MASK flags + // because we now detect when they should be set. + setFlags( old_item.getFlags() | (getFlags() & ~(LLInventoryItem::II_FLAGS_PERM_OVERWRITE_MASK)) ); + + // Enforce the PERM_OVERWRITE flags for any masks that are different + // but only for AT_OBJECT's since that is the only asset type that can + // exist in-world (instead of only in-inventory or in-object-contents). + if (LLAssetType::AT_OBJECT == getType()) + { + LLPermissions old_permissions = old_item.getPermissions(); + U32 flags_to_be_set = 0; + if(old_permissions.getMaskNextOwner() != getPermissions().getMaskNextOwner()) + { + flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM; + } + if(old_permissions.getMaskEveryone() != getPermissions().getMaskEveryone()) + { + flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE; + } + if(old_permissions.getMaskGroup() != getPermissions().getMaskGroup()) + { + flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP; + } + LLSaleInfo old_sale_info = old_item.getSaleInfo(); + if(old_sale_info != getSaleInfo()) + { + flags_to_be_set |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE; + } + setFlags(getFlags() | flags_to_be_set); + } +} const LLSaleInfo& LLInventoryItem::getSaleInfo() const { diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index 094aebe93b..08e3958533 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -262,6 +262,10 @@ public: void setFlags(U32 flags); void setCreationDate(time_t creation_date_utc); + // Check for changes in permissions masks and sale info + // and set the corresponding bits in mFlags + void accumulatePermissionSlamBits(const LLInventoryItem& old_item); + // Put this inventory item onto the current outgoing mesage. It // assumes you have already called nextBlock(). virtual void packMessage(LLMessageSystem* msg) const; diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp index d52ff6c7e8..ce206d8d7d 100644 --- a/indra/llmessage/llmail.cpp +++ b/indra/llmessage/llmail.cpp @@ -265,7 +265,7 @@ std::string LLMail::buildSMTPTransaction( // static bool LLMail::send( const std::string& header, - const std::string& message, + const std::string& raw_message, const char* from_address, const char* to_address) { @@ -276,8 +276,20 @@ bool LLMail::send( return false; } - // *FIX: this translation doesn't deal with a single period on a - // line by itself. + // remove any "." SMTP commands to prevent injection (DEV-35777) + // we don't need to worry about "\r\n.\r\n" because of the + // "\n" --> "\n\n" conversion going into rfc2822_msg below + std::string message = raw_message; + std::string bad_string = "\n.\n"; + std::string good_string = "\n..\n"; + while (1) + { + int index = message.find(bad_string); + if (index == std::string::npos) break; + message.replace(index, bad_string.size(), good_string); + } + + // convert all "\n" into "\r\n" std::ostringstream rfc2822_msg; for(U32 i = 0; i < message.size(); ++i) { diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 58aaf97a76..7b755a7d17 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -746,16 +746,201 @@ BOOL LLPrimitive::setVolume(const LLVolumeParams &volume_params, const S32 detai U32 old_face_mask = mVolumep->mFaceMask; + S32 face_bit = 0; + S32 cur_mask = 0; + + // Grab copies of the old faces from the original shape, ordered by type. + // We will use these to figure out what old texture info gets mapped to new + // faces in the new shape. + std::vector old_faces; + for (S32 face = 0; face < mVolumep->getNumFaces(); face++) + { + old_faces.push_back(mVolumep->getProfile().mFaces[face]); + } + + // Copy the old texture info off to the side, but not in the order in which + // they live in the mTextureList, rather in order of ther "face id" which + // is the corresponding value of LLVolueParams::LLProfile::mFaces::mIndex. + // + // Hence, some elements of old_tes::mEntryList will be invalid. It is + // initialized to a size of 9 (max number of possible faces on a volume?) + // and only the ones with valid types are filled in. + LLPrimTextureList old_tes; + old_tes.setSize(9); + for (face_bit = 0; face_bit < 9; face_bit++) + { + cur_mask = 0x1 << face_bit; + if (old_face_mask & cur_mask) + { + S32 te_index = face_index_from_id(cur_mask, old_faces); + old_tes.copyTexture(face_bit, *(getTE(te_index))); + //llinfos << face_bit << ":" << te_index << ":" << old_tes[face_bit].getID() << llendl; + } + } + + // build the new object sVolumeManager->unrefVolume(mVolumep); mVolumep = volumep; U32 new_face_mask = mVolumep->mFaceMask; - if (old_face_mask != new_face_mask) + S32 i; + + if (old_face_mask == new_face_mask) { + // nothing to do + return TRUE; + } + + if (mVolumep->getNumFaces() == 0 && new_face_mask != 0) + { + llwarns << "Object with 0 faces found...INCORRECT!" << llendl; setNumTEs(mVolumep->getNumFaces()); + return TRUE; + } + + // initialize face_mapping + S32 face_mapping[9]; + for (face_bit = 0; face_bit < 9; face_bit++) + { + face_mapping[face_bit] = face_bit; + } + + // The new shape may have more faces than the original, but we can't just + // add them to the end -- the ordering matters and it may be that we must + // insert the new faces in the middle of the list. When we add a face it + // will pick up the texture/color info of one of the old faces an so we + // now figure out which old face info gets mapped to each new face, and + // store in the face_mapping lookup table. + for (face_bit = 0; face_bit < 9; face_bit++) + { + cur_mask = 0x1 << face_bit; + if (!(new_face_mask & cur_mask)) + { + // Face doesn't exist in new map. + face_mapping[face_bit] = -1; + continue; + } + else if (old_face_mask & cur_mask) + { + // Face exists in new and old map. + face_mapping[face_bit] = face_bit; + continue; + } + + // OK, how we've got a mismatch, where we have to fill a new face with one from + // the old face. + if (cur_mask & (LL_FACE_PATH_BEGIN | LL_FACE_PATH_END | LL_FACE_INNER_SIDE)) + { + // It's a top/bottom/hollow interior face. + if (old_face_mask & LL_FACE_PATH_END) + { + face_mapping[face_bit] = 1; + continue; + } + else + { + S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0; + for (i = 0; i < 4; i++) + { + if (old_face_mask & cur_outer_mask) + { + face_mapping[face_bit] = 5 + i; + break; + } + cur_outer_mask <<= 1; + } + if (i == 4) + { + llwarns << "No path end or outer face in volume!" << llendl; + } + continue; + } + } + + if (cur_mask & (LL_FACE_PROFILE_BEGIN | LL_FACE_PROFILE_END)) + { + // A cut slice. Use the hollow interior if we have it. + if (old_face_mask & LL_FACE_INNER_SIDE) + { + face_mapping[face_bit] = 2; + continue; + } + + // No interior, use the bottom face. + // Could figure out which of the outer faces was nearest, but that would be harder. + if (old_face_mask & LL_FACE_PATH_END) + { + face_mapping[face_bit] = 1; + continue; + } + else + { + S32 cur_outer_mask = LL_FACE_OUTER_SIDE_0; + for (i = 0; i < 4; i++) + { + if (old_face_mask & cur_outer_mask) + { + face_mapping[face_bit] = 5 + i; + break; + } + cur_outer_mask <<= 1; + } + if (i == 4) + { + llwarns << "No path end or outer face in volume!" << llendl; + } + continue; + } + } + + // OK, the face that's missing is an outer face... + // Pull from the nearest adjacent outer face (there's always guaranteed to be one... + S32 cur_outer = face_bit - 5; + S32 min_dist = 5; + S32 min_outer_bit = -1; + S32 i; + for (i = 0; i < 4; i++) + { + if (old_face_mask & (LL_FACE_OUTER_SIDE_0 << i)) + { + S32 dist = abs(i - cur_outer); + if (dist < min_dist) + { + min_dist = dist; + min_outer_bit = i + 5; + } + } + } + if (-1 == min_outer_bit) + { + llinfos << (LLVolume *)mVolumep << llendl; + llwarns << "Bad! No outer faces, impossible!" << llendl; + } + face_mapping[face_bit] = min_outer_bit; } + + setNumTEs(mVolumep->getNumFaces()); + for (face_bit = 0; face_bit < 9; face_bit++) + { + // For each possible face type on the new shape we check to see if that + // face exists and if it does we create a texture entry that is a copy + // of one of the originals. Since the originals might not have a + // matching face, we use the face_mapping lookup table to figure out + // which face information to copy. + cur_mask = 0x1 << face_bit; + if (new_face_mask & cur_mask) + { + if (-1 == face_mapping[face_bit]) + { + llwarns << "No mapping from old face to new face!" << llendl; + } + + S32 te_num = face_index_from_id(cur_mask, mVolumep->getProfile().mFaces); + setTE(te_num, *(old_tes.getTexture(face_mapping[face_bit]))); + } + } return TRUE; } -- cgit v1.3 From 76d05a7e50bee33584f35f2f00f32ffe953752e6 Mon Sep 17 00:00:00 2001 From: Don Kjer Date: Fri, 4 Sep 2009 02:27:28 +0000 Subject: svn merge -r 129999:132607 svn+ssh://svn/svn/linden/branches/server/server-1.30 into trunk QAR-1863: Merge 525 changes from 1.27 -> 1.30 -> trunk 1.27 Changes: * QAR-1721: Vivox Recurring Billing (ViRB) * QAR-1743: 525 AO Classifieds * DEV-37701: Fix cleanup_indra nightly script so that it doesn't fail, and so that we know if it does * DEV-37926 - Fairmarket key roll 8/12/2009 * QAR-1744: 525 Landstore * QAR-1797: disable web services for find_people * QAR-1758: OpenID and Backup/recovery. * QAR-1794: ViRB proc fix - proc/recurring_billing/GetLocaleCountryByPackageId.php * Changing parameter name so the module signal could be used properly in the function below * QAR-1808 : Self-Reported First Name and Self-Reported Last Name have duplicate entries in the registration table * DEV-30204 : Moved the registration table from sequence to indra_aux. * removed dungeon from banned keyword list * DEV-30204 : Moved the registration table from sequence to indra_aux. Reviewed by kelly, cg, jarv * Merging new streambase dwell nightly to server-1.27 * Add update_parcel_dwell.py to serial_maintenance rule in the nightly.make Makefile, removing the dwell rule, since we don't want it running in parallel with other expensive nightly scripts. 1.30 Changes: * DEV-27476: version-manager only works in Firefox * DEV-27472: version-manager appears to load javascript from third party site. * mulib r92 that supports If-Modified-Since header and prevents arbitrary filesystem access through host:12107/manager/mochi/.. * Trivial conductor change that prevents a traceback when no regions are available to start. * Fixing "Out of Connections" error when running tests via SCUT * DEV-37554 - farm_deploy should get its ssh timeout from farm.ini * undo two lines of debugging changes that accidentally were checked in to farm * Adding MochiKit to MANIFEST for version-manager. * revised files for new parcel dwell process * Changing vault from an 'http' svn extern to a 'svn+ssh' svn extern. * DEV-38504 RPS map item queries are too verbose * added --skip-grid-mode-prompt to main in farm * DEV-38607: Region Presence Service includes disabled regions in estate responses, resulting in high slave query rate. * DEV-34781 - enable use_space_server_for_map_items and set map_item_request throttle settings in simulator.xml * DEV-38351 changes to ip_blacklist.xml file never get automatically picked up by the simulator * DEV-35443 Region border crossing issues. * DEV-35443 revert overzealous validity checking on neighbor messages. * DEV-15998 changing settings to re-enable teleport throttle, following DEV-37200 fix * QAR-1822 CPU Overrides update to indra.xml * DEV-15998 changing settings to re-enable teleport throttle, following DEV-37200 fix * DEV-34026 Update LLAgentInfo::forwardViewerStats() to make all viewer statistics * DEV-38906 Teleport throttle blocks prematurely when agent teleports back and forth between 2 regions * DEV-38861 Intra-region TP is blocked by inter-region TP throttl * DEV-38504 RPS map item queries are too verbose * initial import of deploy_to_dev_grid.sh --- indra/llinventory/lltransactiontypes.h | 12 ++++++++++++ indra/llmessage/llcurl.cpp | 13 +++++++++++-- indra/llmessage/llcurl.h | 6 ++++++ indra/llmessage/llhttpclient.cpp | 5 +++++ indra/llmessage/llregionpresenceverifier.cpp | 2 +- 5 files changed, 35 insertions(+), 3 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llinventory/lltransactiontypes.h b/indra/llinventory/lltransactiontypes.h index 1cb7308bd4..2c699bcb87 100644 --- a/indra/llinventory/lltransactiontypes.h +++ b/indra/llinventory/lltransactiontypes.h @@ -69,6 +69,12 @@ const S32 TRANS_PARCEL_DIR_FEE = 2003; const S32 TRANS_GROUP_TAX = 2004; // Taxes incurred as part of group membership const S32 TRANS_CLASSIFIED_RENEW = 2005; +// Codes 2100-2999 reserved for recurring billing services +// New codes can be created through an admin interface so may not +// automatically end up in the list below :-( +// So make sure you check the transaction_description table +const S32 TRANS_RECURRING_GENERIC = 2100; + // Codes 3000-3999 reserved for inventory transactions const S32 TRANS_GIVE_INVENTORY = 3000; @@ -84,6 +90,12 @@ const S32 TRANS_DWELL_BONUS = 5007; const S32 TRANS_PAY_OBJECT = 5008; const S32 TRANS_OBJECT_PAYS = 5009; +// Codes 5100-5999 reserved for recurring billing transfers between users +// New codes can be created through an admin interface so may not +// automatically end up in the list below :-( +// So make sure you check the transaction_description table +const S32 TRANS_RECURRING_GENERIC_USER = 5100; + // Codes 6000-6999 reserved for group transactions //const S32 TRANS_GROUP_JOIN = 6000; //reserved for future use const S32 TRANS_GROUP_LAND_DEED = 6001; diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 1a432cd7df..0d0fee6ee6 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -131,7 +131,7 @@ void LLCurl::Responder::error( // virtual void LLCurl::Responder::error(U32 status, const std::string& reason) { - llinfos << status << ": " << reason << llendl; + llinfos << mURL << " [" << status << "]: " << reason << llendl; } // virtual @@ -139,6 +139,11 @@ void LLCurl::Responder::result(const LLSD& content) { } +void LLCurl::Responder::setURL(const std::string& url) +{ + mURL = url; +} + // virtual void LLCurl::Responder::completedRaw( U32 status, @@ -148,7 +153,11 @@ void LLCurl::Responder::completedRaw( { LLSD content; LLBufferStream istr(channels, buffer.get()); - LLSDSerialize::fromXML(content, istr); + if (!LLSDSerialize::fromXML(content, istr)) + { + llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl; + } + completed(status, reason, content); } diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index ff63904c91..6e45cbc8b5 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -120,8 +120,14 @@ public: // of the header can be parsed. In the ::completed call above only the body is contained in the LLSD. virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content); + // Used internally to set the url for debugging later. + void setURL(const std::string& url); + public: /* but not really -- don't touch this */ U32 mReferenceCount; + + private: + std::string mURL; }; typedef boost::intrusive_ptr ResponderPtr; diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 8b90a4c5ca..12ecbb36eb 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -265,6 +265,11 @@ static void request( } } + if (responder) + { + responder->setURL(url); + } + req->setCallback(new LLHTTPClientURLAdaptor(responder)); if (method == LLURLRequest::HTTP_POST && gMessageSystem) diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp index 08c12f90da..e02a288473 100644 --- a/indra/llmessage/llregionpresenceverifier.cpp +++ b/indra/llmessage/llregionpresenceverifier.cpp @@ -67,7 +67,7 @@ void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content) LLHost destination(host, port); LLUUID id = content["region_id"]; - llinfos << "Verifying " << destination.getString() << " is region " << id << llendl; + lldebugs << "Verifying " << destination.getString() << " is region " << id << llendl; std::stringstream uri; uri << "http://" << destination.getString() << "/state/basic/"; -- cgit v1.3 From 74e584add651adbb5784276aba5770de9e295846 Mon Sep 17 00:00:00 2001 From: Christian Goetze Date: Fri, 4 Sep 2009 18:16:21 +0000 Subject: svn merge -r132607:132665 svn+ssh://svn.lindenlab.com/svn/linden/branches/server/server-1.30 Propagating to trunk: QAR-1705 DEV-29573 QAR-1859 QAR-1804 --- indra/llmessage/lltransfersourceasset.cpp | 1 - scripts/messages/message_template.msg | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'indra/llmessage') diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp index 5a1cd95ffc..41f3f3f607 100644 --- a/indra/llmessage/lltransfersourceasset.cpp +++ b/indra/llmessage/lltransfersourceasset.cpp @@ -270,7 +270,6 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type) case LLAssetType::AT_BODYPART: case LLAssetType::AT_ANIMATION: case LLAssetType::AT_GESTURE: - case LLAssetType::AT_FAVORITE: rv = true; break; default: diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index 9deab1f857..e1b01c569b 100644 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -8950,6 +8950,7 @@ version 2.0 } } +// Link inventory { LinkInventoryItem Low 426 NotTrusted Zerocoded { @@ -8958,12 +8959,16 @@ version 2.0 { SessionID LLUUID } } { - InventoryData Variable + InventoryBlock Single { CallbackID U32 } // Async Response { FolderID LLUUID } + { TransactionID LLUUID } // Going to become TransactionID { OldItemID LLUUID } + { Type S8 } + { InvType S8 } { Name Variable 1 } - { AssetType U8 } + { Description Variable 1 } + } } -- cgit v1.3 From be7ac8bbfe991427636656ec1679b8119c9d9dbe Mon Sep 17 00:00:00 2001 From: Bryan O'Sullivan Date: Thu, 10 Sep 2009 10:31:58 -0700 Subject: Fix a link error with an integration test on OS X. --- .hgignore | 1 + indra/llmessage/CMakeLists.txt | 2 ++ 2 files changed, 3 insertions(+) (limited to 'indra/llmessage') diff --git a/.hgignore b/.hgignore index 61c38705f4..15fb913653 100644 --- a/.hgignore +++ b/.hgignore @@ -24,6 +24,7 @@ indra/newview/res-sdl indra/newview/skins indra/newview/vivox-runtime indra/server-linux-* +indra/test/linden_file.dat indra/test_apps/llmediatest/dependencies/i686-win32 indra/test_apps/terrain_mule/*.dll indra/viewer-linux-* diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index ec52179a39..453286b83d 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -3,6 +3,7 @@ project(llmessage) include(00-Common) +include(GoogleMock) include(LLAddBuildTest) include(LLCommon) include(LLMath) @@ -230,6 +231,7 @@ IF (NOT LINUX AND VIEWER) ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} + ${GOOGLEMOCK_LIBRARIES} ) LL_ADD_INTEGRATION_TEST( -- cgit v1.3