Skip to content
Snippets Groups Projects
Commit dd695162 authored by Oz Linden's avatar Oz Linden
Browse files

pull fix for STORM-376

parents 69ae08ac 068e3cc4
Branches
Tags
No related merge requests found
Showing
with 1383 additions and 204 deletions
...@@ -27,3 +27,4 @@ c6e6324f5be1401f077ad18a4a0f6b46451c2f7b last_sprint ...@@ -27,3 +27,4 @@ c6e6324f5be1401f077ad18a4a0f6b46451c2f7b last_sprint
7076e22f9f43f479a4ea75eac447a36364bead5a 2.2.0-beta1 7076e22f9f43f479a4ea75eac447a36364bead5a 2.2.0-beta1
9822eb3e25f7fe0c28ffd8aba45c507caa383cbc 2.2.0-beta2 9822eb3e25f7fe0c28ffd8aba45c507caa383cbc 2.2.0-beta2
b0cd7e150009809a0b5b0a9d5785cd4bb230413a 2.2.0-beta3 b0cd7e150009809a0b5b0a9d5785cd4bb230413a 2.2.0-beta3
00a831292231faad7e44c69f76cb96f175b8dfad 2.2.0-beta4
...@@ -102,6 +102,26 @@ gooey.login_channel = "Second Life Alpha" ...@@ -102,6 +102,26 @@ gooey.login_channel = "Second Life Alpha"
gooey.viewer_grid = agni gooey.viewer_grid = agni
gooey.build_viewer_update_version_manager = false gooey.build_viewer_update_version_manager = false
# ========================================
# Display Names project
# ========================================
#viewer-identity-evolution.email = leyla@lindenlab.com
viewer-identity.build_Debug = false
viewer-identity.build_RelWithDebInfo = false
viewer-identity.build_viewer = true
viewer-identity.build_server = false
viewer-identity.build_server_tests = false
viewer-identity.build_Linux = true
viewer-identity.build_hg_bundle = true
viewer-identity.bulld_docs = true
viewer-identity.viewer_channel = "Second Life Project Viewer"
viewer-identity.login_channel = "Second Life Project Viewer"
viewer-identity.viewer_grid = aditi
viewer-identity.build_viewer_update_version_manager = false
# ======================================== # ========================================
# palange # palange
# ======================================== # ========================================
......
...@@ -59,6 +59,7 @@ pre_build() ...@@ -59,6 +59,7 @@ pre_build()
-t $variant \ -t $variant \
-G "$cmake_generator" \ -G "$cmake_generator" \
configure \ configure \
-DGRID:STRING="$viewer_grid" \
-DVIEWER_CHANNEL:STRING="$viewer_channel" \ -DVIEWER_CHANNEL:STRING="$viewer_channel" \
-DVIEWER_LOGIN_CHANNEL:STRING="$login_channel" \ -DVIEWER_LOGIN_CHANNEL:STRING="$login_channel" \
-DINSTALL_PROPRIETARY:BOOL=ON \ -DINSTALL_PROPRIETARY:BOOL=ON \
......
...@@ -370,6 +370,14 @@ ...@@ -370,6 +370,14 @@
</map> </map>
<!-- Server to client --> <!-- Server to client -->
<key>DisplayNameUpdate</key>
<map>
<key>flavor</key>
<string>llsd</string>
<key>trusted-sender</key>
<boolean>true</boolean>
</map>
<key>ParcelVoiceInfo</key> <key>ParcelVoiceInfo</key>
<map> <map>
<key>flavor</key> <key>flavor</key>
...@@ -426,6 +434,14 @@ ...@@ -426,6 +434,14 @@
<boolean>true</boolean> <boolean>true</boolean>
</map> </map>
<key>SetDisplayNameReply</key>
<map>
<key>flavor</key>
<string>llsd</string>
<key>trusted-sender</key>
<boolean>true</boolean>
</map>
<key>DirLandReply</key> <key>DirLandReply</key>
<map> <map>
<key>flavor</key> <key>flavor</key>
......
...@@ -26,6 +26,7 @@ set(cmake_SOURCE_FILES ...@@ -26,6 +26,7 @@ set(cmake_SOURCE_FILES
FindBerkeleyDB.cmake FindBerkeleyDB.cmake
FindCARes.cmake FindCARes.cmake
FindELFIO.cmake FindELFIO.cmake
FindFMOD.cmake
FindGooglePerfTools.cmake FindGooglePerfTools.cmake
FindMono.cmake FindMono.cmake
FindMT.cmake FindMT.cmake
......
...@@ -55,9 +55,10 @@ if(WINDOWS) ...@@ -55,9 +55,10 @@ if(WINDOWS)
set(release_files ${release_files} libtcmalloc_minimal.dll) set(release_files ${release_files} libtcmalloc_minimal.dll)
endif(USE_GOOGLE_PERFTOOLS) endif(USE_GOOGLE_PERFTOOLS)
if (FMOD_SDK_DIR) if (FMOD)
set(fmod_files fmod.dll) set(debug_files ${debug_files} fmod.dll)
endif (FMOD_SDK_DIR) set(release_files ${release_files} fmod.dll)
endif (FMOD)
#******************************* #*******************************
# LLKDU # LLKDU
...@@ -237,9 +238,9 @@ elseif(LINUX) ...@@ -237,9 +238,9 @@ elseif(LINUX)
libssl.so.0.9.7 libssl.so.0.9.7
) )
if (FMOD_SDK_DIR) if (FMOD)
set(fmod_files "libfmod-3.75.so") set(release_files ${release_files} "libfmod-3.75.so")
endif (FMOD_SDK_DIR) endif (FMOD)
#******************************* #*******************************
# LLKDU # LLKDU
...@@ -333,30 +334,6 @@ copy_if_different( ...@@ -333,30 +334,6 @@ copy_if_different(
) )
set(third_party_targets ${third_party_targets} ${out_targets}) set(third_party_targets ${third_party_targets} ${out_targets})
if (FMOD_SDK_DIR)
copy_if_different(
${FMOD_SDK_DIR}
"${CMAKE_CURRENT_BINARY_DIR}/Debug"
out_targets
${fmod_files}
)
set(all_targets ${all_targets} ${out_targets})
copy_if_different(
${FMOD_SDK_DIR}
"${CMAKE_CURRENT_BINARY_DIR}/Release"
out_targets
${fmod_files}
)
set(all_targets ${all_targets} ${out_targets})
copy_if_different(
${FMOD_SDK_DIR}
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDbgInfo"
out_targets
${fmod_files}
)
set(all_targets ${all_targets} ${out_targets})
endif (FMOD_SDK_DIR)
#******************************* #*******************************
# LLKDU # LLKDU
set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu") set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")
......
# -*- cmake -*- # -*- cmake -*-
include(Linking) set(FMOD ON CACHE BOOL "Use FMOD sound library.")
if(INSTALL_PROPRIETARY) if (FMOD)
if (STANDALONE)
set(FMOD_FIND_REQUIRED ON)
include(FindFMOD)
else (STANDALONE)
include(Prebuilt) include(Prebuilt)
use_prebuilt_binary(fmod) use_prebuilt_binary(fmod)
endif(INSTALL_PROPRIETARY)
find_library(FMOD_LIBRARY_RELEASE
NAMES fmod fmodvc fmod-3.75
PATHS
${ARCH_PREBUILT_DIRS_RELEASE}
)
find_library(FMOD_LIBRARY_DEBUG
NAMES fmod fmodvc fmod-3.75
PATHS
${ARCH_PREBUILT_DIRS_DEBUG}
)
if (FMOD_LIBRARY_RELEASE AND FMOD_LIBRARY_DEBUG)
set(FMOD_LIBRARY
debug ${FMOD_LIBRARY_DEBUG}
optimized ${FMOD_LIBRARY_RELEASE})
elseif (FMOD_LIBRARY_RELEASE)
set(FMOD_LIBRARY ${FMOD_LIBRARY_RELEASE})
endif (FMOD_LIBRARY_RELEASE AND FMOD_LIBRARY_DEBUG)
if (NOT FMOD_LIBRARY)
set(FMOD_SDK_DIR CACHE PATH "Path to the FMOD SDK.")
if (FMOD_SDK_DIR)
find_library(FMOD_LIBRARY
NAMES fmodvc fmod-3.75 fmod
PATHS
${FMOD_SDK_DIR}/api/lib
${FMOD_SDK_DIR}/api
${FMOD_SDK_DIR}/lib
${FMOD_SDK_DIR}
)
endif (FMOD_SDK_DIR)
endif (NOT FMOD_LIBRARY)
find_path(FMOD_INCLUDE_DIR fmod.h if (WINDOWS)
${LIBS_PREBUILT_DIR}/include set(FMOD_LIBRARY fmod)
${FMOD_SDK_DIR}/api/inc elseif (DARWIN)
${FMOD_SDK_DIR}/inc set(FMOD_LIBRARY fmod)
${FMOD_SDK_DIR} elseif (LINUX)
) set(FMOD_LIBRARY fmod-3.75)
endif (WINDOWS)
if (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
set(FMOD ON CACHE BOOL "Use closed source FMOD sound library.") SET(FMOD_LIBRARIES ${FMOD_LIBRARY})
else (FMOD_LIBRARY AND FMOD_INCLUDE_DIR) set(FMOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
set(FMOD_LIBRARY "") endif (STANDALONE)
set(FMOD_INCLUDE_DIR "")
if (FMOD)
message(STATUS "No support for FMOD audio (need to set FMOD_SDK_DIR?)")
endif (FMOD)
set(FMOD OFF CACHE BOOL "Use closed source FMOD sound library.")
endif (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
if (FMOD)
message(STATUS "Building with FMOD audio support")
endif (FMOD) endif (FMOD)
# -*- cmake -*-
# - Find FMOD
# Find the FMOD includes and library
# This module defines
# FMOD_INCLUDE_DIR, where to find fmod.h and fmod_errors.h
# FMOD_LIBRARIES, the libraries needed to use FMOD.
# FMOD, If false, do not try to use FMOD.
# also defined, but not for general use are
# FMOD_LIBRARY, where to find the FMOD library.
FIND_PATH(FMOD_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod)
SET(FMOD_NAMES ${FMOD_NAMES} fmod fmodvc fmod-3.75)
FIND_LIBRARY(FMOD_LIBRARY
NAMES ${FMOD_NAMES}
PATH_SUFFIXES fmod
)
IF (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
SET(FMOD_LIBRARIES ${FMOD_LIBRARY})
SET(FMOD_FOUND "YES")
ELSE (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
SET(FMOD_FOUND "NO")
ENDIF (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
IF (FMOD_FOUND)
IF (NOT FMOD_FIND_QUIETLY)
MESSAGE(STATUS "Found FMOD: ${FMOD_LIBRARIES}")
ENDIF (NOT FMOD_FIND_QUIETLY)
ELSE (FMOD_FOUND)
IF (FMOD_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find FMOD library")
ENDIF (FMOD_FIND_REQUIRED)
ENDIF (FMOD_FOUND)
# Deprecated declarations.
SET (NATIVE_FMOD_INCLUDE_PATH ${FMOD_INCLUDE_DIR} )
GET_FILENAME_COMPONENT (NATIVE_FMOD_LIB_PATH ${FMOD_LIBRARY} PATH)
MARK_AS_ADVANCED(
FMOD_LIBRARY
FMOD_INCLUDE_DIR
)
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
$LicenseInfo:firstyear=2009&license=viewerlgpl$ $LicenseInfo:firstyear=2009&license=viewerlgpl$
Second Life Viewer Source Code Second Life Viewer Source Code
Copyright (C) 2010, Linden Research, Inc. Copyright (C) 2009-2010, Linden Research, Inc.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
$LicenseInfo:firstyear=2006&license=viewerlgpl$ $LicenseInfo:firstyear=2006&license=viewerlgpl$
Second Life Viewer Source Code Second Life Viewer Source Code
Copyright (C) 2010, Linden Research, Inc. Copyright (C) 2006-2010, Linden Research, Inc.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
......
...@@ -33,6 +33,7 @@ set(llcommon_SOURCE_FILES ...@@ -33,6 +33,7 @@ set(llcommon_SOURCE_FILES
llapp.cpp llapp.cpp
llapr.cpp llapr.cpp
llassettype.cpp llassettype.cpp
llavatarname.cpp
llbase32.cpp llbase32.cpp
llbase64.cpp llbase64.cpp
llcommon.cpp llcommon.cpp
...@@ -115,6 +116,7 @@ set(llcommon_HEADER_FILES ...@@ -115,6 +116,7 @@ set(llcommon_HEADER_FILES
llallocator.h llallocator.h
llallocator_heap_profile.h llallocator_heap_profile.h
llagentconstants.h llagentconstants.h
llavatarname.h
llapp.h llapp.h
llapr.h llapr.h
llassettype.h llassettype.h
......
/**
* @file llavatarname.cpp
* @brief Represents name-related data for an avatar, such as the
* username/SLID ("bobsmith123" or "james.linden") and the display
* name ("James Cook")
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llavatarname.h"
#include "lldate.h"
#include "llsd.h"
// Store these in pre-built std::strings to avoid memory allocations in
// LLSD map lookups
static const std::string USERNAME("username");
static const std::string DISPLAY_NAME("display_name");
static const std::string LEGACY_FIRST_NAME("legacy_first_name");
static const std::string LEGACY_LAST_NAME("legacy_last_name");
static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default");
static const std::string DISPLAY_NAME_EXPIRES("display_name_expires");
static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update");
LLAvatarName::LLAvatarName()
: mUsername(),
mDisplayName(),
mLegacyFirstName(),
mLegacyLastName(),
mIsDisplayNameDefault(false),
mIsDummy(false),
mExpires(F64_MAX),
mNextUpdate(0.0)
{ }
bool LLAvatarName::operator<(const LLAvatarName& rhs) const
{
if (mUsername == rhs.mUsername)
return mDisplayName < rhs.mDisplayName;
else
return mUsername < rhs.mUsername;
}
LLSD LLAvatarName::asLLSD() const
{
LLSD sd;
sd[USERNAME] = mUsername;
sd[DISPLAY_NAME] = mDisplayName;
sd[LEGACY_FIRST_NAME] = mLegacyFirstName;
sd[LEGACY_LAST_NAME] = mLegacyLastName;
sd[IS_DISPLAY_NAME_DEFAULT] = mIsDisplayNameDefault;
sd[DISPLAY_NAME_EXPIRES] = LLDate(mExpires);
sd[DISPLAY_NAME_NEXT_UPDATE] = LLDate(mNextUpdate);
return sd;
}
void LLAvatarName::fromLLSD(const LLSD& sd)
{
mUsername = sd[USERNAME].asString();
mDisplayName = sd[DISPLAY_NAME].asString();
mLegacyFirstName = sd[LEGACY_FIRST_NAME].asString();
mLegacyLastName = sd[LEGACY_LAST_NAME].asString();
mIsDisplayNameDefault = sd[IS_DISPLAY_NAME_DEFAULT].asBoolean();
LLDate expires = sd[DISPLAY_NAME_EXPIRES];
mExpires = expires.secondsSinceEpoch();
LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE];
mNextUpdate = next_update.secondsSinceEpoch();
}
std::string LLAvatarName::getCompleteName() const
{
std::string name;
if (!mUsername.empty())
{
name = mDisplayName + " (" + mUsername + ")";
}
else
{
// ...display names are off, legacy name is in mDisplayName
name = mDisplayName;
}
return name;
}
std::string LLAvatarName::getLegacyName() const
{
std::string name;
name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
name = mLegacyFirstName;
name += " ";
name += mLegacyLastName;
return name;
}
/**
* @file llavatarname.h
* @brief Represents name-related data for an avatar, such as the
* username/SLID ("bobsmith123" or "james.linden") and the display
* name ("James Cook")
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLAVATARNAME_H
#define LLAVATARNAME_H
#include <string>
class LLSD;
class LL_COMMON_API LLAvatarName
{
public:
LLAvatarName();
bool operator<(const LLAvatarName& rhs) const;
LLSD asLLSD() const;
void fromLLSD(const LLSD& sd);
// For normal names, returns "James Linden (james.linden)"
// When display names are disabled returns just "James Linden"
std::string getCompleteName() const;
// Returns "James Linden" or "bobsmith123 Resident" for backwards
// compatibility with systems like voice and muting
// *TODO: Eliminate this in favor of username only
std::string getLegacyName() const;
// "bobsmith123" or "james.linden", US-ASCII only
std::string mUsername;
// "Jose' Sanchez" or "James Linden", UTF-8 encoded Unicode
// Contains data whether or not user has explicitly set
// a display name; may duplicate their username.
std::string mDisplayName;
// For "James Linden", "James"
// For "bobsmith123", "bobsmith123"
// Used to communicate with legacy systems like voice and muting which
// rely on old-style names.
// *TODO: Eliminate this in favor of username only
std::string mLegacyFirstName;
// For "James Linden", "Linden"
// For "bobsmith123", "Resident"
// see above for rationale
std::string mLegacyLastName;
// If true, both display name and SLID were generated from
// a legacy first and last name, like "James Linden (james.linden)"
bool mIsDisplayNameDefault;
// Under error conditions, we may insert "dummy" records with
// names like "???" into caches as placeholders. These can be
// shown in UI, but are not serialized.
bool mIsDummy;
// Names can change, so need to keep track of when name was
// last checked.
// Unix time-from-epoch seconds for efficiency
F64 mExpires;
// You can only change your name every N hours, so record
// when the next update is allowed
// Unix time-from-epoch seconds
F64 mNextUpdate;
};
#endif
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
#ifndef LL_LLCHAT_H #ifndef LL_LLCHAT_H
#define LL_LLCHAT_H #define LL_LLCHAT_H
#include "llstring.h"
#include "lluuid.h" #include "lluuid.h"
#include "v3math.h" #include "v3math.h"
...@@ -71,7 +70,7 @@ typedef enum e_chat_style ...@@ -71,7 +70,7 @@ typedef enum e_chat_style
class LLChat class LLChat
{ {
public: public:
LLChat(const std::string& text = LLStringUtil::null) LLChat(const std::string& text = std::string())
: mText(text), : mText(text),
mFromName(), mFromName(),
mFromID(), mFromID(),
......
...@@ -731,14 +731,17 @@ void LLStringOps::setupDatetimeInfo (bool daylight) ...@@ -731,14 +731,17 @@ void LLStringOps::setupDatetimeInfo (bool daylight)
nowT = time (NULL); nowT = time (NULL);
tmpT = localtime (&nowT);
localT = mktime (tmpT);
tmpT = gmtime (&nowT); tmpT = gmtime (&nowT);
gmtT = mktime (tmpT); gmtT = mktime (tmpT);
sLocalTimeOffset = (long) (gmtT - localT); tmpT = localtime (&nowT);
localT = mktime (tmpT);
sLocalTimeOffset = (long) (gmtT - localT);
if (tmpT->tm_isdst)
{
sLocalTimeOffset -= 60 * 60; // 1 hour
}
sPacificDaylightTime = daylight; sPacificDaylightTime = daylight;
sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60; sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60;
......
...@@ -108,6 +108,9 @@ std::string build_transfer_message_to_source( ...@@ -108,6 +108,9 @@ std::string build_transfer_message_to_source(
std::ostringstream ostr; std::ostringstream ostr;
if(dest_id.isNull()) if(dest_id.isNull())
{ {
// *NOTE: Do not change these strings! The viewer matches
// them in llviewermessage.cpp to perform localization.
// If you need to make changes, add a new, localizable message. JC
ostr << "You paid L$" << amount; ostr << "You paid L$" << amount;
switch(transaction_type) switch(transaction_type)
{ {
...@@ -154,6 +157,9 @@ std::string build_transfer_message_to_destination( ...@@ -154,6 +157,9 @@ std::string build_transfer_message_to_destination(
return description; return description;
} }
std::ostringstream ostr; std::ostringstream ostr;
// *NOTE: Do not change these strings! The viewer matches
// them in llviewermessage.cpp to perform localization.
// If you need to make changes, add a new, localizable message. JC
ostr << source_name << " paid you L$" << amount; ostr << source_name << " paid you L$" << amount;
append_reason(ostr, transaction_type, description); append_reason(ostr, transaction_type, description);
ostr << "."; ostr << ".";
......
...@@ -25,6 +25,7 @@ set(llmessage_SOURCE_FILES ...@@ -25,6 +25,7 @@ set(llmessage_SOURCE_FILES
llares.cpp llares.cpp
llareslistener.cpp llareslistener.cpp
llassetstorage.cpp llassetstorage.cpp
llavatarnamecache.cpp
llblowfishcipher.cpp llblowfishcipher.cpp
llbuffer.cpp llbuffer.cpp
llbufferstream.cpp llbufferstream.cpp
...@@ -110,6 +111,7 @@ set(llmessage_HEADER_FILES ...@@ -110,6 +111,7 @@ set(llmessage_HEADER_FILES
llares.h llares.h
llareslistener.h llareslistener.h
llassetstorage.h llassetstorage.h
llavatarnamecache.h
llblowfishcipher.h llblowfishcipher.h
llbuffer.h llbuffer.h
llbufferstream.h llbufferstream.h
...@@ -248,6 +250,7 @@ if (LL_TESTS) ...@@ -248,6 +250,7 @@ if (LL_TESTS)
"${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
) )
LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
......
This diff is collapsed.
/**
* @file llavatarnamecache.h
* @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
* ("James Cook") from avatar UUIDs.
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLAVATARNAMECACHE_H
#define LLAVATARNAMECACHE_H
#include "llavatarname.h" // for convenience
#include <boost/signals2.hpp>
class LLSD;
class LLUUID;
namespace LLAvatarNameCache
{
typedef boost::signals2::signal<void (void)> use_display_name_signal_t;
// Until the cache is set running, immediate lookups will fail and
// async lookups will be queued. This allows us to block requests
// until we know if the first region supports display names.
void initClass(bool running);
void cleanupClass();
void importFile(std::istream& istr);
void exportFile(std::ostream& ostr);
// On the viewer, usually a simulator capabilitity
// If empty, name cache will fall back to using legacy name
// lookup system
void setNameLookupURL(const std::string& name_lookup_url);
// Do we have a valid lookup URL, hence are we trying to use the
// new display name lookup system?
bool hasNameLookupURL();
// Periodically makes a batch request for display names not already in
// cache. Call once per frame.
void idle();
// If name is in cache, returns true and fills in provided LLAvatarName
// otherwise returns false
bool get(const LLUUID& agent_id, LLAvatarName *av_name);
// Callback types for get() below
typedef boost::signals2::signal<
void (const LLUUID& agent_id, const LLAvatarName& av_name)>
callback_signal_t;
typedef callback_signal_t::slot_type callback_slot_t;
// Fetches name information and calls callback.
// If name information is in cache, callback will be called immediately.
void get(const LLUUID& agent_id, callback_slot_t slot);
// Allow display names to be explicitly disabled for testing.
void setUseDisplayNames(bool use);
bool useDisplayNames();
void erase(const LLUUID& agent_id);
// Force a re-fetch of the most recent data, but keep the current
// data in cache
void fetch(const LLUUID& agent_id);
void insert(const LLUUID& agent_id, const LLAvatarName& av_name);
// Compute name expiration time from HTTP Cache-Control header,
// or return default value, in seconds from epoch.
F64 nameExpirationFromHeaders(LLSD headers);
void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
}
// Parse a cache-control header to get the max-age delta-seconds.
// Returns true if header has max-age param and it parses correctly.
// Exported here to ease unit testing.
bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age);
#endif
...@@ -69,6 +69,8 @@ class LLCacheNameEntry ...@@ -69,6 +69,8 @@ class LLCacheNameEntry
public: public:
bool mIsGroup; bool mIsGroup;
U32 mCreateTime; // unix time_t U32 mCreateTime; // unix time_t
// IDEVO TODO collapse names to one field, which will eliminate
// many string compares on "Resident"
std::string mFirstName; std::string mFirstName;
std::string mLastName; std::string mLastName;
std::string mGroupName; std::string mGroupName;
...@@ -215,6 +217,8 @@ class LLCacheName::Impl ...@@ -215,6 +217,8 @@ class LLCacheName::Impl
Impl(LLMessageSystem* msg); Impl(LLMessageSystem* msg);
~Impl(); ~Impl();
BOOL getName(const LLUUID& id, std::string& first, std::string& last);
boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback); boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback);
void addPending(const LLUUID& id, const LLHost& host); void addPending(const LLUUID& id, const LLHost& host);
...@@ -300,89 +304,10 @@ boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback& ...@@ -300,89 +304,10 @@ boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback&
return impl.mSignal.connect(callback); return impl.mSignal.connect(callback);
} }
void LLCacheName::importFile(LLFILE* fp)
{
S32 count = 0;
const S32 BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE]; /*Flawfinder: ignore*/
// *NOTE: These buffer sizes are hardcoded into sscanf() below
char id_string[MAX_STRING]; /*Flawfinder: ignore*/
char firstname[MAX_STRING]; /*Flawfinder: ignore*/
char lastname[MAX_STRING]; /*Flawfinder: ignore*/
U32 create_time;
// This is OK if the first line is actually a name. We just don't load it.
char* valid = fgets(buffer, BUFFER_SIZE, fp);
if (!valid) return;
// *NOTE: This buffer size is hardcoded into sscanf() below
char version_string[BUFFER_SIZE]; /*Flawfinder: ignore*/
S32 version = 0;
S32 match = sscanf( /* Flawfinder: ignore */
buffer,
"%1023s %d",
version_string, &version);
if ( match != 2
|| strcmp(version_string, "version")
|| version != CN_FILE_VERSION)
{
llwarns << "Ignoring old cache name file format" << llendl;
return;
}
// We'll expire entries more than a week old
U32 now = (U32)time(NULL);
const U32 SECS_PER_DAY = 60 * 60 * 24;
U32 delete_before_time = now - (7 * SECS_PER_DAY);
while(!feof(fp))
{
valid = fgets(buffer, BUFFER_SIZE, fp);
if (!valid) break;
match = sscanf( /* Flawfinder: ignore */
buffer,
"%254s %u %254s %254s",
id_string,
&create_time,
firstname,
lastname);
if (4 != match) continue;
LLUUID id(id_string);
if (id.isNull()) continue;
// undo trivial XOR
S32 i;
for (i = 0; i < UUID_BYTES; i++)
{
id.mData[i] ^= 0x33;
}
// Don't load entries that are more than a week old
if (create_time < delete_before_time) continue;
LLCacheNameEntry* entry = new LLCacheNameEntry();
entry->mIsGroup = false;
entry->mCreateTime = create_time;
entry->mFirstName = firstname;
entry->mLastName = lastname;
impl.mCache[id] = entry;
std::string fullname = entry->mFirstName + " " + entry->mLastName;
impl.mReverseCache[fullname] = id;
count++;
}
llinfos << "LLCacheName loaded " << count << " names" << llendl;
}
bool LLCacheName::importFile(std::istream& istr) bool LLCacheName::importFile(std::istream& istr)
{ {
LLSD data; LLSD data;
if(LLSDSerialize::fromXML(data, istr) < 1) if(LLSDSerialize::fromXMLDocument(data, istr) < 1)
return false; return false;
// We'll expire entries more than a week old // We'll expire entries more than a week old
...@@ -408,7 +333,7 @@ bool LLCacheName::importFile(std::istream& istr) ...@@ -408,7 +333,7 @@ bool LLCacheName::importFile(std::istream& istr)
entry->mFirstName = agent[FIRST].asString(); entry->mFirstName = agent[FIRST].asString();
entry->mLastName = agent[LAST].asString(); entry->mLastName = agent[LAST].asString();
impl.mCache[id] = entry; impl.mCache[id] = entry;
std::string fullname = entry->mFirstName + " " + entry->mLastName; std::string fullname = buildFullName(entry->mFirstName, entry->mLastName);
impl.mReverseCache[fullname] = id; impl.mReverseCache[fullname] = id;
++count; ++count;
...@@ -457,6 +382,7 @@ void LLCacheName::exportFile(std::ostream& ostr) ...@@ -457,6 +382,7 @@ void LLCacheName::exportFile(std::ostream& ostr)
// store it // store it
LLUUID id = iter->first; LLUUID id = iter->first;
std::string id_str = id.asString(); std::string id_str = id.asString();
// IDEVO TODO: Should we store SLIDs with last name "Resident" or not?
if(!entry->mFirstName.empty() && !entry->mLastName.empty()) if(!entry->mFirstName.empty() && !entry->mLastName.empty())
{ {
data[AGENTS][id_str][FIRST] = entry->mFirstName; data[AGENTS][id_str][FIRST] = entry->mFirstName;
...@@ -474,7 +400,7 @@ void LLCacheName::exportFile(std::ostream& ostr) ...@@ -474,7 +400,7 @@ void LLCacheName::exportFile(std::ostream& ostr)
} }
BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& last) BOOL LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last)
{ {
if(id.isNull()) if(id.isNull())
{ {
...@@ -483,7 +409,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las ...@@ -483,7 +409,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
return TRUE; return TRUE;
} }
LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id ); LLCacheNameEntry* entry = get_ptr_in_map(mCache, id );
if (entry) if (entry)
{ {
first = entry->mFirstName; first = entry->mFirstName;
...@@ -494,16 +420,17 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las ...@@ -494,16 +420,17 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
{ {
first = sCacheName["waiting"]; first = sCacheName["waiting"];
last.clear(); last.clear();
if (!impl.isRequestPending(id)) if (!isRequestPending(id))
{ {
impl.mAskNameQueue.insert(id); mAskNameQueue.insert(id);
} }
return FALSE; return FALSE;
} }
} }
// static // static
void LLCacheName::LocalizeCacheName(std::string key, std::string value) void LLCacheName::localizeCacheName(std::string key, std::string value)
{ {
if (key!="" && value!= "" ) if (key!="" && value!= "" )
sCacheName[key]=value; sCacheName[key]=value;
...@@ -514,11 +441,13 @@ void LLCacheName::LocalizeCacheName(std::string key, std::string value) ...@@ -514,11 +441,13 @@ void LLCacheName::LocalizeCacheName(std::string key, std::string value)
BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname) BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
{ {
std::string first_name, last_name; std::string first_name, last_name;
BOOL res = getName(id, first_name, last_name); BOOL res = impl.getName(id, first_name, last_name);
fullname = first_name + " " + last_name; fullname = buildFullName(first_name, last_name);
return res; return res;
} }
BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group) BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
{ {
if(id.isNull()) if(id.isNull())
...@@ -555,13 +484,13 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group) ...@@ -555,13 +484,13 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
BOOL LLCacheName::getUUID(const std::string& first, const std::string& last, LLUUID& id) BOOL LLCacheName::getUUID(const std::string& first, const std::string& last, LLUUID& id)
{ {
std::string fullname = first + " " + last; std::string full_name = buildFullName(first, last);
return getUUID(fullname, id); return getUUID(full_name, id);
} }
BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id) BOOL LLCacheName::getUUID(const std::string& full_name, LLUUID& id)
{ {
ReverseCache::iterator iter = impl.mReverseCache.find(fullname); ReverseCache::iterator iter = impl.mReverseCache.find(full_name);
if (iter != impl.mReverseCache.end()) if (iter != impl.mReverseCache.end())
{ {
id = iter->second; id = iter->second;
...@@ -573,6 +502,55 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id) ...@@ -573,6 +502,55 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
} }
} }
//static
std::string LLCacheName::buildFullName(const std::string& first, const std::string& last)
{
std::string fullname = first;
if (!last.empty()
&& last != "Resident")
{
fullname += ' ';
fullname += last;
}
return fullname;
}
//static
std::string LLCacheName::cleanFullName(const std::string& full_name)
{
return full_name.substr(0, full_name.find(" Resident"));
}
//static
std::string LLCacheName::buildUsername(const std::string& full_name)
{
// rare, but handle hard-coded error names returned from server
if (full_name == "(\?\?\?) (\?\?\?)")
{
return "(\?\?\?)";
}
std::string::size_type index = full_name.find(' ');
if (index != std::string::npos)
{
std::string username;
username = full_name.substr(0, index);
std::string lastname = full_name.substr(index+1);
if (lastname != "Resident")
{
username = username + "." + lastname;
}
LLStringUtil::toLower(username);
return username;
}
// if the input wasn't a correctly formatted legacy name just return it unchanged
return full_name;
}
// This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer. // This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer.
// The reason it is a slot is so that the legacy get() function below can bind an old callback // The reason it is a slot is so that the legacy get() function below can bind an old callback
// and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior // and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior
...@@ -580,7 +558,7 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id) ...@@ -580,7 +558,7 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
// we call it immediately. -Steve // we call it immediately. -Steve
// NOTE: Even though passing first and last name is a bit of extra overhead, it eliminates the // NOTE: Even though passing first and last name is a bit of extra overhead, it eliminates the
// potential need for any parsing should any code need to handle first and last name independently. // potential need for any parsing should any code need to handle first and last name independently.
boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback) boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
{ {
boost::signals2::connection res; boost::signals2::connection res;
...@@ -588,7 +566,7 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co ...@@ -588,7 +566,7 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
{ {
LLCacheNameSignal signal; LLCacheNameSignal signal;
signal.connect(callback); signal.connect(callback);
signal(id, sCacheName["nobody"], "", is_group); signal(id, sCacheName["nobody"], is_group);
return res; return res;
} }
...@@ -600,11 +578,13 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co ...@@ -600,11 +578,13 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
// id found in map therefore we can call the callback immediately. // id found in map therefore we can call the callback immediately.
if (entry->mIsGroup) if (entry->mIsGroup)
{ {
signal(id, entry->mGroupName, "", entry->mIsGroup); signal(id, entry->mGroupName, entry->mIsGroup);
} }
else else
{ {
signal(id, entry->mFirstName, entry->mLastName, entry->mIsGroup); std::string fullname =
buildFullName(entry->mFirstName, entry->mLastName);
signal(id, fullname, entry->mIsGroup);
} }
} }
else else
...@@ -626,9 +606,15 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co ...@@ -626,9 +606,15 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
return res; return res;
} }
boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data) boost::signals2::connection LLCacheName::getGroup(const LLUUID& group_id,
const LLCacheNameCallback& callback)
{
return get(group_id, true, callback);
}
boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data)
{ {
return get(id, is_group, boost::bind(callback, _1, _2, _3, _4, user_data)); return get(id, is_group, boost::bind(callback, _1, _2, _3, user_data));
} }
void LLCacheName::processPending() void LLCacheName::processPending()
...@@ -700,7 +686,7 @@ void LLCacheName::dump() ...@@ -700,7 +686,7 @@ void LLCacheName::dump()
{ {
llinfos llinfos
<< iter->first << " = " << iter->first << " = "
<< entry->mFirstName << " " << entry->mLastName << buildFullName(entry->mFirstName, entry->mLastName)
<< " @ " << entry->mCreateTime << " @ " << entry->mCreateTime
<< llendl; << llendl;
} }
...@@ -719,12 +705,24 @@ void LLCacheName::dumpStats() ...@@ -719,12 +705,24 @@ void LLCacheName::dumpStats()
<< llendl; << llendl;
} }
void LLCacheName::clear()
{
for_each(impl.mCache.begin(), impl.mCache.end(), DeletePairedPointer());
impl.mCache.clear();
}
//static //static
std::string LLCacheName::getDefaultName() std::string LLCacheName::getDefaultName()
{ {
return sCacheName["waiting"]; return sCacheName["waiting"];
} }
//static
std::string LLCacheName::getDefaultLastName()
{
return "Resident";
}
void LLCacheName::Impl::processPendingAsks() void LLCacheName::Impl::processPendingAsks()
{ {
LLMemType mt_ppa(LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS); LLMemType mt_ppa(LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS);
...@@ -746,11 +744,13 @@ void LLCacheName::Impl::processPendingReplies() ...@@ -746,11 +744,13 @@ void LLCacheName::Impl::processPendingReplies()
if (!entry->mIsGroup) if (!entry->mIsGroup)
{ {
(reply->mSignal)(reply->mID, entry->mFirstName, entry->mLastName, FALSE); std::string fullname =
LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
(reply->mSignal)(reply->mID, fullname, false);
} }
else else
{ {
(reply->mSignal)(reply->mID, entry->mGroupName, "", TRUE); (reply->mSignal)(reply->mID, entry->mGroupName, true);
} }
} }
...@@ -921,13 +921,27 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup) ...@@ -921,13 +921,27 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
if (!isGroup) if (!isGroup)
{ {
mSignal(id, entry->mFirstName, entry->mLastName, FALSE); // NOTE: Very occasionally the server sends down a full name
std::string fullname = entry->mFirstName + " " + entry->mLastName; // in the first name field with an empty last name, for example,
mReverseCache[fullname] = id; // first = "Ladanie1 Resident", last = "".
// I cannot reproduce this, nor can I find a bug in the server code.
// Ensure "Resident" does not appear via cleanFullName, because
// buildFullName only checks last name. JC
std::string full_name;
if (entry->mLastName.empty())
{
full_name = cleanFullName(entry->mFirstName);
} }
else else
{ {
mSignal(id, entry->mGroupName, "", TRUE); full_name = LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
}
mSignal(id, full_name, false);
mReverseCache[full_name] = id;
}
else
{
mSignal(id, entry->mGroupName, true);
mReverseCache[entry->mGroupName] = id; mReverseCache[entry->mGroupName] = id;
} }
} }
...@@ -956,4 +970,3 @@ void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** us ...@@ -956,4 +970,3 @@ void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** us
{ {
((LLCacheName::Impl*)userData)->processUUIDReply(msg, true); ((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment