Merge branch 'master' into careminster-presence-refactor

avinationmerge
Melanie 2010-08-06 18:08:40 +01:00
commit 26387252f5
43 changed files with 29189 additions and 24484 deletions

View File

@ -327,7 +327,7 @@ IF EXISTS (SELECT UUID FROM prims WHERE UUID = @UUID)
ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice, ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice,
SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem, SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem,
ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches, ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches,
LinkNumber = @LinkNumber LinkNumber = @LinkNumber, MediaURL = @MediaURL
WHERE UUID = @UUID WHERE UUID = @UUID
END END
ELSE ELSE
@ -342,7 +342,7 @@ ELSE
PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX, PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX,
OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ, OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ,
ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA, ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA,
ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL
) VALUES ( ) VALUES (
@UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask, @UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask,
@EveryoneMask, @BaseMask, @PositionX, @PositionY, @PositionZ, @GroupPositionX, @GroupPositionY, @GroupPositionZ, @VelocityX, @EveryoneMask, @BaseMask, @PositionX, @PositionY, @PositionZ, @GroupPositionX, @GroupPositionY, @GroupPositionZ, @VelocityX,
@ -352,7 +352,7 @@ ELSE
@PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX, @PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX,
@OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ, @OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ,
@ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA, @ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA,
@ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber @ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL
) )
END"; END";
@ -385,7 +385,7 @@ IF EXISTS (SELECT UUID FROM primshapes WHERE UUID = @UUID)
PathSkew = @PathSkew, PathCurve = @PathCurve, PathRadiusOffset = @PathRadiusOffset, PathRevolutions = @PathRevolutions, PathSkew = @PathSkew, PathCurve = @PathCurve, PathRadiusOffset = @PathRadiusOffset, PathRevolutions = @PathRevolutions,
PathTaperX = @PathTaperX, PathTaperY = @PathTaperY, PathTwist = @PathTwist, PathTwistBegin = @PathTwistBegin, PathTaperX = @PathTaperX, PathTaperY = @PathTaperY, PathTwist = @PathTwist, PathTwistBegin = @PathTwistBegin,
ProfileBegin = @ProfileBegin, ProfileEnd = @ProfileEnd, ProfileCurve = @ProfileCurve, ProfileHollow = @ProfileHollow, ProfileBegin = @ProfileBegin, ProfileEnd = @ProfileEnd, ProfileCurve = @ProfileCurve, ProfileHollow = @ProfileHollow,
Texture = @Texture, ExtraParams = @ExtraParams, State = @State Texture = @Texture, ExtraParams = @ExtraParams, State = @State, Media = @Media
WHERE UUID = @UUID WHERE UUID = @UUID
END END
ELSE ELSE
@ -394,11 +394,11 @@ ELSE
primshapes ( primshapes (
UUID, Shape, ScaleX, ScaleY, ScaleZ, PCode, PathBegin, PathEnd, PathScaleX, PathScaleY, PathShearX, PathShearY, UUID, Shape, ScaleX, ScaleY, ScaleZ, PCode, PathBegin, PathEnd, PathScaleX, PathScaleY, PathShearX, PathShearY,
PathSkew, PathCurve, PathRadiusOffset, PathRevolutions, PathTaperX, PathTaperY, PathTwist, PathTwistBegin, ProfileBegin, PathSkew, PathCurve, PathRadiusOffset, PathRevolutions, PathTaperX, PathTaperY, PathTwist, PathTwistBegin, ProfileBegin,
ProfileEnd, ProfileCurve, ProfileHollow, Texture, ExtraParams, State ProfileEnd, ProfileCurve, ProfileHollow, Texture, ExtraParams, State, Media
) VALUES ( ) VALUES (
@UUID, @Shape, @ScaleX, @ScaleY, @ScaleZ, @PCode, @PathBegin, @PathEnd, @PathScaleX, @PathScaleY, @PathShearX, @PathShearY, @UUID, @Shape, @ScaleX, @ScaleY, @ScaleZ, @PCode, @PathBegin, @PathEnd, @PathScaleX, @PathScaleY, @PathShearX, @PathShearY,
@PathSkew, @PathCurve, @PathRadiusOffset, @PathRevolutions, @PathTaperX, @PathTaperY, @PathTwist, @PathTwistBegin, @ProfileBegin, @PathSkew, @PathCurve, @PathRadiusOffset, @PathRevolutions, @PathTaperX, @PathTaperY, @PathTwist, @PathTwistBegin, @ProfileBegin,
@ProfileEnd, @ProfileCurve, @ProfileHollow, @Texture, @ExtraParams, @State @ProfileEnd, @ProfileCurve, @ProfileHollow, @Texture, @ExtraParams, @State, @Media
) )
END"; END";
@ -1128,6 +1128,9 @@ VALUES
prim.PassTouches = true; prim.PassTouches = true;
prim.LinkNum = Convert.ToInt32(primRow["LinkNumber"]); prim.LinkNum = Convert.ToInt32(primRow["LinkNumber"]);
if (!(primRow["MediaURL"] is System.DBNull))
prim.MediaUrl = (string)primRow["MediaURL"];
return prim; return prim;
} }
@ -1180,6 +1183,9 @@ VALUES
{ {
} }
if (!(shapeRow["Media"] is System.DBNull))
baseShape.Media = PrimitiveBaseShape.MediaList.FromXml((string)shapeRow["Media"]);
return baseShape; return baseShape;
} }
@ -1510,6 +1516,7 @@ VALUES
else else
parameters.Add(_Database.CreateParameter("PassTouches", 0)); parameters.Add(_Database.CreateParameter("PassTouches", 0));
parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum)); parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum));
parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl));
return parameters.ToArray(); return parameters.ToArray();
} }
@ -1557,6 +1564,7 @@ VALUES
parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry)); parameters.Add(_Database.CreateParameter("Texture", s.TextureEntry));
parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams)); parameters.Add(_Database.CreateParameter("ExtraParams", s.ExtraParams));
parameters.Add(_Database.CreateParameter("State", s.State)); parameters.Add(_Database.CreateParameter("State", s.State));
parameters.Add(_Database.CreateParameter("Media", null == s.Media ? null : s.Media.ToXml()));
return parameters.ToArray(); return parameters.ToArray();
} }

View File

@ -1,4 +1,4 @@

:VERSION 1 :VERSION 1
CREATE TABLE [dbo].[prims]( CREATE TABLE [dbo].[prims](
@ -925,5 +925,12 @@ ALTER TABLE regionsettings ADD loaded_creation_datetime int NOT NULL default 0
COMMIT COMMIT
:VERSION 24
-- Added post 0.7
BEGIN TRANSACTION
ALTER TABLE prims ADD COLUMN MediaURL varchar(255)
ALTER TABLE primshapes ADD COLUMN Media TEXT
COMMIT

View File

@ -174,7 +174,7 @@ namespace OpenSim.Data.MySQL
"ParticleSystem, ClickAction, Material, " + "ParticleSystem, ClickAction, Material, " +
"CollisionSound, CollisionSoundVolume, " + "CollisionSound, CollisionSoundVolume, " +
"PassTouches, " + "PassTouches, " +
"LinkNumber) values (" + "?UUID, " + "LinkNumber, MediaURL) values (" + "?UUID, " +
"?CreationDate, ?Name, ?Text, " + "?CreationDate, ?Name, ?Text, " +
"?Description, ?SitName, ?TouchName, " + "?Description, ?SitName, ?TouchName, " +
"?ObjectFlags, ?OwnerMask, ?NextOwnerMask, " + "?ObjectFlags, ?OwnerMask, ?NextOwnerMask, " +
@ -205,7 +205,7 @@ namespace OpenSim.Data.MySQL
"?SaleType, ?ColorR, ?ColorG, " + "?SaleType, ?ColorR, ?ColorG, " +
"?ColorB, ?ColorA, ?ParticleSystem, " + "?ColorB, ?ColorA, ?ParticleSystem, " +
"?ClickAction, ?Material, ?CollisionSound, " + "?ClickAction, ?Material, ?CollisionSound, " +
"?CollisionSoundVolume, ?PassTouches, ?LinkNumber)"; "?CollisionSoundVolume, ?PassTouches, ?LinkNumber, ?MediaURL)";
FillPrimCommand(cmd, prim, obj.UUID, regionUUID); FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
@ -222,7 +222,7 @@ namespace OpenSim.Data.MySQL
"PathTaperX, PathTaperY, PathTwist, " + "PathTaperX, PathTaperY, PathTwist, " +
"PathTwistBegin, ProfileBegin, ProfileEnd, " + "PathTwistBegin, ProfileBegin, ProfileEnd, " +
"ProfileCurve, ProfileHollow, Texture, " + "ProfileCurve, ProfileHollow, Texture, " +
"ExtraParams, State) values (?UUID, " + "ExtraParams, State, Media) values (?UUID, " +
"?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " + "?Shape, ?ScaleX, ?ScaleY, ?ScaleZ, " +
"?PCode, ?PathBegin, ?PathEnd, " + "?PCode, ?PathBegin, ?PathEnd, " +
"?PathScaleX, ?PathScaleY, " + "?PathScaleX, ?PathScaleY, " +
@ -233,7 +233,7 @@ namespace OpenSim.Data.MySQL
"?PathTwistBegin, ?ProfileBegin, " + "?PathTwistBegin, ?ProfileBegin, " +
"?ProfileEnd, ?ProfileCurve, " + "?ProfileEnd, ?ProfileCurve, " +
"?ProfileHollow, ?Texture, ?ExtraParams, " + "?ProfileHollow, ?Texture, ?ExtraParams, " +
"?State)"; "?State, ?Media)";
FillShapeCommand(cmd, prim); FillShapeCommand(cmd, prim);
@ -1185,6 +1185,9 @@ namespace OpenSim.Data.MySQL
prim.PassTouches = ((sbyte)row["PassTouches"] != 0); prim.PassTouches = ((sbyte)row["PassTouches"] != 0);
prim.LinkNum = (int)row["LinkNumber"]; prim.LinkNum = (int)row["LinkNumber"];
if (!(row["MediaURL"] is System.DBNull))
prim.MediaUrl = (string)row["MediaURL"];
return prim; return prim;
} }
@ -1521,6 +1524,7 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("PassTouches", 0); cmd.Parameters.AddWithValue("PassTouches", 0);
cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum); cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum);
cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl);
} }
/// <summary> /// <summary>
@ -1701,6 +1705,9 @@ namespace OpenSim.Data.MySQL
s.State = (byte)(int)row["State"]; s.State = (byte)(int)row["State"];
if (!(row["Media"] is System.DBNull))
s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]);
return s; return s;
} }
@ -1743,6 +1750,7 @@ namespace OpenSim.Data.MySQL
cmd.Parameters.AddWithValue("Texture", s.TextureEntry); cmd.Parameters.AddWithValue("Texture", s.TextureEntry);
cmd.Parameters.AddWithValue("ExtraParams", s.ExtraParams); cmd.Parameters.AddWithValue("ExtraParams", s.ExtraParams);
cmd.Parameters.AddWithValue("State", s.State); cmd.Parameters.AddWithValue("State", s.State);
cmd.Parameters.AddWithValue("Media", null == s.Media ? null : s.Media.ToXml());
} }
public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items) public void StorePrimInventory(UUID primID, ICollection<TaskInventoryItem> items)

View File

@ -1,4 +1,4 @@

:VERSION 1 #--------------------- :VERSION 1 #---------------------
BEGIN; BEGIN;
@ -800,3 +800,10 @@ BEGIN;
ALTER TABLE `regionwindlight` CHANGE COLUMN `cloud_scroll_x` `cloud_scroll_x` FLOAT(4,2) NOT NULL DEFAULT '0.20' AFTER `cloud_detail_density`, CHANGE COLUMN `cloud_scroll_y` `cloud_scroll_y` FLOAT(4,2) NOT NULL DEFAULT '0.01' AFTER `cloud_scroll_x_lock`; ALTER TABLE `regionwindlight` CHANGE COLUMN `cloud_scroll_x` `cloud_scroll_x` FLOAT(4,2) NOT NULL DEFAULT '0.20' AFTER `cloud_detail_density`, CHANGE COLUMN `cloud_scroll_y` `cloud_scroll_y` FLOAT(4,2) NOT NULL DEFAULT '0.01' AFTER `cloud_scroll_x_lock`;
COMMIT; COMMIT;
:VERSION 35 #---------------------
-- Added post 0.7
BEGIN;
ALTER TABLE prims ADD COLUMN MediaURL varchar(255);
ALTER TABLE primshapes ADD COLUMN Media TEXT;
COMMIT;

View File

@ -0,0 +1,6 @@
BEGIN;
ALTER TABLE prims ADD COLUMN MediaURL varchar(255);
ALTER TABLE primshapes ADD COLUMN Media TEXT;
COMMIT;

View File

@ -34,6 +34,7 @@ using System.Reflection;
using log4net; using log4net;
using Mono.Data.Sqlite; using Mono.Data.Sqlite;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
@ -975,6 +976,8 @@ namespace OpenSim.Data.SQLite
createCol(prims, "VolumeDetect", typeof(Int16)); createCol(prims, "VolumeDetect", typeof(Int16));
createCol(prims, "MediaURL", typeof(String));
// Add in contraints // Add in contraints
prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]};
@ -1021,6 +1024,7 @@ namespace OpenSim.Data.SQLite
// way to specify this as a blob atm // way to specify this as a blob atm
createCol(shapes, "Texture", typeof (Byte[])); createCol(shapes, "Texture", typeof (Byte[]));
createCol(shapes, "ExtraParams", typeof (Byte[])); createCol(shapes, "ExtraParams", typeof (Byte[]));
createCol(shapes, "Media", typeof(String));
shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]};
@ -1340,6 +1344,12 @@ namespace OpenSim.Data.SQLite
if (Convert.ToInt16(row["VolumeDetect"]) != 0) if (Convert.ToInt16(row["VolumeDetect"]) != 0)
prim.VolumeDetectActive = true; prim.VolumeDetectActive = true;
if (!(row["MediaURL"] is System.DBNull))
{
//m_log.DebugFormat("[SQLITE]: MediaUrl type [{0}]", row["MediaURL"].GetType());
prim.MediaUrl = (string)row["MediaURL"];
}
return prim; return prim;
} }
@ -1614,7 +1624,6 @@ namespace OpenSim.Data.SQLite
row["PayButton3"] = prim.PayPrice[3]; row["PayButton3"] = prim.PayPrice[3];
row["PayButton4"] = prim.PayPrice[4]; row["PayButton4"] = prim.PayPrice[4];
row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation); row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation);
row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem); row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem);
@ -1675,6 +1684,7 @@ namespace OpenSim.Data.SQLite
else else
row["VolumeDetect"] = 0; row["VolumeDetect"] = 0;
row["MediaURL"] = prim.MediaUrl;
} }
/// <summary> /// <summary>
@ -1849,6 +1859,10 @@ namespace OpenSim.Data.SQLite
s.TextureEntry = textureEntry; s.TextureEntry = textureEntry;
s.ExtraParams = (byte[]) row["ExtraParams"]; s.ExtraParams = (byte[]) row["ExtraParams"];
if (!(row["Media"] is System.DBNull))
s.Media = PrimitiveBaseShape.MediaList.FromXml((string)row["Media"]);
return s; return s;
} }
@ -1892,17 +1906,19 @@ namespace OpenSim.Data.SQLite
row["Texture"] = s.TextureEntry; row["Texture"] = s.TextureEntry;
row["ExtraParams"] = s.ExtraParams; row["ExtraParams"] = s.ExtraParams;
if (s.Media != null)
row["Media"] = s.Media.ToXml();
} }
/// <summary> /// <summary>
/// /// Persistently store a prim.
/// </summary> /// </summary>
/// <param name="prim"></param> /// <param name="prim"></param>
/// <param name="sceneGroupID"></param> /// <param name="sceneGroupID"></param>
/// <param name="regionUUID"></param> /// <param name="regionUUID"></param>
private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID)
{ {
DataTable prims = ds.Tables["prims"]; DataTable prims = ds.Tables["prims"];
DataTable shapes = ds.Tables["primshapes"]; DataTable shapes = ds.Tables["primshapes"];

View File

@ -26,12 +26,17 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.IO;
using System.Reflection; using System.Reflection;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization; using System.Xml.Serialization;
using log4net; using log4net;
using OpenMetaverse; using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
@ -171,6 +176,13 @@ namespace OpenSim.Framework
} }
} }
/// <summary>
/// Entries to store media textures on each face
/// </summary>
/// Do not change this value directly - always do it through an IMoapModule.
/// Lock before manipulating.
public MediaList Media { get; set; }
public PrimitiveBaseShape() public PrimitiveBaseShape()
{ {
PCode = (byte) PCodeEnum.Primitive; PCode = (byte) PCodeEnum.Primitive;
@ -1207,5 +1219,104 @@ namespace OpenSim.Framework
return prim; return prim;
} }
/// <summary>
/// Encapsulates a list of media entries.
/// </summary>
/// This class is necessary because we want to replace auto-serialization of MediaEntry with something more
/// OSD like and less vulnerable to change.
public class MediaList : List<MediaEntry>, IXmlSerializable
{
public const string MEDIA_TEXTURE_TYPE = "sl";
public MediaList() : base() {}
public MediaList(IEnumerable<MediaEntry> collection) : base(collection) {}
public MediaList(int capacity) : base(capacity) {}
public XmlSchema GetSchema()
{
return null;
}
public string ToXml()
{
lock (this)
{
using (StringWriter sw = new StringWriter())
{
using (XmlTextWriter xtw = new XmlTextWriter(sw))
{
xtw.WriteStartElement("OSMedia");
xtw.WriteAttributeString("type", MEDIA_TEXTURE_TYPE);
xtw.WriteAttributeString("version", "0.1");
OSDArray meArray = new OSDArray();
foreach (MediaEntry me in this)
{
OSD osd = (null == me ? new OSD() : me.GetOSD());
meArray.Add(osd);
}
xtw.WriteStartElement("OSData");
xtw.WriteRaw(OSDParser.SerializeLLSDXmlString(meArray));
xtw.WriteEndElement();
xtw.WriteEndElement();
xtw.Flush();
return sw.ToString();
}
}
}
}
public void WriteXml(XmlWriter writer)
{
writer.WriteRaw(ToXml());
}
public static MediaList FromXml(string rawXml)
{
MediaList ml = new MediaList();
ml.ReadXml(rawXml);
return ml;
}
public void ReadXml(string rawXml)
{
using (StringReader sr = new StringReader(rawXml))
{
using (XmlTextReader xtr = new XmlTextReader(sr))
{
xtr.MoveToContent();
string type = xtr.GetAttribute("type");
//m_log.DebugFormat("[MOAP]: Loaded media texture entry with type {0}", type);
if (type != MEDIA_TEXTURE_TYPE)
return;
xtr.ReadStartElement("OSMedia");
OSDArray osdMeArray = (OSDArray)OSDParser.DeserializeLLSDXml(xtr.ReadInnerXml());
foreach (OSD osdMe in osdMeArray)
{
MediaEntry me = (osdMe is OSDMap ? MediaEntry.FromOSD(osdMe) : new MediaEntry());
Add(me);
}
xtr.ReadEndElement();
}
}
}
public void ReadXml(XmlReader reader)
{
if (reader.IsEmptyElement)
return;
ReadXml(reader.ReadInnerXml());
}
}
} }
} }

View File

@ -27,6 +27,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using OpenMetaverse; using OpenMetaverse;
namespace OpenSim.Framework.Serialization namespace OpenSim.Framework.Serialization
@ -172,5 +173,29 @@ namespace OpenSim.Framework.Serialization
{ {
return OBJECTS_PATH + CreateOarObjectFilename(objectName, uuid, pos); return OBJECTS_PATH + CreateOarObjectFilename(objectName, uuid, pos);
} }
/// <summary>
/// Extract a plain path from an IAR path
/// </summary>
/// <param name="iarPath"></param>
/// <returns></returns>
public static string ExtractPlainPathFromIarPath(string iarPath)
{
List<string> plainDirs = new List<string>();
string[] iarDirs = iarPath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string iarDir in iarDirs)
{
if (!iarDir.Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
plainDirs.Add(iarDir);
int i = iarDir.LastIndexOf(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
plainDirs.Add(iarDir.Remove(i));
}
return string.Join("/", plainDirs.ToArray());
}
} }
} }

View File

@ -362,7 +362,7 @@ namespace OpenSim.Framework.Servers.HttpServer
string path = request.RawUrl; string path = request.RawUrl;
string handlerKey = GetHandlerKey(request.HttpMethod, path); string handlerKey = GetHandlerKey(request.HttpMethod, path);
//m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path); // m_log.DebugFormat("[BASE HTTP SERVER]: Handling {0} request for {1}", request.HttpMethod, path);
if (TryGetStreamHandler(handlerKey, out requestHandler)) if (TryGetStreamHandler(handlerKey, out requestHandler))
{ {

View File

@ -4327,8 +4327,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount) public void SendLandObjectOwners(LandData land, List<UUID> groups, Dictionary<UUID, int> ownersAndCount)
{ {
int notifyCount = ownersAndCount.Count; int notifyCount = ownersAndCount.Count;
ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply); ParcelObjectOwnersReplyPacket pack = (ParcelObjectOwnersReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelObjectOwnersReply);
@ -4600,6 +4598,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes; update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes;
update.Scale = data.Shape.Scale; update.Scale = data.Shape.Scale;
update.Text = Util.StringToBytes256(data.Text); update.Text = Util.StringToBytes256(data.Text);
update.MediaURL = Util.StringToBytes256(data.MediaUrl);
#region PrimFlags #region PrimFlags

View File

@ -55,6 +55,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
private UserAccount m_userInfo; private UserAccount m_userInfo;
private string m_invPath; private string m_invPath;
/// <summary>
/// Do we want to merge this load with existing inventory?
/// </summary>
protected bool m_merge;
/// <value> /// <value>
/// We only use this to request modules /// We only use this to request modules
/// </value> /// </value>
@ -66,19 +71,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
private Stream m_loadStream; private Stream m_loadStream;
public InventoryArchiveReadRequest( public InventoryArchiveReadRequest(
Scene scene, UserAccount userInfo, string invPath, string loadPath) Scene scene, UserAccount userInfo, string invPath, string loadPath, bool merge)
: this( : this(
scene, scene,
userInfo, userInfo,
invPath, invPath,
new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress)) new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress),
merge)
{ {
} }
public InventoryArchiveReadRequest( public InventoryArchiveReadRequest(
Scene scene, UserAccount userInfo, string invPath, Stream loadStream) Scene scene, UserAccount userInfo, string invPath, Stream loadStream, bool merge)
{ {
m_scene = scene; m_scene = scene;
m_merge = merge;
m_userInfo = userInfo; m_userInfo = userInfo;
m_invPath = invPath; m_invPath = invPath;
m_loadStream = loadStream; m_loadStream = loadStream;
@ -91,7 +98,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
/// A list of the inventory nodes loaded. If folders were loaded then only the root folders are /// A list of the inventory nodes loaded. If folders were loaded then only the root folders are
/// returned /// returned
/// </returns> /// </returns>
public List<InventoryNodeBase> Execute() public HashSet<InventoryNodeBase> Execute()
{ {
try try
{ {
@ -100,7 +107,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
int failedAssetRestores = 0; int failedAssetRestores = 0;
int successfulItemRestores = 0; int successfulItemRestores = 0;
List<InventoryNodeBase> loadedNodes = new List<InventoryNodeBase>(); HashSet<InventoryNodeBase> loadedNodes = new HashSet<InventoryNodeBase>();
List<InventoryFolderBase> folderCandidates List<InventoryFolderBase> folderCandidates
= InventoryArchiveUtils.FindFolderByPath( = InventoryArchiveUtils.FindFolderByPath(
@ -158,9 +165,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
{ {
successfulItemRestores++; successfulItemRestores++;
// If we're loading an item directly into the given destination folder then we need to record // If we aren't loading the folder containing the item then well need to update the
// it separately from any loaded root folders // viewer separately for that item.
if (rootDestinationFolder == foundFolder) if (!loadedNodes.Contains(foundFolder))
loadedNodes.Add(item); loadedNodes.Add(item);
} }
} }
@ -205,14 +212,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
string iarPath, string iarPath,
InventoryFolderBase rootDestFolder, InventoryFolderBase rootDestFolder,
Dictionary <string, InventoryFolderBase> resolvedFolders, Dictionary <string, InventoryFolderBase> resolvedFolders,
List<InventoryNodeBase> loadedNodes) HashSet<InventoryNodeBase> loadedNodes)
{ {
string iarPathExisting = iarPath; string iarPathExisting = iarPath;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); // "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);
InventoryFolderBase destFolder = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders); InventoryFolderBase destFolder
= ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders);
// m_log.DebugFormat( // m_log.DebugFormat(
// "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]", // "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]",
@ -251,22 +259,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
{ {
// string originalArchivePath = archivePath; // string originalArchivePath = archivePath;
InventoryFolderBase destFolder = null; while (archivePath.Length > 0)
if (archivePath.Length > 0)
{ {
while (null == destFolder && archivePath.Length > 0) m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath);
{
// m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath);
if (resolvedFolders.ContainsKey(archivePath)) if (resolvedFolders.ContainsKey(archivePath))
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); // "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
destFolder = resolvedFolders[archivePath]; return resolvedFolders[archivePath];
} }
else else
{ {
if (m_merge)
{
// TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the
// iar name and try to find that instead.
string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
List<InventoryFolderBase> folderCandidates
= InventoryArchiveUtils.FindFolderByPath(
m_scene.InventoryService, m_userInfo.PrincipalID, plainPath);
if (folderCandidates.Count != 0)
{
InventoryFolderBase destFolder = folderCandidates[0];
resolvedFolders[archivePath] = destFolder;
return destFolder;
}
}
// Don't include the last slash so find the penultimate one // Don't include the last slash so find the penultimate one
int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2); int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2);
@ -281,16 +302,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
// "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}", // "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}",
// originalArchivePath); // originalArchivePath);
archivePath = string.Empty; archivePath = string.Empty;
destFolder = rootDestFolder; return rootDestFolder;
}
} }
} }
} }
if (null == destFolder) return rootDestFolder;
destFolder = rootDestFolder;
return destFolder;
} }
/// <summary> /// <summary>
@ -316,24 +333,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
string iarPathExisting, string iarPathExisting,
string iarPathToReplicate, string iarPathToReplicate,
Dictionary <string, InventoryFolderBase> resolvedFolders, Dictionary <string, InventoryFolderBase> resolvedFolders,
List<InventoryNodeBase> loadedNodes) HashSet<InventoryNodeBase> loadedNodes)
{ {
string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
int i = 0;
while (i < rawDirsToCreate.Length) for (int i = 0; i < rawDirsToCreate.Length; i++)
{ {
// m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]); // m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]);
if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
continue;
int identicalNameIdentifierIndex int identicalNameIdentifierIndex
= rawDirsToCreate[i].LastIndexOf( = rawDirsToCreate[i].LastIndexOf(
ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR); ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
if (identicalNameIdentifierIndex < 0)
{
i++;
continue;
}
string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex); string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex);
newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName); newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName);
@ -356,8 +370,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
if (0 == i) if (0 == i)
loadedNodes.Add(destFolder); loadedNodes.Add(destFolder);
i++;
} }
} }

View File

@ -241,10 +241,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
if (CheckPresence(userInfo.PrincipalID)) if (CheckPresence(userInfo.PrincipalID))
{ {
InventoryArchiveReadRequest request; InventoryArchiveReadRequest request;
bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
try try
{ {
request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream); request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadStream, merge);
} }
catch (EntryPointNotFoundException e) catch (EntryPointNotFoundException e)
{ {
@ -285,10 +286,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
if (CheckPresence(userInfo.PrincipalID)) if (CheckPresence(userInfo.PrincipalID))
{ {
InventoryArchiveReadRequest request; InventoryArchiveReadRequest request;
bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
try try
{ {
request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath); request = new InventoryArchiveReadRequest(m_aScene, userInfo, invPath, loadPath, merge);
} }
catch (EntryPointNotFoundException e) catch (EntryPointNotFoundException e)
{ {
@ -334,7 +336,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
if (mainParams.Count < 6) if (mainParams.Count < 6)
{ {
m_log.Error( m_log.Error(
"[INVENTORY ARCHIVER]: usage is load iar <first name> <last name> <inventory path> <user password> [<load file path>]"); "[INVENTORY ARCHIVER]: usage is load iar [--merge] <first name> <last name> <inventory path> <user password> [<load file path>]");
return; return;
} }
@ -469,7 +471,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
/// Notify the client of loaded nodes if they are logged in /// Notify the client of loaded nodes if they are logged in
/// </summary> /// </summary>
/// <param name="loadedNodes">Can be empty. In which case, nothing happens</param> /// <param name="loadedNodes">Can be empty. In which case, nothing happens</param>
private void UpdateClientWithLoadedNodes(UserAccount userInfo, List<InventoryNodeBase> loadedNodes) private void UpdateClientWithLoadedNodes(UserAccount userInfo, HashSet<InventoryNodeBase> loadedNodes)
{ {
if (loadedNodes.Count == 0) if (loadedNodes.Count == 0)
return; return;

View File

@ -629,7 +629,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene);
Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>(); Dictionary <string, InventoryFolderBase> foldersCreated = new Dictionary<string, InventoryFolderBase>();
List<InventoryNodeBase> nodesLoaded = new List<InventoryNodeBase>(); HashSet<InventoryNodeBase> nodesLoaded = new HashSet<InventoryNodeBase>();
string folder1Name = "1"; string folder1Name = "1";
string folder2aName = "2a"; string folder2aName = "2a";
@ -644,7 +644,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
{ {
// Test replication of path1 // Test replication of path1
new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false)
.ReplicateArchivePathToUserInventory( .ReplicateArchivePathToUserInventory(
iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
foldersCreated, nodesLoaded); foldersCreated, nodesLoaded);
@ -661,7 +661,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
{ {
// Test replication of path2 // Test replication of path2
new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false)
.ReplicateArchivePathToUserInventory( .ReplicateArchivePathToUserInventory(
iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
foldersCreated, nodesLoaded); foldersCreated, nodesLoaded);
@ -707,10 +707,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null, false)
.ReplicateArchivePathToUserInventory( .ReplicateArchivePathToUserInventory(
itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
new Dictionary<string, InventoryFolderBase>(), new List<InventoryNodeBase>()); new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
List<InventoryFolderBase> folder1PostCandidates List<InventoryFolderBase> folder1PostCandidates
= InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
@ -732,5 +732,45 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests
= InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1Post, "b"); = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1Post, "b");
Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
} }
/// <summary>
/// Test replication of a partly existing archive path to the user's inventory. This should create
/// a merged path.
/// </summary>
[Test]
public void TestMergeIarPath()
{
TestHelper.InMethod();
log4net.Config.XmlConfigurator.Configure();
Scene scene = SceneSetupHelpers.SetupScene("inventory");
UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene);
string folder1ExistingName = "a";
string folder2Name = "b";
InventoryFolderBase folder1
= UserInventoryTestUtils.CreateInventoryFolder(
scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random());
string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random());
string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName });
new InventoryArchiveReadRequest(scene, ua1, folder1ExistingName, (Stream)null, true)
.ReplicateArchivePathToUserInventory(
itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID),
new Dictionary<string, InventoryFolderBase>(), new HashSet<InventoryNodeBase>());
List<InventoryFolderBase> folder1PostCandidates
= InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName);
Assert.That(folder1PostCandidates.Count, Is.EqualTo(1));
Assert.That(folder1PostCandidates[0].ID, Is.EqualTo(folder1.ID));
List<InventoryFolderBase> folder2PostCandidates
= InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1PostCandidates[0], "b");
Assert.That(folder2PostCandidates.Count, Is.EqualTo(1));
}
} }
} }

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -173,16 +173,16 @@ namespace OpenSim.Region.CoreModules.Framework.Library
m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName); m_log.InfoFormat("[LIBRARY MODULE]: Loading library archive {0} ({1})...", iarFileName, simpleName);
simpleName = GetInventoryPathFromName(simpleName); simpleName = GetInventoryPathFromName(simpleName);
InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName); InventoryArchiveReadRequest archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, simpleName, iarFileName, false);
try try
{ {
List<InventoryNodeBase> nodes = archread.Execute(); HashSet<InventoryNodeBase> nodes = archread.Execute();
if (nodes != null && nodes.Count == 0) if (nodes != null && nodes.Count == 0)
{ {
// didn't find the subfolder with the given name; place it on the top // didn't find the subfolder with the given name; place it on the top
m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName); m_log.InfoFormat("[LIBRARY MODULE]: Didn't find {0} in library. Placing archive on the top level", simpleName);
archread.Close(); archread.Close();
archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, "/", iarFileName); archread = new InventoryArchiveReadRequest(m_MockScene, uinfo, "/", iarFileName, false);
archread.Execute(); archread.Execute();
} }
foreach (InventoryNodeBase node in nodes) foreach (InventoryNodeBase node in nodes)

View File

@ -0,0 +1,596 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;
using System.IO;
using System.Web;
using System.Xml;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenMetaverse;
using OpenMetaverse.Messages.Linden;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Capabilities;
using OpenSim.Framework.Servers;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using Caps = OpenSim.Framework.Capabilities.Caps;
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
using OSDMap = OpenMetaverse.StructuredData.OSDMap;
namespace OpenSim.Region.CoreModules.Media.Moap
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "MoapModule")]
public class MoapModule : INonSharedRegionModule, IMoapModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public string Name { get { return "MoapModule"; } }
public Type ReplaceableInterface { get { return null; } }
/// <summary>
/// Is this module enabled?
/// </summary>
protected bool m_isEnabled = true;
/// <summary>
/// The scene to which this module is attached
/// </summary>
protected Scene m_scene;
/// <summary>
/// Track the ObjectMedia capabilities given to users keyed by path
/// </summary>
protected Dictionary<string, UUID> m_omCapUsers = new Dictionary<string, UUID>();
/// <summary>
/// Track the ObjectMedia capabilities given to users keyed by agent. Lock m_omCapUsers to manipulate.
/// </summary>
protected Dictionary<UUID, string> m_omCapUrls = new Dictionary<UUID, string>();
/// <summary>
/// Track the ObjectMediaUpdate capabilities given to users keyed by path
/// </summary>
protected Dictionary<string, UUID> m_omuCapUsers = new Dictionary<string, UUID>();
/// <summary>
/// Track the ObjectMediaUpdate capabilities given to users keyed by agent. Lock m_omuCapUsers to manipulate
/// </summary>
protected Dictionary<UUID, string> m_omuCapUrls = new Dictionary<UUID, string>();
public void Initialise(IConfigSource configSource)
{
IConfig config = configSource.Configs["MediaOnAPrim"];
if (config != null && !config.GetBoolean("Enabled", false))
m_isEnabled = false;
// else
// m_log.Debug("[MOAP]: Initialised module.")l
}
public void AddRegion(Scene scene)
{
if (!m_isEnabled)
return;
m_scene = scene;
m_scene.RegisterModuleInterface<IMoapModule>(this);
}
public void RemoveRegion(Scene scene) {}
public void RegionLoaded(Scene scene)
{
if (!m_isEnabled)
return;
m_scene.EventManager.OnRegisterCaps += OnRegisterCaps;
m_scene.EventManager.OnDeregisterCaps += OnDeregisterCaps;
m_scene.EventManager.OnSceneObjectPartCopy += OnSceneObjectPartCopy;
}
public void Close()
{
if (!m_isEnabled)
return;
m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
m_scene.EventManager.OnDeregisterCaps -= OnDeregisterCaps;
m_scene.EventManager.OnSceneObjectPartCopy -= OnSceneObjectPartCopy;
}
public void OnRegisterCaps(UUID agentID, Caps caps)
{
// m_log.DebugFormat(
// "[MOAP]: Registering ObjectMedia and ObjectMediaNavigate capabilities for agent {0}", agentID);
string omCapUrl = "/CAPS/" + UUID.Random();
lock (m_omCapUsers)
{
m_omCapUsers[omCapUrl] = agentID;
m_omCapUrls[agentID] = omCapUrl;
// Even though we're registering for POST we're going to get GETS and UPDATES too
caps.RegisterHandler(
"ObjectMedia", new RestStreamHandler("POST", omCapUrl, HandleObjectMediaMessage));
}
string omuCapUrl = "/CAPS/" + UUID.Random();
lock (m_omuCapUsers)
{
m_omuCapUsers[omuCapUrl] = agentID;
m_omuCapUrls[agentID] = omuCapUrl;
// Even though we're registering for POST we're going to get GETS and UPDATES too
caps.RegisterHandler(
"ObjectMediaNavigate", new RestStreamHandler("POST", omuCapUrl, HandleObjectMediaNavigateMessage));
}
}
public void OnDeregisterCaps(UUID agentID, Caps caps)
{
lock (m_omCapUsers)
{
string path = m_omCapUrls[agentID];
m_omCapUrls.Remove(agentID);
m_omCapUsers.Remove(path);
}
lock (m_omuCapUsers)
{
string path = m_omuCapUrls[agentID];
m_omuCapUrls.Remove(agentID);
m_omuCapUsers.Remove(path);
}
}
protected void OnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
{
if (original.Shape.Media != null)
{
PrimitiveBaseShape.MediaList dupeMedia = new PrimitiveBaseShape.MediaList();
lock (original.Shape.Media)
{
foreach (MediaEntry me in original.Shape.Media)
{
if (me != null)
dupeMedia.Add(MediaEntry.FromOSD(me.GetOSD()));
else
dupeMedia.Add(null);
}
}
copy.Shape.Media = dupeMedia;
}
}
public MediaEntry GetMediaEntry(SceneObjectPart part, int face)
{
MediaEntry me = null;
CheckFaceParam(part, face);
List<MediaEntry> media = part.Shape.Media;
if (null == media)
{
me = null;
}
else
{
lock (media)
me = media[face];
// TODO: Really need a proper copy constructor down in libopenmetaverse
if (me != null)
me = MediaEntry.FromOSD(me.GetOSD());
}
// m_log.DebugFormat("[MOAP]: GetMediaEntry for {0} face {1} found {2}", part.Name, face, me);
return me;
}
public void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me)
{
CheckFaceParam(part, face);
if (null == part.Shape.Media)
part.Shape.Media = new PrimitiveBaseShape.MediaList(new MediaEntry[part.GetNumberOfSides()]);
lock (part.Shape.Media)
part.Shape.Media[face] = me;
UpdateMediaUrl(part, UUID.Zero);
part.ScheduleFullUpdate();
part.TriggerScriptChangedEvent(Changed.MEDIA);
}
public void ClearMediaEntry(SceneObjectPart part, int face)
{
SetMediaEntry(part, face, null);
}
/// <summary>
/// Sets or gets per face media textures.
/// </summary>
/// <param name="request"></param>
/// <param name="path"></param>
/// <param name="param"></param>
/// <param name="httpRequest"></param>
/// <param name="httpResponse"></param>
/// <returns></returns>
protected string HandleObjectMediaMessage(
string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
{
// m_log.DebugFormat("[MOAP]: Got ObjectMedia path [{0}], raw request [{1}]", path, request);
OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
ObjectMediaMessage omm = new ObjectMediaMessage();
omm.Deserialize(osd);
if (omm.Request is ObjectMediaRequest)
return HandleObjectMediaRequest(omm.Request as ObjectMediaRequest);
else if (omm.Request is ObjectMediaUpdate)
return HandleObjectMediaUpdate(path, omm.Request as ObjectMediaUpdate);
throw new Exception(
string.Format(
"[MOAP]: ObjectMediaMessage has unrecognized ObjectMediaBlock of {0}",
omm.Request.GetType()));
}
/// <summary>
/// Handle a fetch request for media textures
/// </summary>
/// <param name="omr"></param>
/// <returns></returns>
protected string HandleObjectMediaRequest(ObjectMediaRequest omr)
{
UUID primId = omr.PrimID;
SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
if (null == part)
{
m_log.WarnFormat(
"[MOAP]: Received a GET ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
primId, m_scene.RegionInfo.RegionName);
return string.Empty;
}
if (null == part.Shape.Media)
return string.Empty;
ObjectMediaResponse resp = new ObjectMediaResponse();
resp.PrimID = primId;
lock (part.Shape.Media)
resp.FaceMedia = part.Shape.Media.ToArray();
resp.Version = part.MediaUrl;
string rawResp = OSDParser.SerializeLLSDXmlString(resp.Serialize());
// m_log.DebugFormat("[MOAP]: Got HandleObjectMediaRequestGet raw response is [{0}]", rawResp);
return rawResp;
}
/// <summary>
/// Handle an update of media textures.
/// </summary>
/// <param name="path">Path on which this request was made</param>
/// <param name="omu">/param>
/// <returns></returns>
protected string HandleObjectMediaUpdate(string path, ObjectMediaUpdate omu)
{
UUID primId = omu.PrimID;
SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
if (null == part)
{
m_log.WarnFormat(
"[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}",
primId, m_scene.RegionInfo.RegionName);
return string.Empty;
}
// m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId);
// for (int i = 0; i < omu.FaceMedia.Length; i++)
// {
// MediaEntry me = omu.FaceMedia[i];
// string v = (null == me ? "null": OSDParser.SerializeLLSDXmlString(me.GetOSD()));
// m_log.DebugFormat("[MOAP]: Face {0} [{1}]", i, v);
// }
if (omu.FaceMedia.Length > part.GetNumberOfSides())
{
m_log.WarnFormat(
"[MOAP]: Received {0} media entries from client for prim {1} {2} but this prim has only {3} faces. Dropping request.",
omu.FaceMedia.Length, part.Name, part.UUID, part.GetNumberOfSides());
return string.Empty;
}
UUID agentId = default(UUID);
lock (m_omCapUsers)
agentId = m_omCapUsers[path];
List<MediaEntry> media = part.Shape.Media;
if (null == media)
{
// m_log.DebugFormat("[MOAP]: Setting all new media list for {0}", part.Name);
part.Shape.Media = new PrimitiveBaseShape.MediaList(omu.FaceMedia);
for (int i = 0; i < omu.FaceMedia.Length; i++)
{
if (omu.FaceMedia[i] != null)
{
// FIXME: Race condition here since some other texture entry manipulator may overwrite/get
// overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry
// directly.
Primitive.TextureEntry te = part.Shape.Textures;
Primitive.TextureEntryFace face = te.CreateFace((uint)i);
face.MediaFlags = true;
part.Shape.Textures = te;
// m_log.DebugFormat(
// "[MOAP]: Media flags for face {0} is {1}",
// i, part.Shape.Textures.FaceTextures[i].MediaFlags);
}
}
}
else
{
// We need to go through the media textures one at a time to make sure that we have permission
// to change them
// FIXME: Race condition here since some other texture entry manipulator may overwrite/get
// overwritten. Unfortunately, PrimitiveBaseShape does not allow us to change texture entry
// directly.
Primitive.TextureEntry te = part.Shape.Textures;
lock (media)
{
for (int i = 0; i < media.Count; i++)
{
if (m_scene.Permissions.CanControlPrimMedia(agentId, part.UUID, i))
{
media[i] = omu.FaceMedia[i];
// When a face is cleared this is done by setting the MediaFlags in the TextureEntry via a normal
// texture update, so we don't need to worry about clearing MediaFlags here.
if (null == media[i])
continue;
Primitive.TextureEntryFace face = te.CreateFace((uint)i);
face.MediaFlags = true;
// m_log.DebugFormat(
// "[MOAP]: Media flags for face {0} is {1}",
// i, face.MediaFlags);
// m_log.DebugFormat("[MOAP]: Set media entry for face {0} on {1}", i, part.Name);
}
}
}
part.Shape.Textures = te;
// for (int i2 = 0; i2 < part.Shape.Textures.FaceTextures.Length; i2++)
// m_log.DebugFormat("[MOAP]: FaceTexture[{0}] is {1}", i2, part.Shape.Textures.FaceTextures[i2]);
}
UpdateMediaUrl(part, agentId);
// Arguably, we could avoid sending a full update to the avatar that just changed the texture.
part.ScheduleFullUpdate();
part.TriggerScriptChangedEvent(Changed.MEDIA);
return string.Empty;
}
/// <summary>
/// Received from the viewer if a user has changed the url of a media texture.
/// </summary>
/// <param name="request"></param>
/// <param name="path"></param>
/// <param name="param"></param>
/// <param name="httpRequest">/param>
/// <param name="httpResponse">/param>
/// <returns></returns>
protected string HandleObjectMediaNavigateMessage(
string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
{
// m_log.DebugFormat("[MOAP]: Got ObjectMediaNavigate request [{0}]", request);
OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request);
ObjectMediaNavigateMessage omn = new ObjectMediaNavigateMessage();
omn.Deserialize(osd);
UUID primId = omn.PrimID;
SceneObjectPart part = m_scene.GetSceneObjectPart(primId);
if (null == part)
{
m_log.WarnFormat(
"[MOAP]: Received an ObjectMediaNavigateMessage for prim {0} but this doesn't exist in region {1}",
primId, m_scene.RegionInfo.RegionName);
return string.Empty;
}
UUID agentId = default(UUID);
lock (m_omuCapUsers)
agentId = m_omuCapUsers[path];
if (!m_scene.Permissions.CanInteractWithPrimMedia(agentId, part.UUID, omn.Face))
return string.Empty;
// m_log.DebugFormat(
// "[MOAP]: Received request to update media entry for face {0} on prim {1} {2} to {3}",
// omn.Face, part.Name, part.UUID, omn.URL);
// If media has never been set for this prim, then just return.
if (null == part.Shape.Media)
return string.Empty;
MediaEntry me = null;
lock (part.Shape.Media)
me = part.Shape.Media[omn.Face];
// Do the same if media has not been set up for a specific face
if (null == me)
return string.Empty;
if (me.EnableWhiteList)
{
if (!CheckUrlAgainstWhitelist(omn.URL, me.WhiteList))
{
// m_log.DebugFormat(
// "[MOAP]: Blocking change of face {0} on prim {1} {2} to {3} since it's not on the enabled whitelist",
// omn.Face, part.Name, part.UUID, omn.URL);
return string.Empty;
}
}
me.CurrentURL = omn.URL;
UpdateMediaUrl(part, agentId);
part.ScheduleFullUpdate();
part.TriggerScriptChangedEvent(Changed.MEDIA);
return OSDParser.SerializeLLSDXmlString(new OSD());
}
/// <summary>
/// Check that the face number is valid for the given prim.
/// </summary>
/// <param name="part"></param>
/// <param name="face"></param>
protected void CheckFaceParam(SceneObjectPart part, int face)
{
if (face < 0)
throw new ArgumentException("Face cannot be less than zero");
int maxFaces = part.GetNumberOfSides() - 1;
if (face > maxFaces)
throw new ArgumentException(
string.Format("Face argument was {0} but max is {1}", face, maxFaces));
}
/// <summary>
/// Update the media url of the given part
/// </summary>
/// <param name="part"></param>
/// <param name="updateId">
/// The id to attach to this update. Normally, this is the user that changed the
/// texture
/// </param>
protected void UpdateMediaUrl(SceneObjectPart part, UUID updateId)
{
if (null == part.MediaUrl)
{
// TODO: We can't set the last changer until we start tracking which cap we give to which agent id
part.MediaUrl = "x-mv:0000000000/" + updateId;
}
else
{
string rawVersion = part.MediaUrl.Substring(5, 10);
int version = int.Parse(rawVersion);
part.MediaUrl = string.Format("x-mv:{0:D10}/{1}", ++version, updateId);
}
// m_log.DebugFormat("[MOAP]: Storing media url [{0}] in prim {1} {2}", part.MediaUrl, part.Name, part.UUID);
}
/// <summary>
/// Check the given url against the given whitelist.
/// </summary>
/// <param name="rawUrl"></param>
/// <param name="whitelist"></param>
/// <returns>true if the url matches an entry on the whitelist, false otherwise</returns>
protected bool CheckUrlAgainstWhitelist(string rawUrl, string[] whitelist)
{
Uri url = new Uri(rawUrl);
foreach (string origWlUrl in whitelist)
{
string wlUrl = origWlUrl;
// Deal with a line-ending wildcard
if (wlUrl.EndsWith("*"))
wlUrl = wlUrl.Remove(wlUrl.Length - 1);
// m_log.DebugFormat("[MOAP]: Checking whitelist URL pattern {0}", origWlUrl);
// Handle a line starting wildcard slightly differently since this can only match the domain, not the path
if (wlUrl.StartsWith("*"))
{
wlUrl = wlUrl.Substring(1);
if (url.Host.Contains(wlUrl))
{
// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl);
return true;
}
}
else
{
string urlToMatch = url.Authority + url.AbsolutePath;
if (urlToMatch.StartsWith(wlUrl))
{
// m_log.DebugFormat("[MOAP]: Whitelist URL {0} matches {1}", origWlUrl, rawUrl);
return true;
}
}
}
return false;
}
}
}

View File

@ -164,6 +164,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
private Dictionary<string, bool> GrantYP = new Dictionary<string, bool>(); private Dictionary<string, bool> GrantYP = new Dictionary<string, bool>();
private IFriendsModule m_friendsModule; private IFriendsModule m_friendsModule;
private IGroupsModule m_groupsModule; private IGroupsModule m_groupsModule;
private IMoapModule m_moapModule;
#endregion #endregion
@ -177,7 +178,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule"); string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule");
List<string> modules=new List<string>(permissionModules.Split(',')); List<string> modules = new List<string>(permissionModules.Split(','));
if (!modules.Contains("DefaultPermissionsModule")) if (!modules.Contains("DefaultPermissionsModule"))
return; return;
@ -250,6 +251,9 @@ namespace OpenSim.Region.CoreModules.World.Permissions
m_scene.Permissions.OnTeleport += CanTeleport; //NOT YET IMPLEMENTED m_scene.Permissions.OnTeleport += CanTeleport; //NOT YET IMPLEMENTED
m_scene.Permissions.OnControlPrimMedia += CanControlPrimMedia;
m_scene.Permissions.OnInteractWithPrimMedia += CanInteractWithPrimMedia;
m_scene.AddCommand(this, "bypass permissions", m_scene.AddCommand(this, "bypass permissions",
"bypass permissions <true / false>", "bypass permissions <true / false>",
"Bypass permission checks", "Bypass permission checks",
@ -394,6 +398,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions
if (m_groupsModule == null) if (m_groupsModule == null)
m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work"); m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work");
m_moapModule = m_scene.RequestModuleInterface<IMoapModule>();
// This log line will be commented out when no longer required for debugging
// if (m_moapModule == null)
// m_log.Warn("[PERMISSIONS]: Media on a prim module not found, media on a prim permissions will not work");
} }
public void Close() public void Close()
@ -1894,5 +1904,80 @@ namespace OpenSim.Region.CoreModules.World.Permissions
} }
return(false); return(false);
} }
private bool CanControlPrimMedia(UUID agentID, UUID primID, int face)
{
// m_log.DebugFormat(
// "[PERMISSONS]: Performing CanControlPrimMedia check with agentID {0}, primID {1}, face {2}",
// agentID, primID, face);
if (null == m_moapModule)
return false;
SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
if (null == part)
return false;
MediaEntry me = m_moapModule.GetMediaEntry(part, face);
// If there is no existing media entry then it can be controlled (in this context, created).
if (null == me)
return true;
// m_log.DebugFormat(
// "[PERMISSIONS]: Checking CanControlPrimMedia for {0} on {1} face {2} with control permissions {3}",
// agentID, primID, face, me.ControlPermissions);
return GenericPrimMediaPermission(part, agentID, me.ControlPermissions);
}
private bool CanInteractWithPrimMedia(UUID agentID, UUID primID, int face)
{
// m_log.DebugFormat(
// "[PERMISSONS]: Performing CanInteractWithPrimMedia check with agentID {0}, primID {1}, face {2}",
// agentID, primID, face);
if (null == m_moapModule)
return false;
SceneObjectPart part = m_scene.GetSceneObjectPart(primID);
if (null == part)
return false;
MediaEntry me = m_moapModule.GetMediaEntry(part, face);
// If there is no existing media entry then it can be controlled (in this context, created).
if (null == me)
return true;
// m_log.DebugFormat(
// "[PERMISSIONS]: Checking CanInteractWithPrimMedia for {0} on {1} face {2} with interact permissions {3}",
// agentID, primID, face, me.InteractPermissions);
return GenericPrimMediaPermission(part, agentID, me.InteractPermissions);
}
private bool GenericPrimMediaPermission(SceneObjectPart part, UUID agentID, MediaPermission perms)
{
// if (IsAdministrator(agentID))
// return true;
if ((perms & MediaPermission.Anyone) == MediaPermission.Anyone)
return true;
if ((perms & MediaPermission.Owner) == MediaPermission.Owner)
{
if (agentID == part.OwnerID)
return true;
}
if ((perms & MediaPermission.Group) == MediaPermission.Group)
{
if (IsGroupMember(part.GroupID, agentID, 0))
return true;
}
return false;
}
} }
} }

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using OpenMetaverse;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces
{
/// <summary>
/// Provides methods from manipulating media-on-a-prim
/// </summary>
public interface IMoapModule
{
/// <summary>
/// Get the media entry for a given prim face.
/// </summary>
/// A copy of the media entry is returned rather than the original, so this can be altered at will without
/// affecting the original settings.
/// <param name="part"></param>
/// <param name="face"></param>
/// <returns></returns>
MediaEntry GetMediaEntry(SceneObjectPart part, int face);
/// <summary>
/// Set the media entry for a given prim face.
/// </summary>
/// <param name="SceneObjectPart"></param>
/// <param name="face"></param>
/// <param name="me"></param>
void SetMediaEntry(SceneObjectPart part, int face, MediaEntry me);
/// <summary>
/// Clear the media entry for a given prim face.
/// </summary>
///
/// This is the equivalent of setting a media entry of null
///
/// <param name="part"></param>
/// <param name="face">/param>
void ClearMediaEntry(SceneObjectPart part, int face);
}
}

View File

@ -336,6 +336,34 @@ namespace OpenSim.Region.Framework.Scenes
public delegate void Attach(uint localID, UUID itemID, UUID avatarID); public delegate void Attach(uint localID, UUID itemID, UUID avatarID);
public event Attach OnAttach; public event Attach OnAttach;
/// <summary>
/// Called immediately after an object is loaded from storage.
/// </summary>
public event SceneObjectDelegate OnSceneObjectLoaded;
public delegate void SceneObjectDelegate(SceneObjectGroup so);
/// <summary>
/// Called immediately before an object is saved to storage.
/// </summary>
/// <param name="persistingSo">
/// The scene object being persisted.
/// This is actually a copy of the original scene object so changes made here will be saved to storage but will not be kept in memory.
/// </param>
/// <param name="originalSo">
/// The original scene object being persisted. Changes here will stay in memory but will not be saved to storage on this save.
/// </param>
public event SceneObjectPreSaveDelegate OnSceneObjectPreSave;
public delegate void SceneObjectPreSaveDelegate(SceneObjectGroup persistingSo, SceneObjectGroup originalSo);
/// <summary>
/// Called when a scene object part is cloned within the region.
/// </summary>
/// <param name="copy"></param>
/// <param name="original"></param>
/// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
public delegate void RegionUp(GridRegion region); public delegate void RegionUp(GridRegion region);
public event RegionUp OnRegionUp; public event RegionUp OnRegionUp;
@ -2037,5 +2065,68 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
} }
public void TriggerOnSceneObjectLoaded(SceneObjectGroup so)
{
SceneObjectDelegate handler = OnSceneObjectLoaded;
if (handler != null)
{
foreach (SceneObjectDelegate d in handler.GetInvocationList())
{
try
{
d(so);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerOnSceneObjectLoaded failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
public void TriggerOnSceneObjectPreSave(SceneObjectGroup persistingSo, SceneObjectGroup originalSo)
{
SceneObjectPreSaveDelegate handler = OnSceneObjectPreSave;
if (handler != null)
{
foreach (SceneObjectPreSaveDelegate d in handler.GetInvocationList())
{
try
{
d(persistingSo, originalSo);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPreSave failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
public void TriggerOnSceneObjectPartCopy(SceneObjectPart copy, SceneObjectPart original, bool userExposed)
{
SceneObjectPartCopyDelegate handler = OnSceneObjectPartCopy;
if (handler != null)
{
foreach (SceneObjectPartCopyDelegate d in handler.GetInvocationList())
{
try
{
d(copy, original, userExposed);
}
catch (Exception e)
{
m_log.ErrorFormat(
"[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPartCopy failed - continuing. {0} {1}",
e.Message, e.StackTrace);
}
}
}
}
} }
} }

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
@ -82,6 +82,8 @@ namespace OpenSim.Region.Framework.Scenes
public delegate bool CopyUserInventoryHandler(UUID itemID, UUID userID); public delegate bool CopyUserInventoryHandler(UUID itemID, UUID userID);
public delegate bool DeleteUserInventoryHandler(UUID itemID, UUID userID); public delegate bool DeleteUserInventoryHandler(UUID itemID, UUID userID);
public delegate bool TeleportHandler(UUID userID, Scene scene); public delegate bool TeleportHandler(UUID userID, Scene scene);
public delegate bool ControlPrimMediaHandler(UUID userID, UUID primID, int face);
public delegate bool InteractWithPrimMediaHandler(UUID userID, UUID primID, int face);
#endregion #endregion
public class ScenePermissions public class ScenePermissions
@ -141,6 +143,8 @@ namespace OpenSim.Region.Framework.Scenes
public event CopyUserInventoryHandler OnCopyUserInventory; public event CopyUserInventoryHandler OnCopyUserInventory;
public event DeleteUserInventoryHandler OnDeleteUserInventory; public event DeleteUserInventoryHandler OnDeleteUserInventory;
public event TeleportHandler OnTeleport; public event TeleportHandler OnTeleport;
public event ControlPrimMediaHandler OnControlPrimMedia;
public event InteractWithPrimMediaHandler OnInteractWithPrimMedia;
#endregion #endregion
#region Object Permission Checks #region Object Permission Checks
@ -964,5 +968,35 @@ namespace OpenSim.Region.Framework.Scenes
} }
return true; return true;
} }
public bool CanControlPrimMedia(UUID userID, UUID primID, int face)
{
ControlPrimMediaHandler handler = OnControlPrimMedia;
if (handler != null)
{
Delegate[] list = handler.GetInvocationList();
foreach (ControlPrimMediaHandler h in list)
{
if (h(userID, primID, face) == false)
return false;
}
}
return true;
}
public bool CanInteractWithPrimMedia(UUID userID, UUID primID, int face)
{
InteractWithPrimMediaHandler handler = OnInteractWithPrimMedia;
if (handler != null)
{
Delegate[] list = handler.GetInvocationList();
foreach (InteractWithPrimMediaHandler h in list)
{
if (h(userID, primID, face) == false)
return false;
}
}
return true;
}
} }
} }

View File

@ -1918,9 +1918,11 @@ namespace OpenSim.Region.Framework.Scenes
foreach (SceneObjectGroup group in PrimsFromDB) foreach (SceneObjectGroup group in PrimsFromDB)
{ {
EventManager.TriggerOnSceneObjectLoaded(group);
if (group.RootPart == null) if (group.RootPart == null)
{ {
m_log.ErrorFormat("[SCENE] Found a SceneObjectGroup with m_rootPart == null and {0} children", m_log.ErrorFormat("[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
group.Children == null ? 0 : group.Children.Count); group.Children == null ? 0 : group.Children.Count);
} }

View File

@ -1745,6 +1745,7 @@ namespace OpenSim.Region.Framework.Scenes
backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem; backup_group.RootPart.ParticleSystem = RootPart.ParticleSystem;
HasGroupChanged = false; HasGroupChanged = false;
m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
backup_group.ForEachPart(delegate(SceneObjectPart part) backup_group.ForEachPart(delegate(SceneObjectPart part)
@ -1795,6 +1796,7 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Duplicates this object, including operations such as physics set up and attaching to the backup event. /// Duplicates this object, including operations such as physics set up and attaching to the backup event.
/// </summary> /// </summary>
/// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
/// <returns></returns> /// <returns></returns>
public SceneObjectGroup Copy(bool userExposed) public SceneObjectGroup Copy(bool userExposed)
{ {

View File

@ -59,6 +59,7 @@ namespace OpenSim.Region.Framework.Scenes
REGION = 256, REGION = 256,
TELEPORT = 512, TELEPORT = 512,
REGION_RESTART = 1024, REGION_RESTART = 1024,
MEDIA = 2048,
ANIMATION = 16384 ANIMATION = 16384
} }
@ -331,6 +332,11 @@ namespace OpenSim.Region.Framework.Scenes
protected Vector3 m_lastAngularVelocity; protected Vector3 m_lastAngularVelocity;
protected int m_lastTerseSent; protected int m_lastTerseSent;
/// <summary>
/// Stores media texture data
/// </summary>
protected string m_mediaUrl;
// TODO: Those have to be changed into persistent properties at some later point, // TODO: Those have to be changed into persistent properties at some later point,
// or sit-camera on vehicles will break on sim-crossing. // or sit-camera on vehicles will break on sim-crossing.
private Vector3 m_cameraEyeOffset; private Vector3 m_cameraEyeOffset;
@ -984,12 +990,33 @@ namespace OpenSim.Region.Framework.Scenes
TriggerScriptChangedEvent(Changed.SCALE); TriggerScriptChangedEvent(Changed.SCALE);
} }
} }
public byte UpdateFlag public byte UpdateFlag
{ {
get { return m_updateFlag; } get { return m_updateFlag; }
set { m_updateFlag = value; } set { m_updateFlag = value; }
} }
/// <summary>
/// Used for media on a prim.
/// </summary>
/// Do not change this value directly - always do it through an IMoapModule.
public string MediaUrl
{
get
{
return m_mediaUrl;
}
set
{
m_mediaUrl = value;
if (ParentGroup != null)
ParentGroup.HasGroupChanged = true;
}
}
[XmlIgnore] [XmlIgnore]
public bool CreateSelected public bool CreateSelected
{ {
@ -1553,6 +1580,11 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Duplicates this part. /// Duplicates this part.
/// </summary> /// </summary>
/// <param name="localID"></param>
/// <param name="AgentID"></param>
/// <param name="GroupID"></param>
/// <param name="linkNum"></param>
/// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
/// <returns></returns> /// <returns></returns>
public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
{ {
@ -1616,6 +1648,10 @@ namespace OpenSim.Region.Framework.Scenes
dupe.DoPhysicsPropertyUpdate(UsePhysics, true); dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
} }
ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
return dupe; return dupe;
} }

View File

@ -1059,6 +1059,11 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public void MakeChildAgent() public void MakeChildAgent()
{ {
// It looks like m_animator is set to null somewhere, and MakeChild
// is called after that. Probably in aborted teleports.
if (m_animator == null)
m_animator = new ScenePresenceAnimator(this);
else
Animator.ResetAnimations(); Animator.ResetAnimations();
// m_log.DebugFormat( // m_log.DebugFormat(

View File

@ -2111,7 +2111,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; return;
// Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
LSL_Vector currentPos = llGetLocalPos(); LSL_Vector currentPos = GetPartLocalPos(part);
float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
@ -2144,33 +2144,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Vector llGetLocalPos() public LSL_Vector llGetLocalPos()
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
if (m_host.IsAttachment == true) { return GetPartLocalPos(m_host);
if (m_host.IsRoot == true) }
{
return new LSL_Vector(m_host.AbsolutePosition.X,
m_host.AbsolutePosition.Y,
m_host.AbsolutePosition.Z);
protected LSL_Vector GetPartLocalPos(SceneObjectPart part)
{
m_host.AddScriptLPS(1);
if (part.ParentID != 0)
{
return new LSL_Vector(part.OffsetPosition.X,
part.OffsetPosition.Y,
part.OffsetPosition.Z);
} }
else else
{ {
return new LSL_Vector(m_host.OffsetPosition.X, return new LSL_Vector(part.AbsolutePosition.X,
m_host.OffsetPosition.Y, part.AbsolutePosition.Y,
m_host.OffsetPosition.Z); part.AbsolutePosition.Z);
}
}
if (m_host.ParentID != 0)
{
return new LSL_Vector(m_host.OffsetPosition.X,
m_host.OffsetPosition.Y,
m_host.OffsetPosition.Z);
}
else
{
return new LSL_Vector(m_host.AbsolutePosition.X,
m_host.AbsolutePosition.Y,
m_host.AbsolutePosition.Z);
} }
} }
@ -8300,6 +8290,241 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return res; return res;
} }
public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
{
m_host.AddScriptLPS(1);
ScriptSleep(1000);
// LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid
// TODO: Need to correctly handle case where a face has no media (which gives back an empty list).
// Assuming silently fail means give back an empty list. Ideally, need to check this.
if (face < 0 || face > m_host.GetNumberOfSides() - 1)
return new LSL_List();
return GetPrimMediaParams(face, rules);
}
private LSL_List GetPrimMediaParams(int face, LSL_List rules)
{
IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
if (null == module)
throw new Exception("Media on a prim functions not available");
MediaEntry me = module.GetMediaEntry(m_host, face);
// As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams
if (null == me)
return new LSL_List();
LSL_List res = new LSL_List();
for (int i = 0; i < rules.Length; i++)
{
int code = (int)rules.GetLSLIntegerItem(i);
switch (code)
{
case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
// Not implemented
res.Add(new LSL_Integer(0));
break;
case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
if (me.Controls == MediaControls.Standard)
res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD));
else
res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI));
break;
case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
res.Add(new LSL_String(me.CurrentURL));
break;
case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
res.Add(new LSL_String(me.HomeURL));
break;
case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
break;
case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
break;
case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
break;
case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
break;
case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
break;
case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
res.Add(new LSL_Integer(me.Width));
break;
case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
res.Add(new LSL_Integer(me.Height));
break;
case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
res.Add(me.EnableWhiteList ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
break;
case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
string[] urls = (string[])me.WhiteList.Clone();
for (int j = 0; j < urls.Length; j++)
urls[j] = Uri.EscapeDataString(urls[j]);
res.Add(new LSL_String(string.Join(", ", urls)));
break;
case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
res.Add(new LSL_Integer((int)me.InteractPermissions));
break;
case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
res.Add(new LSL_Integer((int)me.ControlPermissions));
break;
}
}
return res;
}
public LSL_Integer llSetPrimMediaParams(int face, LSL_List rules)
{
m_host.AddScriptLPS(1);
ScriptSleep(1000);
// LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
// Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
// Don't perform the media check directly
if (face < 0 || face > m_host.GetNumberOfSides() - 1)
return ScriptBaseClass.LSL_STATUS_OK;
return SetPrimMediaParams(face, rules);
}
private LSL_Integer SetPrimMediaParams(int face, LSL_List rules)
{
IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
if (null == module)
throw new Exception("Media on a prim functions not available");
MediaEntry me = module.GetMediaEntry(m_host, face);
if (null == me)
me = new MediaEntry();
int i = 0;
while (i < rules.Length - 1)
{
int code = rules.GetLSLIntegerItem(i++);
switch (code)
{
case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0 ? true : false);
break;
case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
int v = rules.GetLSLIntegerItem(i++);
if (ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD == v)
me.Controls = MediaControls.Standard;
else
me.Controls = MediaControls.Mini;
break;
case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
me.CurrentURL = rules.GetLSLStringItem(i++);
break;
case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
me.HomeURL = rules.GetLSLStringItem(i++);
break;
case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
break;
case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
break;
case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
break;
case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
break;
case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
break;
case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
me.Width = (int)rules.GetLSLIntegerItem(i++);
break;
case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
me.Height = (int)rules.GetLSLIntegerItem(i++);
break;
case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
break;
case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new char[] { ',' });
List<string> whiteListUrls = new List<string>();
Array.ForEach(
rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); });
me.WhiteList = whiteListUrls.ToArray();
break;
case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
me.InteractPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
break;
case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
me.ControlPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
break;
}
}
module.SetMediaEntry(m_host, face, me);
return ScriptBaseClass.LSL_STATUS_OK;
}
public LSL_Integer llClearPrimMedia(LSL_Integer face)
{
m_host.AddScriptLPS(1);
ScriptSleep(1000);
// LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid
// Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
// FIXME: Don't perform the media check directly
if (face < 0 || face > m_host.GetNumberOfSides() - 1)
return ScriptBaseClass.LSL_STATUS_OK;
IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
if (null == module)
throw new Exception("Media on a prim functions not available");
module.ClearMediaEntry(m_host, face);
return ScriptBaseClass.LSL_STATUS_OK;
}
// <remarks> // <remarks>
// <para> // <para>
// The .NET definition of base 64 is: // The .NET definition of base 64 is:

View File

@ -1,4 +1,4 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *

View File

@ -62,6 +62,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
void llBreakLink(int linknum); void llBreakLink(int linknum);
LSL_Integer llCeil(double f); LSL_Integer llCeil(double f);
void llClearCameraParams(); void llClearCameraParams();
LSL_Integer llClearPrimMedia(LSL_Integer face);
void llCloseRemoteDataChannel(string channel); void llCloseRemoteDataChannel(string channel);
LSL_Float llCloud(LSL_Vector offset); LSL_Float llCloud(LSL_Vector offset);
void llCollisionFilter(string name, string id, int accept); void llCollisionFilter(string name, string id, int accept);
@ -162,6 +163,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_List llGetParcelPrimOwners(LSL_Vector pos); LSL_List llGetParcelPrimOwners(LSL_Vector pos);
LSL_Integer llGetPermissions(); LSL_Integer llGetPermissions();
LSL_Key llGetPermissionsKey(); LSL_Key llGetPermissionsKey();
LSL_List llGetPrimMediaParams(int face, LSL_List rules);
LSL_Vector llGetPos(); LSL_Vector llGetPos();
LSL_List llGetPrimitiveParams(LSL_List rules); LSL_List llGetPrimitiveParams(LSL_List rules);
LSL_Integer llGetRegionAgentCount(); LSL_Integer llGetRegionAgentCount();
@ -332,6 +334,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
void llSetParcelMusicURL(string url); void llSetParcelMusicURL(string url);
void llSetPayPrice(int price, LSL_List quick_pay_buttons); void llSetPayPrice(int price, LSL_List quick_pay_buttons);
void llSetPos(LSL_Vector pos); void llSetPos(LSL_Vector pos);
LSL_Integer llSetPrimMediaParams(int face, LSL_List rules);
void llSetPrimitiveParams(LSL_List rules); void llSetPrimitiveParams(LSL_List rules);
void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules); void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules);
void llSetPrimURL(string url); void llSetPrimURL(string url);

View File

@ -277,6 +277,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int CHANGED_TELEPORT = 512; public const int CHANGED_TELEPORT = 512;
public const int CHANGED_REGION_RESTART = 1024; public const int CHANGED_REGION_RESTART = 1024;
public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART
public const int CHANGED_MEDIA = 2048;
public const int CHANGED_ANIMATION = 16384; public const int CHANGED_ANIMATION = 16384;
public const int TYPE_INVALID = 0; public const int TYPE_INVALID = 0;
public const int TYPE_INTEGER = 1; public const int TYPE_INTEGER = 1;
@ -519,6 +520,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public static readonly vector TOUCH_INVALID_TEXCOORD = new vector(-1.0, -1.0, 0.0); public static readonly vector TOUCH_INVALID_TEXCOORD = new vector(-1.0, -1.0, 0.0);
public static readonly vector TOUCH_INVALID_VECTOR = ZERO_VECTOR; public static readonly vector TOUCH_INVALID_VECTOR = ZERO_VECTOR;
// constants for llGetPrimMediaParams/llSetPrimMediaParams
public const int PRIM_MEDIA_ALT_IMAGE_ENABLE = 0;
public const int PRIM_MEDIA_CONTROLS = 1;
public const int PRIM_MEDIA_CURRENT_URL = 2;
public const int PRIM_MEDIA_HOME_URL = 3;
public const int PRIM_MEDIA_AUTO_LOOP = 4;
public const int PRIM_MEDIA_AUTO_PLAY = 5;
public const int PRIM_MEDIA_AUTO_SCALE = 6;
public const int PRIM_MEDIA_AUTO_ZOOM = 7;
public const int PRIM_MEDIA_FIRST_CLICK_INTERACT = 8;
public const int PRIM_MEDIA_WIDTH_PIXELS = 9;
public const int PRIM_MEDIA_HEIGHT_PIXELS = 10;
public const int PRIM_MEDIA_WHITELIST_ENABLE = 11;
public const int PRIM_MEDIA_WHITELIST = 12;
public const int PRIM_MEDIA_PERMS_INTERACT = 13;
public const int PRIM_MEDIA_PERMS_CONTROL = 14;
public const int PRIM_MEDIA_CONTROLS_STANDARD = 0;
public const int PRIM_MEDIA_CONTROLS_MINI = 1;
public const int PRIM_MEDIA_PERM_NONE = 0;
public const int PRIM_MEDIA_PERM_OWNER = 1;
public const int PRIM_MEDIA_PERM_GROUP = 2;
public const int PRIM_MEDIA_PERM_ANYONE = 4;
// extra constants for llSetPrimMediaParams
public static readonly LSLInteger LSL_STATUS_OK = new LSLInteger(0);
public static readonly LSLInteger LSL_STATUS_MALFORMED_PARAMS = new LSLInteger(1000);
public static readonly LSLInteger LSL_STATUS_TYPE_MISMATCH = new LSLInteger(1001);
public static readonly LSLInteger LSL_STATUS_BOUNDS_ERROR = new LSLInteger(1002);
public static readonly LSLInteger LSL_STATUS_NOT_FOUND = new LSLInteger(1003);
public static readonly LSLInteger LSL_STATUS_NOT_SUPPORTED = new LSLInteger(1004);
public static readonly LSLInteger LSL_STATUS_INTERNAL_ERROR = new LSLInteger(1999);
public static readonly LSLInteger LSL_STATUS_WHITELIST_FAILED = new LSLInteger(2001);
// Constants for default textures // Constants for default textures
public const string TEXTURE_BLANK = "5748decc-f629-461c-9a36-a35a221fe21f"; public const string TEXTURE_BLANK = "5748decc-f629-461c-9a36-a35a221fe21f";
public const string TEXTURE_DEFAULT = "89556747-24cb-43ed-920b-47caed15465f"; public const string TEXTURE_DEFAULT = "89556747-24cb-43ed-920b-47caed15465f";

View File

@ -1834,5 +1834,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{ {
return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2); return m_LSL_Functions.llXorBase64StringsCorrect(str1, str2);
} }
public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
{
return m_LSL_Functions.llGetPrimMediaParams(face, rules);
}
public LSL_Integer llSetPrimMediaParams(int face, LSL_List rules)
{
return m_LSL_Functions.llSetPrimMediaParams(face, rules);
}
public LSL_Integer llClearPrimMedia(LSL_Integer face)
{
return m_LSL_Functions.llClearPrimMedia(face);
}
} }
} }

View File

@ -358,7 +358,7 @@ namespace OpenSim.Services.Connectors.Hypergrid
private bool GetBoolResponse(XmlRpcRequest request, out string reason) private bool GetBoolResponse(XmlRpcRequest request, out string reason)
{ {
//m_log.Debug("[HGrid]: Linking to " + uri); //m_log.Debug("[USER AGENT CONNECTOR]: GetBoolResponse from/to " + m_ServerURL);
XmlRpcResponse response = null; XmlRpcResponse response = null;
try try
{ {
@ -366,14 +366,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Debug("[USER AGENT CONNECTOR]: Unable to contact remote server "); m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL);
reason = "Exception: " + e.Message; reason = "Exception: " + e.Message;
return false; return false;
} }
if (response.IsFault) if (response.IsFault)
{ {
m_log.ErrorFormat("[HGrid]: remote call returned an error: {0}", response.FaultString); m_log.ErrorFormat("[HGrid]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString);
reason = "XMLRPC Fault"; reason = "XMLRPC Fault";
return false; return false;
} }
@ -383,15 +383,29 @@ namespace OpenSim.Services.Connectors.Hypergrid
// m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value); // m_log.Debug(">> " + ((DictionaryEntry)o).Key + ":" + ((DictionaryEntry)o).Value);
try try
{ {
if (hash == null)
{
m_log.ErrorFormat("[USER AGENT CONNECTOR]: Got null response from {0}! THIS IS BAAAAD", m_ServerURL);
reason = "Internal error 1";
return false;
}
bool success = false; bool success = false;
reason = string.Empty; reason = string.Empty;
if (hash.ContainsKey("result"))
Boolean.TryParse((string)hash["result"], out success); Boolean.TryParse((string)hash["result"], out success);
else
{
reason = "Internal error 2";
m_log.WarnFormat("[USER AGENT CONNECTOR]: response from {0} does not have expected key 'result'", m_ServerURL);
}
return success; return success;
} }
catch (Exception e) catch (Exception e)
{ {
m_log.Error("[HGrid]: Got exception while parsing GetEndPoint response " + e.StackTrace); m_log.ErrorFormat("[HGrid]: Got exception on GetBoolResponse response.");
if (hash.ContainsKey("result") && hash["result"] != null)
m_log.ErrorFormat("Reply was ", (string)hash["result"]);
reason = "Exception: " + e.Message; reason = "Exception: " + e.Message;
return false; return false;
} }

View File

@ -73,7 +73,7 @@ namespace OpenSim.Services.HypergridService
throw new Exception(String.Format("No section GatekeeperService in config file")); throw new Exception(String.Format("No section GatekeeperService in config file"));
string accountService = serverConfig.GetString("UserAccountService", String.Empty); string accountService = serverConfig.GetString("UserAccountService", String.Empty);
string homeUsersService = serverConfig.GetString("HomeUsersSecurityService", string.Empty); string homeUsersService = serverConfig.GetString("UserAgentService", string.Empty);
string gridService = serverConfig.GetString("GridService", String.Empty); string gridService = serverConfig.GetString("GridService", String.Empty);
string presenceService = serverConfig.GetString("PresenceService", String.Empty); string presenceService = serverConfig.GetString("PresenceService", String.Empty);
string simulationService = serverConfig.GetString("SimulationService", String.Empty); string simulationService = serverConfig.GetString("SimulationService", String.Empty);
@ -283,8 +283,12 @@ namespace OpenSim.Services.HypergridService
return false; return false;
} }
if (userURL == m_ExternalName)
return m_UserAgentService.VerifyAgent(aCircuit.SessionID, aCircuit.ServiceSessionID);
else
{
Object[] args = new Object[] { userURL }; Object[] args = new Object[] { userURL };
IUserAgentService userAgentService = new UserAgentServiceConnector(userURL); //ServerUtils.LoadPlugin<IUserAgentService>(m_AuthDll, args); IUserAgentService userAgentService = new UserAgentServiceConnector(userURL);
if (userAgentService != null) if (userAgentService != null)
{ {
try try
@ -297,6 +301,7 @@ namespace OpenSim.Services.HypergridService
return false; return false;
} }
} }
}
return false; return false;
} }

View File

@ -61,9 +61,11 @@ namespace OpenSim.Services.HypergridService
protected static IGridUserService m_GridUserService; protected static IGridUserService m_GridUserService;
protected static IGridService m_GridService; protected static IGridService m_GridService;
//protected static GatekeeperServiceConnector m_GatekeeperConnector; protected static GatekeeperServiceConnector m_GatekeeperConnector;
protected static IGatekeeperService m_GatekeeperService; protected static IGatekeeperService m_GatekeeperService;
protected static string m_GridName;
protected static bool m_BypassClientVerification; protected static bool m_BypassClientVerification;
public UserAgentService(IConfigSource config) public UserAgentService(IConfigSource config)
@ -90,8 +92,15 @@ namespace OpenSim.Services.HypergridService
Object[] args = new Object[] { config }; Object[] args = new Object[] { config };
m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args); m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args); m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(gridUserService, args);
//m_GatekeeperConnector = new GatekeeperServiceConnector(); m_GatekeeperConnector = new GatekeeperServiceConnector();
m_GatekeeperService = ServerUtils.LoadPlugin<IGatekeeperService>(gatekeeperService, args); m_GatekeeperService = ServerUtils.LoadPlugin<IGatekeeperService>(gatekeeperService, args);
m_GridName = serverConfig.GetString("ExternalName", string.Empty);
if (m_GridName == string.Empty)
{
serverConfig = config.Configs["GatekeeperService"];
m_GridName = serverConfig.GetString("ExternalName", string.Empty);
}
} }
} }
@ -139,7 +148,12 @@ namespace OpenSim.Services.HypergridService
TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region); TravelingAgentInfo old = UpdateTravelInfo(agentCircuit, region);
//bool success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out reason); //bool success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out reason);
bool success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason); bool success = false;
string gridName = "http://" + gatekeeper.ExternalHostName + ":" + gatekeeper.HttpPort;
if (m_GridName == gridName)
success = m_GatekeeperService.LoginAgent(agentCircuit, finalDestination, out reason);
else
success = m_GatekeeperConnector.CreateAgent(region, agentCircuit, (uint)Constants.TeleportFlags.ViaLogin, out reason);
if (!success) if (!success)
{ {
@ -179,7 +193,7 @@ namespace OpenSim.Services.HypergridService
m_TravelingAgents[agentCircuit.SessionID] = travel; m_TravelingAgents[agentCircuit.SessionID] = travel;
} }
travel.UserID = agentCircuit.AgentID; travel.UserID = agentCircuit.AgentID;
travel.GridExternalName = region.ExternalHostName + ":" + region.HttpPort; travel.GridExternalName = "http://" + region.ExternalHostName + ":" + region.HttpPort;
travel.ServiceToken = agentCircuit.ServiceSessionID; travel.ServiceToken = agentCircuit.ServiceSessionID;
if (old != null) if (old != null)
travel.ClientToken = old.ClientToken; travel.ClientToken = old.ClientToken;
@ -215,6 +229,7 @@ namespace OpenSim.Services.HypergridService
return false; return false;
TravelingAgentInfo travel = m_TravelingAgents[sessionID]; TravelingAgentInfo travel = m_TravelingAgents[sessionID];
return travel.GridExternalName == thisGridExternalName; return travel.GridExternalName == thisGridExternalName;
} }

View File

@ -241,21 +241,6 @@ namespace OpenSim.Tools.Configger
config.Set("EventQueue", true); config.Set("EventQueue", true);
} }
{
IConfig config = defaultConfig.Configs["Network"];
if (null == config)
config = defaultConfig.AddConfig("Network");
config.Set("default_location_x", 1000);
config.Set("default_location_y", 1000);
config.Set("grid_send_key", "null");
config.Set("grid_recv_key", "null");
config.Set("user_send_key", "null");
config.Set("user_recv_key", "null");
config.Set("secure_inventory_server", "true");
}
return defaultConfig; return defaultConfig;
} }

View File

@ -15,6 +15,67 @@
</summary> </summary>
</member> </member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.DeserializeLLSDNotationElement(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.PeekAndSkipWhitespace(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.ReadAndSkipWhitespace(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.GetLengthInBrackets(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.GetStringDelimitedBy(System.IO.StringReader,System.Char)">
<summary>
</summary>
<param name="reader"></param>
<param name="delimiter"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.BufferCharactersEqual(System.IO.StringReader,System.Char[],System.Int32)">
<summary>
</summary>
<param name="reader"></param>
<param name="buffer"></param>
<param name="offset"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.UnescapeCharacter(System.String,System.Char)">
<summary>
</summary>
<param name="s"></param>
<param name="c"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.EscapeCharacter(System.String,System.Char)">
<summary>
</summary>
<param name="s"></param>
<param name="c"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.DeserializeLLSDBinary(System.Byte[])"> <member name="M:OpenMetaverse.StructuredData.OSDParser.DeserializeLLSDBinary(System.Byte[])">
<summary> <summary>
@ -151,67 +212,6 @@
<param name="reader"></param> <param name="reader"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.DeserializeLLSDNotationElement(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.PeekAndSkipWhitespace(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.ReadAndSkipWhitespace(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.GetLengthInBrackets(System.IO.StringReader)">
<summary>
</summary>
<param name="reader"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.GetStringDelimitedBy(System.IO.StringReader,System.Char)">
<summary>
</summary>
<param name="reader"></param>
<param name="delimiter"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.BufferCharactersEqual(System.IO.StringReader,System.Char[],System.Int32)">
<summary>
</summary>
<param name="reader"></param>
<param name="buffer"></param>
<param name="offset"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.UnescapeCharacter(System.String,System.Char)">
<summary>
</summary>
<param name="s"></param>
<param name="c"></param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.StructuredData.OSDParser.EscapeCharacter(System.String,System.Char)">
<summary>
</summary>
<param name="s"></param>
<param name="c"></param>
<returns></returns>
</member>
<member name="T:OpenMetaverse.StructuredData.OSDType"> <member name="T:OpenMetaverse.StructuredData.OSDType">
<summary> <summary>

Binary file not shown.

View File

@ -1,98 +0,0 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>OpenMetaverse.Utilities</name>
</assembly>
<members>
<member name="F:OpenMetaverse.Utilities.VoiceManager.BlockingTimeout">
<summary>Amount of time to wait for the voice daemon to respond.
The value needs to stay relatively high because some of the calls
require the voice daemon to make remote queries before replying</summary>
</member>
<member name="M:OpenMetaverse.Utilities.VoiceManager.RequestRenderAudioStart(System.String,System.Boolean)">
<summary>
Does not appear to be working
</summary>
<param name="fileName"></param>
<param name="loop"></param>
</member>
<member name="M:OpenMetaverse.RegistrationApi.CreateUser(OpenMetaverse.RegistrationApi.CreateUserParam)">
<summary>
Returns the new user ID or throws an exception containing the error code
The error codes can be found here: https://wiki.secondlife.com/wiki/RegAPIError
</summary>
<param name="user">New user account to create</param>
<returns>The UUID of the new user account</returns>
</member>
<member name="T:OpenMetaverse.RegistrationApi.CreateUserParam">
<summary>
See https://secure-web6.secondlife.com/developers/third_party_reg/#service_create_user or
https://wiki.secondlife.com/wiki/RegAPIDoc for description
</summary>
</member>
<member name="T:OpenMetaverse.Utilities.WaterType">
<summary>
</summary>
</member>
<member name="F:OpenMetaverse.Utilities.WaterType.Unknown">
<summary></summary>
</member>
<member name="F:OpenMetaverse.Utilities.WaterType.Dry">
<summary></summary>
</member>
<member name="F:OpenMetaverse.Utilities.WaterType.Waterfront">
<summary></summary>
</member>
<member name="F:OpenMetaverse.Utilities.WaterType.Underwater">
<summary></summary>
</member>
<member name="M:OpenMetaverse.Utilities.Realism.Shoot(OpenMetaverse.GridClient,OpenMetaverse.Vector3)">
<summary>
Aims at the specified position, enters mouselook, presses and
releases the left mouse button, and leaves mouselook
</summary>
<param name="client"></param>
<param name="target">Target to shoot at</param>
<returns></returns>
</member>
<member name="M:OpenMetaverse.Utilities.Realism.Shoot(OpenMetaverse.GridClient)">
<summary>
Enters mouselook, presses and releases the left mouse button, and leaves mouselook
</summary>
<returns></returns>
</member>
<member name="M:OpenMetaverse.Utilities.Realism.Chat(OpenMetaverse.GridClient,System.String)">
<summary>
A psuedo-realistic chat function that uses the typing sound and
animation, types at three characters per second, and randomly
pauses. This function will block until the message has been sent
</summary>
<param name="client">A reference to the client that will chat</param>
<param name="message">The chat message to send</param>
</member>
<member name="M:OpenMetaverse.Utilities.Realism.Chat(OpenMetaverse.GridClient,System.String,OpenMetaverse.ChatType,System.Int32)">
<summary>
A psuedo-realistic chat function that uses the typing sound and
animation, types at a given rate, and randomly pauses. This
function will block until the message has been sent
</summary>
<param name="client">A reference to the client that will chat</param>
<param name="message">The chat message to send</param>
<param name="type">The chat type (usually Normal, Whisper or Shout)</param>
<param name="cps">Characters per second rate for chatting</param>
</member>
<member name="F:OpenMetaverse.Utilities.VoiceServiceType.Unknown">
<summary>Unknown voice service level</summary>
</member>
<member name="F:OpenMetaverse.Utilities.VoiceServiceType.TypeA">
<summary>Spatialized local chat</summary>
</member>
<member name="F:OpenMetaverse.Utilities.VoiceServiceType.TypeB">
<summary>Remote multi-party chat</summary>
</member>
<member name="F:OpenMetaverse.Utilities.VoiceServiceType.TypeC">
<summary>One-to-one and small group chat</summary>
</member>
</members>
</doc>

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -1267,6 +1267,11 @@ UseSafetyCommit = true
; DefaultAdministratorGroupUUID = ""; ; DefaultAdministratorGroupUUID = "";
; DefaultAdministratorParcelName = ""; ; DefaultAdministratorParcelName = "";
[MediaOnAPrim]
; Enable media on a prim facilities
Enabled = true;
;; ;;
;; These are defaults that are overwritten below in [Architecture]. ;; These are defaults that are overwritten below in [Architecture].
;; These defaults allow OpenSim to work out of the box with ;; These defaults allow OpenSim to work out of the box with

View File

@ -2245,6 +2245,7 @@
<Reference name="OpenSim.Region.Framework"/> <Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenMetaverseTypes.dll"/> <Reference name="OpenMetaverseTypes.dll"/>
<Reference name="OpenMetaverse.dll"/> <Reference name="OpenMetaverse.dll"/>
<Reference name="OpenMetaverse.StructuredData.dll"/>
<Reference name="Mono.Data.Sqlite"/> <Reference name="Mono.Data.Sqlite"/>
<Reference name="Mono.Addins.dll" /> <Reference name="Mono.Addins.dll" />
<Reference name="log4net.dll"/> <Reference name="log4net.dll"/>