Merge branch 'release/0.9.3.9030'
Some checks failed
CodeQL / Analyze (push) Has been cancelled

This commit is contained in:
Mike Dickson 2024-09-23 13:39:40 -04:00
commit 04f67c0272
103 changed files with 8021 additions and 259 deletions

1
Helpers/README.MD Normal file
View file

@ -0,0 +1 @@
This directory is for helper applications and tools that augment the server.

427
Helpers/xinv.php Normal file
View file

@ -0,0 +1,427 @@
<?php
// Inventory repair
// Balpien Hammerer, 2024
// Creative Commons: CC-BY-SA
// 2024/08/15 1.0 - Backend grid manager inventory check/fix
error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
define('DEBUG', false);
$sqllink = null;
// require '/var/www/html/common.php';
// Set grid specific table names
define('INVENTORYFOLDERS', 'inventoryfolders');
define('INVENTORYITEMS', 'inventoryitems');
define('USERACCOUNTS', 'UserAccounts');
if (!function_exists('ConnectDB'))
{
function ConnectDB($db)
{
// write a function to open a database via mysqli based on its friendly name (e.g. 'robust')
// The database must contain tables UserAccount, inventoryfolders, inventoryitems
// Return the link reference or false;
return false;
}
}
if (!function_exists('CloseDB'))
{
function CloseDB()
{
global $sqllink;
mysqli_close($sqllink);
$sqllink = null;
}
}
if (!function_exists('mkuuid'))
{
function mkuuid()
{
// Compute a uuid
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
// 32 bits for "time_low"
random_int(0, 0xffff), random_int(0, 0xffff),
// 16 bits for "time_mid"
random_int(0, 0xffff),
// 16 bits for "time_hi_and_version",
// four most significant bits holds version number 4
random_int(0, 0x0fff) | 0x4000,
// 16 bits, 8 bits for "clk_seq_hi_res",
// 8 bits for "clk_seq_low",
// two most significant bits holds zero and one for variant DCE1.1
random_int(0, 0x3fff) | 0x8000,
// 48 bits for "node"
random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff)
);
}
}
function OpenRobustDB()
{
global $sqllink;
$sqllink = ConnectDB('robust');
if ($sqllink === false) return false;
return true;
}
function GetAvatarUUID($aname)
{
global $sqllink;
$aname = trim($aname);
// Check for UUID (very basic) 00000000-0000-0000-0000-000000000000
if (strlen($aname) == 36 && substr($aname, 8,1) == '-' && substr($aname, 13,1) == '-' && substr($aname, 18,1) == '-' && substr($aname, 23,1) == '-')
{
return [$aname];
}
if (trim($aname) != '')
{
// Single avatar
$aa = explode(' ', $aname);
$fn = $aa[0];
$ln = @$aa[1];
if ($ln == '') $ln = 'Resident';
$query = "SELECT PrincipalID FROM " .USERACCOUNTS ." WHERE FirstName='$fn' AND LastName='$ln' ";
$result = mysqli_query($sqllink, $query);
if (mysqli_num_rows($result) == 0) return false;
$vars = mysqli_fetch_assoc($result);
return [$vars['PrincipalID']];
}
else
{
// All active avatars
$query = "SELECT PrincipalID FROM " .USERACCOUNTS ." WHERE UserLevel >= 0 ORDER BY Firstname, LastName ";
$result = mysqli_query($sqllink, $query);
if (mysqli_num_rows($result) == 0) return false;
$auuids = [];
while($vars = mysqli_fetch_assoc($result))
{
$auuids[] = $vars['PrincipalID'];
}
return $auuids;
}
}
function CheckDuplicateSystemFolders($rootid, $fix)
{
global $sqllink;
global $verbose;
$msgs = [];
// Look for duplicate system folders (type >= 0) that point to the root.
// Change the rest to ordinary folders (type -1) and rename them to duplicate-{foldername}
$query = "SELECT * FROM " .INVENTORYFOLDERS ." WHERE type >= 0 AND parentFolderID='$rootid' ORDER BY type, folderName, version DESC";
$result = mysqli_query($sqllink, $query);
// The list is ordered by type, folder name, version (count of next level folders).
$currftype = '';
$currfname = '';
$numfolders = 0;
while ($vars = mysqli_fetch_assoc($result))
{
$ftype = $vars['type'];
$fname = $vars['folderName'];
$fid = $vars['folderID'];
$fver = $vars['version'];
$fparent = $vars['parentFolderID'];
if ($currftype == '') $currftype = $ftype;
if ($currfname == '') $currfname = $fname;
if ($currftype != $ftype || $currfname != $fname)
{
$currftype = $ftype;
$currfname = $fname;
$numfolders = 0;
}
if ($currfname == $fname)
{
$numfolders++;
if ($numfolders > 1)
{
if ($fix)
{
$fname = mysqli_real_escape_string($sqllink, $fname);
$query = "UPDATE " .INVENTORYFOLDERS ." SET type=-1, folderName='Duplicate-$fname' WHERE folderID='$fid' ";
mysqli_query($sqllink, $query);
$msgs[] = "Duplicate ($numfolders) type $ftype folderID=$fid fixedname=Duplicate-$fname";
}
else
{
$msgs[] = "Duplicate ($numfolders) type $ftype folderID=$fid parentID=$fparent subfolders=$fver name=$fname";
}
}
else
{
if ($verbose) $msgs[] = "System folder type $ftype folderID=$fid parentID=$fparent subfolders=$fver name=$fname";
}
}
}
$msgs[] = "";
return $msgs;
}
function CheckInventory($auuid, $fix=false)
{
global $sqllink;
global $verbose;
// This performs basic integrity tests
// Returns [false, msgs...] if failures or [true, msgs...] if inventory is OK.
//
$msgs = [];
// Verify uuid is listed in UserAccounts. Issue warning but continue.
$query = "SELECT FirstName, LastName, UserLevel FROM " .USERACCOUNTS ." WHERE PrincipalID='$auuid' ";
$result = mysqli_query($sqllink, $query);
if ($vars = mysqli_fetch_assoc($result))
{
$msgs[] = "Checked UUID=$auuid Name={$vars['FirstName']} {$vars['LastName']} ";
}
else
{
$msgs[] = "Warning: UUID=$auuid does not exist in table " .USERACCOUNTS;
}
// Find root folder(s)
$query = "SELECT * FROM " .INVENTORYFOLDERS ." WHERE agentID='$auuid' AND (type=8 OR type=9) ORDER BY type ";
$result = mysqli_query($sqllink, $query);
$vars = mysqli_fetch_assoc($result);
$num = mysqli_num_rows($result);
if ($num == 0)
{
if ($fix)
{
$rootid = mkuuid();
$query = "INSERT INTO " .INVENTORYFOLDERS ." (folderName,type,version,folderID,agentID,parentFolderID)
VALUES('My Inventory', 8, 1, '$rootid', '$auuid','00000000-0000-0000-0000-000000000000')";
mysqli_query($sqllink, $query);
// Rerun select
$query = "SELECT * FROM " .INVENTORYFOLDERS ." WHERE agentID='$auuid' AND type=8 ";
$result = mysqli_query($sqllink, $query);
$vars = mysqli_fetch_assoc($result);
$num = mysqli_num_rows($result);
$msgs[] = "Warning: Missing root folder added. Consieder orphan check afterward: --chkorphan='uuid' ";
}
else
{
$msgs[] = "Warning: Root folder missing - needs adding root then orphan check required: --chkorphan='uuid' ";
return array_merge([false], $msgs);
}
}
if ($num > 1)
{
$msgs[] = "Multiple ($num) roots found - manual inspection required";
return array_merge([false], $msgs);
}
$rtype = $vars['type'];
$rootid = $vars['folderID'];
$rname = $vars['folderName'];
// One root, could be type 9 (olde version of IAR). Fix it if found.
if ($rtype != 8)
{
if ($fix)
{
$query = "UPDATE " .INVENTORYFOLDERS ." SET type=8 WHERE agentID='$auuid' AND type=9";
mysqli_query($sqllink, $query);
$msgs[] = "Warning: Old type 9 root found, converted to type=8";
}
else
{
$msgs[] = "Warning: Old type 9 root found, needs conversion to type 8";
}
}
if ($verbose) $msgs[] = "Root Folder type=$rtype folderID=$rootid name='$rname' ";
// Cleanup parentFolder of root type 8/9
$pfolder = $vars['parentFolderID'];
if ($pfolder != '00000000-0000-0000-0000-000000000000')
{
if ($fix)
{
$query = "UPDATE " .INVENTORYFOLDERS ." SET parentFolderID='00000000-0000-0000-0000-000000000000' WHERE agentID='$auuid' AND type=$rtype";
mysqli_query($sqllink, $query);
$msgs[] = "Warning: type $rtype root parent folder ID was $pfolder, set to null key";
}
else
{
$msgs[] = "Warning: type $rtype root parent folder ID was $pfolder, should be null key";
}
}
// Check the root folder.
$rc = CheckDuplicateSystemFolders($rootid, $fix);
$msgs = array_merge($msgs, $rc);
// Check for the My Suitcase folder.
$query = "SELECT * FROM " .INVENTORYFOLDERS ." WHERE agentID='$auuid' AND type=100 ";
$result = mysqli_query($sqllink, $query);
$vars = mysqli_fetch_assoc($result);
$num = mysqli_num_rows($result);
if ($num == 0)
{
if ($fix)
{
$suitid = mkuuid();
$query = "INSERT INTO " .INVENTORYFOLDERS ." (folderName,type,version,folderID,agentID,parentFolderID)
VALUES('My Suitcase', 100, 1, '$suitid', '$auuid','$rootid')";
mysqli_query($sqllink, $query);
// Rerun select
$query = "SELECT * FROM " .INVENTORYFOLDERS ." WHERE agentID='$auuid' AND type=100 ";
$result = mysqli_query($sqllink, $query);
$vars = mysqli_fetch_assoc($result);
$num = mysqli_num_rows($result);
$msgs[] = "Warning: Missing Suitcase folder added. Consieder orphan check afterward: --chkorphan='uuid' ";
}
else
{
$msgs[] = "My Suitcase folder is missing ";
}
}
if ($num > 1)
{
if ($fix)
{
$msgs[] = "Multiple ($num) roots found - converting one to ordinary folder";
}
else
{
$msgs[] = "Multiple ($num) roots found";
}
}
$rtype = $vars['type'];
$suitid = $vars['folderID'];
$rname = $vars['folderName'];
if ($verbose) $msgs[] = "My Suitcase Folder type=$rtype folderID=$suitid name='$rname' ";
// Fix parentFolder of My Suitcase type=100
$pfolder = $vars['parentFolderID'];
if ($pfolder != $rootid)
{
if ($fix)
{
$query = "UPDATE " .INVENTORYFOLDERS ." SET parentFolderID='$rootid' WHERE agentID='$auuid' AND type=$rtype";
mysqli_query($sqllink, $query);
$msgs[] = "Warning: type $rtype root parent folder ID was $pfolder, set to $rootid";
}
else
{
$msgs[] = "Warning: type $rtype root parent folder ID was $pfolder, should be $rootid";
}
}
// Check the suitcase folder.
$rc = CheckDuplicateSystemFolders($suitid, $fix);
$msgs = array_merge($msgs, $rc);
$msgs[] = "Scan Completed";
if ($verbose) $msgs[] = "";
return array_merge([true], $msgs);
}
// ===============================================================================================================
$sqllink = null;
$opts = getopt('v', ['chkinv::','fixinv:'] );
if (!OpenRobustDB())
{
echo "Unable to open grid database";
exit;
}
$cmd = '';
if (isset($opts['v'])) $verbose = true;
else $verbose = false;
/**/ if (isset($opts['chkinv'])) $cmd = 'chkinv';
else if (isset($opts['fixinv'])) $cmd = 'fixinv';
if ($cmd == '')
{
echo 'missing parameters: php xinv.php {--chkinv="firstname lastname" | --fixinv="firstname lastname"}' ."\n";
CloseDB();
exit;
}
// php xchkinv.php --chkinv="firstname lastname" or --chkinv="uuid"
if ($cmd == 'chkinv')
{
$auuids = false;
$aname = $opts['chkinv'];
// If avatar name is blank, get all active avatars
$auuids = GetAvatarUUID($aname);
if (!$auuids)
{
echo "Avatar $aname does not exist.\n";
}
else
{
foreach($auuids AS $auuid)
{
//echo "$aname uuid=$auuid\n";
$rc = CheckInventory($auuid, false);
foreach ($rc as $msg)
{
if ($msg === false) echo "Errors\n";
else if ($msg === true) echo "Success\n";
else echo $msg ."\n";
}
}
}
}
// php xchkinv.php --fixinv="firstname lastname" or --fixinv="uuid"
else if ($cmd == 'fixinv')
{
$aname = $opts['fixinv'];
$auuid = GetAvatarUUID($aname);
if (!$auuid)
{
error_log("$aname does not exist.");
}
else
{
$auuid = $auuid[0];
error_log("Avatar $aname uuid=$auuid");
$rc = CheckInventory($auuid, true);
foreach ($rc as $msg)
{
if ($msg === false) echo "Errors\n";
else if ($msg === true) echo "Success\n";
else echo $msg ."\n";
}
}
}
CloseDB();
exit;
?>

View file

@ -1,43 +0,0 @@
# hey, emacs! this is a -*- makefile -*-
#
# OpenSim makefile
#
RUBY = $(strip $(shell which ruby 2>/dev/null))
ifeq ($(RUBY),)
NANT = nant
else
NANT = $(shell if test "$$EMACS" = "t" ; then echo "nant"; else echo "./nant-color"; fi)
endif
all: prebuild
# @export PATH=/usr/local/bin:$(PATH)
${NANT}
find OpenSim -name \*.mdb -exec cp {} bin \;
release: prebuild
${NANT} -D:project.config=Release
find OpenSim -name \*.mdb -exec cp {} bin \;
prebuild:
./runprebuild.sh
clean:
# @export PATH=/usr/local/bin:$(PATH)
-${NANT} clean
test: prebuild
${NANT} test
test-xml: prebuild
${NANT} test-xml
tags:
find OpenSim -name \*\.cs | xargs etags
cscope-tags:
find OpenSim -name \*\.cs -fprint cscope.files
cscope -b
include $(wildcard Makefile.local)

View file

@ -147,6 +147,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenSim.Region.OptionalModu
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenSim.Server.MoneyServer", "addon-modules\OpenSim.Server.MoneyServer\OpenSim.Server.MoneyServer\OpenSim.Server.MoneyServer.csproj", "{C3AEE6AC-BE40-4003-A7A3-E8AA039E4451}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSim.Services.ExperienceService", "OpenSim\Services\ExperienceService\OpenSim.Services.ExperienceService.csproj", "{186509B6-EF90-431A-9034-75A1221E4120}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{7F5EC7C6-FD99-4084-8530-5D3F28D6D7C0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSim.Tests.Common", "Tests\OpenSim.Tests.Common\OpenSim.Tests.Common.csproj", "{4B7616BC-6CCE-4B78-AE40-1F24C92442F5}"
@ -457,6 +459,10 @@ Global
{B120B128-D6C6-40B6-9D83-4F1F7D921109}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B120B128-D6C6-40B6-9D83-4F1F7D921109}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B120B128-D6C6-40B6-9D83-4F1F7D921109}.Release|Any CPU.Build.0 = Release|Any CPU
{186509B6-EF90-431A-9034-75A1221E4120}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{186509B6-EF90-431A-9034-75A1221E4120}.Debug|Any CPU.Build.0 = Debug|Any CPU
{186509B6-EF90-431A-9034-75A1221E4120}.Release|Any CPU.ActiveCfg = Release|Any CPU
{186509B6-EF90-431A-9034-75A1221E4120}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -1645,8 +1645,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController
bool mergeOar = false;
bool skipAssets = false;
// bool lookupAliases = false;
// bool allowReassign = false;
bool lookupAliases = false;
bool noDefaultUser = false;
if ((string)requestData["merge"] == "true")
{
@ -1656,22 +1656,22 @@ namespace OpenSim.ApplicationPlugins.RemoteController
{
skipAssets = true;
}
// if ((string)requestData["lookup-aliases"] == "true")
// {
// lookupAliases = true;
// }
// if ((string)requestData["allow-reassign"] == "true")
// {
// allowReassign = true;
// }
if ((string)requestData["lookup-aliases"] == "true")
{
lookupAliases = true;
}
if ((string)requestData["no-defaultuser"] == "true")
{
noDefaultUser = true;
}
IRegionArchiverModule archiver = scene.RequestModuleInterface<IRegionArchiverModule>();
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
if (mergeOar) archiveOptions.Add("merge", null);
if (skipAssets) archiveOptions.Add("skipAssets", null);
// if (lookupAliases) archiveOptions.Add("lookupAliases", null);
// if (allowReassign) archiveOptions.Add("allowReassign", null);
if (lookupAliases) archiveOptions.Add("lookup-aliases", null);
if (noDefaultUser) archiveOptions.Add("no-defaultuser", null);
if (archiver != null)
archiver.DearchiveRegion(filename, Guid.Empty, archiveOptions);

View file

@ -46,5 +46,10 @@ namespace OpenSim.Framework.Capabilities
/// State of the upload. So far have only even seen this set to "complete"
/// </summary>
public string state;
/// <summary>
/// What experience key should be used with this script
/// </summary>
public UUID experience = UUID.Zero;
}
}

View file

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using OpenMetaverse;
using OpenSim.Framework;
namespace OpenSim.Data
{
public interface IExperienceData
{
Dictionary<UUID, bool> GetExperiencePermissions(UUID agent_id);
bool ForgetExperiencePermissions(UUID agent_id, UUID experience_id);
bool SetExperiencePermissions(UUID agent_id, UUID experience_id, bool allow);
ExperienceInfoData[] GetExperienceInfos(UUID[] experiences);
ExperienceInfoData[] FindExperiences(string search);
UUID[] GetAgentExperiences(UUID agent_id);
UUID[] GetGroupExperiences(UUID agent_id);
UUID[] GetExperiencesForGroups(UUID[] groups);
bool UpdateExperienceInfo(ExperienceInfoData data);
// KeyValue
string GetKeyValue(UUID experience, string key);
bool SetKeyValue(UUID experience, string key, string val);
bool DeleteKey(UUID experience, string key);
int GetKeyCount(UUID experience);
string[] GetKeys(UUID experience, int start, int count);
int GetKeyValueSize(UUID experience);
}
}

View file

@ -131,6 +131,8 @@ namespace OpenSim.Data.MySQL
es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
es.AllowedExperiences = LoadUUIDList(es.EstateID, "estate_allowed_experiences");
es.KeyExperiences = LoadUUIDList(es.EstateID, "estate_key_experiences");
return es;
}
@ -184,6 +186,8 @@ namespace OpenSim.Data.MySQL
es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers");
es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users");
es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups");
es.AllowedExperiences = LoadUUIDList(es.EstateID, "estate_allowed_experiences");
es.KeyExperiences = LoadUUIDList(es.EstateID, "estate_key_experiences");
return es;
}
@ -278,6 +282,8 @@ namespace OpenSim.Data.MySQL
SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers);
SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess);
SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups);
SaveUUIDList(es.EstateID, "estate_allowed_experiences", es.AllowedExperiences);
SaveUUIDList(es.EstateID, "estate_key_experiences", es.KeyExperiences);
}
private void LoadBanList(EstateSettings es)

View file

@ -0,0 +1,429 @@
using System.Reflection;
using System.Data;
using MySqlConnector;
using OpenSim.Framework;
using System.Collections.Generic;
using OpenMetaverse;
using OpenMetaverse.Packets;
using System.Linq;
using log4net;
namespace OpenSim.Data.MySQL
{
public class MySqlExperienceData : MySqlFramework, IExperienceData
{
protected virtual Assembly Assembly
{
get { return GetType().Assembly; }
}
public MySqlExperienceData(string connectionString)
: base(connectionString)
{
m_connectionString = connectionString;
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
Migration m = new Migration(dbcon, Assembly, "Experience");
m.Update();
dbcon.Close();
}
}
public Dictionary<UUID, bool> GetExperiencePermissions(UUID agent_id)
{
Dictionary<UUID, bool> experiencePermissions = new Dictionary<UUID, bool>();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd
= new MySqlCommand("select * from `experience_permissions` where avatar = ?avatar", dbcon))
{
cmd.Parameters.AddWithValue("?avatar", agent_id.ToString());
using (IDataReader result = cmd.ExecuteReader())
{
while (result.Read())
{
string uuid = result.GetString(0);
bool allow = result.GetBoolean(2);
UUID experience_key;
if(UUID.TryParse(uuid, out experience_key))
{
experiencePermissions.Add(experience_key, allow);
}
}
dbcon.Close();
}
}
}
return experiencePermissions;
}
public bool ForgetExperiencePermissions(UUID agent_id, UUID experience_id)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd
= new MySqlCommand("delete from `experience_permissions` where avatar = ?avatar AND experience = ?experience LIMIT 1", dbcon))
{
cmd.Parameters.AddWithValue("?avatar", agent_id.ToString());
cmd.Parameters.AddWithValue("?experience", experience_id.ToString());
return (cmd.ExecuteNonQuery() > 0);
}
}
}
public bool SetExperiencePermissions(UUID agent_id, UUID experience_id, bool allow)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("replace into `experience_permissions` (avatar, experience, allow) VALUES (?avatar, ?experience, ?allow)", dbcon))
{
cmd.Parameters.AddWithValue("?avatar", agent_id.ToString());
cmd.Parameters.AddWithValue("?experience", experience_id.ToString());
cmd.Parameters.AddWithValue("?allow", allow);
return (cmd.ExecuteNonQuery() > 0);
}
}
}
public ExperienceInfoData[] GetExperienceInfos(UUID[] experiences)
{
List<string> uuids = new List<string>();
foreach (var u in experiences)
uuids.Add("'" + u.ToString() + "'");
string joined = string.Join(",", uuids);
List<ExperienceInfoData> infos = new List<ExperienceInfoData>();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM `experiences` WHERE public_id IN (" + joined + ")", dbcon))
{
using (IDataReader result = cmd.ExecuteReader())
{
while (result.Read())
{
ExperienceInfoData info = new ExperienceInfoData();
info.public_id = UUID.Parse(result["public_id"].ToString());
info.owner_id = UUID.Parse(result["owner_id"].ToString());
info.group_id = UUID.Parse(result["group_id"].ToString());
info.name = result["name"].ToString();
info.description = result["description"].ToString();
info.logo = UUID.Parse(result["logo"].ToString());
info.marketplace = result["marketplace"].ToString();
info.slurl = result["slurl"].ToString();
info.maturity = int.Parse(result["maturity"].ToString());
info.properties = int.Parse(result["properties"].ToString());
infos.Add(info);
}
}
}
dbcon.Close();
}
return infos.ToArray();
}
public UUID[] GetAgentExperiences(UUID agent_id)
{
List<UUID> experiences = new List<UUID>();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM `experiences` WHERE owner_id = ?avatar", dbcon))
{
cmd.Parameters.AddWithValue("?avatar", agent_id.ToString());
using (IDataReader result = cmd.ExecuteReader())
{
while (result.Read())
{
experiences.Add(UUID.Parse(result["public_id"].ToString()));
}
}
}
dbcon.Close();
}
return experiences.ToArray();
}
public bool UpdateExperienceInfo(ExperienceInfoData data)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("replace into `experiences` (public_id, owner_id, name, description, group_id, logo, marketplace, slurl, maturity, properties) VALUES (?public_id, ?owner_id, ?name, ?description, ?group_id, ?logo, ?marketplace, ?slurl, ?maturity, ?properties)", dbcon))
{
cmd.Parameters.AddWithValue("?public_id", data.public_id.ToString());
cmd.Parameters.AddWithValue("?owner_id", data.owner_id.ToString());
cmd.Parameters.AddWithValue("?name", data.name);
cmd.Parameters.AddWithValue("?description", data.description);
cmd.Parameters.AddWithValue("?group_id", data.group_id.ToString());
cmd.Parameters.AddWithValue("?logo", data.logo.ToString());
cmd.Parameters.AddWithValue("?marketplace", data.marketplace);
cmd.Parameters.AddWithValue("?slurl", data.slurl);
cmd.Parameters.AddWithValue("?maturity", data.maturity);
cmd.Parameters.AddWithValue("?properties", data.properties);
return (cmd.ExecuteNonQuery() > 0);
}
}
}
public ExperienceInfoData[] FindExperiences(string search)
{
List<ExperienceInfoData> experiences = new List<ExperienceInfoData>();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM `experiences` WHERE name LIKE ?search", dbcon))
{
cmd.Parameters.AddWithValue("?search", string.Format("%{0}%", search));
using (IDataReader result = cmd.ExecuteReader())
{
while (result.Read())
{
ExperienceInfoData info = new ExperienceInfoData();
info.public_id = UUID.Parse(result["public_id"].ToString());
info.owner_id = UUID.Parse(result["owner_id"].ToString());
info.group_id = UUID.Parse(result["group_id"].ToString());
info.name = result["name"].ToString();
info.description = result["description"].ToString();
info.logo = UUID.Parse(result["logo"].ToString());
info.marketplace = result["marketplace"].ToString();
info.slurl = result["slurl"].ToString();
info.maturity = int.Parse(result["maturity"].ToString());
info.properties = int.Parse(result["properties"].ToString());
experiences.Add(info);
}
}
}
dbcon.Close();
}
return experiences.ToArray();
}
public UUID[] GetGroupExperiences(UUID group_id)
{
List<UUID> experiences = new List<UUID>();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM `experiences` WHERE group_id = ?group", dbcon))
{
cmd.Parameters.AddWithValue("?group", group_id.ToString());
using (IDataReader result = cmd.ExecuteReader())
{
while (result.Read())
{
experiences.Add(UUID.Parse(result["public_id"].ToString()));
}
}
}
dbcon.Close();
}
return experiences.ToArray();
}
public UUID[] GetExperiencesForGroups(UUID[] groups)
{
List<string> uuids = new List<string>();
foreach (var u in groups)
uuids.Add("'" + u.ToString() + "'");
string joined = string.Join(",", uuids);
List<UUID> experiences = new List<UUID>();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM `experiences` WHERE group_id IN (" + joined + ")", dbcon))
{
using (IDataReader result = cmd.ExecuteReader())
{
while (result.Read())
{
experiences.Add(UUID.Parse(result["public_id"].ToString()));
}
}
}
dbcon.Close();
}
return experiences.ToArray();
}
// KeyValue
public bool SetKeyValue(UUID experience, string key, string val)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("REPLACE INTO `experience_kv` (`experience`, `key`, `value`) VALUES (?experience, ?key, ?value)", dbcon))
{
cmd.Parameters.AddWithValue("?experience", experience.ToString());
cmd.Parameters.AddWithValue("?key", key);
cmd.Parameters.AddWithValue("?value", val);
return (cmd.ExecuteNonQuery() > 0);
}
}
}
public string GetKeyValue(UUID experience, string key)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM `experience_kv` WHERE `experience` = ?experience AND `key` = ?key LIMIT 1", dbcon))
{
cmd.Parameters.AddWithValue("?experience", experience.ToString());
cmd.Parameters.AddWithValue("?key", key);
using (IDataReader result = cmd.ExecuteReader())
{
if (result.Read())
{
return result["value"].ToString();
}
}
}
dbcon.Close();
}
return null;
}
public bool DeleteKey(UUID experience, string key)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("DELETE FROM `experience_kv` WHERE `experience` = ?experience AND `key` = ?key LIMIT 1", dbcon))
{
cmd.Parameters.AddWithValue("?experience", experience.ToString());
cmd.Parameters.AddWithValue("?key", key);
return (cmd.ExecuteNonQuery() > 0);
}
}
}
public int GetKeyCount(UUID experience)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) AS `count` FROM `experience_kv` WHERE `experience` = ?experience", dbcon))
{
cmd.Parameters.AddWithValue("?experience", experience.ToString());
using (IDataReader result = cmd.ExecuteReader())
{
if (result.Read())
{
return int.Parse(result["count"].ToString());
}
}
}
dbcon.Close();
}
return 0;
}
public string[] GetKeys(UUID experience, int start, int count)
{
List<string> keys = new List<string>();
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT `key` FROM `experience_kv` WHERE `experience` = ?experience LIMIT ?start, ?count;", dbcon))
{
cmd.Parameters.AddWithValue("?experience", experience.ToString());
cmd.Parameters.AddWithValue("?start", start);
cmd.Parameters.AddWithValue("?count", count);
using (IDataReader result = cmd.ExecuteReader())
{
while (result.Read())
{
keys.Add(result["key"].ToString());
}
}
}
dbcon.Close();
}
return keys.ToArray();
}
public int GetKeyValueSize(UUID experience)
{
using (MySqlConnection dbcon = new MySqlConnection(m_connectionString))
{
dbcon.Open();
using (MySqlCommand cmd = new MySqlCommand("SELECT IFNULL(SUM(LENGTH(`key`) + LENGTH(`value`)), 0) AS `size` FROM `experience_kv` WHERE `experience` = ?experience", dbcon))
{
cmd.Parameters.AddWithValue("?experience", experience.ToString());
using (IDataReader result = cmd.ExecuteReader())
{
if (result.Read())
{
return int.Parse(result["size"].ToString());
}
}
}
dbcon.Close();
}
return 0;
}
}
}

View file

@ -171,7 +171,7 @@ namespace OpenSim.Data.MySQL
"PhysicsShapeType, Density, GravityModifier, " +
"Friction, Restitution, Vehicle, PhysInertia, DynAttrs, " +
"RotationAxisLocks, sopanims, sitactrange, pseudocrc, " +
"linksetdata" +
"linksetdata, AllowUnsit, ScriptedSitOnly" +
") values (" + "?UUID, " +
"?CreationDate, ?Name, ?Text, " +
"?Description, ?SitName, ?TouchName, " +
@ -207,7 +207,7 @@ namespace OpenSim.Data.MySQL
"?PhysicsShapeType, ?Density, ?GravityModifier, " +
"?Friction, ?Restitution, ?Vehicle, ?PhysInertia, ?DynAttrs," +
"?RotationAxisLocks, ?sopanims, ?sitactrange, ?pseudocrc, " +
"?linksetdata)";
"?linksetdata, ?AllowUnsit, ?ScriptedSitOnly)";
FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
@ -1191,6 +1191,9 @@ namespace OpenSim.Data.MySQL
prim.LinksetData = LinksetData.DeserializeLinksetData((string)row["linksetdata"]);
}
prim.AllowUnsit = ((sbyte)row["AllowUnsit"] != 0);
prim.ScriptedSitOnly = ((sbyte)row["ScriptedSitOnly"] != 0);
return prim;
}
@ -1624,7 +1627,17 @@ namespace OpenSim.Data.MySQL
else
{
cmd.Parameters.AddWithValue("linksetdata", null);
}
}
if (prim.AllowUnsit)
cmd.Parameters.AddWithValue("AllowUnsit", 1);
else
cmd.Parameters.AddWithValue("AllowUnsit", 0);
if (prim.ScriptedSitOnly)
cmd.Parameters.AddWithValue("ScriptedSitOnly", 1);
else
cmd.Parameters.AddWithValue("ScriptedSitOnly", 0);
}
/// <summary>

View file

@ -66,15 +66,16 @@ namespace OpenSim.Data.MySQL
{
if (words.Length == 1)
{
cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search) and active=1", m_Realm);
cmd.CommandText = string.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?search or LastName like ?search or DisplayName like ?search) and active=1", m_Realm);
cmd.Parameters.AddWithValue("?search", "%" + words[0] + "%");
cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
}
else
{
cmd.CommandText = String.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst and LastName like ?searchLast) and active=1", m_Realm);
cmd.CommandText = string.Format("select * from {0} where (ScopeID=?ScopeID or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like ?searchFirst and LastName like ?searchLast or DisplayName like ?searchDisplay) and active=1", m_Realm);
cmd.Parameters.AddWithValue("?searchFirst", "%" + words[0] + "%");
cmd.Parameters.AddWithValue("?searchLast", "%" + words[1] + "%");
cmd.Parameters.AddWithValue("?searchDisplay", "%" + query + "%");
cmd.Parameters.AddWithValue("?ScopeID", scopeID.ToString());
}

View file

@ -33,6 +33,7 @@
<EmbeddedResource Include="Resources\Avatar.migrations" />
<EmbeddedResource Include="Resources\EstateStore.migrations" />
<EmbeddedResource Include="Resources\FriendsStore.migrations" />
<EmbeddedResource Include="Resources\Experience.migrations" />
<EmbeddedResource Include="Resources\FSAssetStore.migrations" />
<EmbeddedResource Include="Resources\GridStore.migrations" />
<EmbeddedResource Include="Resources\GridUserStore.migrations" />

View file

@ -81,3 +81,17 @@ BEGIN;
ALTER TABLE `estate_settings`
ADD COLUMN `AllowEnviromentOverride` tinyint(4) NOT NULL DEFAULT '0';
COMMIT;
:VERSION 37
CREATE TABLE IF NOT EXISTS `estate_allowed_experiences` (
`EstateID` int(10) unsigned NOT NULL,
`uuid` char(36) NOT NULL,
KEY `EstateID` (`EstateID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `estate_key_experiences` (
`EstateID` int(10) unsigned NOT NULL,
`uuid` char(36) NOT NULL,
KEY `EstateID` (`EstateID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
COMMIT;

View file

@ -0,0 +1,40 @@
:VERSION 3 # -----------------
BEGIN;
CREATE TABLE IF NOT EXISTS `experiences` (
`public_id` VARCHAR(36) NOT NULL,
`owner_id` VARCHAR(36) NOT NULL,
`name` VARCHAR(42) NOT NULL,
`description` VARCHAR(128) NOT NULL,
`group_id` VARCHAR(36) NOT NULL,
`logo` VARCHAR(36) NOT NULL,
`marketplace` VARCHAR(256) NOT NULL,
`slurl` VARCHAR(256) NOT NULL,
`maturity` INT NOT NULL,
`properties` INT NOT NULL,
PRIMARY KEY (`public_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `experience_permissions` (
`experience` VARCHAR(36) NOT NULL COLLATE 'utf8_unicode_ci',
`avatar` VARCHAR(36) NOT NULL COLLATE 'utf8_unicode_ci',
`allow` BIT(1) NOT NULL,
PRIMARY KEY (`experience`, `avatar`) USING BTREE,
INDEX `avatar` (`avatar`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
COMMIT;
:VERSION 4 # -----------------
BEGIN;
CREATE TABLE IF NOT EXISTS `experience_kv` (
`experience` VARCHAR(36) NOT NULL,
`key` VARCHAR(1011) NOT NULL COLLATE 'latin1_bin',
`value` VARCHAR(4095) NOT NULL COLLATE 'utf8mb4_0900_ai_ci',
PRIMARY KEY(`experience`, `key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
COMMIT;

View file

@ -566,4 +566,11 @@ ALTER TABLE `regionsettings` ADD COLUMN `TerrainPBR1` varchar(36) NOT NULL DEFAU
ALTER TABLE `regionsettings` ADD COLUMN `TerrainPBR2` varchar(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
ALTER TABLE `regionsettings` ADD COLUMN `TerrainPBR3` varchar(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
ALTER TABLE `regionsettings` ADD COLUMN `TerrainPBR4` varchar(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000';
COMMIT;
COMMIT;
:VERSION 67 #----- Add allow unsit and scripted sit only
BEGIN;
ALTER TABLE `prims`
ADD COLUMN `AllowUnsit` TINYINT(3) NULL DEFAULT '1',
ADD COLUMN `ScriptedSitOnly` TINYINT(3) NULL DEFAULT '0';
COMMIT;

View file

@ -29,3 +29,13 @@ BEGIN;
ALTER TABLE `UserAccounts` ADD `active` INT NOT NULL DEFAULT '1';
COMMIT;
:VERSION 7 # -------------------------
BEGIN;
ALTER TABLE `UserAccounts`
ADD COLUMN `DisplayName` VARCHAR(31) NULL AFTER `active`,
ADD COLUMN `NameChanged` INT NULL DEFAULT 0 AFTER `DisplayName`;
COMMIT;

View file

@ -36,6 +36,7 @@
<Compile Remove="MySQL\MySQLAuthenticationData.cs" />
<Compile Remove="MySQL\MySQLAvatarData.cs" />
<Compile Remove="MySQL\MySQLEstateData.cs" />
<Compile Remove="MySQL\MySQLExperienceData.cs" />
<Compile Remove="MySQL\MySQLFramework.cs" />
<Compile Remove="MySQL\MySQLFriendsData.cs" />
<Compile Remove="MySQL\MySQLFSAssetData.cs" />

View file

@ -983,9 +983,9 @@ namespace OpenSim.Data.PGSQL
command.Parameters.AddRange(CreateRegionSettingParameters(regionSettings));
command.ExecuteNonQuery();
command.Transaction.Commit();
}
}
catch (Exception e)
{
{
Console.WriteLine(e);
command.Transaction.Rollback();
throw;

View file

@ -96,7 +96,9 @@ namespace OpenSim.Framework
AllowedAccess = MaxEstateAccessIds,
AllowedGroups = 63,
EstateBans = 500,
EstateManagers = MaxEstateManagers
EstateManagers = MaxEstateManagers,
AllowedExperiences = 8,
KeyExperiences = 8
}
[Flags]public enum TeleportFlags : uint

View file

@ -278,6 +278,22 @@ namespace OpenSim.Framework
set { l_EstateGroups = new List<UUID>(value); }
}
private List<UUID> l_AllowedExperiences = new List<UUID>();
public UUID[] AllowedExperiences
{
get { return l_AllowedExperiences.ToArray(); }
set { l_AllowedExperiences = new List<UUID>(value); }
}
private List<UUID> l_KeyExperiences = new List<UUID>();
public UUID[] KeyExperiences
{
get { return l_KeyExperiences.ToArray(); }
set { l_KeyExperiences = new List<UUID>(value); }
}
public bool DoDenyMinors = true;
public bool DoDenyAnonymous = true;
@ -449,6 +465,46 @@ namespace OpenSim.Framework
return l_EstateGroups.Contains(groupID);
}
public int AllowedExperiencesCount()
{
return l_AllowedExperiences.Count;
}
public void AddAllowedExperience(UUID experienceKey)
{
if (experienceKey == UUID.Zero)
return;
if (!l_AllowedExperiences.Contains(experienceKey) &&
(l_AllowedExperiences.Count < (int)Constants.EstateAccessLimits.AllowedExperiences))
l_AllowedExperiences.Add(experienceKey);
}
public void RemoveAllowedExperience(UUID experienceKey)
{
if (l_AllowedExperiences.Contains(experienceKey))
l_AllowedExperiences.Remove(experienceKey);
}
public int KeyExperiencesCount()
{
return l_KeyExperiences.Count;
}
public void AddKeyExperience(UUID experienceKey)
{
if (experienceKey == UUID.Zero)
return;
if (!l_KeyExperiences.Contains(experienceKey) &&
(l_KeyExperiences.Count < (int)Constants.EstateAccessLimits.KeyExperiences))
l_KeyExperiences.Add(experienceKey);
}
public void RemoveKeyExperience(UUID experienceKey)
{
if (l_KeyExperiences.Contains(experienceKey))
l_KeyExperiences.Remove(experienceKey);
}
public Dictionary<string, object> ToMap()
{
Dictionary<string, object> map = new();

View file

@ -0,0 +1,36 @@
using OpenMetaverse;
using System.Collections.Generic;
namespace OpenSim.Framework
{
public class ExperienceInfoData
{
public UUID public_id;
public UUID owner_id;
public UUID group_id;
public string name;
public string description;
public UUID logo;
public string marketplace;
public string slurl;
public int maturity;
public int properties;
public Dictionary<string, object> ToDictionary()
{
Dictionary<string, object> dict = new Dictionary<string, object>();
dict["public_id"] = public_id;
dict["owner_id"] = owner_id;
dict["group_id"] = group_id;
dict["name"] = name;
dict["description"] = description;
dict["logo"] = logo;
dict["marketplace"] = marketplace;
dict["slurl"] = slurl;
dict["maturity"] = maturity;
dict["properties"] = properties;
return dict;
}
}
}

View file

@ -0,0 +1,108 @@
using OpenMetaverse.StructuredData;
using OpenMetaverse;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.TimeZoneInfo;
using System.Security.AccessControl;
namespace OpenSim.Framework
{
public abstract class EnvironmentUpdate
{
public string ObjectName = string.Empty;
public UUID OwnerID = UUID.Zero;
public string ParcelName = string.Empty;
public int Permission = 0;
public string Action = string.Empty;
public float TransitionTime = 0.0f;
public abstract OSDMap ToMap();
}
public class FullEnvironmentUpdate : EnvironmentUpdate
{
public UUID AssetID = UUID.Zero;
public new string Action => "PushFullEnvironment";
public override OSDMap ToMap()
{
OSDMap map = new OSDMap();
map["ObjectName"] = ObjectName;
map["OwnerID"] = OwnerID;
map["ParcelName"] = ParcelName;
map["Permission"] = Permission;
map["action"] = Action;
OSDMap action_data = new OSDMap();
action_data["asset_id"] = AssetID;
action_data["transition_time"] = TransitionTime;
map["action_data"] = action_data;
return map;
}
}
public class PartialEnvironmentUpdate : EnvironmentUpdate
{
public OSDMap water = new OSDMap();
public OSDMap sky = new OSDMap();
public new string Action => "PushPartialEnvironment";
public override OSDMap ToMap()
{
OSDMap map = new OSDMap();
map["ObjectName"] = ObjectName;
map["OwnerID"] = OwnerID;
map["ParcelName"] = ParcelName;
map["Permission"] = Permission;
map["action"] = Action;
OSDMap settings = new OSDMap();
if (water.Count > 0)
settings["water"] = water;
if (sky.Count > 0)
settings["sky"] = sky;
OSDMap action_data = new OSDMap();
action_data["settings"] = settings;
action_data["transition_time"] = TransitionTime;
map["action_data"] = action_data;
return map;
}
}
public class ClearEnvironmentUpdate : EnvironmentUpdate
{
public new string Action => "ClearEnvironment";
public override OSDMap ToMap()
{
OSDMap map = new OSDMap();
map["ObjectName"] = ObjectName;
map["OwnerID"] = OwnerID;
map["ParcelName"] = ParcelName;
map["Permission"] = Permission;
map["action"] = Action;
OSDMap action_data = new OSDMap();
action_data["transition_time"] = TransitionTime;
map["action_data"] = action_data;
return map;
}
}
}

View file

@ -378,6 +378,9 @@ namespace OpenSim.Framework
public delegate void UpdateEstateAccessDeltaRequest(
IClientAPI remote_client, UUID invoice, int estateAccessType, UUID user);
public delegate void UpdateEstateExperienceDeltaRequest(
IClientAPI remote_client, UUID invoice, int estateAccessType, UUID user);
public delegate void SimulatorBlueBoxMessageRequest(
IClientAPI remoteClient, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message);
@ -931,6 +934,7 @@ namespace OpenSim.Framework
event EstateRestartSimRequest OnEstateRestartSimRequest;
event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
event UpdateEstateExperienceDeltaRequest OnUpdateEstateExperienceDeltaRequest;
event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
event EstateDebugRegionRequest OnEstateDebugRegionRequest;
@ -1099,6 +1103,8 @@ namespace OpenSim.Framework
void SendGenericMessage(string method, UUID invoice, List<string> message);
void SendGenericMessage(string method, UUID invoice, List<byte[]> message);
void SendGenericMessageForExperience(UUID experience_id, UUID avatar_id, int action, string obj_name, string parcel, bool is_attachment = false);
bool CanSendLayerData();
void SendLayerData();
@ -1249,7 +1255,7 @@ namespace OpenSim.Framework
void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] membershipType, string flAbout,
uint flags, UUID flImageID, UUID imageID, string profileURL, UUID partnerID);
void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question);
void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question, UUID experience);
void SendHealth(float health);
@ -1263,6 +1269,8 @@ namespace OpenSim.Framework
void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags,
uint sunPosition, UUID covenant, uint covenantChanged, string abuseEmail, UUID estateOwner);
void SendEstateExperiences(UUID invoice, UUID[] allowed, UUID[] key, uint estateID);
/// <summary>
/// Send land properties to the client.
/// </summary>

View file

@ -42,6 +42,56 @@ namespace OpenSim.Framework
public bool HasGridUserTried;
public bool IsLocal;
public double LastWebFail = -1;
public string DisplayName;
public DateTime NameChanged;
public bool IsNameDefault
{
get
{
return string.IsNullOrWhiteSpace(DisplayName);
}
}
public string LegacyName
{
get
{
if (LastName.ToLower() == "resident")
return FirstName;
else return $"{FirstName} {LastName}";
}
}
public string Username
{
get
{
if (LastName.ToLower() == "resident")
return FirstName;
else if(LastName.StartsWith("@"))
return $"{FirstName}{LastName}";
else return $"{FirstName}.{LastName}";
}
}
public string LowerUsername
{
get
{
return Username.ToLower();
}
}
public string ViewerDisplayName
{
get
{
if (IsNameDefault)
return LegacyName;
else return DisplayName;
}
}
}
public interface IPeople

View file

@ -308,7 +308,7 @@ namespace OpenSim.Framework.Servers.HttpServer
if(htype == UriHostNameType.Unknown || htype == UriHostNameType.Basic)
return false;
if(htype == UriHostNameType.Dns)
if(htype == UriHostNameType.Dns || htype == UriHostNameType.IPv4)
{
foreach(string name in m_certNames)
{

View file

@ -123,6 +123,7 @@ namespace OpenSim.Framework
public uint NextPermissions { get; set; } = FULL_MASK_PERMISSIONS_GENERAL;
public UUID PermsGranter { get; set; }
public int PermsMask { get; set; }
public UUID ExperienceID { get; set; }
private bool _ownerChanged = false;
public bool OwnerChanged

View file

@ -56,6 +56,7 @@ using OpenMetaverse.StructuredData;
using Amib.Threading;
using System.Collections.Concurrent;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
namespace OpenSim.Framework
{
@ -1098,14 +1099,18 @@ namespace OpenSim.Framework
/// Is the platform Windows?
/// </summary>
/// <returns>true if so, false otherwise</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsWindows()
{
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
/*
PlatformID platformId = Environment.OSVersion.Platform;
return (platformId == PlatformID.Win32NT
|| platformId == PlatformID.Win32S
|| platformId == PlatformID.Win32Windows
|| platformId == PlatformID.WinCE);
*/
}
public static bool LoadArchSpecificWindowsDll(string libraryName)
@ -1480,6 +1485,71 @@ namespace OpenSim.Framework
return streamReader.ReadToEnd();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CreateOrUpdateSelfsignedCert(string certFileName, string certHostName, string certHostIp, string certPassword)
{
CreateOrUpdateSelfsignedCertificate(certFileName, certHostName, certHostIp, certPassword);
}
/// <summary>
/// Create or renew an SSL selfsigned certificate using the parameters set in the startup section of OpenSim.ini
/// </summary>
/// <param name="certFileName">The certificate file name.</param>
/// <param name="certHostName">The certificate host DNS name (CN).</param>
/// <param name="certHostIp">The certificate host IP address.</param>
/// <param name="certPassword">The certificate password.</param>
private static void CreateOrUpdateSelfsignedCertificate(string certFileName, string certHostName, string certHostIp, string certPassword)
{
SubjectAlternativeNameBuilder san = new();
san.AddDnsName(certHostName);
san.AddIpAddress(IPAddress.Parse(certHostIp));
// What OpenSim check (CN).
X500DistinguishedName dn = new($"CN={certHostName}");
using (RSA rsa = RSA.Create(2048))
{
CertificateRequest request = new(dn, rsa, HashAlgorithmName.SHA256,RSASignaturePadding.Pkcs1);
// (Optional)...
request.CertificateExtensions.Add(
new X509KeyUsageExtension(X509KeyUsageFlags.DataEncipherment | X509KeyUsageFlags.KeyEncipherment | X509KeyUsageFlags.DigitalSignature , false));
// (Optional) SSL Server Authentication...
request.CertificateExtensions.Add(
new X509EnhancedKeyUsageExtension(
new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, false));
request.CertificateExtensions.Add(san.Build());
X509Certificate2 certificate = request.CreateSelfSigned(new DateTimeOffset(DateTime.UtcNow), new DateTimeOffset(DateTime.UtcNow.AddDays(3650)));
string privateKey = Convert.ToBase64String(rsa.ExportRSAPrivateKey(), Base64FormattingOptions.InsertLineBreaks);
// Create the SSL folder and sub folders if not exists.
if (!Directory.Exists("SSL\\src\\"))
Directory.CreateDirectory("SSL\\src\\");
if (!Directory.Exists("SSL\\ssl\\"))
Directory.CreateDirectory("SSL\\ssl\\");
// Store the RSA key in SSL\src\
File.WriteAllText($"SSL\\src\\{certFileName}.txt", privateKey);
// Export and store the .pfx and .p12 certificates in SSL\ssl\.
// Note: Pfx is a Pkcs12 certificate and both files work for OpenSim.
byte[] pfxCertBytes = string.IsNullOrEmpty(certPassword)
? certificate.Export(X509ContentType.Pfx)
: certificate.Export(X509ContentType.Pfx, certPassword);
File.WriteAllBytes($"SSL\\ssl\\{certFileName}.pfx", pfxCertBytes);
byte[] p12CertBytes = string.IsNullOrEmpty(certPassword)
? certificate.Export(X509ContentType.Pkcs12)
: certificate.Export(X509ContentType.Pkcs12, certPassword);
File.WriteAllBytes($"SSL\\ssl\\{certFileName}.p12", p12CertBytes);
}
}
public static int fast_distance2d(int x, int y)
{
x = Math.Abs(x);
@ -3034,6 +3104,39 @@ namespace OpenSim.Framework
return false;
}
[DllImport("winmm.dll")]
private static extern uint timeBeginPeriod(uint period);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void TimeBeginPeriod(uint period)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
timeBeginPeriod(period);
}
[DllImport("winmm.dll")]
private static extern uint timeEndPeriod(uint period);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void TimeEndPeriod(uint period)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
timeEndPeriod(period);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ThreadSleep(int period)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
timeEndPeriod(1);
Thread.Sleep(period);
timeEndPeriod(1);
}
else
Thread.Sleep(period);
}
/// <summary>
/// Used to trigger an early library load on Windows systems.
/// </summary>

View file

@ -39,7 +39,7 @@ namespace OpenSim
{
public const string VersionNumber = "0.9.3";
public const string AssemblyVersionNumber = "0.9.3";
public const string Release = "8984";
public const string Release = "9032";
public static string Version
{

View file

@ -285,7 +285,7 @@ namespace OpenSim
Uri configUri;
return Uri.TryCreate(file, UriKind.Absolute,
out configUri) && configUri.Scheme == Uri.UriSchemeHttp;
out configUri) && (configUri.Scheme == Uri.UriSchemeHttp || configUri.Scheme == Uri.UriSchemeHttps);
}
/// <summary>

View file

@ -280,11 +280,16 @@ namespace OpenSim
SavePrimsXml2);
m_console.Commands.AddCommand("Archiving", false, "load oar",
"load oar [-m|--merge] [-s|--skip-assets]"
"load oar"
+ " [-m|--merge]"
+ " [-s|--skip-assets]"
+ " [--default-user \"User Name\"]"
+ " [--merge-terrain] [--merge-parcels]"
+ " [--merge-terrain]"
+ " [--merge-parcels]"
+ " [--mergeReplaceObjects]"
+ " [--no-objects]"
+ " [--no-defaultuser]"
+ " [--lookup-aliases]"
+ " [--rotation degrees]"
+ " [--bounding-origin \"<x,y,z>\"]"
+ " [--bounding-size \"<x,y,z>\"]"
@ -299,9 +304,9 @@ namespace OpenSim
+ " --mergeReplaceObjects if scene as a object with same id, replace it\n"
+ " without this option, skip loading that object\n"
+ "--skip-assets will load the OAR but ignore the assets it contains.\n"
// + "--lookup-aliases will lookup aliases for local users and update creator/owner/last owner information accordingly.\n"
// + "--allow-reassign allow reassignment of creator/owner/lastowner to the region owner/default user\n"
// + " if no local user (or alias) is found. Default is false\n"
+ "--no-defaultuser don't perform reassignment of creator/owner/lastowner to the region owner/default user\n"
+ " if no local user (or alias if enabled) is found.\n"
+ "--lookup-aliases will lookup aliases for local users and update creator/owner/last owner information accordingly.\n"
+ "--default-user will use this user for any objects with an owner whose UUID is not found in the grid.\n"
+ "--no-objects suppresses the addition of any objects (good for loading only the terrain).\n"
+ "--rotation specified rotation to be applied to the oar. Specified in degrees.\n"

View file

@ -352,7 +352,25 @@ namespace OpenSim
IConfig startupConfig = Config.Configs["Startup"];
if (startupConfig == null || startupConfig.GetBoolean("JobEngineEnabled", true))
WorkManager.JobEngine.Start();
// Sure is not the right place for this but do the job...
// Must always be called before (all) / the HTTP servers starting for the Certs creation or renewals.
if (startupConfig is not null)
{
if (startupConfig.GetBoolean("EnableSelfsignedCertSupport", false))
{
if(!File.Exists("SSL\\ssl\\"+ startupConfig.GetString("CertFileName") +".p12") || startupConfig.GetBoolean("CertRenewOnStartup"))
{
Util.CreateOrUpdateSelfsignedCert(
string.IsNullOrEmpty(startupConfig.GetString("CertFileName")) ? "OpenSim" : startupConfig.GetString("CertFileName"),
string.IsNullOrEmpty(startupConfig.GetString("CertHostName")) ? "localhost" : startupConfig.GetString("CertHostName"),
string.IsNullOrEmpty(startupConfig.GetString("CertHostIp")) ? "127.0.0.1" : startupConfig.GetString("CertHostIp"),
string.IsNullOrEmpty(startupConfig.GetString("CertPassword")) ? string.Empty : startupConfig.GetString("CertPassword")
);
}
}
}
if(m_networkServersInfo.HttpUsesSSL)
{
m_httpServerSSL = true;

View file

@ -179,13 +179,10 @@ namespace OpenSim.Region.ClientStack.Linden
LLSDPerson p = new LLSDPerson();
p.legacy_first_name = user.FirstName;
p.legacy_last_name = user.LastName;
p.display_name = user.FirstName + " " + user.LastName;
if (user.LastName.StartsWith("@"))
p.username = user.FirstName.ToLower() + user.LastName.ToLower();
else
p.username = user.FirstName.ToLower() + "." + user.LastName.ToLower();
p.display_name = user.ViewerDisplayName;
p.username = user.LowerUsername;
p.id = user.Id;
p.is_display_name_default = false;
p.is_display_name_default = user.IsNameDefault;
return p;
}
}

View file

@ -63,14 +63,14 @@ namespace OpenSim.Region.ClientStack.Linden
int cost, UUID texturesFolder, int nreqtextures, int nreqmeshs, int nreqinstances,
bool IsAtestUpload, ref string error, ref int nextOwnerMask, ref int groupMask, ref int everyoneMask, int[] meshesSides);
public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors);
public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, UUID experience, byte[] data, ref ArrayList errors);
public delegate void NewInventoryItem(UUID userID, InventoryItemBase item, uint cost);
public delegate void NewAsset(AssetBase asset);
public delegate ArrayList TaskScriptUpdatedCallback(UUID userID, UUID itemID, UUID primID,
bool isScriptRunning, byte[] data);
bool isScriptRunning, UUID experience, byte[] data);
/// <summary>
/// XXX Probably not a particularly nice way of allow us to get the scene presence from the scene (chiefly so that
@ -2234,16 +2234,15 @@ namespace OpenSim.Region.ClientStack.Linden
if (string.IsNullOrEmpty(ud.FirstName) || ud.FirstName.Equals("Unkown"))
continue;
string fullname = ud.FirstName + " " + ud.LastName;
LLSDxmlEncode2.AddMap(lsl);
LLSDxmlEncode2.AddElem("username", fullname, lsl);
LLSDxmlEncode2.AddElem("display_name", fullname, lsl);
LLSDxmlEncode2.AddElem("display_name_next_update", DateTime.UtcNow.AddDays(8), lsl);
LLSDxmlEncode2.AddElem("display_name_expires", DateTime.UtcNow.AddMonths(1), lsl);
LLSDxmlEncode2.AddElem("username", ud.LowerUsername, lsl);
LLSDxmlEncode2.AddElem("display_name", ud.ViewerDisplayName, lsl);
LLSDxmlEncode2.AddElem("display_name_next_update", ud.NameChanged.AddDays(7), lsl);
LLSDxmlEncode2.AddElem("display_name_expires", DateTime.UtcNow.AddDays(1), lsl);
LLSDxmlEncode2.AddElem("legacy_first_name", ud.FirstName, lsl);
LLSDxmlEncode2.AddElem("legacy_last_name", ud.LastName, lsl);
LLSDxmlEncode2.AddElem("id", ud.Id, lsl);
LLSDxmlEncode2.AddElem("is_display_name_default", true, lsl);
LLSDxmlEncode2.AddElem("is_display_name_default", ud.IsNameDefault, lsl);
LLSDxmlEncode2.AddEndMap(lsl);
}
LLSDxmlEncode2.AddEndArray(lsl);

View file

@ -159,6 +159,7 @@ namespace OpenSim.Region.ClientStack.Linden
UUID itemID = UUID.Zero;
UUID objectID = UUID.Zero;
bool is_script_running = false;
UUID experience_key = UUID.Zero;
OSD tmp;
try
{
@ -168,6 +169,8 @@ namespace OpenSim.Region.ClientStack.Linden
objectID = tmp;
if (map.TryGetValue("is_script_running", out tmp))
is_script_running = tmp;
if (map.TryGetValue("experience", out tmp))
experience_key = tmp;
}
catch { }
@ -215,7 +218,7 @@ namespace OpenSim.Region.ClientStack.Linden
uploadResponse.uploader = uploaderURL;
uploadResponse.state = "upload";
TaskInventoryScriptUpdater uploader = new TaskInventoryScriptUpdater(itemID, objectID, is_script_running,
TaskInventoryScriptUpdater uploader = new TaskInventoryScriptUpdater(itemID, objectID, is_script_running, experience_key,
uploaderPath, m_HostCapsObj.HttpListener, httpRequest.RemoteIPEndPoint.Address, m_dumpAssetsToFile);
uploader.OnUpLoad += TaskScriptUpdated;
@ -243,11 +246,11 @@ namespace OpenSim.Region.ClientStack.Linden
/// <param name="primID">Prim containing item to update</param>
/// <param name="isScriptRunning">Signals whether the script to update is currently running</param>
/// <param name="data">New asset data</param>
public void TaskScriptUpdated(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors)
public void TaskScriptUpdated(UUID itemID, UUID primID, bool isScriptRunning, UUID experience, byte[] data, ref ArrayList errors)
{
if (TaskScriptUpdatedCall != null)
{
ArrayList e = TaskScriptUpdatedCall(m_HostCapsObj.AgentID, itemID, primID, isScriptRunning, data);
ArrayList e = TaskScriptUpdatedCall(m_HostCapsObj.AgentID, itemID, primID, isScriptRunning, experience, data);
foreach (Object item in e)
errors.Add(item);
}
@ -353,10 +356,11 @@ namespace OpenSim.Region.ClientStack.Linden
private UUID m_inventoryItemID;
private UUID m_primID;
private bool m_isScriptRunning;
private UUID m_experienceKey;
private bool m_dumpAssetToFile;
public IPAddress m_remoteAddress;
public TaskInventoryScriptUpdater(UUID inventoryItemID, UUID primID, bool isScriptRunning,
public TaskInventoryScriptUpdater(UUID inventoryItemID, UUID primID, bool isScriptRunning, UUID experience_id,
string path, IHttpServer httpServer, IPAddress address,
bool dumpAssetToFile) : base(httpServer, path)
{
@ -364,6 +368,7 @@ namespace OpenSim.Region.ClientStack.Linden
m_inventoryItemID = inventoryItemID;
m_primID = primID;
m_isScriptRunning = isScriptRunning;
m_experienceKey = experience_id;
m_remoteAddress = address;
Start(30000);
}
@ -405,7 +410,7 @@ namespace OpenSim.Region.ClientStack.Linden
LLSDTaskScriptUploadComplete uploadComplete = new LLSDTaskScriptUploadComplete();
ArrayList errors = new ArrayList();
OnUpLoad?.Invoke(m_inventoryItemID, m_primID, m_isScriptRunning, data, ref errors);
OnUpLoad?.Invoke(m_inventoryItemID, m_primID, m_isScriptRunning, m_experienceKey, data, ref errors);
uploadComplete.new_asset = m_inventoryItemID;
uploadComplete.compiled = errors.Count > 0 ? false : true;

View file

@ -0,0 +1,238 @@
using System.Reflection;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using Caps = OpenSim.Framework.Capabilities.Caps;
using OpenSim.Framework;
using System.Net;
namespace OpenSim.Region.ClientStack.LindenCaps
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DisplayNameModule")]
public class DisplayNameModule : IDisplayNameModule, INonSharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IEventQueue m_EventQueue = null;
protected Scene m_Scene = null;
private bool m_Enabled = false;
#region ISharedRegionModule
public void Initialise(IConfigSource source)
{
IConfig config = source.Configs["ClientStack.LindenCaps"];
if (config == null)
return;
string url = config.GetString("Cap_SetDisplayName", string.Empty);
if (url == "localhost")
m_Enabled = true;
if (!m_Enabled)
return;
m_log.Info("[DISPLAY NAMES] Plugin enabled!");
}
public void AddRegion(Scene scene)
{
if (!m_Enabled)
return;
m_Scene = scene;
scene.RegisterModuleInterface<IDisplayNameModule>(this);
}
public void RemoveRegion(Scene scene)
{
if (!m_Enabled)
return;
m_Scene = null;
}
public void RegionLoaded(Scene scene)
{
if (!m_Enabled)
return;
m_EventQueue = scene.RequestModuleInterface<IEventQueue>();
if (m_EventQueue is null)
{
m_log.Info("[DISPLAY NAMES]: Module disabled becuase IEventQueue was not found!");
return;
}
scene.EventManager.OnRegisterCaps += OnRegisterCaps;
}
public void PostInitialise() { }
public void Close() { }
public string Name { get { return "DisplayNamesModule"; } }
public Type ReplaceableInterface
{
get { return null; }
}
#endregion
#region IDisplayNameModule
public string GetDisplayName(UUID avatar)
{
var user = m_Scene.UserManagementModule.GetUserData(avatar);
if (user is not null)
{
return user.ViewerDisplayName;
}
return string.Empty;
}
#endregion
private void OnRegisterCaps(UUID agentID, Caps caps)
{
if (m_Scene.UserManagementModule.IsLocalGridUser(agentID))
{
caps.RegisterSimpleHandler("SetDisplayName", new SimpleStreamHandler($"/{UUID.Random()}", (req, resp) => SetDisplayName(agentID, req, resp)));
return;
}
}
private void SetDisplayName(UUID agent_id, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
if (httpRequest.HttpMethod != "POST")
{
httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
ScenePresence sp = m_Scene.GetScenePresence(agent_id);
if (sp == null || sp.IsDeleted)
{
httpResponse.StatusCode = (int)HttpStatusCode.Gone;
return;
}
if (sp.IsInTransit && !sp.IsInLocalTransit)
{
httpResponse.StatusCode = (int)HttpStatusCode.ServiceUnavailable;
httpResponse.AddHeader("Retry-After", "30");
return;
}
var userData = m_Scene.UserManagementModule.GetUserData(agent_id);
if (userData.NameChanged.AddDays(7) > DateTime.UtcNow)
{
m_Scene.GetScenePresence(agent_id).ControllingClient.SendAlertMessage("You can only change your display name once a week!");
return;
}
OSDMap req = (OSDMap)OSDParser.DeserializeLLSDXml(httpRequest.InputStream);
if (req.ContainsKey("display_name"))
{
OSDArray name = req["display_name"] as OSDArray;
string oldName = name[0].AsString();
string newName = name[1].AsString();
bool resetting = string.IsNullOrWhiteSpace(newName);
if (resetting) newName = string.Empty;
bool success = m_Scene.UserManagementModule.SetDisplayName(agent_id, newName);
if (success)
{
// Update the current object
userData.DisplayName = newName;
userData.NameChanged = DateTime.UtcNow;
if (resetting)
m_log.InfoFormat("[DISPLAY NAMES] {0} {1} reset their display name", userData.FirstName, userData.LastName);
else
m_log.InfoFormat("[DISPLAY NAMES] {0} {1} changed their display name to {2}", userData.FirstName, userData.LastName, userData.DisplayName);
DateTime next_update = DateTime.UtcNow.AddDays(7);
OSD update = FormatDisplayNameUpdate(oldName, userData, next_update);
m_Scene.ForEachClient(x => {
m_EventQueue.Enqueue(update, x.AgentId);
});
SendSetDisplayNameReply(newName, oldName, userData, next_update);
}
else
{
m_Scene.GetScenePresence(agent_id).ControllingClient.SendAlertMessage("Failed to update display name.");
httpResponse.StatusCode = (int)HttpStatusCode.InternalServerError;
return;
}
}
httpResponse.ContentType = "application/llsd+xml";
httpResponse.RawBuffer = Utils.StringToBytes("<llsd><undef/></llsd>");
httpResponse.StatusCode = (int)HttpStatusCode.OK;
}
public OSD FormatDisplayNameUpdate(string oldName, UserData userData, DateTime nextUpdate)
{
var agentData = new OSDMap();
agentData["display_name"] = OSD.FromString(userData.ViewerDisplayName);
agentData["id"] = OSD.FromUUID(userData.Id);
agentData["is_display_name_default"] = OSD.FromBoolean(userData.IsNameDefault);
agentData["legacy_first_name"] = OSD.FromString(userData.FirstName);
agentData["legacy_last_name"] = OSD.FromString(userData.LastName);
agentData["username"] = OSD.FromString(userData.Username);
agentData["display_name_next_update"] = OSD.FromDate(nextUpdate);
var body = new OSDMap();
body["agent"] = agentData;
body["agent_id"] = OSD.FromString(userData.Id.ToString());
body["old_display_name"] = OSD.FromString(oldName);
var nameReply = new OSDMap();
nameReply["body"] = body;
nameReply["message"] = OSD.FromString("DisplayNameUpdate");
return nameReply;
}
public void SendSetDisplayNameReply(string newDisplayName, string oldDisplayName, UserData nameInfo, DateTime nextUpdate)
{
var content = new OSDMap();
content["display_name"] = OSD.FromString(nameInfo.ViewerDisplayName);
content["display_name_next_update"] = OSD.FromDate(nextUpdate);
content["id"] = OSD.FromUUID(nameInfo.Id);
content["is_display_name_default"] = OSD.FromBoolean(nameInfo.IsNameDefault);
content["legacy_first_name"] = OSD.FromString(nameInfo.FirstName);
content["legacy_last_name"] = OSD.FromString(nameInfo.LastName);
content["username"] = OSD.FromString(nameInfo.LowerUsername);
var body = new OSDMap();
body["content"] = content;
body["reason"] = OSD.FromString("OK");
body["status"] = OSD.FromInteger(200);
var nameReply = new OSDMap();
nameReply["body"] = body;
nameReply["message"] = OSD.FromString("SetDisplayNameReply");
m_EventQueue.Enqueue((OSD)nameReply, nameInfo.Id);
}
}
}

View file

@ -412,6 +412,12 @@ namespace OpenSim.Region.ClientStack.Linden
Enqueue(EndEventToBytes(sb), avatarID);
}
public void SendEnvironmentUpdate(UUID experience_id, UUID agent_id, EnvironmentUpdate update)
{
string update_message = "<? llsd/notation ?>\n" + OSDParser.SerializeLLSDNotation(update.ToMap());
SendLargeGenericMessage(agent_id, UUID.Zero, UUID.Zero, "PushExpEnvironment", experience_id, new List<string> { update_message });
}
public void SendBulkUpdateInventoryItem(InventoryItemBase item, UUID avatarID, UUID? transationID = null)
{
const uint FULL_MASK_PERMISSIONS = (uint)0x7ffffff;

File diff suppressed because it is too large Load diff

View file

@ -28,6 +28,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Frozen;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime;
@ -52,6 +53,7 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
using PermissionMask = OpenSim.Framework.PermissionMask;
using RegionFlags = OpenMetaverse.RegionFlags;
namespace OpenSim.Region.ClientStack.LindenUDP
{
public delegate void PacketMethod(Packet packet);
@ -215,6 +217,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public event EstateRestartSimRequest OnEstateRestartSimRequest;
public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
public event UpdateEstateExperienceDeltaRequest OnUpdateEstateExperienceDeltaRequest;
public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
@ -1349,6 +1352,92 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
public void SendGenericMessageForExperience(UUID experience_id, UUID avatar_id, int action, string obj_name, string parcel, bool is_attachment)
{
// Todo: Finish decoding this. Stop manaully making the bytes. And use the proper serialiser! And drink some water while you're at it.
// <? LLSD/Binary ?>\n
// {
// 0x00 0x00 0x00 0x02 == number of args
// 'k' key
// 0x00 0x00 0x00 0x07 == Length of the following arg header
// 0x4F 0x77 0x6E 0x65 0x72 0x49 0x44 == "OwnerID"
// 0x75 == 'u' == uuid
// 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 == 16 bytes owner of the script
// 'k' key
// 0x00 0x00 0x00 0x0A == Length of the following arg header
// 0x50 0x65 0x72 0x6D 0x69 0x73 0x73 0x69 0x6F 0x6E == "Permission"
// 0x69 == 'i' == integer
// 0x00, 0x00, 0x00, 0x10 == 4 byte permission int
// }
// 0x00
byte[] header = new byte[18] { 0x3C, 0x3F, 0x20, 0x4C, 0x4C, 0x53, 0x44, 0x2F, 0x42, 0x69, 0x6E, 0x61, 0x72, 0x79, 0x20, 0x3F, 0x3E, 0x0A };
Dictionary<string, object> vals = new Dictionary<string, object>();
vals.Add("OwnerID", avatar_id);
vals.Add("Permission", action);
if (is_attachment)
vals.Add("IsAttachment", 1);
byte[] arg_count = Utils.IntToBytes(vals.Count).Reverse().ToArray();
List<byte> new_body = new List<byte>();
new_body.AddRange(header); // <? LLSD/Binary ?>\n
new_body.Add(0x7B); // {
new_body.AddRange(arg_count); // How many args
foreach (var pair in vals)
{
object o = pair.Value;
new_body.Add(0x6B); // k
byte[] val_name = Util.StringToBytes256(pair.Key);
Array.Resize(ref val_name, val_name.Length - 1); // trim the trailing 0x00
byte[] value_length = Utils.IntToBytes(val_name.Length).Reverse().ToArray();
new_body.AddRange(value_length); // How long is the header name
new_body.AddRange(val_name); // Header name in bytes
if (o is UUID)
{
byte[] uuid_bytes = ((UUID)o).GetBytes();
new_body.Add(0x75); // u Value is a UUID
new_body.AddRange(uuid_bytes); // Owner of the script doigthe action
}
else if (o is int)
{
byte[] int_bytes = Utils.IntToBytes((int)o).Reverse().ToArray();
new_body.Add(0x69); // i Value is an int32
new_body.AddRange(int_bytes); // What permission was used
}
}
new_body.Add(0x7D); // }
new_body.Add(0x00); // 0x00 Null end Parameter
GenericMessagePacket p = new GenericMessagePacket();
p.AgentData = new GenericMessagePacket.AgentDataBlock();
p.AgentData.AgentID = m_agentId;
p.MethodData = new GenericMessagePacket.MethodDataBlock();
p.MethodData.Method = Util.StringToBytes256("ExperienceEvent");
p.MethodData.Invoice = experience_id;
p.ParamList = new GenericMessagePacket.ParamListBlock[3];
p.ParamList[0] = new GenericMessagePacket.ParamListBlock();
p.ParamList[0].Parameter = new_body.ToArray();
p.ParamList[1] = new GenericMessagePacket.ParamListBlock();
p.ParamList[1].Parameter = Util.StringToBytes256(obj_name);
p.ParamList[2] = new GenericMessagePacket.ParamListBlock();
p.ParamList[2].Parameter = Util.StringToBytes256(parcel); // this function seems to add the trailing 0x00
OutPacket(p, ThrottleOutPacketType.Task);
}
public void SendGroupActiveProposals(UUID groupID, UUID transactionID, GroupActiveProposals[] Proposals)
{
/* not in use and broken
@ -6352,6 +6441,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP
} while (TotalnumberIDs > 0);
}
public void SendEstateExperiences(UUID invoice, UUID[] allowed, UUID[] key, uint estateID)
{
EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
packet.AgentData.TransactionID = UUID.Random();
packet.AgentData.AgentID = AgentId;
packet.AgentData.SessionID = SessionId;
packet.MethodData.Invoice = invoice;
packet.MethodData.Method = Utils.StringToBytes("setexperience");
int numberIDs = allowed.Length + key.Length;
EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[5 + numberIDs];
for (int i = 0; i < (5 + numberIDs); i++)
{
returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock();
}
returnblock[0].Parameter = Utils.StringToBytes(estateID.ToString());
returnblock[1].Parameter = Utils.StringToBytes("0");
returnblock[2].Parameter = Utils.StringToBytes("0");
returnblock[3].Parameter = Utils.StringToBytes(key.Length.ToString());
returnblock[4].Parameter = Utils.StringToBytes(allowed.Length.ToString());
int j = 5;
for (int i = 0; i < key.Length; i++)
{
returnblock[j].Parameter = key[i].GetBytes();
j++;
}
for (int i = 0; i < allowed.Length; i++)
{
returnblock[j].Parameter = allowed[i].GetBytes();
j++;
}
packet.ParamList = returnblock;
packet.Header.Reliable = true;
OutPacket(packet, ThrottleOutPacketType.Task);
}
public void SendBannedUserList(UUID invoice, EstateBan[] bl, uint estateID)
{
List<UUID> BannedUsers = new();
@ -10869,6 +11002,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
c.OnUpdateEstateAccessDeltaRequest?.Invoke(c, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)));
}
return;
case "estateexperiencedelta":
if (c.m_scene.Permissions.CanIssueEstateCommand(c.m_agentId, false))
{
int estateAccessType = Convert.ToInt16(Utils.BytesToString(messagePacket.ParamList[1].Parameter));
c.OnUpdateEstateExperienceDeltaRequest(c, messagePacket.MethodData.Invoice, estateAccessType, new UUID(Utils.BytesToString(messagePacket.ParamList[2].Parameter)));
}
return;
case "simulatormessage":
@ -12179,7 +12321,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#endregion Packet Handlers
public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question)
public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question, UUID experience)
{
ScriptQuestionPacket scriptQuestion = (ScriptQuestionPacket)PacketPool.Instance.GetPacket(PacketType.ScriptQuestion);
scriptQuestion.Data.TaskID = taskID;
@ -12187,6 +12329,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
scriptQuestion.Data.Questions = question;
scriptQuestion.Data.ObjectName = Util.StringToBytes256(taskName);
scriptQuestion.Data.ObjectOwner = Util.StringToBytes256(ownerName);
if (experience != UUID.Zero)
{
scriptQuestion.Experience = new ScriptQuestionPacket.ExperienceBlock
{
ExperienceID = experience
};
}
OutPacket(scriptQuestion, ThrottleOutPacketType.Task);
}

View file

@ -575,12 +575,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
}
public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent,
bool addToInventory, bool append)
bool addToInventory, bool append, UUID experience)
{
if (!Enabled)
return false;
return AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append);
return AttachObjectInternal(sp, group, attachmentPt, silent, addToInventory, false, append, experience);
}
/// <summary>
@ -594,7 +594,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// <param name='addToInventory'>If true then add object to user inventory.</param>
/// <param name='resumeScripts'>If true then scripts are resumed on the attached object.</param>
private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt,
bool silent, bool addToInventory, bool resumeScripts, bool append)
bool silent, bool addToInventory, bool resumeScripts, bool append, UUID experience)
{
//m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
@ -708,7 +708,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (addToInventory && sp.PresenceType != PresenceType.Npc)
UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append);
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
AttachToAgent(sp, group, attachmentPt, attachPos, silent, experience);
if (resumeScripts)
{
@ -1089,7 +1089,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// <param name="attachmentpoint"></param>
/// <param name="attachOffset"></param>
/// <param name="silent"></param>
private void AttachToAgent(IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
private void AttachToAgent(IScenePresence sp, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent, UUID experience)
{
if (DebugLevel > 0)
m_log.DebugFormat(
@ -1117,6 +1117,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
so.RootPart.AttachedPos = attachOffset;
so.RootPart.GroupPosition = attachOffset; // can not set absolutepos
so.IsAttachment = true;
so.AttachedExperienceID = experience;
sp.AddAttachment(so);
@ -1325,7 +1326,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
objatt.ResetOwnerChangeFlag();
}
doneAttach = AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append);
doneAttach = AttachObjectInternal(sp, objatt, attachmentPt, false, true, true, append, UUID.Zero);
}
catch (Exception e)
{
@ -1455,7 +1456,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
AttachmentPt &= 0x7f;
// Calls attach with a Zero position
if (AttachObject(sp, group , AttachmentPt, false, true, append))
if (AttachObject(sp, group , AttachmentPt, false, true, append, UUID.Zero))
{
if (DebugLevel > 0)
m_log.Debug(

View file

@ -304,6 +304,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
ud.HasGridUserTried = true;
ud.IsUnknownUser = false;
ud.IsLocal = acc.LocalToGrid;
ud.DisplayName = acc.DisplayName;
ud.NameChanged = Utils.UnixTimeToDateTime(acc.NameChanged);
users.Add(ud);
found.Add(id);
}
@ -468,6 +470,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
userdata.IsUnknownUser = false;
userdata.IsLocal = true;
userdata.HasGridUserTried = true;
userdata.DisplayName = uac.DisplayName;
userdata.NameChanged = Utils.UnixTimeToDateTime(uac.NameChanged);
m_userCacheByID.Add(id, userdata, 1800000);
ret[id] = uac.FirstName + " " + uac.LastName;
@ -599,6 +603,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
userdata.IsUnknownUser = false;
userdata.IsLocal = true;
userdata.HasGridUserTried = true;
userdata.DisplayName = uac.DisplayName;
userdata.NameChanged = Utils.UnixTimeToDateTime(uac.NameChanged);
m_userCacheByID.Add(id, userdata, 1800000);
ret[id] = uac.FirstName + " " + uac.LastName;
@ -716,6 +722,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
userdata.IsUnknownUser = false;
userdata.IsLocal = true;
userdata.HasGridUserTried = true;
userdata.DisplayName = uac.DisplayName;
userdata.NameChanged = Utils.UnixTimeToDateTime(uac.NameChanged);
m_userCacheByID.Add(id, userdata, 1800000);
ret.Add(userdata);
@ -1017,6 +1025,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
userdata.IsUnknownUser = false;
userdata.IsLocal = true;
userdata.HasGridUserTried = true;
userdata.DisplayName = account.DisplayName;
userdata.NameChanged = Utils.UnixTimeToDateTime(account.NameChanged);
}
}
@ -1281,6 +1291,11 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
return true;
}
public bool SetDisplayName(UUID agentID, string displayName)
{
return m_userAccountService.SetDisplayName(agentID, displayName);
}
#endregion IUserManagement
protected virtual void Init(IConfigSource config)

View file

@ -92,6 +92,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
protected bool m_enabled = false;
protected string m_ErrorStr;
protected uint m_HttpsPort = 0;
protected uint m_HttpPort = 0;
protected IHttpServer m_HttpServer = null;
protected IHttpServer m_HttpsServer = null;
@ -134,6 +135,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
bool ssl_enabled = config.Configs["Network"].GetBoolean("https_listener", false);
m_HttpPort = (uint)config.Configs["Network"].GetInt("http_listener_port", 9000);
if (ssl_enabled)
m_HttpsPort = (uint)config.Configs["Network"].GetInt("https_port", (int)m_HttpsPort);
}
@ -180,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
{
// There can only be one
//
m_HttpServer = MainServer.Instance;
m_HttpServer = MainServer.GetHttpServer(m_HttpPort);
//
// We can use the https if it is enabled
if (m_HttpsPort > 0)

View file

@ -0,0 +1,207 @@
using log4net;
using Mono.Addins;
using Nini.Config;
using System;
using System.Collections.Generic;
using System.Reflection;
using OpenSim.Framework;
using OpenSim.Server.Base;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using OpenMetaverse;
using OpenSim.Data;
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Experience
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalExperienceServicesConnector")]
public class LocalExperienceServicesConnector : ISharedRegionModule, IExperienceService
{
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private List<Scene> m_Scenes = new List<Scene>();
protected IExperienceService m_service = null;
private bool m_Enabled = false;
#region ISharedRegionModule
public Type ReplaceableInterface
{
get { return null; }
}
public string Name
{
get { return "LocalExperienceServicesConnector"; }
}
public void Initialise(IConfigSource source)
{
IConfig moduleConfig = source.Configs["Modules"];
if (moduleConfig == null)
return;
string name = moduleConfig.GetString("ExperienceService", "");
if(name != Name)
return;
IConfig userConfig = source.Configs["ExperienceService"];
if (userConfig == null)
{
m_log.Error("[EXPERIENCE LOCALCONNECTOR]: ExperienceService missing from configuration");
return;
}
string serviceDll = userConfig.GetString("LocalServiceModule",
String.Empty);
if (serviceDll == String.Empty)
{
m_log.Error("[EXPERIENCE LOCALCONNECTOR]: No ExperienceModule named in section ExperienceService");
return;
}
Object[] args = new Object[] { source };
try
{
m_service = ServerUtils.LoadPlugin<IExperienceService>(serviceDll, args);
}
catch
{
m_log.Error("[EXPERIENCE LOCALCONNECTOR]: Failed to load experience service");
return;
}
if (m_service == null)
{
m_log.Error("[EXPERIENCE LOCALCONNECTOR]: Can't load experience service");
return;
}
m_Enabled = true;
m_log.Info("[EXPERIENCE LOCALCONNECTOR]: Enabled!");
}
public void Close()
{
}
public void AddRegion(Scene scene)
{
if (!m_Enabled)
return;
lock(m_Scenes)
{
m_Scenes.Add(scene);
scene.RegisterModuleInterface<IExperienceService>(this);
}
}
public void RegionLoaded(Scene scene)
{
}
public void PostInitialise()
{
}
public void RemoveRegion(Scene scene)
{
if (!m_Enabled)
return;
lock(m_Scenes)
{
if (m_Scenes.Contains(scene))
{
m_Scenes.Remove(scene);
scene.UnregisterModuleInterface<IExperienceService>(this);
}
}
}
#endregion ISharedRegionModule
#region IExperienceService
public Dictionary<UUID, bool> FetchExperiencePermissions(UUID agent_id)
{
return m_service.FetchExperiencePermissions(agent_id);
}
public bool UpdateExperiencePermissions(UUID agent_id, UUID experience, ExperiencePermission perm)
{
return m_service.UpdateExperiencePermissions(agent_id, experience, perm);
}
public ExperienceInfo[] GetExperienceInfos(UUID[] experiences)
{
return m_service.GetExperienceInfos(experiences);
}
public UUID[] GetAgentExperiences(UUID agent_id)
{
return m_service.GetAgentExperiences(agent_id);
}
public ExperienceInfo UpdateExpereienceInfo(ExperienceInfo info)
{
return m_service.UpdateExpereienceInfo(info);
}
public ExperienceInfo[] FindExperiencesByName(string search)
{
return m_service.FindExperiencesByName(search);
}
public UUID[] GetGroupExperiences(UUID group_id)
{
return m_service.GetGroupExperiences(group_id);
}
public UUID[] GetExperiencesForGroups(UUID[] groups)
{
return m_service.GetExperiencesForGroups(groups);
}
public string GetKeyValue(UUID experience, string key)
{
return m_service.GetKeyValue(experience, key);
}
public string CreateKeyValue(UUID experience, string key, string value)
{
return m_service.CreateKeyValue(experience, key, value);
}
public string UpdateKeyValue(UUID experience, string key, string val, bool check, string original)
{
return m_service.UpdateKeyValue(experience, key, val, check, original);
}
public string DeleteKey(UUID experience, string key)
{
return m_service.DeleteKey(experience, key);
}
public int GetKeyCount(UUID experience)
{
return m_service.GetKeyCount(experience);
}
public string[] GetKeys(UUID experience, int start, int count)
{
return m_service.GetKeys(experience, start, count);
}
public int GetSize(UUID experience)
{
return m_service.GetSize(experience);
}
#endregion IExperienceService
}
}

View file

@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Services.Connectors;
using OpenMetaverse;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenSim.Data;
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Experience
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteExperienceServicesConnector")]
public class RemoteExperienceServicesConnector : ISharedRegionModule, IExperienceService
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
#region ISharedRegionModule
private bool m_Enabled = false;
private IExperienceService m_remoteConnector;
public Type ReplaceableInterface
{
get { return null; }
}
public string Name
{
get { return "RemoteExperienceServicesConnector"; }
}
public void Initialise(IConfigSource source)
{
IConfig moduleConfig = source.Configs["Modules"];
if (moduleConfig != null)
{
string name = moduleConfig.GetString("ExperienceServices", "");
if (name == Name)
{
m_remoteConnector = new ExperienceServicesConnector(source);
m_Enabled = true;
m_log.Info("[EXPERIENCE CONNECTOR]: Remote ExperienceService enabled");
}
}
}
public void PostInitialise()
{
}
public void Close()
{
}
public void AddRegion(Scene scene)
{
if (!m_Enabled)
return;
scene.RegisterModuleInterface<IExperienceService>(this);
m_log.InfoFormat("[EXPERIENCE CONNECTOR]: Enabled for region {0}", scene.RegionInfo.RegionName);
}
public void RemoveRegion(Scene scene)
{
if (!m_Enabled)
return;
}
public void RegionLoaded(Scene scene)
{
if (!m_Enabled)
return;
}
#endregion
#region IExperienceService
public Dictionary<UUID, bool> FetchExperiencePermissions(UUID agent_id)
{
return m_remoteConnector.FetchExperiencePermissions(agent_id);
}
public bool UpdateExperiencePermissions(UUID agent_id, UUID experience, ExperiencePermission perm)
{
return m_remoteConnector.UpdateExperiencePermissions(agent_id, experience, perm);
}
public ExperienceInfo[] GetExperienceInfos(UUID[] experiences)
{
return m_remoteConnector.GetExperienceInfos(experiences);
}
public UUID[] GetAgentExperiences(UUID agent_id)
{
return m_remoteConnector.GetAgentExperiences(agent_id);
}
public ExperienceInfo UpdateExpereienceInfo(ExperienceInfo info)
{
return m_remoteConnector.UpdateExpereienceInfo(info);
}
public ExperienceInfo[] FindExperiencesByName(string search)
{
return m_remoteConnector.FindExperiencesByName(search);
}
public UUID[] GetGroupExperiences(UUID group_id)
{
return m_remoteConnector.GetGroupExperiences(group_id);
}
public UUID[] GetExperiencesForGroups(UUID[] groups)
{
return m_remoteConnector.GetExperiencesForGroups(groups);
}
public string GetKeyValue(UUID experience, string key)
{
return m_remoteConnector.GetKeyValue(experience, key);
}
public string CreateKeyValue(UUID experience, string key, string value)
{
return m_remoteConnector.CreateKeyValue(experience, key, value);
}
public string UpdateKeyValue(UUID experience, string key, string val, bool check, string original)
{
return m_remoteConnector.UpdateKeyValue(experience, key, val, check, original);
}
public string DeleteKey(UUID experience, string key)
{
return m_remoteConnector.DeleteKey(experience, key);
}
public int GetKeyCount(UUID experience)
{
return m_remoteConnector.GetKeyCount(experience);
}
public string[] GetKeys(UUID experience, int start, int count)
{
return m_remoteConnector.GetKeys(experience, start, count);
}
public int GetSize(UUID experience)
{
return m_remoteConnector.GetSize(experience);
}
#endregion IExperienceService
}
}

View file

@ -248,6 +248,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts
m_Cache.Invalidate(userID);
}
public bool SetDisplayName(UUID agentID, string displayName)
{
return UserAccountService.SetDisplayName(agentID, displayName);
}
#endregion
}
}

View file

@ -25,11 +25,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Reflection;
using System.Text;
using System.Xml;
@ -39,13 +35,11 @@ using OpenSim.Framework;
using OpenSim.Framework.Monitoring;
using OpenSim.Framework.Serialization;
using OpenSim.Framework.Serialization.External;
using OpenSim.Region.CoreModules.World.Terrain;
using OpenSim.Region.CoreModules.World.Land;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Scenes.Serialization;
using OpenSim.Services.Interfaces;
using System.Threading;
namespace OpenSim.Region.CoreModules.World.Archiver
{
@ -156,7 +150,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
/// Used to cache lookups for valid uuids.
/// </summary>
private readonly Dictionary<UUID, bool> m_validUserUuids = new();
private IUserManagement m_UserMan;
private IUserManagement UserManager
{
@ -178,6 +172,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver
private UUID m_defaultUser;
protected bool m_noDefaultUser = false;
protected bool m_lookupAliases = false;
private IUserAliasService m_UserAliasService = null;
private IUserAliasService UserAliasService
{
get
{
m_UserAliasService ??= m_rootScene.RequestModuleInterface<IUserAliasService>();
return m_UserAliasService;
}
}
/// <summary>
/// Cache aliased user lookups since we will likely have many instances
/// </summary>
private readonly Dictionary<UUID, UserAlias> m_userAliases = new();
public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionary<string, object> options)
{
m_rootScene = scene;
@ -213,6 +227,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_mergeParcels = options.ContainsKey("merge-parcels");
m_noObjects = options.ContainsKey("no-objects");
m_skipAssets = options.ContainsKey("skipAssets");
m_noDefaultUser = options.ContainsKey("no-defaultuser");
m_lookupAliases = options.ContainsKey("lookup-aliases");
m_requestId = requestId;
m_displacement = options.ContainsKey("displacement") ? (Vector3)options["displacement"] : Vector3.Zero;
m_rotation = options.ContainsKey("rotation") ? (float)options["rotation"] : 0f;
@ -274,6 +292,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_requestId = requestId;
m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner;
m_noDefaultUser = options.ContainsKey("no-defaultuser");
m_lookupAliases = options.ContainsKey("lookup-aliases");
// Zero can never be a valid user id
m_validUserUuids[UUID.Zero] = false;
@ -770,24 +790,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
if (string.IsNullOrEmpty(part.CreatorData))
{
if (!ResolveUserUuid(scene, part.CreatorID))
part.CreatorID = m_defaultUser;
// Creators can't be groups.
part.CreatorID = ResolveUserAliasOrDefault(scene, part.CreatorID, checkGroup: false);
}
if (UserManager is not null)
{
UserManager.AddCreatorUser(part.CreatorID, part.CreatorData);
}
if (!(ResolveUserUuid(scene, part.OwnerID) || ResolveGroupUuid(part.OwnerID)))
part.OwnerID = m_defaultUser;
part.OwnerID = ResolveUserAliasOrDefault(scene, part.OwnerID, checkGroup: true);
part.LastOwnerID = ResolveUserAliasOrDefault(scene, part.LastOwnerID, checkGroup: true);
if (!(ResolveUserUuid(scene, part.LastOwnerID) || ResolveGroupUuid(part.LastOwnerID)))
part.LastOwnerID = m_defaultUser;
if (!ResolveGroupUuid(part.GroupID))
// If there is no matching local group initialize it to a null key
if (ResolveGroupUuid(part.GroupID) is false)
part.GroupID = UUID.Zero;
// And zap any troublesome sit target information
// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
// part.SitTargetPosition = new Vector3(0, 0, 0);
// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
// part.SitTargetPosition = new Vector3(0, 0, 0);
// Fix ownership/creator of inventory items
// Not doing so results in inventory items
@ -802,23 +823,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver
TaskInventoryDictionary inv = part.TaskInventory;
foreach (KeyValuePair<UUID, TaskInventoryItem> kvp in inv)
{
if (!(ResolveUserUuid(scene, kvp.Value.OwnerID) || ResolveGroupUuid(kvp.Value.OwnerID)))
{
kvp.Value.OwnerID = m_defaultUser;
}
if (string.IsNullOrEmpty(kvp.Value.CreatorData))
{
if (!ResolveUserUuid(scene, kvp.Value.CreatorID))
kvp.Value.CreatorID = m_defaultUser;
// Creator can't be a group
kvp.Value.CreatorID = ResolveUserAliasOrDefault(scene, kvp.Value.CreatorID, checkGroup: false);
}
if (UserManager is not null)
{
UserManager.AddCreatorUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
}
kvp.Value.OwnerID = ResolveUserAliasOrDefault(scene, kvp.Value.OwnerID, checkGroup: true);
if (!ResolveGroupUuid(kvp.Value.GroupID))
kvp.Value.GroupID = UUID.Zero;
}
part.TaskInventory.LockItemsForRead(false);
}
}
@ -1028,6 +1049,66 @@ namespace OpenSim.Region.CoreModules.World.Archiver
}
}
/// <summary>
/// Look up and return the original user, the default user or a user alias if one is found
/// based on the options passed in at run time.
/// </summary>
/// <param name="scene">The scene we are loading this OAR into.</param>
/// <param name="aliasID">The id we are locally for locally or as an alias</param>
/// <param name="checkGroup">The incoming ID may be a group so check for that as well</param>
/// <returns>UUID - the ID to use based on incoming ID and settings</returns>
private UUID ResolveUserAliasOrDefault(Scene scene, UUID aliasID, bool checkGroup)
{
if (ResolveUserUuid(scene, aliasID) is true)
{
return aliasID;
}
if (checkGroup && ResolveGroupUuid(aliasID) is true)
{
return aliasID;
}
if (m_lookupAliases is true)
{
UserAlias aliasUser = null;
lock (m_userAliases)
{
// Have we seen this UUID before?
if (m_userAliases.TryGetValue(aliasID, out aliasUser) is false)
{
// If not look it up and get result, null if it doesnt exist
aliasUser = UserAliasService?.GetUserForAlias(aliasID);
// Plug it into the cache
m_userAliases[aliasID] = aliasUser;
// And since its the first time we've seen this and no alias exists print a warning
if (aliasUser is null)
{
m_log.Warn($"[ARCHIVEREADREQUEST] No alias found for User {aliasID} and not a local user");
}
}
}
if (aliasUser != null)
{
if (ResolveUserUuid(scene, aliasUser.UserID) is true)
return aliasUser.UserID;
}
}
if (m_noDefaultUser is false)
{
return m_defaultUser;
}
else
{
return aliasID;
}
}
private bool TryUploadAsset(UUID assetID, sbyte assetType, byte[] data)
{
if (assetType == (sbyte)AssetType.Unknown)

View file

@ -106,6 +106,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
bool mergeTerrain = false;
bool mergeParcels = false;
bool noObjects = false;
bool noDefaultUser = false;
bool lookupAliases = false;
Vector3 displacement = new Vector3(0f, 0f, 0f);
String defaultUser = "";
float rotation = 0f;
@ -115,6 +118,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
bool debug = false;
OptionSet options = new OptionSet();
options.Add("m|merge", delegate(string v) { mergeOar = (v != null); });
options.Add("mergeReplaceObjects", delegate (string v) { mergeReplaceObjects = (v != null); });
options.Add("s|skip-assets", delegate(string v) { skipAssets = (v != null); });
@ -126,6 +130,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
options.Add("forceparcels", delegate (string v) { mergeParcels = (v != null); }); // downward compatibility
options.Add("no-objects", delegate(string v) { noObjects = (v != null); });
options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; });
options.Add("no-defaultuser", delegate(string v) { noDefaultUser = (v != null); });
options.Add("lookup-aliases", delegate(string v) { lookupAliases = (v != null); });
options.Add("displacement=", delegate(string v)
{
try
@ -151,6 +157,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
m_log.ErrorFormat("[ARCHIVER MODULE] Must be an angle in degrees between -360 and +360: --rotation 45");
return;
}
//pass this in as degrees now, convert to radians later during actual work phase
rotation = Math.Clamp(rotation, -359f, 359f);
});
@ -214,6 +221,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// m_log.DebugFormat("GOT PARAM [{0}]", param);
Dictionary<string, object> archiveOptions = new Dictionary<string, object>();
if (mergeOar) archiveOptions.Add("merge", null);
if (skipAssets) archiveOptions.Add("skipAssets", null);
if (mergeReplaceObjects) archiveOptions.Add("mReplaceObjects", null);
@ -241,11 +249,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
archiveOptions.Add("default-user", defaultUserUUID);
}
}
if (noDefaultUser) archiveOptions.Add("no-defaultuser", null);
if (lookupAliases) archiveOptions.Add("lookup-aliases", null);
archiveOptions.Add("displacement", displacement);
archiveOptions.Add("rotation", rotation);
archiveOptions.Add("rotation-center", rotationCenter);
archiveOptions.Add("bounding-origin", boundingOrigin);
archiveOptions.Add("bounding-size", boundingSize);
if (debug) archiveOptions.Add("debug", null);
if (mainParams.Count > 2)

View file

@ -1165,6 +1165,249 @@ namespace OpenSim.Region.CoreModules.World.Estate
runnigDeltaExec = false;
}
private object expdeltareqLock = new object();
private bool runnigExpDeltaExec = false;
private class EstateExperienceDeltaRequest
{
public IClientAPI remote_client;
public UUID invoice;
public int estateAccessType;
public UUID experience;
}
private BlockingCollection<EstateExperienceDeltaRequest> experienceDeltaRequests = new BlockingCollection<EstateExperienceDeltaRequest>();
private void handleEstateExperienceDeltaRequest(IClientAPI _remote_client, UUID _invoice, int _estateAccessType, UUID _experience)
{
EstateExperienceDeltaRequest newreq = new EstateExperienceDeltaRequest();
newreq.remote_client = _remote_client;
newreq.invoice = _invoice;
newreq.estateAccessType = _estateAccessType;
newreq.experience = _experience;
experienceDeltaRequests.Add(newreq);
lock (expdeltareqLock)
{
if (!runnigExpDeltaExec)
{
runnigExpDeltaExec = true;
WorkManager.RunInThreadPool(execExpDeltaRequests, null, "execExpDeltaRequests");
}
}
}
private void execExpDeltaRequests(object o)
{
IClientAPI remote_client;
UUID invoice;
int estateAccessType;
UUID experience;
Dictionary<int, EstateSettings> changed = new Dictionary<int, EstateSettings>();
Dictionary<IClientAPI, UUID> sendExperienceLists = new Dictionary<IClientAPI, UUID>();
List<EstateSettings> otherEstates = new List<EstateSettings>();
bool sentAllowedFull = false;
EstateExperienceDeltaRequest req;
while (Scene.IsRunning)
{
req = null;
experienceDeltaRequests.TryTake(out req, 500);
if (!Scene.IsRunning)
break;
if (req == null)
{
if (changed.Count > 0)
{
foreach (EstateSettings est in changed.Values)
Scene.EstateDataService.StoreEstateSettings(est);
TriggerEstateInfoChange();
}
EstateSettings es = Scene.RegionInfo.EstateSettings;
foreach (KeyValuePair<IClientAPI, UUID> kvp in sendExperienceLists)
{
IClientAPI cli = kvp.Key;
UUID invoive = kvp.Value;
cli.SendEstateExperiences(invoive, es.AllowedExperiences, es.KeyExperiences, es.EstateID);
}
sendExperienceLists.Clear();
otherEstates.Clear();
changed.Clear();
lock (expdeltareqLock)
{
if (experienceDeltaRequests.Count != 0)
continue;
runnigExpDeltaExec = false;
return;
}
}
remote_client = req.remote_client;
if (!remote_client.IsActive)
continue;
invoice = req.invoice;
experience = req.experience;
estateAccessType = req.estateAccessType;
bool needReply = ((estateAccessType & 1024) == 0);
bool doOtherEstates = ((estateAccessType & 3) != 0);
EstateSettings thisSettings = Scene.RegionInfo.EstateSettings;
int thisEstateID = (int)thisSettings.EstateID;
UUID agentID = remote_client.AgentId;
bool isadmin = Scene.Permissions.IsAdministrator(agentID);
// just in case recheck rights
if (!isadmin && !Scene.Permissions.IsEstateManager(agentID))
{
remote_client.SendAlertMessage("Method EstateAccess Failed, you don't have permissions");
continue;
}
otherEstates.Clear();
if (doOtherEstates)
{
UUID thisOwner = Scene.RegionInfo.EstateSettings.EstateOwner;
List<int> estateIDs = Scene.EstateDataService.GetEstatesByOwner(thisOwner);
foreach (int estateID in estateIDs)
{
if (estateID == thisEstateID)
continue;
EstateSettings estateSettings;
if (changed.ContainsKey(estateID))
estateSettings = changed[estateID];
else
estateSettings = Scene.EstateDataService.LoadEstateSettings(estateID);
if (!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
continue;
otherEstates.Add(estateSettings);
}
estateIDs.Clear();
}
if ((estateAccessType & 4) != 0) // add key experience
{
if (thisSettings.KeyExperiencesCount() >= (int)Constants.EstateAccessLimits.KeyExperiences)
{
if (!sentAllowedFull)
{
sentAllowedFull = true;
remote_client.SendAlertMessage("Estate Allowed Experiences list is full");
}
}
else
{
if (doOtherEstates)
{
foreach (EstateSettings estateSettings in otherEstates)
{
if (!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
continue;
if (estateSettings.KeyExperiencesCount() >= (int)Constants.EstateAccessLimits.KeyExperiences)
continue;
estateSettings.AddKeyExperience(experience);
changed[(int)estateSettings.EstateID] = estateSettings;
}
}
thisSettings.AddKeyExperience(experience);
changed[thisEstateID] = thisSettings;
if (needReply)
sendExperienceLists[remote_client] = invoice;
}
}
if ((estateAccessType & 8) != 0) // remove key experience
{
if (doOtherEstates) // All estates
{
foreach (EstateSettings estateSettings in otherEstates)
{
if (!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
continue;
estateSettings.RemoveKeyExperience(experience);
changed[(int)estateSettings.EstateID] = estateSettings;
}
}
thisSettings.RemoveKeyExperience(experience);
changed[thisEstateID] = thisSettings;
if (needReply)
sendExperienceLists[remote_client] = invoice;
}
if ((estateAccessType & 16) != 0) // add allowed experience
{
if (thisSettings.AllowedExperiencesCount() >= (int)Constants.EstateAccessLimits.AllowedExperiences)
{
if (!sentAllowedFull)
{
sentAllowedFull = true;
remote_client.SendAlertMessage("Estate Allowed Experiences list is full");
}
}
else
{
if (doOtherEstates)
{
foreach (EstateSettings estateSettings in otherEstates)
{
if (!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
continue;
if (estateSettings.AllowedExperiencesCount() >= (int)Constants.EstateAccessLimits.AllowedExperiences)
continue;
estateSettings.AddAllowedExperience(experience);
changed[(int)estateSettings.EstateID] = estateSettings;
}
}
thisSettings.AddAllowedExperience(experience);
changed[thisEstateID] = thisSettings;
if (needReply)
sendExperienceLists[remote_client] = invoice;
}
}
if ((estateAccessType & 32) != 0) // remove allowed experience
{
if (doOtherEstates) // All estates
{
foreach (EstateSettings estateSettings in otherEstates)
{
if (!isadmin && !estateSettings.IsEstateManagerOrOwner(agentID))
continue;
estateSettings.RemoveAllowedExperience(experience);
changed[(int)estateSettings.EstateID] = estateSettings;
}
}
thisSettings.RemoveAllowedExperience(experience);
changed[thisEstateID] = thisSettings;
if (needReply)
sendExperienceLists[remote_client] = invoice;
}
}
lock (deltareqLock)
runnigDeltaExec = false;
}
public void HandleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
{
SceneObjectPart part;
@ -1856,6 +2099,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
client.OnEstateChangeInfo += HandleEstateChangeInfo;
client.OnEstateManageTelehub += HandleOnEstateManageTelehub;
client.OnUpdateEstateAccessDeltaRequest += HandleEstateAccessDeltaRequest;
client.OnUpdateEstateExperienceDeltaRequest += handleEstateExperienceDeltaRequest;
client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage;
client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage;
client.OnEstateDebugRegionRequest += HandleEstateDebugRegionRequest;

View file

@ -690,7 +690,9 @@ namespace OpenSim.Region.CoreModules.World.Land
uint flags, UUID transactionID, int landLocalID, List<LandAccessEntry> entries,
IClientAPI remote_client)
{
if ((flags & 0x03) == 0)
// Todo: update the actual AccessList enum!
if ((flags & (uint)0x1Bu) == 0)
return; // we only have access and ban
if(m_scene.RegionInfo.EstateSettings.TaxFree)
@ -709,8 +711,12 @@ namespace OpenSim.Region.CoreModules.World.Land
requiredPowers |= GroupPowers.LandManageAllowed;
if ((flags & (uint)AccessList.Ban) != 0)
requiredPowers |= GroupPowers.LandManageBanned;
if ((flags & (uint)8u) != 0)
requiredPowers |= GroupPowers.LandManageAllowed;
if ((flags & (uint)0x10u) != 0)
requiredPowers |= GroupPowers.LandManageBanned;
if(requiredPowers == GroupPowers.None)
if (requiredPowers == GroupPowers.None)
return;
if (m_scene.Permissions.CanEditParcelProperties(agentID,

View file

@ -1016,6 +1016,8 @@ namespace OpenSim.Region.CoreModules.World.Land
int now = Util.UnixTimeSinceEpoch();
List<LandAccessEntry> accesslist = new();
List<LandAccessEntry> banlist = new();
List<LandAccessEntry> allowed = new();
List<LandAccessEntry> blocked = new();
foreach (LandAccessEntry entry in LandData.ParcelAccessList)
{
if(entry.Expires > now || entry.Expires == 0)
@ -1024,6 +1026,10 @@ namespace OpenSim.Region.CoreModules.World.Land
accesslist.Add(entry);
else if (entry.Flags == AccessList.Ban)
banlist.Add(entry);
else if((uint)entry.Flags == 8u) // Todo: Update to AccessList.Allowed
allowed.Add(entry);
else if((uint)entry.Flags == 0x10u) // Todo: Update to AccessList.Blocked
blocked.Add(entry);
}
}
@ -1046,7 +1052,7 @@ namespace OpenSim.Region.CoreModules.World.Land
public void UpdateAccessList(uint flags, UUID transactionID, List<LandAccessEntry> entries)
{
flags &= 0x03;
flags &= 0x1Bu; // Todo: Update to AccessList.All
if (flags == 0)
return; // we only have access and ban

View file

@ -2336,9 +2336,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
return false;
}
bool notSameOwner = srcsog.OwnerID.NotEqual(destsog.OwnerID);
if(notSameOwner)
if(srcsog.OwnerID.NotEqual(destsog.OwnerID))
{
if((itperms & (uint)PermissionMask.Transfer) == 0)
return false;
@ -2350,7 +2348,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
}
else
{
if((destsogEffectiveOwnerPerms & (uint)PermissionMask.Modify) == 0)
if((destsogEffectiveOwnerPerms & (uint)PermissionMask.Modify) == 0 &&
(destsog.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
return false;
}

View file

@ -91,7 +91,7 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="append">Append to attachment point rather than replace.</param>
/// <returns>true if the object was successfully attached, false otherwise</returns>
bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent,
bool addToInventory, bool append);
bool addToInventory, bool append, UUID experience);
/// <summary>
/// Rez an attachment from user inventory and change inventory status to match.

View file

@ -0,0 +1,15 @@
using OpenMetaverse;
using OpenSim.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OpenSim.Region.Framework.Interfaces
{
public interface IDisplayNameModule
{
public string GetDisplayName(UUID avatar);
}
}

View file

@ -106,6 +106,7 @@ namespace OpenSim.Region.Framework.Interfaces
byte[] BuildEvent(string eventName, OSD eventBody);
void partPhysicsProperties(uint localID, byte physhapetype, float density, float friction, float bounce, float gravmod, UUID avatarID);
void WindlightRefreshEvent(int interpolate, UUID avatarID);
void SendEnvironmentUpdate(UUID experience_id, UUID agent_id, EnvironmentUpdate update);
void SendBulkUpdateInventoryItem(InventoryItemBase item, UUID avatarID, UUID? transationID = null);
osUTF8 StartEvent(string eventName);
osUTF8 StartEvent(string eventName, int cap);

View file

@ -0,0 +1,45 @@
using OpenMetaverse;
using OpenSim.Services.Interfaces;
namespace OpenSim.Region.Framework.Interfaces
{
public interface IExperienceModule
{
ExperiencePermission GetExperiencePermission(UUID avatar_id, UUID experience_id);
bool SetExperiencePermission(UUID avatar_id, UUID experience_id, ExperiencePermission perm);
bool SetExperiencePermissions(UUID avatar_id, UUID experience_id, bool allow);
bool ForgetExperiencePermissions(UUID avatar_id, UUID experience_id);
UUID[] GetAllowedExperiences(UUID avatar_id);
UUID[] GetBlockedExperiences(UUID avatar_id);
UUID[] GetAgentExperiences(UUID agent_id);
UUID[] GetAdminExperiences(UUID agent_id);
UUID[] GetConributorExperiences(UUID agent_id);
ExperienceInfo GetExperienceInfo(UUID experience_id, bool fetch = false);
ExperienceInfo[] GetExperienceInfos(UUID[] experience_ids, bool fetch = false);
ExperienceInfo[] FindExperiencesByName(string query);
UUID[] GetGroupExperiences(UUID group_id);
ExperienceInfo UpdateExperienceInfo(ExperienceInfo info);
bool IsExperienceAdmin(UUID agent_id, UUID experience_id);
bool IsExperienceContributor(UUID agent_id, UUID experience_id);
UUID[] GetEstateAllowedExperiences();
UUID[] GetEstateKeyExperiences();
bool IsExperienceEnabled(UUID experience_id);
string GetKeyValue(UUID experience, string key);
string CreateKeyValue(UUID experience, string key, string value);
string UpdateKeyValue(UUID experience, string key, string val, bool check, string original);
string DeleteKey(UUID experience, string key);
int GetKeyCount(UUID experience);
string[] GetKeys(UUID experience, int start, int count);
int GetSize(UUID experience);
}
}

View file

@ -354,7 +354,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="isScriptRunning">Indicates whether the script to update is currently running</param>
/// <param name="data"></param>
public ArrayList CapsUpdateTaskInventoryScriptAsset(IClientAPI remoteClient, UUID itemId,
UUID primId, bool isScriptRunning, byte[] data)
UUID primId, bool isScriptRunning, UUID experience, byte[] data)
{
if (!Permissions.CanEditScript(itemId, primId, remoteClient.AgentId))
{
@ -391,16 +391,36 @@ namespace OpenSim.Region.Framework.Scenes
part.Inventory.RemoveScriptInstance(item.ItemID, false);
ArrayList errors = new ArrayList();
bool allowed_to_contribute = true;
if (experience != UUID.Zero)
{
allowed_to_contribute = ExperienceModule.IsExperienceContributor(remoteClient.AgentId, experience);
if (!allowed_to_contribute)
{
experience = UUID.Zero;
errors = new ArrayList(1);
errors.Add("Access denied to experience!");
}
}
// Update item with new asset
item.AssetID = asset.FullID;
item.ExperienceID = experience;
group.UpdateInventoryItem(item);
group.InvalidateEffectivePerms();
part.SendPropertiesToClient(remoteClient);
// Trigger rerunning of script (use TriggerRezScript event, see RezScript)
// Needs to determine which engine was running it and use that
ArrayList errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 1);
if (allowed_to_contribute)
{
// Trigger rerunning of script (use TriggerRezScript event, see RezScript)
// Needs to determine which engine was running it and use that
errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 1);
}
// Tell anyone managing scripts that a script has been reloaded/changed
EventManager.TriggerUpdateScript(remoteClient.AgentId, itemId, primId, isScriptRunning, item.AssetID);
@ -413,12 +433,12 @@ namespace OpenSim.Region.Framework.Scenes
/// <see>CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[])</see>
/// </summary>
public ArrayList CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId,
UUID primId, bool isScriptRunning, byte[] data)
UUID primId, bool isScriptRunning, UUID experience, byte[] data)
{
if (TryGetScenePresence(avatarId, out ScenePresence avatar))
{
return CapsUpdateTaskInventoryScriptAsset(
avatar.ControllingClient, itemId, primId, isScriptRunning, data);
avatar.ControllingClient, itemId, primId, isScriptRunning, experience, data);
}
else
{

View file

@ -311,6 +311,7 @@ namespace OpenSim.Region.Framework.Scenes
protected IAuthorizationService m_AuthorizationService;
protected IInventoryService m_InventoryService;
protected IGridService m_GridService;
protected IExperienceModule m_ExperienceModule;
protected ILibraryService m_LibraryService;
protected ISimulationService m_simulationService;
protected IAuthenticationService m_AuthenticationService;
@ -634,6 +635,27 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public IExperienceModule ExperienceModule
{
get
{
m_ExperienceModule ??= RequestModuleInterface<IExperienceModule>();
return m_ExperienceModule;
//if (m_ExperienceModule == null)
//{
// m_ExperienceModule = RequestModuleInterface<IExperienceModule>();
// if (m_ExperienceModule == null)
// {
// throw new Exception("No IExperienceModule available. This could happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set.");
// }
//}
//return m_ExperienceModule;
}
}
public ILibraryService LibraryService
{
get
@ -3057,7 +3079,7 @@ namespace OpenSim.Region.Framework.Scenes
// We currently do this in Scene.MakeRootAgent() instead.
bool attached = false;
if (AttachmentsModule is not null)
attached = AttachmentsModule.AttachObject(sp, grp, 0, false, false, true);
attached = AttachmentsModule.AttachObject(sp, grp, 0, false, false, true, UUID.Zero);
if (attached)
RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
@ -4030,7 +4052,7 @@ namespace OpenSim.Region.Framework.Scenes
m_log.DebugFormat(
"[SCENE]: Access denied for {0} {1} using {2}",
acd.firstname, acd.lastname, curViewer);
reason = "Access denied, your viewer is banned";
reason = "Access denied, your viewer " +curViewer.Trim() +" is not allowed.";
return false;
}

View file

@ -89,9 +89,11 @@ namespace OpenSim.Region.Framework.Scenes
path_update = 40,
linkset_data = 41,
experience_permissions = 42,
experience_permissions_denied = 43,
// marks highest numbered event
Size = 42
Size = 44
}
// this is not the right place for this
@ -143,6 +145,8 @@ namespace OpenSim.Region.Framework.Scenes
path_update = 1UL << 40,
linkset_data = 1UL << 41,
experience_permissions = 1UL << 42,
experience_permissions_denied = 1UL << 43,
anytouch = touch | touch_end | touch_start,
anyTarget = at_target | not_at_target | at_rot_target | not_at_rot_target,
@ -312,6 +316,12 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary>
public bool IsAttachment { get; set; }
/// <summary>
/// What experience temp attached this item
/// This will not be set if the object wasn't temp attached
/// </summary>
public UUID AttachedExperienceID { get; set; }
/// <summary>
/// The avatar to which this scene object is attached.
/// </summary>
@ -5159,35 +5169,35 @@ namespace OpenSim.Region.Framework.Scenes
try
{
float time = 0.0f;
float time = 0.0f;
// get all the scripts in all parts
SceneObjectPart[] parts = m_parts.GetArray();
List<TaskInventoryItem> scripts = new();
for (int i = 0; i < parts.Length; i++)
{
// get all the scripts in all parts
SceneObjectPart[] parts = m_parts.GetArray();
List<TaskInventoryItem> scripts = new();
for (int i = 0; i < parts.Length; i++)
{
IEntityInventory inv = parts[i].Inventory;
if (inv is not null)
scripts.AddRange(parts[i].Inventory.GetInventoryItems(InventoryType.LSL));
}
// extract the UUIDs
HashSet<UUID> unique = new();
foreach (TaskInventoryItem script in scripts)
unique.Add(script.ItemID);
List<UUID> ids = unique.ToList();
// Offer the list of script UUIDs to each engine found and accumulate the time
foreach (IScriptModule e in engines)
{
if (e is not null)
{
time += e.GetScriptExecutionTime(ids);
scripts.AddRange(parts[i].Inventory.GetInventoryItems(InventoryType.LSL));
}
// extract the UUIDs
HashSet<UUID> unique = new();
foreach (TaskInventoryItem script in scripts)
unique.Add(script.ItemID);
List<UUID> ids = unique.ToList();
// Offer the list of script UUIDs to each engine found and accumulate the time
foreach (IScriptModule e in engines)
{
if (e is not null)
{
time += e.GetScriptExecutionTime(ids);
}
}
return time;
}
return time;
}
catch
{
return 0.0f;
@ -5203,40 +5213,39 @@ namespace OpenSim.Region.Framework.Scenes
try
{
// get all the scripts in all parts
SceneObjectPart[] parts = m_parts.GetArray();
List<TaskInventoryItem> scripts = new();
for (int i = 0; i < parts.Length; i++)
{
// get all the scripts in all parts
SceneObjectPart[] parts = m_parts.GetArray();
List<TaskInventoryItem> scripts = new();
for (int i = 0; i < parts.Length; i++)
{
IEntityInventory inv = parts[i].Inventory;
if(inv is not null)
scripts.AddRange(inv.GetInventoryItems(InventoryType.LSL));
}
if (scripts.Count == 0)
return false;
// extract the UUIDs
HashSet<UUID> unique = new();
foreach (TaskInventoryItem script in scripts)
unique.Add(script.ItemID);
List<UUID> ids = unique.ToList();
// Offer the list of script UUIDs to each engine found and accumulate the memory
foreach (IScriptModule e in engines)
{
if (e is not null)
{
memory += e.GetScriptsMemory(ids);
}
if (scripts.Count == 0)
return false;
// extract the UUIDs
HashSet<UUID> unique = new();
foreach (TaskInventoryItem script in scripts)
unique.Add(script.ItemID);
List<UUID> ids = unique.ToList();
// Offer the list of script UUIDs to each engine found and accumulate the memory
foreach (IScriptModule e in engines)
{
if (e is not null)
{
memory += e.GetScriptsMemory(ids);
}
}
return true;
}
return true;
}
catch
{
return false;
}
}
/// <summary>

View file

@ -303,6 +303,9 @@ namespace OpenSim.Region.Framework.Scenes
private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
private Quaternion m_sitTargetOrientation = Quaternion.Identity;
private Vector3 m_sitTargetPosition;
private bool m_scriptedSitOnly = false;
private bool m_allowUnsit = true;
private UUID m_experienceUsedForSit = UUID.Zero;
private string m_sitAnimation = "SIT";
private UndoRedoState m_UndoRedo = null;
private readonly object m_UndoLock = new object();
@ -1264,8 +1267,44 @@ namespace OpenSim.Region.Framework.Scenes
set { m_sitTargetOrientation = value; }
}
public float SitActiveRange { get; set; }
public Vector3 StandOffset { get; set; }
[XmlIgnore]
public bool AllowUnsit
{
get { return m_allowUnsit; }
set
{
m_allowUnsit = value;
if (ParentGroup != null)
ParentGroup.HasGroupChanged = true;
}
}
[XmlIgnore]
public bool ScriptedSitOnly
{
get { return m_scriptedSitOnly; }
set
{
m_scriptedSitOnly = value;
if (ParentGroup != null)
ParentGroup.HasGroupChanged = true;
}
}
[XmlIgnore]
public UUID ExperienceUsedForSit
{
get { return m_experienceUsedForSit; }
set
{
m_experienceUsedForSit = value;
}
}
public float SitActiveRange { get; set;}
public Vector3 StandOffset { get; set;}
public bool Stopped
{

View file

@ -2645,7 +2645,19 @@ namespace OpenSim.Region.Framework.Scenes
// SendAgentTerseUpdate(this);
if ((allFlags & ACFlags.AGENT_CONTROL_STAND_UP) != 0)
{
if (ParentPart != null && !ParentPart.AllowUnsit)
{
// Check that the experience still has permission to keep the user seated
if(Scene.ExperienceModule.GetExperiencePermission(remoteClient.AgentId, ParentPart.ExperienceUsedForSit) == ExperiencePermission.Allowed)
{
ControllingClient.SendAgentAlertMessage(string.Format("'{0}' will not allow you to stand at this time.", ParentPart.Name), false);
return;
}
}
StandUp();
}
if ((allFlags & ACFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
HandleAgentSitOnGround();
@ -3374,10 +3386,31 @@ namespace OpenSim.Region.Framework.Scenes
if (IsChildAgent)
return;
SceneObjectPart part = Scene.GetSceneObjectPart(targetID);
if (part == null)
return;
if(part.ScriptedSitOnly)
{
ControllingClient.SendAgentAlertMessage("There is no suitable surface to sit on, try another spot.", false);
return;
}
if (ParentID != 0)
{
if (targetID.Equals(ParentPart.UUID))
return; // already sitting here, ignore
if (!ParentPart.AllowUnsit)
{
if (Scene.ExperienceModule.GetExperiencePermission(this.UUID, ParentPart.ExperienceUsedForSit) == ExperiencePermission.Allowed)
{
ControllingClient.SendAgentAlertMessage(string.Format("'{0}' will not allow you to change your seat at this time.", ParentPart.Name), false);
return;
}
}
StandUp();
}
else if (SitGround)
@ -3386,6 +3419,26 @@ namespace OpenSim.Region.Framework.Scenes
SendSitResponse(targetID, offset, Quaternion.Identity);
}
public void ScriptedSit(SceneObjectPart part, UUID agent_id, UUID experience_id)
{
// todo: come back to this!
if (IsChildAgent)
return;
if (ParentID != 0)
{
if (agent_id.Equals(ParentPart.UUID))
return; // already sitting here, ignore
StandUp();
}
else if (SitGround)
StandUp();
SendSitResponse(part.UUID, part.SitTargetPositionLL, part.SitTargetOrientationLL);
}
// returns false if does not suport so older sit can be tried
public bool PhysicsSit(SceneObjectPart part, Vector3 offset)
{

View file

@ -515,7 +515,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
{"SOPAnims", ProcessSOPAnims },
{"SitActRange", ProcessSitActRange },
{"LinksetData", ProcessLinksetData}
{"LinksetData", ProcessLinksetData },
{"AllowUnsit", ProcessAllowUnsit },
{"ScriptedSitOnly", ProcessScriptedSitOnly }
}.ToFrozenDictionary();
private static readonly FrozenDictionary<string, Action<TaskInventoryItem, XmlReader>> m_TaskInventoryXmlProcessors = new Dictionary<string, Action<TaskInventoryItem, XmlReader>>()
@ -815,6 +817,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
obj.SitActiveRange = reader.ReadElementContentAsFloat("SitActRange", string.Empty);
}
private static void ProcessAllowUnsit(SceneObjectPart obj, XmlReader reader)
{
obj.AllowUnsit = Util.ReadBoolean(reader);
}
private static void ProcessScriptedSitOnly(SceneObjectPart obj, XmlReader reader)
{
obj.ScriptedSitOnly = Util.ReadBoolean(reader);
}
private static void ProcessLinksetData(SceneObjectPart obj, XmlReader reader)
{
try
@ -1683,7 +1695,10 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
var lsd = sop.SerializeLinksetData();
if (string.IsNullOrWhiteSpace(lsd) is false)
writer.WriteElementString("LinksetData", lsd);
writer.WriteElementString("AllowUnsit", sop.AllowUnsit.ToString().ToLower());
writer.WriteElementString("ScriptedSitOnly", sop.ScriptedSitOnly.ToString().ToLower());
writer.WriteEndElement();
}

View file

@ -827,6 +827,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
public event EstateRestartSimRequest OnEstateRestartSimRequest;
public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
public event UpdateEstateExperienceDeltaRequest OnUpdateEstateExperienceDeltaRequest;
public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
@ -1250,7 +1251,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
}
public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question)
public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question, UUID experience)
{
}
public void SendEstateExperiences(UUID invoice, UUID[] allowed, UUID[] key, uint estateID)
{
}
@ -1778,5 +1784,8 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
return 0;
}
public void SendGenericMessageForExperience(UUID experience_id, UUID avatar_id, int action, string obj_name, string parcel, bool is_attachment)
{
}
}
}

View file

@ -66,7 +66,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
//private static readonly string m_chatSessionRequestPath = "0209/";
// Control info
private static bool m_Enabled = false;
private static bool m_Enabled = false;
// FreeSwitch server is going to contact us and ask us all
// sorts of things.
@ -111,8 +111,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
try
{
string serviceDll = m_Config.GetString("LocalServiceModule",
String.Empty);
string serviceDll = m_Config.GetString("LocalServiceModule", String.Empty);
if (serviceDll.Length == 0)
{
@ -325,6 +324,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
m_log.DebugFormat(
"[FreeSwitchVoice][PROVISIONVOICE]: ProvisionVoiceAccountRequest() request for {0}", agentID.ToString());
Stream inputStream = request.InputStream;
if (inputStream.Length > 0)
{
OSD tmp = OSDParser.DeserializeLLSDXml(inputStream);
request.InputStream.Dispose();
if (tmp is OSDMap map)
{
if (map.TryGetValue("voice_server_type", out OSD vstosd))
{
if (vstosd is OSDString vst && !((string)vst).Equals("vivox", StringComparison.OrdinalIgnoreCase))
{
response.RawBuffer = Util.UTF8.GetBytes("<llsd><undef /></llsd>");
return;
}
}
}
}
response.StatusCode = (int)HttpStatusCode.OK;
ScenePresence avatar = scene.GetScenePresence(agentID);

View file

@ -459,6 +459,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
response.StatusCode = (int)HttpStatusCode.OK;
try
{
Stream inputStream = request.InputStream;
if (inputStream.Length > 0)
{
OSD tmp = OSDParser.DeserializeLLSDXml(inputStream);
request.InputStream.Dispose();
if (tmp is OSDMap map)
{
if (map.TryGetValue("voice_server_type", out OSD vstosd))
{
if (vstosd is OSDString vst && !((string)vst).Equals("vivox", StringComparison.OrdinalIgnoreCase))
{
response.RawBuffer = Util.UTF8.GetBytes("<llsd><undef /></llsd>");
return;
}
}
}
}
ScenePresence avatar = null;
string avatarName = null;

View file

@ -458,6 +458,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
public event EstateRestartSimRequest OnEstateRestartSimRequest;
public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest;
public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest;
public event UpdateEstateExperienceDeltaRequest OnUpdateEstateExperienceDeltaRequest;
public event SimulatorBlueBoxMessageRequest OnSimulatorBlueBoxMessageRequest;
public event EstateBlueBoxMessageRequest OnEstateBlueBoxMessageRequest;
public event EstateDebugRegionRequest OnEstateDebugRegionRequest;
@ -1085,13 +1086,17 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{
}
public void SendScriptQuestion(UUID objectID, string taskName, string ownerName, UUID itemID, int question)
public void SendScriptQuestion(UUID objectID, string taskName, string ownerName, UUID itemID, int question, UUID experience)
{
}
public void SendHealth(float health)
{
}
public void SendEstateExperiences(UUID invoice, UUID[] allowed, UUID[] key, uint estateID)
{
}
public void SendEstateList(UUID invoice, int code, UUID[] Data, uint estateID)
{
}
@ -1401,5 +1406,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
return 0;
}
public void SendGenericMessageForExperience(UUID experience_id, UUID avatar_id, int action, string obj_name, string parcel, bool is_attachment)
{
}
}
}

View file

@ -5561,6 +5561,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return LSL_String.NullKey;
}
public LSL_List osGetLinkInventoryKeys(LSL_Integer linkNumber, LSL_Integer type)
{
LSL_List ret = new();
SceneObjectPart part = GetSingleLinkPart(linkNumber);
if(part == null)
return ret;
part.TaskInventory.LockItemsForRead(true);
foreach (KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory)
{
if (inv.Value.Type == type || type == -1 &&
(inv.Value.CurrentPermissions
& (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
== (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
ret.Add(inv.Value.AssetID.ToString());
}
part.TaskInventory.LockItemsForRead(false);
return ret;
}
public LSL_Key osGetLinkInventoryItemKey(LSL_Integer linkNumber, LSL_String name)
{
SceneObjectPart part = GetSingleLinkPart(linkNumber);

View file

@ -523,6 +523,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_Integer llLinksetDataDeleteProtected(LSL_String name, LSL_String pass);
LSL_Integer llIsFriend(LSL_Key agent_id);
LSL_Integer llDerezObject(LSL_Key objectUUID, LSL_Integer flag);
}
LSL_Integer llDerezObject(LSL_Key objectUUID, LSL_Integer flag);
void llRequestExperiencePermissions(string agent_id, string unused);
LSL_Integer llAgentInExperience(string agent_id);
LSL_List llGetExperienceDetails(string experience_key);
LSL_String llGetExperienceErrorMessage(LSL_Integer error);
LSL_Integer llSitOnLink(string agent_id, LSL_Integer link);
LSL_Key llCreateKeyValue(string key, string value);
LSL_Key llDeleteKeyValue(string key);
LSL_Key llReadKeyValue(string key);
LSL_Key llUpdateKeyValue(string key, string value, LSL_Integer check, string original);
LSL_Key llKeyCountKeyValue();
LSL_Key llKeysKeyValue(LSL_Integer first, LSL_Integer count);
LSL_Key llDataSizeKeyValue();
LSL_Integer llSetAgentEnvironment(LSL_Key agent_id, LSL_Float transition, LSL_List param_list);
LSL_Integer llReplaceAgentEnvironment(LSL_Key agent_id, LSL_Float transition, LSL_String environment);
}
}

View file

@ -562,6 +562,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_Key osGetInventoryLastOwner(LSL_String itemNameOrId);
LSL_Key osGetInventoryItemKey(LSL_String name);
LSL_Key osGetLinkInventoryKey(LSL_Integer linkNumber, LSL_String name, LSL_Integer type);
LSL_List osGetLinkInventoryKeys(LSL_Integer linkNumber, LSL_Integer type);
LSL_Key osGetLinkInventoryItemKey(LSL_Integer linkNumber, LSL_String name);
LSL_String osGetInventoryName(LSL_Key itemId);
LSL_String osGetLinkInventoryName(LSL_Integer linkNumber, LSL_Key itemId);

View file

@ -1015,6 +1015,73 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int TARGETED_EMAIL_ROOT_CREATOR = 1;
public const int TARGETED_EMAIL_OBJECT_OWNER = 2;
// Experience
public const int XP_ERROR_NONE = 0;
public const int XP_ERROR_THROTTLED = 1;
public const int XP_ERROR_EXPERIENCES_DISABLED = 2;
public const int XP_ERROR_INVALID_PARAMETERS = 3;
public const int XP_ERROR_NOT_PERMITTED = 4;
public const int XP_ERROR_NO_EXPERIENCE = 5;
public const int XP_ERROR_NOT_FOUND = 6;
public const int XP_ERROR_INVALID_EXPERIENCE = 7;
public const int XP_ERROR_EXPERIENCE_DISABLED = 8;
public const int XP_ERROR_EXPERIENCE_SUSPENDED = 9;
public const int XP_ERROR_UNKNOWN_ERROR = 10;
public const int XP_ERROR_QUOTA_EXCEEDED = 11;
public const int XP_ERROR_STORE_DISABLED = 12;
public const int XP_ERROR_STORAGE_EXCEPTION = 13;
public const int XP_ERROR_KEY_NOT_FOUND = 14;
public const int XP_ERROR_RETRY_UPDATE = 15;
public const int XP_ERROR_MATURITY_EXCEEDED = 16;
public const int XP_ERROR_NOT_PERMITTED_LAND = 17;
public const int XP_ERROR_REQUEST_PERM_TIMEOUT = 18;
// llSitOnLink
public const int SIT_NOT_EXPERIENCE = -1;
public const int SIT_NO_EXPERIENCE_PERMISSION = -2;
public const int SIT_NO_SIT_TARGET = -3;
public const int SIT_INVALID_AGENT = -4;
public const int SIT_INVALID_LINK = -5;
public const int SIT_NO_ACCESS = -6;
public const int SIT_INVALID_OBJECT = -7;
// EEP
public const int ENV_NOT_EXPERIENCE = -1;
public const int ENV_NO_EXPERIENCE_PERMISSION = -2;
public const int ENV_NO_ENVIRONMENT = -3;
public const int ENV_INVALID_AGENT = -4;
public const int ENV_INVALID_RULE = -5;
public const int ENV_VALIDATION_FAIL = -6;
public const int ENV_NO_EXPERIENCE_LAND = -7;
public const int ENV_THROTTLE = -8;
public const int SKY_CLOUDS = 2;
public const int SKY_CLOUD_TEXTURE = 19;
public const int SKY_DOME = 4;
public const int SKY_GAMMA = 5;
public const int SKY_GLOW = 6;
public const int SKY_MOON = 9;
public const int SKY_MOON_TEXTURE = 20;
public const int SKY_STAR_BRIGHTNESS = 13;
public const int SKY_SUN = 14;
public const int SKY_SUN_TEXTURE = 21;
public const int SKY_PLANET = 10;
public const int SKY_REFRACTION = 11;
public const int WATER_BLUR_MULTIPLIER = 100;
public const int WATER_FOG = 101;
public const int WATER_FRESNEL = 102;
public const int WATER_NORMAL_TEXTURE = 107;
public const int WATER_NORMAL_SCALE = 104;
public const int WATER_REFRACTION = 105;
public const int WATER_WAVE_DIRECTION = 106;
public const int SKY_AMBIENT = 0;
public const int SKY_BLUE = 22;
public const int SKY_HAZE = 23;
public const int SKY_REFLECTION_PROBE_AMBIANCE = 24;
public const int NPCLOOKAT_NONE = 0;
public const int NPCLOOKAT_IDLE = 1;
public const int NPCLOOKAT_LISTEN = 2;

View file

@ -1465,6 +1465,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{
return m_OSSL_Functions.osGetLinkInventoryKey(linkNumber, name, type);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public LSL_List osGetLinkInventoryKeys(LSL_Integer linkNumber, LSL_Integer type)
{
return m_OSSL_Functions.osGetLinkInventoryKeys(linkNumber, type);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public LSL_Key osGetLinkInventoryItemKey(LSL_Integer linkNumber, LSL_String name)

View file

@ -154,7 +154,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
while (++comma < str.Length)
{
c = Unsafe.Add(ref MemoryMarshal.GetReference(str), comma);
if (c == ' ' || c == '>')
if (c == '>')
break;
}
@ -575,7 +575,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
while (++comma < str.Length)
{
c = Unsafe.Add(ref MemoryMarshal.GetReference(str), comma);
if (c == ' ' || c == '>')
if (c == '>')
break;
}

View file

@ -75,5 +75,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
void path_update(int type, LSL_List data);
void region_cross(LSL_Vector newpos, LSL_Vector oldpos);
void linkset_data(LSL_Integer action, string name, string value);
void experience_permissions(LSL_Key agent_id);
void experience_permissions_denied(LSL_Key agent_id, LSL_Integer reason);
}
}

View file

@ -85,7 +85,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
path_update = 40,
linkset_data = 41,
experience_permissions = 42,
experience_permissions_denied = 43,
// marks highest numbered event
Size = 42
Size = 44
}
}

View file

@ -184,6 +184,12 @@ namespace OpenSim.Region.ScriptEngine.Yengine
scriptStateN.AppendChild(plugins);
//m_RunOnePhase = "GetExecutionState H";
XmlElement experienceN = doc.CreateElement("", "ExperienceKey", "");
experienceN.AppendChild(doc.CreateTextNode(m_Item.ExperienceID.ToString()));
scriptStateN.AppendChild(experienceN);
//m_RunOnePhase = "GetExecutionState I";
//CheckRunLockInvariants(true);
// Let script run again.
suspendOnCheckRunHold = false;

View file

@ -544,6 +544,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
MigrateInEventHandler(ms);
}
XmlElement experienceKey = (XmlElement)scriptStateN.SelectSingleNode("ExperienceKey");
m_Item.ExperienceID = UUID.Parse(experienceKey.InnerText);
XmlElement permissionsN = (XmlElement)scriptStateN.SelectSingleNode("Permissions");
m_Item.PermsGranter = new UUID(permissionsN.GetAttribute("granter"));
m_Item.PermsMask = Convert.ToInt32(permissionsN.GetAttribute("mask"));
@ -593,6 +596,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
int permsMask = 0;
double minEventDelay = 0.0;
Object[] pluginData = new Object[0];
UUID experienceKey = UUID.Zero;
LinkedList<EventParams> eventQueue = new LinkedList<EventParams>();
@ -661,6 +665,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
case "Running":
running = bool.Parse(part.InnerText);
break;
case "ExperienceKey":
experienceKey = UUID.Parse(part.InnerText);
break;
case "Variables":
int indx;
XmlNodeList varL = part.ChildNodes;
@ -880,6 +887,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
m_Item.PermsGranter = permsGranter;
m_Item.PermsMask = permsMask;
m_Item.ExperienceID = experienceKey;
m_Part.Inventory.UpdateInventoryItem(m_Item, false, false);
lock (m_RunLock)

View file

@ -138,7 +138,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
// guards m_DetachQuantum, m_EventQueue, m_EventCounts, m_Running, m_Suspended
public Object m_QueueLock = new Object();
// true iff allowed to accept new events
// true if allowed to accept new events
public bool m_Running = true;
// queue of events that haven't been acted upon yet
@ -242,7 +242,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
{"sensor", ScriptEventCode.sensor},
{"http_request", ScriptEventCode.http_request},
{"path_update", ScriptEventCode.path_update},
{"linkset_data", ScriptEventCode.linkset_data}
{"linkset_data", ScriptEventCode.linkset_data},
{"experience_permissions", ScriptEventCode.experience_permissions},
{"experience_permissions_denied", ScriptEventCode.experience_permissions_denied},
};
}
}

View file

@ -133,6 +133,19 @@ namespace OpenSim.Server.Base
m_configDirectory = startupConfig.GetString("ConfigDirectory", m_configDirectory);
prompt = startupConfig.GetString("Prompt", prompt);
if(startupConfig.GetBoolean("EnableRobustSelfsignedCertSupport", false))
{
if(!File.Exists("SSL\\ssl\\"+ startupConfig.GetString("RobustCertFileName") +".p12") || startupConfig.GetBoolean("RobustCertRenewOnStartup"))
{
Util.CreateOrUpdateSelfsignedCert(
string.IsNullOrEmpty(startupConfig.GetString("RobustCertFileName")) ? "Robust" : startupConfig.GetString("RobustCertFileName"),
string.IsNullOrEmpty(startupConfig.GetString("RobustCertHostName")) ? "localhost" : startupConfig.GetString("RobustCertHostName"),
string.IsNullOrEmpty(startupConfig.GetString("RobustCertHostIp")) ? "127.0.0.1" : startupConfig.GetString("RobustCertHostIp"),
string.IsNullOrEmpty(startupConfig.GetString("RobustCertPassword")) ? string.Empty : startupConfig.GetString("RobustCertPassword")
);
}
}
}
// Allow derived classes to load config before the console is opened.
ReadConfig();
@ -327,7 +340,7 @@ namespace OpenSim.Server.Base
Uri configUri;
return Uri.TryCreate(file, UriKind.Absolute,
out configUri) && configUri.Scheme == Uri.UriSchemeHttp;
out configUri) && (configUri.Scheme == Uri.UriSchemeHttp || configUri.Scheme == Uri.UriSchemeHttps);
}
IConfigSource ReadConfigSource(string iniFile)
@ -340,7 +353,7 @@ namespace OpenSim.Server.Base
try
{
if (Uri.TryCreate(iniFile, UriKind.Absolute, out configUri) &&
configUri.Scheme == Uri.UriSchemeHttp)
(configUri.Scheme == Uri.UriSchemeHttp || configUri.Scheme == Uri.UriSchemeHttps))
{
XmlReader r = XmlReader.Create(iniFile);
s = new XmlConfigSource(r);

View file

@ -0,0 +1,36 @@
using System;
using Nini.Config;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework.ServiceAuth;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Server.Handlers.Base;
namespace OpenSim.Server.Handlers.Experience
{
public class ExperienceServiceConnector : ServiceConnector
{
private IExperienceService m_ExperienceService;
private string m_ConfigName = "ExperienceService";
public ExperienceServiceConnector(IConfigSource config, IHttpServer server, string configName) :
base(config, server, configName)
{
IConfig serverConfig = config.Configs[m_ConfigName];
if (serverConfig == null)
throw new Exception(String.Format("No section {0} in config file", m_ConfigName));
string service = serverConfig.GetString("LocalServiceModule", String.Empty);
if (service == String.Empty)
throw new Exception("LocalServiceModule not present in ExperienceService config file ExperienceService section");
Object[] args = new Object[] { config };
m_ExperienceService = ServerUtils.LoadPlugin<IExperienceService>(service, args);
IServiceAuth auth = ServiceAuth.Create(config, m_ConfigName);
server.AddStreamHandler(new ExperienceServerPostHandler(m_ExperienceService, auth));
}
}
}

View file

@ -0,0 +1,456 @@
using Nini.Config;
using log4net;
using System;
using System.Reflection;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenSim.Framework;
using OpenSim.Framework.ServiceAuth;
using OpenSim.Framework.Servers.HttpServer;
using OpenMetaverse;
using System.Linq;
namespace OpenSim.Server.Handlers.Experience
{
public class ExperienceServerPostHandler : BaseStreamHandler
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private IExperienceService m_service;
public ExperienceServerPostHandler(IExperienceService service, IServiceAuth auth) :
base("POST", "/experience", auth)
{
m_service = service;
}
protected override byte[] ProcessRequest(string path, Stream requestData,
IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
{
string body;
using(StreamReader sr = new StreamReader(requestData))
body = sr.ReadToEnd();
body = body.Trim();
//m_log.InfoFormat("[EXPERIENCE POST HANDLER]: {0}", body);
string method = string.Empty;
try
{
Dictionary<string, object> request = ServerUtils.ParseQueryString(body);
if (!request.ContainsKey("METHOD"))
return FailureResult();
method = request["METHOD"].ToString();
switch (method)
{
case "getpermissions":
return GetPermissions(request);
case "updatepermission":
return UpdatePermission(request);
case "getexperienceinfos":
return GetExperienceInfos(request);
case "getagentexperiences":
return GetAgentExperiences(request);
case "updateexperienceinfo":
return UpdateExperienceInfo(request);
case "findexperiences":
return FindExperiences(request);
case "getgroupexperiences":
return GetGroupExperiences(request);
case "getexperiencesforgroups":
return GetExperiencesForGroups(request);
case "accesskvdatabase":
return AccessKeyValueDatabase(request);
}
m_log.DebugFormat("[EXPERIENCE HANDLER]: unknown method request: {0}", method);
}
catch (Exception e)
{
m_log.DebugFormat("[EXPERIENCE HANDLER]: Exception in method {0}: {1}", method, e);
}
return FailureResult();
}
private byte[] GetExperiencesForGroups(Dictionary<string, object> request)
{
List<UUID> groups = new List<UUID>();
int i = 0;
while (true)
{
string key = string.Format("id_{0}", i);
if (request.ContainsKey(key) == false)
break;
UUID group_id;
if (!UUID.TryParse(request[key].ToString(), out group_id))
break;
groups.Add(group_id);
i++;
}
Dictionary<string, object> result = new Dictionary<string, object>();
UUID[] experiences = m_service.GetExperiencesForGroups(groups.ToArray());
i = 0;
foreach (var id in experiences)
result.Add("id_" + i++, id.ToString());
string xmlString = ServerUtils.BuildXmlResponse(result);
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
private byte[] GetGroupExperiences(Dictionary<string, object> request)
{
UUID group_id;
if (!UUID.TryParse(request["GROUP"].ToString(), out group_id))
return FailureResult();
UUID[] experiences = m_service.GetGroupExperiences(group_id);
Dictionary<string, object> result = new Dictionary<string, object>();
int i = 0;
foreach (var id in experiences)
result.Add("id_" + i++, id.ToString());
string xmlString = ServerUtils.BuildXmlResponse(result);
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
private byte[] FindExperiences(Dictionary<string, object> request)
{
if (!request.ContainsKey("SEARCH"))
return FailureResult();
string search = request["SEARCH"].ToString();
ExperienceInfo[] infos = m_service.FindExperiencesByName(search);
Dictionary<string, object> result = new Dictionary<string, object>();
if ((infos == null) || ((infos != null) && (infos.Length == 0)))
{
result["result"] = "null";
}
else
{
int n = 0;
foreach (ExperienceInfo ex in infos)
{
if (ex == null)
continue;
Dictionary<string, object> rinfoDict = ex.ToDictionary();
result["experience_" + n] = rinfoDict;
n++;
}
}
string xmlString = ServerUtils.BuildXmlResponse(result);
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
byte[] GetPermissions(Dictionary<string, object> request)
{
UUID agent_id;
if( !UUID.TryParse(request["agent_id"].ToString(), out agent_id))
return FailureResult();
Dictionary<UUID, bool> reply_data = m_service.FetchExperiencePermissions(agent_id);
XmlDocument doc = new XmlDocument();
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
doc.AppendChild(xmlnode);
XmlElement rootElement = doc.CreateElement("", "ServerResponse", "");
doc.AppendChild(rootElement);
int i = 0;
foreach(var pair in reply_data)
{
XmlElement key = doc.CreateElement("", string.Format("uuid_{0}", i), "");
key.AppendChild(doc.CreateTextNode(pair.Key.ToString()));
rootElement.AppendChild(key);
XmlElement perm = doc.CreateElement("", string.Format("perm_{0}", i), "");
perm.AppendChild(doc.CreateTextNode(pair.Value.ToString()));
rootElement.AppendChild(perm);
i++;
}
return Util.DocToBytes(doc);
}
byte[] GetAgentExperiences(Dictionary<string, object> request)
{
UUID agent_id;
if (!UUID.TryParse(request["AGENT"].ToString(), out agent_id))
return FailureResult();
UUID[] experiences = m_service.GetAgentExperiences(agent_id);
Dictionary<string, object> result = new Dictionary<string, object>();
int i = 0;
foreach (var id in experiences)
result.Add("id_" + i++, id.ToString());
string xmlString = ServerUtils.BuildXmlResponse(result);
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
byte[] UpdatePermission(Dictionary<string, object> request)
{
UUID agent_id;
UUID experience;
if (!UUID.TryParse(request["agent_id"].ToString(), out agent_id))
return FailureResult();
if (!UUID.TryParse(request["experience"].ToString(), out experience))
return FailureResult();
string perm = request["permission"].ToString();
ExperiencePermission permissions = ExperiencePermission.None;
if (perm == "allow") permissions = ExperiencePermission.Allowed;
else if (perm == "block") permissions = ExperiencePermission.Blocked;
return m_service.UpdateExperiencePermissions(agent_id, experience, permissions) ? SuccessResult() : FailureResult();
}
byte[] GetExperienceInfos(Dictionary<string, object> request)
{
List<UUID> experiences = new List<UUID>();
int i = 0;
while(true)
{
string key = string.Format("id_{0}", i);
if (request.ContainsKey(key) == false)
break;
UUID experience_id;
if (!UUID.TryParse(request[key].ToString(), out experience_id))
break;
experiences.Add(experience_id);
i++;
}
ExperienceInfo[] infos = m_service.GetExperienceInfos(experiences.ToArray());
Dictionary<string, object> result = new Dictionary<string, object>();
if ((infos == null) || ((infos != null) && (infos.Length == 0)))
{
result["result"] = "null";
}
else
{
int n = 0;
foreach (ExperienceInfo ex in infos)
{
if (ex == null)
continue;
Dictionary<string, object> rinfoDict = ex.ToDictionary();
result["experience_" + n] = rinfoDict;
n++;
}
}
string xmlString = ServerUtils.BuildXmlResponse(result);
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
byte[] UpdateExperienceInfo(Dictionary<string, object> request)
{
Dictionary<string, object> result = new Dictionary<string, object>();
if (request.ContainsKey("public_id"))
{
ExperienceInfo info = new ExperienceInfo(request);
var updated = m_service.UpdateExpereienceInfo(info);
if(updated != null)
{
result = updated.ToDictionary();
}
else result["result"] = "failed";
}
else result["result"] = "failed";
string xmlString = ServerUtils.BuildXmlResponse(result);
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
private byte[] AccessKeyValueDatabase(Dictionary<string, object> request)
{
UUID experience_id;
if (!UUID.TryParse(request["EXPERIENCE"].ToString(), out experience_id))
return FailureResult();
if (request.ContainsKey("ACTION") == false)
return FailureResult();
string action = request["ACTION"].ToString();
Dictionary<string, object> result = new Dictionary<string, object>();
if (action == "GET")
{
if (request.ContainsKey("KEY") == false)
return FailureResult();
string key = request["KEY"].ToString();
string get = m_service.GetKeyValue(experience_id, key);
if(get != null)
{
result.Add("result", "success");
result.Add("value", get);
}
else
{
result.Add("result", "missing");
}
}
else if (action == "CREATE")
{
if (request.ContainsKey("KEY") == false || request.ContainsKey("VALUE") == false)
return FailureResult();
string key = request["KEY"].ToString();
string val = request["VALUE"].ToString();
string get = m_service.GetKeyValue(experience_id, key);
if (get == null)
{
result.Add("result", m_service.CreateKeyValue(experience_id, key, val));
}
else
{
result.Add("result", "exists");
}
}
else if (action == "UPDATE")
{
if (request.ContainsKey("KEY") == false || request.ContainsKey("VALUE") == false || request.ContainsKey("CHECK") == false)
return FailureResult();
string key = request["KEY"].ToString();
string val = request["VALUE"].ToString();
bool check = request["CHECK"].ToString() == "TRUE";
string original = string.Empty;
if (check)
{
if (request.ContainsKey("ORIGINAL") == false)
return FailureResult();
else
original = request["ORIGINAL"].ToString();
}
result.Add("result", m_service.UpdateKeyValue(experience_id, key, val, check, original));
}
else if (action == "DELETE")
{
if (request.ContainsKey("KEY") == false)
return FailureResult();
string key = request["KEY"].ToString();
result.Add("result", m_service.DeleteKey(experience_id, key));
}
else if (action == "COUNT")
{
int count = m_service.GetKeyCount(experience_id);
result.Add("result", "success");
result.Add("count", count);
}
else if (action == "GETKEYS")
{
if (request.ContainsKey("START") == false || request.ContainsKey("COUNT") == false)
return FailureResult();
int start = int.Parse(request["START"].ToString());
int count = int.Parse(request["COUNT"].ToString());
string[] keys = m_service.GetKeys(experience_id, start, count);
int i = 0;
foreach (var str in keys)
result.Add("key_" + i++, str);
}
else if(action == "SIZE")
{
int size = m_service.GetSize(experience_id);
result.Add("result", "success");
result.Add("count", size);
}
string xmlString = ServerUtils.BuildXmlResponse(result);
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
private byte[] SuccessResult()
{
XmlDocument doc = new XmlDocument();
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
doc.AppendChild(xmlnode);
XmlElement rootElement = doc.CreateElement("", "ServerResponse", "");
doc.AppendChild(rootElement);
XmlElement result = doc.CreateElement("", "result", "");
result.AppendChild(doc.CreateTextNode("Success"));
rootElement.AppendChild(result);
return Util.DocToBytes(doc);
}
private byte[] FailureResult()
{
XmlDocument doc = new XmlDocument();
XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, "", "");
doc.AppendChild(xmlnode);
XmlElement rootElement = doc.CreateElement("", "ServerResponse", "");
doc.AppendChild(rootElement);
XmlElement result = doc.CreateElement("", "result", "");
result.AppendChild(doc.CreateTextNode("Failure"));
rootElement.AppendChild(result);
return Util.DocToBytes(doc);
}
}
}

View file

@ -104,6 +104,8 @@ namespace OpenSim.Server.Handlers.UserAccounts
return GetAccounts(request);
case "getmultiaccounts":
return GetMultiAccounts(request);
case "setdisplayname":
return SetDisplayName(request);
case "setaccount":
if (m_AllowSetAccount)
return StoreAccount(request);
@ -256,6 +258,28 @@ namespace OpenSim.Server.Handlers.UserAccounts
return Util.UTF8NoBomEncoding.GetBytes(xmlString);
}
byte[] SetDisplayName(Dictionary<string, object> request)
{
object otmp;
UUID principalID = UUID.Zero;
if (request.TryGetValue("PrincipalID", out otmp) && !UUID.TryParse(otmp.ToString(), out principalID))
return FailureResult();
UserAccount existingAccount = m_UserAccountService.GetUserAccount(UUID.Zero, principalID);
if (existingAccount == null)
return FailureResult();
if (!request.TryGetValue("DisplayName", out otmp))
return FailureResult();
if (!m_UserAccountService.SetDisplayName(principalID, otmp.ToString()))
return FailureResult();
Dictionary<string, object> result = new Dictionary<string, object>();
result["result"] = "success";
return ResultToBytes(result);
}
byte[] StoreAccount(Dictionary<string, object> request)
{
object otmp;

View file

@ -195,17 +195,24 @@ namespace OpenSim.Services.Connectors
// /estates/estate/?region=uuid&create=[t|f]
string uri = m_ServerURI + string.Format("/estates/estate/?region={0}&create={1}", regionID, create);
//MakeRequest is bugged as its using the older deprecated WebRequest. A call to the estate
// service here will return a 404 if the estate doesnt exist which is correct but the code
// assumes thats a fatal error. BTW We should never ever call Enviroinment.Exit from a supporting
// module or a library like this. So its gonna go.
reply = MakeRequest("GET", uri, string.Empty);
if(reply == null)
if (reply is null)
{
// this is a fatal error
m_log.DebugFormat("[ESTATE CONNECTOR] connection to remote estates service failed");
m_log.DebugFormat("[ESTATE CONNECTOR] simulator needs to terminate");
Environment.Exit(-1);
//m_log.DebugFormat("[ESTATE CONNECTOR] simulator needs to terminate");
//Environment.Exit(-1);
return null;
}
if (String.IsNullOrEmpty(reply))
{
return null;
}
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
@ -216,7 +223,9 @@ namespace OpenSim.Services.Connectors
return es;
}
else
{
m_log.DebugFormat("[ESTATE CONNECTOR]: LoadEstateSettings(regionID) from {0} received null or zero response", uri);
}
return null;
}

View file

@ -0,0 +1,528 @@
using log4net;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Framework.ServiceAuth;
using OpenSim.Services.Interfaces;
using GridRegion = OpenSim.Services.Interfaces.GridRegion;
using OpenSim.Server.Base;
using OpenMetaverse;
using System.Security.AccessControl;
using OpenSim.Data;
using System.Linq;
namespace OpenSim.Services.Connectors
{
public class ExperienceServicesConnector : BaseServiceConnector, IExperienceService
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private string m_ServerURI = String.Empty;
public ExperienceServicesConnector()
{
}
public ExperienceServicesConnector(string serverURI)
{
m_ServerURI = serverURI.TrimEnd('/') + "/experience";
}
public ExperienceServicesConnector(IConfigSource source)
{
Initialise(source);
}
public virtual void Initialise(IConfigSource source)
{
IConfig gridConfig = source.Configs["ExperienceService"];
if (gridConfig == null)
{
m_log.Error("[EXPERIENCE CONNECTOR]: ExperienceService missing from configuration");
throw new Exception("Experience connector init error");
}
string serviceURI = gridConfig.GetString("ExperienceServerURI",
String.Empty);
if (serviceURI == String.Empty)
{
m_log.Error("[EXPERIENCE CONNECTOR]: No Server URI named in section GridUserService");
throw new Exception("Experience connector init error");
}
m_ServerURI = serviceURI + "/experience";
base.Initialise(source, "ExperienceService");
}
#region IExperienceService
public Dictionary<UUID, bool> FetchExperiencePermissions(UUID agent_id)
{
//m_log.InfoFormat("[ExperienceServiceConnector]: FetchExperiencePermissions for {0}", agent_id);
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "getpermissions";
sendData["agent_id"] = agent_id.ToString();
string request_str = ServerUtils.BuildQueryString(sendData);
Dictionary<UUID, bool> experiences = new Dictionary<UUID, bool>();
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
int iter = 0;
while(true)
{
string key = string.Format("uuid_{0}", iter);
string perm = string.Format("perm_{0}", iter);
if (replyData.ContainsKey(key) && replyData.ContainsKey(perm))
{
UUID experience_id;
if (UUID.TryParse(replyData[key].ToString(), out experience_id))
{
bool allow = bool.Parse(replyData[perm].ToString());
experiences.Add(experience_id, allow);
//m_log.InfoFormat("[EXPERIENCE SERVICE CONNECTOR]: {0} = {1}", experience_id, allow);
}
}
else break;
iter++;
}
}
return experiences;
}
public bool UpdateExperiencePermissions(UUID agent_id, UUID experience, ExperiencePermission perm)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "updatepermission";
sendData["agent_id"] = agent_id.ToString();
sendData["experience"] = experience.ToString();
sendData["permission"] = perm == ExperiencePermission.None ? "forget" : perm == ExperiencePermission.Allowed ? "allow" : "block";
string request_str = ServerUtils.BuildQueryString(sendData);
return doSimplePost(request_str, "updatepermission");
}
public ExperienceInfo[] GetExperienceInfos(UUID[] experiences)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "getexperienceinfos";
int i = 0;
foreach(UUID id in experiences)
{
sendData[string.Format("id_{0}", i)] = id.ToString();
i++;
}
string request_str = ServerUtils.BuildQueryString(sendData);
List<ExperienceInfo> infos = new List<ExperienceInfo>();
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
//m_log.InfoFormat("[EXPERIENCE SERVICE CONNECTOR]: Reply: {0}", reply);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
Dictionary<string, object>.ValueCollection experienceList = replyData.Values;
foreach (object ex in experienceList)
{
if (ex is Dictionary<string, object>)
{
Dictionary<string, object> experience = (Dictionary<string, object>)ex;
infos.Add(new ExperienceInfo(experience));
}
}
}
return infos.ToArray();
}
#endregion IExperienceService
private bool doSimplePost(string reqString, string meth)
{
try
{
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, reqString, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData.ContainsKey("result"))
{
if (replyData["result"].ToString().ToLower() == "success")
return true;
else
return false;
}
else
m_log.DebugFormat("[EXPERIENCE CONNECTOR]: {0} reply data does not contain result field", meth);
}
else
m_log.DebugFormat("[EXPERIENCE CONNECTOR]: {0} received empty reply", meth);
}
catch (Exception e)
{
m_log.DebugFormat("[EXPERIENCE CONNECTOR]: Exception when contacting server at {0}: {1}", m_ServerURI, e.Message);
}
return false;
}
public UUID[] GetAgentExperiences(UUID agent_id)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "getagentexperiences";
sendData["AGENT"] = agent_id.ToString();
string request_str = ServerUtils.BuildQueryString(sendData);
List<ExperienceInfo> infos = new List<ExperienceInfo>();
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
//m_log.InfoFormat("[EXPERIENCE SERVICE CONNECTOR]: Reply: {0}", reply);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if(replyData != null)
{
Dictionary<string, object>.ValueCollection experienceList = replyData.Values;
return experienceList.Select(x => UUID.Parse(x.ToString())).ToArray();
}
}
return new UUID[0];
}
public ExperienceInfo UpdateExpereienceInfo(ExperienceInfo info)
{
// let's just pray they never add a parameter named "method"
Dictionary<string, object> sendData = info.ToDictionary();
sendData["METHOD"] = "updateexperienceinfo";
string request_str = ServerUtils.BuildQueryString(sendData);
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
//m_log.InfoFormat("[EXPERIENCE SERVICE CONNECTOR]: UpdateExpereienceInfo Reply: {0}", reply);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
ExperienceInfo responseInfo = new ExperienceInfo(replyData);
return responseInfo;
}
return null;
}
public ExperienceInfo[] FindExperiencesByName(string search)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "findexperiences";
sendData["SEARCH"] = search;
string request_str = ServerUtils.BuildQueryString(sendData);
List<ExperienceInfo> infos = new List<ExperienceInfo>();
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
Dictionary<string, object>.ValueCollection experienceList = replyData.Values;
foreach (object ex in experienceList)
{
if (ex is Dictionary<string, object>)
{
Dictionary<string, object> experience = (Dictionary<string, object>)ex;
infos.Add(new ExperienceInfo(experience));
}
}
}
return infos.ToArray();
}
public UUID[] GetGroupExperiences(UUID group_id)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "getgroupexperiences";
sendData["GROUP"] = group_id.ToString();
string request_str = ServerUtils.BuildQueryString(sendData);
List<ExperienceInfo> infos = new List<ExperienceInfo>();
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData != null)
{
Dictionary<string, object>.ValueCollection experienceList = replyData.Values;
return experienceList.Select(x => UUID.Parse(x.ToString())).ToArray();
}
}
return new UUID[0];
}
public UUID[] GetExperiencesForGroups(UUID[] groups)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "getexperiencesforgroups";
int i = 0;
foreach(var id in groups)
{
sendData["id_" + i] = id.ToString();
i++;
}
string request_str = ServerUtils.BuildQueryString(sendData);
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData != null)
{
Dictionary<string, object>.ValueCollection experienceList = replyData.Values;
return experienceList.Select(x => UUID.Parse(x.ToString())).ToArray();
}
}
return new UUID[0];
}
public string GetKeyValue(UUID experience, string key)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "accesskvdatabase";
sendData["ACTION"] = "GET";
sendData["EXPERIENCE"] = experience.ToString();
sendData["KEY"] = key;
string request_str = ServerUtils.BuildQueryString(sendData);
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData != null)
{
if(replyData.ContainsKey("result"))
{
if(replyData["result"].ToString() == "success")
{
if (replyData.ContainsKey("value"))
{
return replyData["value"].ToString();
}
}
}
}
}
return null;
}
public string CreateKeyValue(UUID experience, string key, string value)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "accesskvdatabase";
sendData["ACTION"] = "CREATE";
sendData["EXPERIENCE"] = experience.ToString();
sendData["KEY"] = key;
sendData["VALUE"] = value;
string request_str = ServerUtils.BuildQueryString(sendData);
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData != null)
{
if (replyData.ContainsKey("result"))
{
return replyData["result"].ToString();
}
}
}
return "error";
}
public string UpdateKeyValue(UUID experience, string key, string val, bool check, string original)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "accesskvdatabase";
sendData["ACTION"] = "UPDATE";
sendData["EXPERIENCE"] = experience.ToString();
sendData["KEY"] = key;
sendData["VALUE"] = val;
sendData["CHECK"] = check ? "TRUE" : "FALSE";
sendData["ORIGINAL"] = check ? original : string.Empty;
string request_str = ServerUtils.BuildQueryString(sendData);
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData != null)
{
if (replyData.ContainsKey("result"))
{
return replyData["result"].ToString();
}
}
}
return "error";
}
public string DeleteKey(UUID experience, string key)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "accesskvdatabase";
sendData["ACTION"] = "DELETE";
sendData["EXPERIENCE"] = experience.ToString();
sendData["KEY"] = key;
string request_str = ServerUtils.BuildQueryString(sendData);
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData != null)
{
if (replyData.ContainsKey("result"))
{
return replyData["result"].ToString();
}
}
}
return "error";
}
public int GetKeyCount(UUID experience)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "accesskvdatabase";
sendData["ACTION"] = "COUNT";
sendData["EXPERIENCE"] = experience.ToString();
string request_str = ServerUtils.BuildQueryString(sendData);
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData != null)
{
if (replyData.ContainsKey("result"))
{
if(replyData["result"].ToString() == "success")
{
if (replyData.ContainsKey("count"))
{
return int.Parse(replyData["count"].ToString());
}
}
}
}
}
return 0;
}
public string[] GetKeys(UUID experience, int start, int count)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "accesskvdatabase";
sendData["ACTION"] = "GETKEYS";
sendData["EXPERIENCE"] = experience.ToString();
sendData["START"] = start.ToString();
sendData["COUNT"] = count.ToString();
string request_str = ServerUtils.BuildQueryString(sendData);
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData != null)
{
Dictionary<string, object>.ValueCollection keyList = replyData.Values;
return keyList.Select(x => x.ToString()).ToArray();
}
}
return new string[0];
}
public int GetSize(UUID experience)
{
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["METHOD"] = "accesskvdatabase";
sendData["ACTION"] = "SIZE";
sendData["EXPERIENCE"] = experience.ToString();
string request_str = ServerUtils.BuildQueryString(sendData);
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI, request_str, m_Auth);
if (reply != string.Empty)
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData != null)
{
if (replyData.ContainsKey("result"))
{
if (replyData["result"].ToString() == "success")
{
if (replyData.ContainsKey("count"))
{
return int.Parse(replyData["count"].ToString());
}
}
}
}
}
return 0;
}
}
}

View file

@ -294,6 +294,20 @@ namespace OpenSim.Services.Connectors
{
}
public bool SetDisplayName(UUID agentID, string displayName)
{
//m_log.DebugFormat("[ACCOUNTS CONNECTOR]: SetDisplayName {0}", agentID);
Dictionary<string, object> sendData = new Dictionary<string, object>();
sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString();
sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString();
sendData["METHOD"] = "setdisplayname";
sendData["PrincipalID"] = agentID.ToString();
sendData["DisplayName"] = displayName;
return SendAndGetBoolReply(sendData);
}
public List<UserAccount> GetUserAccountsWhere(UUID scopeID, string where)
{
return null; // Not implemented for regions

View file

@ -0,0 +1,329 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using Nini.Config;
using log4net;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Data;
using OpenSim.Services.Interfaces;
using OpenMetaverse;
namespace OpenSim.Services.ExperienceService
{
public class ExperienceService : ExperienceServiceBase, IExperienceService
{
private static readonly ILog m_log =
LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType);
private IUserAccountService m_UserService = null;
private const int MAX_QUOTA = 1024 * 1024 * 16;
public ExperienceService(IConfigSource config)
: base(config)
{
m_log.Debug("[EXPERIENCE SERVICE]: Starting experience service");
IConfig userConfig = config.Configs["ExperienceService"];
if (userConfig == null)
throw new Exception("No ExperienceService configuration");
string userServiceDll = userConfig.GetString("UserAccountService", string.Empty);
if (userServiceDll != string.Empty)
m_UserService = LoadPlugin<IUserAccountService>(userServiceDll, new Object[] { config });
if (MainConsole.Instance != null)
{
MainConsole.Instance.Commands.AddCommand("Experience", false,
"create experience",
"create experience <first> <last>",
"Create a new experience owned by a user.", HandleCreateNewExperience);
MainConsole.Instance.Commands.AddCommand("Experience", false,
"suspend experience",
"suspend experience <key> <true/false>",
"Suspend/unsuspend an experience by its key.", HandleSuspendExperience);
}
}
private void HandleCreateNewExperience(string module, string[] cmdparams)
{
string firstName;
string lastName;
string experienceKey;
if (cmdparams.Length < 3)
firstName = MainConsole.Instance.Prompt("Experience owner first name", "Test");
else firstName = cmdparams[2];
if (cmdparams.Length < 4)
lastName = MainConsole.Instance.Prompt("Experience owner last name", "Resident");
else lastName = cmdparams[3];
UUID suggestedKey = UUID.Random();
if (cmdparams.Length < 5)
experienceKey = MainConsole.Instance.Prompt("Experience Key", suggestedKey.ToString());
else experienceKey = cmdparams[4];
UUID newExperienceKey;
if(!UUID.TryParse(experienceKey, out newExperienceKey))
{
MainConsole.Instance.Output("Invalid UUID");
return;
}
UserAccount account = m_UserService.GetUserAccount(UUID.Zero, firstName, lastName);
if (account == null)
{
MainConsole.Instance.Output("No such user as {0} {1}", firstName, lastName);
return;
}
var existing = GetExperienceInfos(new UUID[] { newExperienceKey });
if(existing.Length > 0)
{
MainConsole.Instance.Output("Experience already exists!");
return;
}
ExperienceInfo new_info = new ExperienceInfo
{
public_id = newExperienceKey,
owner_id = account.PrincipalID
};
var stored_info = UpdateExpereienceInfo(new_info);
if (stored_info == null)
MainConsole.Instance.Output("Unable to create experience!");
else
{
MainConsole.Instance.Output("Experience created!");
}
}
private void HandleSuspendExperience(string module, string[] cmdparams)
{
string experience_key;
string enabled_str;
if (cmdparams.Length < 3)
experience_key = MainConsole.Instance.Prompt("Experience Key");
else experience_key = cmdparams[2];
UUID experienceID;
if(!UUID.TryParse(experience_key, out experienceID))
{
MainConsole.Instance.Output("Invalid key!");
return;
}
if (cmdparams.Length < 4)
enabled_str = MainConsole.Instance.Prompt("Suspended:", "false");
else enabled_str = cmdparams[3];
bool suspend = enabled_str == "true";
var infos = GetExperienceInfos(new UUID[] { experienceID });
if(infos.Length != 1)
{
MainConsole.Instance.Output("Experience not found!");
return;
}
ExperienceInfo info = infos[0];
bool is_suspended = (info.properties & (int)ExperienceFlags.Suspended) != 0;
string message = "";
bool update = false;
if (suspend && !is_suspended)
{
info.properties |= (int)ExperienceFlags.Suspended;
message = "Experience has been suspended";
update = true;
}
else if(!suspend && is_suspended)
{
info.properties &= ~(int)ExperienceFlags.Suspended;
message = "Experience has been unsuspended";
update = true;
}
else if(suspend && is_suspended)
{
message = "Experience is already suspended";
}
else if (!suspend && !is_suspended)
{
message = "Experience is not suspended";
}
if(update)
{
var updated = UpdateExpereienceInfo(info);
if (updated != null)
{
MainConsole.Instance.Output(message);
}
else
MainConsole.Instance.Output("Error updating experience!");
}
else
{
MainConsole.Instance.Output(message);
}
}
public Dictionary<UUID, bool> FetchExperiencePermissions(UUID agent_id)
{
return m_Database.GetExperiencePermissions(agent_id);
}
public ExperienceInfo[] FindExperiencesByName(string search)
{
List<ExperienceInfo> infos = new List<ExperienceInfo>();
ExperienceInfoData[] datas = m_Database.FindExperiences(search);
foreach (var data in datas)
{
ExperienceInfo info = new ExperienceInfo(data.ToDictionary());
infos.Add(info);
}
return infos.ToArray();
}
public UUID[] GetAgentExperiences(UUID agent_id)
{
return m_Database.GetAgentExperiences(agent_id);
}
public ExperienceInfo[] GetExperienceInfos(UUID[] experiences)
{
ExperienceInfoData[] datas = m_Database.GetExperienceInfos(experiences);
List<ExperienceInfo> infos = new List<ExperienceInfo>();
foreach (var data in datas)
{
infos.Add(new ExperienceInfo(data.ToDictionary()));
}
return infos.ToArray();
}
public UUID[] GetExperiencesForGroups(UUID[] groups)
{
return m_Database.GetExperiencesForGroups(groups);
}
public UUID[] GetGroupExperiences(UUID group_id)
{
return m_Database.GetGroupExperiences(group_id);
}
public ExperienceInfo UpdateExpereienceInfo(ExperienceInfo info)
{
ExperienceInfoData data = new ExperienceInfoData();
data.public_id = info.public_id;
data.owner_id = info.owner_id;
data.name = info.name;
data.description = info.description;
data.group_id = info.group_id;
data.slurl = info.slurl;
data.logo = info.logo;
data.marketplace = info.marketplace;
data.maturity = info.maturity;
data.properties = info.properties;
if (m_Database.UpdateExperienceInfo(data))
{
var find = GetExperienceInfos(new UUID[] { data.public_id });
if(find.Length == 1)
{
return new ExperienceInfo(find[0].ToDictionary());
}
}
return null;
}
public bool UpdateExperiencePermissions(UUID agent_id, UUID experience, ExperiencePermission perm)
{
if (perm == ExperiencePermission.None)
return m_Database.ForgetExperiencePermissions(agent_id, experience);
else return m_Database.SetExperiencePermissions(agent_id, experience, perm == ExperiencePermission.Allowed);
}
public string GetKeyValue(UUID experience, string key)
{
return m_Database.GetKeyValue(experience, key);
}
public string CreateKeyValue(UUID experience, string key, string value)
{
int current_size = m_Database.GetKeyValueSize(experience);
if (current_size + key.Length + value.Length > MAX_QUOTA)
return "full";
string get = m_Database.GetKeyValue(experience, key);
if (get == null)
{
if (m_Database.SetKeyValue(experience, key, value))
return "success";
else return "error";
}
else return "exists";
}
public string UpdateKeyValue(UUID experience, string key, string val, bool check, string original)
{
string get = m_Database.GetKeyValue(experience, key);
if (get != null)
{
if (check && get != original)
return "mismatch";
int current_size = m_Database.GetKeyValueSize(experience);
if ((current_size - get.Length) + val.Length > MAX_QUOTA)
return "full";
if (m_Database.SetKeyValue(experience, key, val))
return "success";
else return "error";
}
else return "missing";
}
public string DeleteKey(UUID experience, string key)
{
string get = m_Database.GetKeyValue(experience, key);
if (get != null)
{
return m_Database.DeleteKey(experience, key) ? "success" : "failed";
}
return "missing";
}
public int GetKeyCount(UUID experience)
{
return m_Database.GetKeyCount(experience);
}
public string[] GetKeys(UUID experience, int start, int count)
{
return m_Database.GetKeys(experience, start, count);
}
public int GetSize(UUID experience)
{
return m_Database.GetKeyValueSize(experience);
}
}
}

View file

@ -0,0 +1,55 @@
using System;
using System.Reflection;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Data;
using OpenSim.Services.Interfaces;
using OpenSim.Services.Base;
namespace OpenSim.Services.ExperienceService
{
public class ExperienceServiceBase : ServiceBase
{
protected IExperienceData m_Database = null;
public ExperienceServiceBase(IConfigSource config)
: base(config)
{
string dllName = string.Empty;
string connString = string.Empty;
//
// Try reading the [DatabaseService] section, if it exists
//
IConfig dbConfig = config.Configs["DatabaseService"];
if (dbConfig != null)
{
if (dllName == string.Empty)
dllName = dbConfig.GetString("StorageProvider", string.Empty);
if (connString == string.Empty)
connString = dbConfig.GetString("ConnectionString", string.Empty);
}
//
// [ExperienceService] section overrides [DatabaseService], if it exists
//
IConfig presenceConfig = config.Configs["ExperienceService"];
if (presenceConfig != null)
{
dllName = presenceConfig.GetString("StorageProvider", dllName);
connString = presenceConfig.GetString("ConnectionString", connString);
}
//
// We tried, but this doesn't exist. We can't proceed.
//
if (dllName.Equals(string.Empty))
throw new Exception("No StorageProvider configured");
m_Database = LoadPlugin<IExperienceData>(dllName, new object[] { connString });
if (m_Database == null)
throw new Exception("Could not find a storage interface in the given module " + dllName);
}
}
}

View file

@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Data\OpenSim.Data.csproj" />
<ProjectReference Include="..\..\Framework\Console\OpenSim.Framework.Console.csproj" />
<ProjectReference Include="..\..\Framework\OpenSim.Framework.csproj" />
<ProjectReference Include="..\Base\OpenSim.Services.Base.csproj" />
<ProjectReference Include="..\Connectors\OpenSim.Services.Connectors.csproj" />
<ProjectReference Include="..\Interfaces\OpenSim.Services.Interfaces.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Nini">
<HintPath>..\..\..\bin\Nini.dll</HintPath>
</Reference>
<Reference Include="OpenMetaverse">
<HintPath>..\..\..\bin\OpenMetaverse.dll</HintPath>
</Reference>
<Reference Include="OpenMetaverseTypes">
<HintPath>..\..\..\bin\OpenMetaverseTypes.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View file

@ -114,6 +114,11 @@ namespace OpenSim.Services.HypergridService
{
return false;
}
public bool SetDisplayName(UUID agentID, string displayName)
{
return false;
}
#endregion
}

View file

@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using OpenSim.Framework;
using OpenMetaverse;
namespace OpenSim.Services.Interfaces
{
public enum ExperiencePermission
{
None,
Allowed,
Blocked
}
public enum ExperienceFlags
{
None = 0,
Invalid = 1 << 0,
Privileged = 1 << 3,
Grid = 1 << 4,
Private = 1 << 5,
Disabled = 1 << 6,
Suspended = 1 << 7
}
public class ExperienceInfo
{
public UUID public_id = UUID.Zero;
public UUID owner_id = UUID.Zero;
public string name = string.Empty;
public string description = string.Empty;
public UUID group_id = UUID.Zero;
// extended
public UUID logo = UUID.Zero;
public string marketplace = string.Empty;
public string slurl = string.Empty;
public int properties = 0;
public int maturity = 0;
public DateTime CachedTime = DateTime.Now;
public int quota = 16;
public Dictionary<string, object> ToDictionary()
{
Dictionary<string, object> dict = new Dictionary<string, object>();
dict["public_id"] = public_id;
dict["owner_id"] = owner_id;
dict["group_id"] = group_id;
dict["name"] = name;
dict["description"] = description;
dict["logo"] = logo;
dict["marketplace"] = marketplace;
dict["slurl"] = slurl;
dict["properties"] = properties;
dict["maturity"] = maturity;
return dict;
}
public ExperienceInfo()
{
}
public ExperienceInfo(Dictionary<string, object> data)
{
if (data.ContainsKey("public_id"))
public_id = UUID.Parse(data["public_id"].ToString());
if (data.ContainsKey("owner_id"))
owner_id = UUID.Parse(data["owner_id"].ToString());
if (data.ContainsKey("group_id"))
group_id = UUID.Parse(data["group_id"].ToString());
if (data.ContainsKey("name"))
name = data["name"].ToString();
if (data.ContainsKey("description"))
description = data["description"].ToString();
if (data.ContainsKey("logo"))
logo = UUID.Parse(data["logo"].ToString());
if (data.ContainsKey("marketplace"))
marketplace = data["marketplace"].ToString();
if (data.ContainsKey("slurl"))
slurl = data["slurl"].ToString();
if (data.ContainsKey("properties"))
properties = int.Parse(data["properties"].ToString());
if (data.ContainsKey("maturity"))
maturity = int.Parse(data["maturity"].ToString());
}
}
public interface IExperienceService
{
Dictionary<UUID, bool> FetchExperiencePermissions(UUID agent_id);
bool UpdateExperiencePermissions(UUID agent_id, UUID experience, ExperiencePermission perm);
ExperienceInfo[] GetExperienceInfos(UUID[] experiences);
UUID[] GetAgentExperiences(UUID agent_id);
ExperienceInfo UpdateExpereienceInfo(ExperienceInfo info);
ExperienceInfo[] FindExperiencesByName(string search);
UUID[] GetGroupExperiences(UUID group_id);
UUID[] GetExperiencesForGroups(UUID[] groups);
string GetKeyValue(UUID experience, string key);
string CreateKeyValue(UUID experience, string key, string value);
string UpdateKeyValue(UUID experience, string key, string val, bool check, string original);
string DeleteKey(UUID experience, string key);
int GetKeyCount(UUID experience);
string[] GetKeys(UUID experience, int start, int count);
int GetSize(UUID experience);
}
}

View file

@ -98,11 +98,32 @@ namespace OpenSim.Services.Interfaces
public int Created;
public string DisplayName;
public uint NameChanged;
public string Name
{
get { return FirstName + " " + LastName; }
}
public string FormattedName
{
get
{
bool is_resident = LastName.ToLower() == "resident";
if (string.IsNullOrWhiteSpace(DisplayName))
{
return is_resident ? FirstName : $"{FirstName} {LastName}";
}
else
{
var username = is_resident ? FirstName : $"{FirstName}.{LastName}";
return $"{DisplayName} ({username.ToLower()})";
}
}
}
public UserAccount(Dictionary<string, object> kvp)
{
if (kvp.ContainsKey("FirstName"))
@ -125,6 +146,10 @@ namespace OpenSim.Services.Interfaces
UserCountry = kvp["UserCountry"].ToString();
if (kvp.ContainsKey("LocalToGrid"))
Boolean.TryParse(kvp["LocalToGrid"].ToString(), out LocalToGrid);
if (kvp.ContainsKey("DisplayName"))
DisplayName = kvp["DisplayName"].ToString();
if (kvp.ContainsKey("NameChanged"))
NameChanged = Convert.ToUInt32(kvp["NameChanged"].ToString());
if (kvp.ContainsKey("Created"))
Created = Convert.ToInt32(kvp["Created"].ToString());
@ -160,6 +185,8 @@ namespace OpenSim.Services.Interfaces
result["UserTitle"] = UserTitle;
result["UserCountry"] = UserCountry;
result["LocalToGrid"] = LocalToGrid.ToString();
result["DisplayName"] = DisplayName;
result["NameChanged"] = NameChanged.ToString();
string str = string.Empty;
foreach (KeyValuePair<string, object> kvp in ServiceURLs)
@ -179,6 +206,8 @@ namespace OpenSim.Services.Interfaces
UserAccount GetUserAccount(UUID scopeID, string FirstName, string LastName);
UserAccount GetUserAccount(UUID scopeID, string Email);
bool SetDisplayName(UUID agentID, string displayName);
/// <summary>
/// Returns the list of avatars that matches both the search criterion and the scope ID passed
/// </summary>

View file

@ -92,5 +92,7 @@ namespace OpenSim.Framework
void AddUser(UUID uuid, string firstName, string lastName, string homeURL);
bool RemoveUser(UUID uuid);
bool IsLocalGridUser(UUID uuid);
bool SetDisplayName(UUID agentID, string displayName);
}
}

View file

@ -141,6 +141,11 @@ namespace OpenSim.Services.UserAccountService
"show account",
"show account <first> <last>",
"Show account details for the given user", HandleShowAccount);
MainConsole.Instance.Commands.AddCommand("Users", false,
"set display name",
"set display name <first> <last> <new display name>",
"Sets the display name for the given user", HandleSetDisplayName);
}
}
}
@ -227,6 +232,14 @@ namespace OpenSim.Services.UserAccountService
else
u.ServiceURLs = new Dictionary<string, object>();
if (d.Data.ContainsKey("DisplayName") && d.Data["DisplayName"] != null)
u.DisplayName = d.Data["DisplayName"].ToString();
else
u.DisplayName = string.Empty;
if (d.Data.ContainsKey("NameChanged") && d.Data["NameChanged"] != null)
uint.TryParse(d.Data["NameChanged"], out u.NameChanged);
return u;
}
@ -334,6 +347,9 @@ namespace OpenSim.Services.UserAccountService
d.Data["ServiceURLs"] = string.Join(" ", parts.ToArray());
d.Data["DisplayName"] = data.DisplayName;
d.Data["NameChanged"] = data.NameChanged.ToString();
return m_Database.Store(d);
}
@ -367,6 +383,19 @@ namespace OpenSim.Services.UserAccountService
return ret;
}
public bool SetDisplayName(UUID agentID, string displayName)
{
var account = GetUserAccount(UUID.Zero, agentID);
if (account is null)
return false;
account.DisplayName = displayName;
account.NameChanged = Utils.GetUnixTime();
return StoreUserAccount(account);
}
#endregion
#region Console commands
@ -455,7 +484,7 @@ namespace OpenSim.Services.UserAccountService
return;
}
MainConsole.Instance.Output("Name: {0}", ua.Name);
MainConsole.Instance.Output("Name: {0}", ua.FormattedName);
MainConsole.Instance.Output("ID: {0}", ua.PrincipalID);
MainConsole.Instance.Output("Title: {0}", ua.UserTitle);
MainConsole.Instance.Output("E-mail: {0}", ua.Email);
@ -577,6 +606,40 @@ namespace OpenSim.Services.UserAccountService
MainConsole.Instance.Output("User level set for user {0} {1} to {2}", firstName, lastName, level);
}
protected void HandleSetDisplayName(string module, string[] cmdparams)
{
string firstName;
string lastName;
string displayName;
if (cmdparams.Length < 4)
firstName = MainConsole.Instance.Prompt("First name");
else firstName = cmdparams[3];
if (cmdparams.Length < 5)
lastName = MainConsole.Instance.Prompt("Last name");
else lastName = cmdparams[4];
if (cmdparams.Length < 6)
displayName = MainConsole.Instance.Prompt("Display name");
else displayName = cmdparams[5];
UserAccount account = GetUserAccount(UUID.Zero, firstName, lastName);
if (account == null)
{
MainConsole.Instance.Output("No such user as {0} {1}", firstName, lastName);
return;
}
account.DisplayName = displayName;
account.NameChanged = Utils.GetUnixTime();
if (StoreUserAccount(account))
MainConsole.Instance.Output("Display name updated!");
else
MainConsole.Instance.Output("Unable to set DisplayName for account {0} {1}.", firstName, lastName);
}
#endregion
/// <summary>

View file

@ -201,7 +201,7 @@ namespace OpenSim.Tools.Configger
Uri configUri;
return Uri.TryCreate(file, UriKind.Absolute,
out configUri) && configUri.Scheme == Uri.UriSchemeHttp;
out configUri) && (configUri.Scheme == Uri.UriSchemeHttp || configUri.Scheme == Uri.UriSchemeHttps);
}
/// <summary>

View file

@ -339,6 +339,7 @@ namespace OpenSim.Tests.Common
public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
public event GenericCall2 OnUpdateThrottles;
public event AgentFOV OnAgentFOV;
public event UpdateEstateExperienceDeltaRequest OnUpdateEstateExperienceDeltaRequest;
#pragma warning restore 67
@ -1406,5 +1407,19 @@ namespace OpenSim.Tests.Common
return 0x1000;
}
public void SendGenericMessageForExperience(UUID experience_id, UUID avatar_id, int action, string obj_name, string parcel, bool is_attachment = false)
{
throw new NotImplementedException();
}
public void SendScriptQuestion(UUID taskID, string taskName, string ownerName, UUID itemID, int question, UUID experience)
{
throw new NotImplementedException();
}
public void SendEstateExperiences(UUID invoice, UUID[] allowed, UUID[] key, uint estateID)
{
throw new NotImplementedException();
}
}
}

View file

@ -224,5 +224,10 @@ namespace OpenSim.Tests.Common
{
throw new NotImplementedException();
}
public void SendEnvironmentUpdate(UUID experience_id, UUID agent_id, EnvironmentUpdate update)
{
throw new NotImplementedException();
}
}
}

View file

@ -52,7 +52,7 @@
;# {BaseHostname} {} {BaseHostname} {"example.com" "127.0.0.1"} "127.0.0.1"
BaseHostname = "127.0.0.1"
;# {BaseURL} {} {BaseURL} {"http://${Const|BaseHostname}} "http://${Const|BaseHostname}"
;# {BaseURL} {} {BaseURL} {"http://${Const|BaseHostname"}} "http://${Const|BaseHostname}"
BaseURL = http://${Const|BaseHostname}
; If you run a grid, several services should not be availble to world, access to them should be blocked on firewall
@ -310,6 +310,35 @@
; TelehubAllowLandmark = false
;; SSL selfsigned certificate settings.
;; Enable selfsigned certificate creation for local and external use. When set to true, will create a folder SSL\ and 2 sub folders SSL\ssl\ and SSL\src\.
;; Next creates and store an RSA private key in SSL\src\ and the derived selfsigned certificate in SSL\ssl\ folder.
;;Is also possible to renew the certificate on every server restart if CertRenewOnStartup is set to true.
;# {EnbleSelfsignedCertSupport} {} {Enable selfsigned certificate creation and renew} {true false} false
EnableSelfsignedCertSupport = false
;; Renew the selfsigned certificate on every server startup ?
;# {CertRenewOnStartup} {} {renew the selfsigned certificate on the server startup} {true false} true
CertRenewOnStartup = false
;; Certificate options:
;; Set the certificate file name. the output files extensions are CertFileName.p12 and CertFileName.pfx.
;# {CertFileName} {} {set the certificate file name} {} "OpenSim"
CertFileName = "OpenSim"
;; Set the certificate password.
;# {CertPassword} {} {set the certificate password} {} ""
CertPassword = "mycertpass"
;; The certificate host name (domain or IP of this machine CN). Must be the same as "ExternalHostName" in Regions.ini
;# {CertHostName} {} {set the certificate host name} {} "myRegionsExternalHostName"
CertHostName = "myRegionsExternalHostName"
;; The certificate host IP (IP of this machine).
;# {CertHostIp} {} {set the certificate host IP} {}
CertHostIp = "127.0.0.1"
;; SSL certificate validation options
;; you can allow selfsigned certificates or no official CA with next option set to true
;# {NoVerifyCertChain} {} {do not verify SSL Cert Chain} {true false} true
@ -418,7 +447,7 @@
;;
;; If set to false, then, in theory, the server never carries out
;; permission checks (allowing anybody to copy
;; any item, etc. This may not yet be implemented uniformally.
;; any item, etc). This may not yet be implemented uniformally.
;; If set to true, then all permissions checks are carried out
; serverside_object_permissions = true
@ -581,24 +610,24 @@
; the main unsecure port will still open for some services. this may change in future.
; set http_listener_ssl to enable main server ssl. it will replace unsecure port on most functions
;# {http_listener_ssl}{} {enable main server ssl port)} {} false
;# {http_listener_ssl}{} {enable main server ssl port} {} false
;http_listener_ssl = false
; Set port for main SSL connections
;# {http_listener_sslport}{} {main server ssl port)} {} 9001
;# {http_listener_sslport}{} {main server ssl port} {} 9001
;http_listener_sslport = 9001 ;
; currently if using ssl, regions ExternalHostName must the the same and equal to http_listener_cn
; this may be removed in future
;# {http_listener_cn}{} {main server ssl externalHostName)} {} ""
;# {http_listener_cn}{} {main server ssl externalHostName} {} ""
;http_listener_cn = "myRegionsExternalHostName"
; the path for the certificate path
;# {http_listener_cert_path}{} {main server ssl certificate file path)} {} ""
;http_listener_cert_path = "mycert.p12"
;# {http_listener_cert_path}{} {main server ssl certificate file path} {} ""
;http_listener_cert_path = "SSL\ssl\OpenSim.p12"
;# {http_listener_cert_pass}{} {main server ssl certificate password)} {} ""
;http_listener_cert_pass = "mycertpass" ; the cert passwork
;# {http_listener_cert_pass}{} {main server ssl certificate password} {} ""
;http_listener_cert_pass = "mycertpass"
; By default, OpenSimulator does not allow scripts to make HTTP calls to addresses on the simulator's LAN.
; See the OutboundDisallowForUserScripts parameter in OpenSimDefaults.ini for more information on this filter.
@ -722,6 +751,7 @@
Cap_GetMesh = "localhost"
Cap_AvatarPickerSearch = "localhost"
Cap_GetDisplayNames = "localhost"
Cap_SetDisplayName = "localhost"
[SimulatorFeatures]
@ -1322,6 +1352,10 @@
; FullNames = "Test User, Foo Bar"
; Surnames = "Kryztlsk"
[Experience]
;# {Enabled} {} {Use Experience Tools on this region} {true false} false
; Enabled = true
[Architecture]
;# {Include-Architecture} {} {Choose one of the following architectures} {config-include/Standalone.ini config-include/StandaloneHypergrid.ini config-include/Grid.ini config-include/GridHypergrid.ini} config-include/Standalone.ini
;; Uncomment one of the following includes as required. For instance, to create a standalone OpenSim,

View file

@ -399,6 +399,31 @@
; routing and land at the landmark coordinates when set to true
; default is false
; TelehubAllowLandmark = false
; #
; # SSL selfsigned certificate settings.
; #
; Enable selfsigned certificate creation for local and external use. When set to true, will create a folder SSL\ and 2 sub folders SSL\ssl\ and SSL\src\.
; Next creates and store an RSA private key in SSL\src\ and the derived selfsigned certificate in SSL\ssl\ folder.
; Is also possible to renew the certificate on every server restart if CertRenewOnStartup is set to true.
EnableSelfsignedCertSupport = false
;Renew the selfsigned certificate on every server startup ?
CertRenewOnStartup = false
; # Certificate options:
; Set the certificate file name. the output files extensions are CertFileName.p12 and CertFileName.pfx.
CertFileName = "OpenSim"
; Set the certificate password.
CertPassword = "mycertpass"
; The certificate host name (domain or IP of this machine CN). Must be the same as "ExternalHostName" in Regions.ini
CertHostName = "myRegionsExternalHostName"
; The certificate host IP (IP of this machine).
CertHostIp = "127.0.0.1"
; #
; # SSL certificates validation options

View file

@ -23,9 +23,15 @@
; * uses to write data.
; *
[Const]
; The domain or IP of the Robust server.
BaseHostname = "127.0.0.1"
; The URL of the Robust server
BaseURL = "http://127.0.0.1"
; The http URL of the Robust server.
BaseURL = "http://${Const|BaseHostname}"
; The https URL of the Robust server.
; Use this if you have the SSL enabled.
; BaseURL = "https://${Const|BaseHostname}"
; The public port of the Robust server
PublicPort = "8002"
@ -72,7 +78,29 @@
; Time stamp commands in history file (default false)
; ConsoleHistoryTimeStamp = false
;; SSL selfsigned certificate settings.
; Enable selfsigned certificate creation for local and external use. When set to true, will create a folder SSL\ and 2 sub folders SSL\ssl\ and SSL\src\.
; Next creates and store an RSA private key in SSL\src\ and the derived selfsigned certificate in SSL\ssl\ folder.
; Is also possible to renew the certificate on every server restart if CertRenewOnStartup is set to true.
EnableRobustSelfsignedCertSupport = false
;Renew the selfsigned certificate on every server startup ?
RobustCertRenewOnStartup = false
;; Certificate options:
; Set the certificate file name. the output files extensions are CertFileName.p12 and RobustCertFileName.pfx. This must be different than CertFileName in OpenSim.ini
RobustCertFileName = "Robust"
; Set the certificate password.
RobustCertPassword = "mycertpass"
; The certificate host name (CN).
RobustCertHostName = ${Const|BaseHostname}
; The certificate host IP.
RobustCertHostIp = "127.0.0.1"
; peers SSL certificate validation options
; you can allow selfsigned certificates or no official CA with next option set to true
NoVerifyCertChain = true
@ -100,6 +128,8 @@
FriendsServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
MapAddServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
MapGetServiceConnector = "${Const|PublicPort}/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
;; Uncomment this if you want experience tools to work
; ExperienceServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:ExperienceServiceConnector"
;; Uncomment this if you want offline IM to work
; OfflineIMServiceConnector = "${Const|PrivatePort}/OpenSim.Addons.OfflineIM.dll:OfflineIMServiceRobustConnector"
;; Uncomment this if you want Groups V2 to work
@ -856,3 +886,10 @@
[MuteListService]
LocalServiceModule = "OpenSim.Services.MuteListService.dll:MuteListService"
[ExperienceService]
LocalServiceModule = "OpenSim.Services.ExperienceService.dll:ExperienceService"
;; ConnectionString = "Data Source=localhost;Database=robust;User ID=robust;Password=*****;Old Guids=true;CharSet=utf8mb4;"
UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService"

View file

@ -15,8 +15,15 @@
; *
[Const]
; The URL of the Robust server
BaseURL = "http://127.0.0.1"
; The domain or IP of the Robust server.
BaseHostname = "127.0.0.1"
; The http URL of the Robust server.
BaseURL = "http://${Const|BaseHostname}"
; The https URL of the Robust server.
; Use this if you have the SSL enabled.
; BaseURL = "https://${Const|BaseHostname}"
; The public port of the Robust server
PublicPort = "8002"
@ -64,7 +71,29 @@
; Time stamp commands in history file (default false)
; ConsoleHistoryTimeStamp = false
;; SSL selfsigned certificate settings.
; Enable selfsigned certificate creation for local and external use. When set to true, will create a folder SSL\ and 2 sub folders SSL\ssl\ and SSL\src\.
; Next creates and store an RSA private key in SSL\src\ and the derived selfsigned certificate in SSL\ssl\ folder.
; Is also possible to renew the certificate on every server restart if CertRenewOnStartup is set to true.
EnableRobustSelfsignedCertSupport = false
; Renew the selfsigned certificate on every server startup ?
RobustCertRenewOnStartup = false
;; Certificate options:
; Set the certificate file name. the output files extensions are RobustCertFileName.p12 and RobustCertFileName.pfx.
RobustCertFileName = "Robust"
; Set the certificate password.
RobustCertPassword = "mycertpass"
; The certificate host name (CN).
RobustCertHostName = ${Const|BaseHostname}
; The certificate host IP.
RobustCertHostIp = "127.0.0.1"
; peers SSL certificate validation options
; you can allow selfsigned certificates or no official CA with next option set to true
NoVerifyCertChain = true
@ -91,6 +120,8 @@
FriendsServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:FriendsServiceConnector"
MapAddServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:MapAddServiceConnector"
MapGetServiceConnector = "${Const|PublicPort}/OpenSim.Server.Handlers.dll:MapGetServiceConnector"
;; Uncomment this if you want experience tools to work
; ExperienceServiceConnector = "${Const|PrivatePort}/OpenSim.Server.Handlers.dll:ExperienceServiceConnector"
;; Uncomment this if you want offline IM to work
; OfflineIMServiceConnector = "${Const|PrivatePort}/OpenSim.Addons.OfflineIM.dll:OfflineIMServiceRobustConnector"
;; Uncomment this if you want Groups V2 to work
@ -605,3 +636,10 @@
[MuteListService]
LocalServiceModule = "OpenSim.Services.MuteListService.dll:MuteListService"
[ExperienceService]
LocalServiceModule = "OpenSim.Services.ExperienceService.dll:ExperienceService"
;; ConnectionString = "Data Source=localhost;Database=robust;User ID=robust;Password=*****;Old Guids=true;CharSet=utf8mb4;"
UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService"

View file

@ -26,6 +26,7 @@
MapImageService = "MapImageServiceModule"
SearchModule = "BasicSearchModule"
MuteListService = "RemoteMuteListServicesConnector"
ExperienceServices = "RemoteExperienceServicesConnector"
LandServiceInConnector = true
NeighbourServiceInConnector = true

View file

@ -158,6 +158,12 @@
;
UserAccountServerURI = "${Const|PrivURL}:${Const|PrivatePort}"
[UserAliasService]
;
; Change this to your grid-wide user accounts server
;
UserAliasServerURI = "${Const|PrivURL}:${Const|PrivatePort}"
[GridUserService]
;
; Change this to your grid-wide user server
@ -234,3 +240,11 @@
[MuteListService]
MuteListServerURI = "${Const|PrivURL}:${Const|PrivatePort}"
[ExperienceService]
LocalServiceModule = "OpenSim.Services.Connectors.dll:RemoteExperienceServicesConnector"
;
; Change this to your grid-wide experience server
;
ExperienceServerURI = "${Const|BaseURL}:${Const|PrivatePort}"

Some files were not shown because too many files have changed in this diff Show more