OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
UploadObjectAssetModule.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections;
30 using System.Collections.Specialized;
31 using System.Reflection;
32 using System.IO;
33 using System.Web;
34 using Mono.Addins;
35 using log4net;
36 using Nini.Config;
37 using OpenMetaverse;
38 using OpenMetaverse.StructuredData;
39 using OpenMetaverse.Messages.Linden;
40 using OpenSim.Framework;
41 using OpenSim.Framework.Servers;
42 using OpenSim.Framework.Servers.HttpServer;
43 using OpenSim.Region.Framework.Interfaces;
44 using OpenSim.Region.Framework.Scenes;
45 using OpenSim.Services.Interfaces;
49 using OpenSim.Framework.Capabilities;
51 
52 namespace OpenSim.Region.ClientStack.Linden
53 {
54  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UploadObjectAssetModule")]
56  {
57  private static readonly ILog m_log =
58  LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
59  private Scene m_scene;
60 
61  #region Region Module interfaceBase Members
62 
63 
64  public Type ReplaceableInterface
65  {
66  get { return null; }
67  }
68 
69  public void Initialise(IConfigSource source)
70  {
71 
72  }
73 
74  public void AddRegion(Scene pScene)
75  {
76  m_scene = pScene;
77  }
78 
79  public void RemoveRegion(Scene scene)
80  {
81 
82  m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
83  m_scene = null;
84  }
85 
86  public void RegionLoaded(Scene scene)
87  {
88 
89  m_scene.EventManager.OnRegisterCaps += RegisterCaps;
90  }
91 
92  #endregion
93 
94 
95  #region Region Module interface
96 
97 
98 
99  public void Close() { }
100 
101  public string Name { get { return "UploadObjectAssetModuleModule"; } }
102 
103 
104  public void RegisterCaps(UUID agentID, Caps caps)
105  {
106  UUID capID = UUID.Random();
107 
108 // m_log.Debug("[UPLOAD OBJECT ASSET MODULE]: /CAPS/" + capID);
109  caps.RegisterHandler(
110  "UploadObjectAsset",
111  new RestHTTPHandler(
112  "POST",
113  "/CAPS/OA/" + capID + "/",
114  httpMethod => ProcessAdd(httpMethod, agentID, caps),
115  "UploadObjectAsset",
116  agentID.ToString()));
117 
118  /*
119  caps.RegisterHandler("NewFileAgentInventoryVariablePrice",
120 
121  new LLSDStreamhandler<LLSDAssetUploadRequest, LLSDNewFileAngentInventoryVariablePriceReplyResponse>("POST",
122  "/CAPS/" + capID.ToString(),
123  delegate(LLSDAssetUploadRequest req)
124  {
125  return NewAgentInventoryRequest(req,agentID);
126  }));
127  */
128 
129  }
130 
131  #endregion
132 
133 
141  public Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap)
142  {
143  Hashtable responsedata = new Hashtable();
144  responsedata["int_response_code"] = 400; //501; //410; //404;
145  responsedata["content_type"] = "text/plain";
146  responsedata["keepalive"] = false;
147  responsedata["str_response_string"] = "Request wasn't what was expected";
148  ScenePresence avatar;
149 
150  if (!m_scene.TryGetScenePresence(AgentId, out avatar))
151  return responsedata;
152 
153  OSDMap r = (OSDMap)OSDParser.Deserialize((string)request["requestbody"]);
154  UploadObjectAssetMessage message = new UploadObjectAssetMessage();
155  try
156  {
157  message.Deserialize(r);
158 
159  }
160  catch (Exception ex)
161  {
162  m_log.Error("[UPLOAD OBJECT ASSET MODULE]: Error deserializing message " + ex.ToString());
163  message = null;
164  }
165 
166  if (message == null)
167  {
168  responsedata["int_response_code"] = 400; //501; //410; //404;
169  responsedata["content_type"] = "text/plain";
170  responsedata["keepalive"] = false;
171  responsedata["str_response_string"] =
172  "<llsd><map><key>error</key><string>Error parsing Object</string></map></llsd>";
173 
174  return responsedata;
175  }
176 
177  Vector3 pos = avatar.AbsolutePosition + (Vector3.UnitX * avatar.Rotation);
178  Quaternion rot = Quaternion.Identity;
179  Vector3 rootpos = Vector3.Zero;
180 // Quaternion rootrot = Quaternion.Identity;
181 
182  SceneObjectGroup rootGroup = null;
183  SceneObjectGroup[] allparts = new SceneObjectGroup[message.Objects.Length];
184  for (int i = 0; i < message.Objects.Length; i++)
185  {
186  UploadObjectAssetMessage.Object obj = message.Objects[i];
187  PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox();
188 
189  if (i == 0)
190  {
191  rootpos = obj.Position;
192 // rootrot = obj.Rotation;
193  }
194 
195  // Combine the extraparams data into it's ugly blob again....
196  //int bytelength = 0;
197  //for (int extparams = 0; extparams < obj.ExtraParams.Length; extparams++)
198  //{
199  // bytelength += obj.ExtraParams[extparams].ExtraParamData.Length;
200  //}
201  //byte[] extraparams = new byte[bytelength];
202  //int position = 0;
203 
204 
205 
206  //for (int extparams = 0; extparams < obj.ExtraParams.Length; extparams++)
207  //{
208  // Buffer.BlockCopy(obj.ExtraParams[extparams].ExtraParamData, 0, extraparams, position,
209  // obj.ExtraParams[extparams].ExtraParamData.Length);
210  //
211  // position += obj.ExtraParams[extparams].ExtraParamData.Length;
212  // }
213 
214  //pbs.ExtraParams = extraparams;
215  for (int extparams = 0; extparams < obj.ExtraParams.Length; extparams++)
216  {
217  UploadObjectAssetMessage.Object.ExtraParam extraParam = obj.ExtraParams[extparams];
218  switch ((ushort)extraParam.Type)
219  {
220  case (ushort)ExtraParamType.Sculpt:
221  Primitive.SculptData sculpt = new Primitive.SculptData(extraParam.ExtraParamData, 0);
222 
223  pbs.SculptEntry = true;
224 
225  pbs.SculptTexture = obj.SculptID;
226  pbs.SculptType = (byte)sculpt.Type;
227 
228  break;
229  case (ushort)ExtraParamType.Flexible:
230  Primitive.FlexibleData flex = new Primitive.FlexibleData(extraParam.ExtraParamData, 0);
231  pbs.FlexiEntry = true;
232  pbs.FlexiDrag = flex.Drag;
233  pbs.FlexiForceX = flex.Force.X;
234  pbs.FlexiForceY = flex.Force.Y;
235  pbs.FlexiForceZ = flex.Force.Z;
236  pbs.FlexiGravity = flex.Gravity;
237  pbs.FlexiSoftness = flex.Softness;
238  pbs.FlexiTension = flex.Tension;
239  pbs.FlexiWind = flex.Wind;
240  break;
241  case (ushort)ExtraParamType.Light:
242  Primitive.LightData light = new Primitive.LightData(extraParam.ExtraParamData, 0);
243  pbs.LightColorA = light.Color.A;
244  pbs.LightColorB = light.Color.B;
245  pbs.LightColorG = light.Color.G;
246  pbs.LightColorR = light.Color.R;
247  pbs.LightCutoff = light.Cutoff;
248  pbs.LightEntry = true;
249  pbs.LightFalloff = light.Falloff;
250  pbs.LightIntensity = light.Intensity;
251  pbs.LightRadius = light.Radius;
252  break;
253  case 0x40:
254  pbs.ReadProjectionData(extraParam.ExtraParamData, 0);
255  break;
256  }
257  }
258 
259  pbs.PathBegin = (ushort) obj.PathBegin;
260  pbs.PathCurve = (byte) obj.PathCurve;
261  pbs.PathEnd = (ushort) obj.PathEnd;
262  pbs.PathRadiusOffset = (sbyte) obj.RadiusOffset;
263  pbs.PathRevolutions = (byte) obj.Revolutions;
264  pbs.PathScaleX = (byte) obj.ScaleX;
265  pbs.PathScaleY = (byte) obj.ScaleY;
266  pbs.PathShearX = (byte) obj.ShearX;
267  pbs.PathShearY = (byte) obj.ShearY;
268  pbs.PathSkew = (sbyte) obj.Skew;
269  pbs.PathTaperX = (sbyte) obj.TaperX;
270  pbs.PathTaperY = (sbyte) obj.TaperY;
271  pbs.PathTwist = (sbyte) obj.Twist;
272  pbs.PathTwistBegin = (sbyte) obj.TwistBegin;
273  pbs.HollowShape = (HollowShape) obj.ProfileHollow;
274  pbs.PCode = (byte) PCode.Prim;
275  pbs.ProfileBegin = (ushort) obj.ProfileBegin;
276  pbs.ProfileCurve = (byte) obj.ProfileCurve;
277  pbs.ProfileEnd = (ushort) obj.ProfileEnd;
278  pbs.Scale = obj.Scale;
279  pbs.State = (byte) 0;
280  pbs.LastAttachPoint = (byte) 0;
282  prim.UUID = UUID.Random();
283  prim.CreatorID = AgentId;
284  prim.OwnerID = AgentId;
285  prim.GroupID = obj.GroupID;
286  prim.LastOwnerID = prim.OwnerID;
287  prim.CreationDate = Util.UnixTimeSinceEpoch();
288  prim.Name = obj.Name;
289  prim.Description = "";
290 
291  prim.PayPrice[0] = -2;
292  prim.PayPrice[1] = -2;
293  prim.PayPrice[2] = -2;
294  prim.PayPrice[3] = -2;
295  prim.PayPrice[4] = -2;
296  Primitive.TextureEntry tmp =
297  new Primitive.TextureEntry(UUID.Parse("89556747-24cb-43ed-920b-47caed15465f"));
298 
299  for (int j = 0; j < obj.Faces.Length; j++)
300  {
301  UploadObjectAssetMessage.Object.Face face = obj.Faces[j];
302 
303  Primitive.TextureEntryFace primFace = tmp.CreateFace((uint) j);
304 
305  primFace.Bump = face.Bump;
306  primFace.RGBA = face.Color;
307  primFace.Fullbright = face.Fullbright;
308  primFace.Glow = face.Glow;
309  primFace.TextureID = face.ImageID;
310  primFace.Rotation = face.ImageRot;
311  primFace.MediaFlags = ((face.MediaFlags & 1) != 0);
312 
313  primFace.OffsetU = face.OffsetS;
314  primFace.OffsetV = face.OffsetT;
315  primFace.RepeatU = face.ScaleS;
316  primFace.RepeatV = face.ScaleT;
317  primFace.TexMapType = (MappingType) (face.MediaFlags & 6);
318  }
319 
320  pbs.TextureEntry = tmp.GetBytes();
321  prim.Shape = pbs;
322  prim.Scale = obj.Scale;
323 
325 
326  grp.SetRootPart(prim);
327  prim.ParentID = 0;
328  if (i == 0)
329  {
330  rootGroup = grp;
331 
332  }
333  grp.AttachToScene(m_scene);
334  grp.AbsolutePosition = obj.Position;
335  prim.RotationOffset = obj.Rotation;
336 
337  // Required for linking
338  grp.RootPart.ClearUpdateSchedule();
339 
340  if (m_scene.Permissions.CanRezObject(1, avatar.UUID, pos))
341  {
342  m_scene.AddSceneObject(grp);
343  grp.AbsolutePosition = obj.Position;
344  }
345 
346  allparts[i] = grp;
347  }
348 
349  for (int j = 1; j < allparts.Length; j++)
350  {
351  // Required for linking
352  rootGroup.RootPart.ClearUpdateSchedule();
353  allparts[j].RootPart.ClearUpdateSchedule();
354  rootGroup.LinkToGroup(allparts[j]);
355  }
356 
357  rootGroup.ScheduleGroupForFullUpdate();
358  pos
359  = m_scene.GetNewRezLocation(
360  Vector3.Zero, rootpos, UUID.Zero, rot, (byte)1, 1, true, allparts[0].GroupScale, false);
361 
362  responsedata["int_response_code"] = 200; //501; //410; //404;
363  responsedata["content_type"] = "text/plain";
364  responsedata["keepalive"] = false;
365  responsedata["str_response_string"] = String.Format("<llsd><map><key>local_id</key>{0}</map></llsd>", ConvertUintToBytes(allparts[0].LocalId));
366 
367  return responsedata;
368  }
369 
370  private string ConvertUintToBytes(uint val)
371  {
372  byte[] resultbytes = Utils.UIntToBytes(val);
373  if (BitConverter.IsLittleEndian)
374  Array.Reverse(resultbytes);
375  return String.Format("<binary encoding=\"base64\">{0}</binary>", Convert.ToBase64String(resultbytes));
376  }
377  }
378 }
A scene object group is conceptually an object in the scene. The object is constituted of SceneObject...
Hashtable ProcessAdd(Hashtable request, UUID AgentId, Caps cap)
Parses add request
OpenMetaverse.StructuredData.OSDMap OSDMap
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
OpenMetaverse.StructuredData.OSD OSD
OpenMetaverse.ExtraParamType ExtraParamType
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
void Initialise(IConfigSource source)
This is called to initialize the region module. For shared modules, this is called exactly once...
OpenSim.Framework.Capabilities.Caps Caps
void AddRegion(Scene pScene)
This is called whenever a Scene is added. For shared modules, this can happen several times...