aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/ApplicationPlugins
diff options
context:
space:
mode:
authorDr Scofield2009-05-07 12:33:53 +0000
committerDr Scofield2009-05-07 12:33:53 +0000
commit547f883f745ee17b4dbadc19bad6a4327672990d (patch)
tree18628ee779f533e58f55a16f01cd0977db9a86e1 /OpenSim/ApplicationPlugins
parentChange avatar updates to be processed the same way object updates are, e.g. (diff)
downloadopensim-SC_OLD-547f883f745ee17b4dbadc19bad6a4327672990d.zip
opensim-SC_OLD-547f883f745ee17b4dbadc19bad6a4327672990d.tar.gz
opensim-SC_OLD-547f883f745ee17b4dbadc19bad6a4327672990d.tar.bz2
opensim-SC_OLD-547f883f745ee17b4dbadc19bad6a4327672990d.tar.xz
From: Alan M Webb <alan_webb@us.ibm.com>
This update implements support for creation of one or more default avatars from information contained in a file default_appearance.xml. Each avatar may have any number of "outfits" with each outfit representing a different ensemble. The default avatars get created the first time the RemoteAdmin interface is used to define a user. I've tested this quite a bit, but it will benefit from lost of attention, I'm sure.
Diffstat (limited to '')
-rw-r--r--OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs779
1 files changed, 673 insertions, 106 deletions
diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
index 1daa07f..b508c5c 100644
--- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Xml;
32using System.Net; 33using System.Net;
33using System.Reflection; 34using System.Reflection;
34using System.Timers; 35using System.Timers;
@@ -38,6 +39,7 @@ using Nwc.XmlRpc;
38using OpenMetaverse; 39using OpenMetaverse;
39using OpenSim; 40using OpenSim;
40using OpenSim.Framework; 41using OpenSim.Framework;
42using OpenSim.Framework.Communications;
41using OpenSim.Framework.Communications.Cache; 43using OpenSim.Framework.Communications.Cache;
42using OpenSim.Framework.Console; 44using OpenSim.Framework.Console;
43using OpenSim.Framework.Servers; 45using OpenSim.Framework.Servers;
@@ -52,6 +54,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
52 { 54 {
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 56
57 private static bool daload = false;
55 private static Object rslock = new Object(); 58 private static Object rslock = new Object();
56 59
57 private OpenSimBase m_app; 60 private OpenSimBase m_app;
@@ -60,7 +63,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
60 private IConfigSource m_configSource; 63 private IConfigSource m_configSource;
61 private string m_requiredPassword = String.Empty; 64 private string m_requiredPassword = String.Empty;
62 65
63 // TODO: required by IPlugin, but likely not at all right
64 private string m_name = "RemoteAdminPlugin"; 66 private string m_name = "RemoteAdminPlugin";
65 private string m_version = "0.0"; 67 private string m_version = "0.0";
66 68
@@ -80,7 +82,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
80 throw new PluginNotInitialisedException(Name); 82 throw new PluginNotInitialisedException(Name);
81 } 83 }
82 84
83
84 public void Initialise(OpenSimBase openSim) 85 public void Initialise(OpenSimBase openSim)
85 { 86 {
86 m_configSource = openSim.ConfigSource.Source; 87 m_configSource = openSim.ConfigSource.Source;
@@ -387,52 +388,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
387 m_app.Shutdown(); 388 m_app.Shutdown();
388 } 389 }
389 390
390
391 private static void checkStringParameters(XmlRpcRequest request, string[] param)
392 {
393 Hashtable requestData = (Hashtable) request.Params[0];
394 foreach (string p in param)
395 {
396 if (!requestData.Contains(p))
397 throw new Exception(String.Format("missing string parameter {0}", p));
398 if (String.IsNullOrEmpty((string) requestData[p]))
399 throw new Exception(String.Format("parameter {0} is empty", p));
400 }
401 }
402
403 private static void checkIntegerParams(XmlRpcRequest request, string[] param)
404 {
405 Hashtable requestData = (Hashtable) request.Params[0];
406 foreach (string p in param)
407 {
408 if (!requestData.Contains(p))
409 throw new Exception(String.Format("missing integer parameter {0}", p));
410 }
411 }
412
413 private bool getBoolean(Hashtable requestData, string tag, bool defv)
414 {
415 // If an access value has been provided, apply it.
416 if (requestData.Contains(tag))
417 {
418 switch (((string)requestData[tag]).ToLower())
419 {
420 case "true" :
421 case "t" :
422 case "1" :
423 return true;
424 case "false" :
425 case "f" :
426 case "0" :
427 return false;
428 default :
429 return defv;
430 }
431 }
432 else
433 return defv;
434 }
435
436 /// <summary> 391 /// <summary>
437 /// Create a new region. 392 /// Create a new region.
438 /// <summary> 393 /// <summary>
@@ -523,7 +478,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController
523 if (m_regionLimit != 0 && m_app.SceneManager.Scenes.Count >= m_regionLimit) 478 if (m_regionLimit != 0 && m_app.SceneManager.Scenes.Count >= m_regionLimit)
524 throw new Exception(String.Format("cannot instantiate new region, server capacity {0} already reached; delete regions first", 479 throw new Exception(String.Format("cannot instantiate new region, server capacity {0} already reached; delete regions first",
525 m_regionLimit)); 480 m_regionLimit));
526
527 // extract or generate region ID now 481 // extract or generate region ID now
528 Scene scene = null; 482 Scene scene = null;
529 UUID regionID = UUID.Zero; 483 UUID regionID = UUID.Zero;
@@ -949,31 +903,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController
949 throw new Exception(String.Format("failed to create new user {0} {1}", 903 throw new Exception(String.Format("failed to create new user {0} {1}",
950 firstname, lastname)); 904 firstname, lastname));
951 905
952 // User has been created. Now establish gender and appearance. 906 // Establish the avatar's initial appearance
953 // Default appearance is 'Default Male'. Specifying gender can
954 // establish "Default Female". Specifying a specific model can
955 // establish a specific appearance without regard for gender.
956
957 try
958 {
959 string model = "Default Male";
960 if (requestData.Contains("gender"))
961 if ((string)requestData["gender"] == "f")
962 model = "Default Female";
963
964 if (requestData.Contains("model"))
965 model = (string)requestData["model"];
966
967 string[] uname = model.Split();
968 UserProfileData udata = m_app.CommunicationsManager.UserService.GetUserProfile(uname[0],uname[1]);
969 AvatarAppearance ava = m_app.CommunicationsManager.AvatarService.GetUserAppearance(udata.ID);
970 m_app.CommunicationsManager.AvatarService.UpdateUserAppearance(userID, ava);
971 907
972 } 908 updateUserAppearance(responseData, requestData, userID);
973 catch (Exception e)
974 {
975 m_log.ErrorFormat("[RADMIN] Error establishing initial appearance : {0}", e.Message);
976 }
977 909
978 responseData["success"] = "true"; 910 responseData["success"] = "true";
979 responseData["avatar_uuid"] = userID.ToString(); 911 responseData["avatar_uuid"] = userID.ToString();
@@ -1110,6 +1042,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1110 /// <description>error message if success is false</description></item> 1042 /// <description>error message if success is false</description></item>
1111 /// </list> 1043 /// </list>
1112 /// </remarks> 1044 /// </remarks>
1045
1113 public XmlRpcResponse XmlRpcUpdateUserAccountMethod(XmlRpcRequest request) 1046 public XmlRpcResponse XmlRpcUpdateUserAccountMethod(XmlRpcRequest request)
1114 { 1047 {
1115 m_log.Info("[RADMIN]: UpdateUserAccount: new request"); 1048 m_log.Info("[RADMIN]: UpdateUserAccount: new request");
@@ -1202,32 +1135,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1202 // establish "Default Female". Specifying a specific model can 1135 // establish "Default Female". Specifying a specific model can
1203 // establish a specific appearance without regard for gender. 1136 // establish a specific appearance without regard for gender.
1204 1137
1205 try 1138 updateUserAppearance(responseData, requestData, userProfile.ID);
1206 {
1207 string model = "*none*";
1208 if (requestData.Contains("gender"))
1209 {
1210 if ((string)requestData["gender"] == "f")
1211 model = "Default Female";
1212 else
1213 model = "Default Male";
1214 }
1215
1216 if (requestData.Contains("model"))
1217 model = (string)requestData["model"];
1218
1219 if (model != "*none*")
1220 {
1221 string[] uname = model.Split();
1222 UserProfileData udata = m_app.CommunicationsManager.UserService.GetUserProfile(uname[0],uname[1]);
1223 AvatarAppearance ava = m_app.CommunicationsManager.AvatarService.GetUserAppearance(udata.ID);
1224 m_app.CommunicationsManager.AvatarService.UpdateUserAppearance(userProfile.ID, ava);
1225 }
1226 }
1227 catch (Exception e)
1228 {
1229 m_log.ErrorFormat("[RADMIN] Error establishing initial appearance : {0}", e.Message);
1230 }
1231 1139
1232 if (!m_app.CommunicationsManager.UserService.UpdateUserProfile(userProfile)) 1140 if (!m_app.CommunicationsManager.UserService.UpdateUserProfile(userProfile))
1233 throw new Exception("did not manage to update user profile"); 1141 throw new Exception("did not manage to update user profile");
@@ -1257,6 +1165,510 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1257 } 1165 }
1258 1166
1259 /// <summary> 1167 /// <summary>
1168 /// This method is called by the user-create and user-modify methods to establish
1169 /// or change, the user's appearance. Default avatar names can be specified via
1170 /// the config file, but must correspond to avatars in the default appearance
1171 /// file, or pre-existing in the user database.
1172 /// This should probably get moved into somewhere more core eventually.
1173 /// </summary>
1174
1175 private void updateUserAppearance(Hashtable responseData, Hashtable requestData, UUID userid)
1176 {
1177
1178 m_log.DebugFormat("[RADMIN] updateUserAppearance");
1179
1180 string dmale = m_config.GetString("default_male", "Default Male");
1181 string dfemale = m_config.GetString("default_female", "Default Female");
1182 string dneut = m_config.GetString("default_female", "Default Default");
1183 string dmodel = dneut;
1184 string model = dneut;
1185
1186 // Has a gender preference been supplied?
1187
1188 if (requestData.Contains("gender"))
1189 {
1190 if ((string)requestData["gender"] == "f")
1191 dmodel = dmale;
1192 else
1193 dmodel = dfemale;
1194 }
1195 else
1196 dmodel = dneut;
1197
1198 // Has an explicit model been specified?
1199
1200 if (requestData.Contains("model"))
1201 model = (string)requestData["model"];
1202 else
1203 model = dmodel;
1204
1205 m_log.DebugFormat("[RADMIN] Setting appearance for avatar {0}, using model {1}", userid, model);
1206
1207 string[] nomens = model.Split();
1208 if (nomens.Length != 2)
1209 {
1210 m_log.WarnFormat("[RADMIN] User appearance not set for {0}. Invalid model name : <{1}>",
1211 userid, model);
1212 nomens = dmodel.Split();
1213 }
1214
1215 UserProfileData mprof = m_app.CommunicationsManager.UserService.GetUserProfile(nomens[0], nomens[1]);
1216
1217 // Is this the first time one of the default models has been used? Create it if that is the case
1218 // otherwise default to male.
1219
1220 if (mprof == null)
1221 {
1222 if(model != dmale && model != dfemale)
1223 {
1224 m_log.WarnFormat("[RADMIN] Requested model ({0}) not found. Default appearance assumed",
1225 model);
1226 nomens = dmodel.Split();
1227 }
1228 if (createDefaultAvatars())
1229 {
1230 mprof = m_app.CommunicationsManager.UserService.GetUserProfile(nomens[0], nomens[1]);
1231 }
1232 }
1233
1234 if (mprof == null)
1235 {
1236 m_log.WarnFormat("[RADMIN] User appearance not set for {0}. Model avatar not found : <{1}>",
1237 userid, model);
1238 }
1239 else
1240 {
1241
1242 // Set current user's appearance. This bit is easy. The appearance structure is populated with
1243 // actual asset ids, however to complete the magic we need to populate the inventory with the
1244 // assets in question.
1245
1246 establishAppearance(userid, mprof.ID);
1247
1248 }
1249
1250 m_log.DebugFormat("[RADMIN] Finished setting appearance for avatar {0}, using model {1}",
1251 userid, model);
1252
1253 }
1254
1255 /// <summary>
1256 /// This method is called by updateAvatarAppearance once any specified model has been
1257 /// ratified, or an appropriate default value has been adopted. The intended prototype
1258 /// is known to exist, as is the target avatar.
1259 /// </summary>
1260
1261 private AvatarAppearance establishAppearance(UUID dest, UUID srca)
1262 {
1263
1264 m_log.DebugFormat("[RADMIN] Initializing inventory for {0} from {1}", dest, srca);
1265
1266 AvatarAppearance ava = m_app.CommunicationsManager.AvatarService.GetUserAppearance(srca);
1267
1268 // If the model has no associated appearance we're done.
1269
1270 if (ava == null)
1271 {
1272 return new AvatarAppearance();
1273 }
1274
1275 UICallback sic = new UICallback();
1276 UICallback dic = new UICallback();
1277 IInventoryServices iserv = m_app.CommunicationsManager.InventoryService;
1278
1279 try
1280 {
1281 Dictionary<UUID,UUID> imap = new Dictionary<UUID,UUID>();
1282
1283 iserv.RequestInventoryForUser(dest, dic.callback);
1284 iserv.RequestInventoryForUser(srca, sic.callback);
1285
1286 dic.GetInventory();
1287 sic.GetInventory();
1288
1289 if (sic.OK && dic.OK)
1290 {
1291
1292 InventoryFolderImpl efolder;
1293 InventoryFolderImpl srcf = sic.root.FindFolderForType(5);
1294 InventoryFolderImpl dstf = dic.root.FindFolderForType(5);
1295
1296 if (srcf == null || dstf == null)
1297 throw new Exception("Cannot locate clothing folder(s)");
1298
1299 foreach (InventoryFolderImpl folder in sic.folders)
1300 {
1301 if (folder.ParentID == srcf.ID)
1302 {
1303 efolder = new InventoryFolderImpl();
1304 efolder.ID = UUID.Random();
1305 efolder.Name = folder.Name;
1306 efolder.Type = folder.Type;
1307 efolder.Version = folder.Version;
1308 efolder.Owner = dest;
1309 dstf.AddChildFolder(efolder);
1310 iserv.AddFolder(efolder);
1311 m_log.DebugFormat("[RADMIN] Added outfile folder {0} to folder {1}", efolder.ID, srcf.ID);
1312 foreach (InventoryItemBase item in sic.items)
1313 {
1314 if (item.Folder == folder.ID)
1315 {
1316 InventoryItemBase dsti = new InventoryItemBase();
1317 dsti.ID = UUID.Random();
1318 dsti.Name = item.Name;
1319 dsti.Description = item.Description;
1320 dsti.InvType = item.InvType;
1321 dsti.AssetType = item.AssetType;
1322 dsti.Flags = item.Flags;
1323 dsti.AssetID = item.AssetID;
1324 dsti.Folder = efolder.ID;
1325 dsti.Owner = dest;
1326 dsti.BasePermissions = item.BasePermissions;
1327 dsti.NextPermissions = item.NextPermissions;
1328 dsti.CurrentPermissions = item.CurrentPermissions;
1329 dsti.GroupPermissions = item.GroupPermissions;
1330 dsti.EveryOnePermissions = item.EveryOnePermissions;
1331 iserv.AddItem(dsti);
1332 imap.Add(item.ID, dsti.ID);
1333 m_log.DebugFormat("[RADMIN] Added item {0} to folder {1}", dsti.ID, efolder.ID);
1334 }
1335 }
1336 }
1337 }
1338
1339 // Update appearance tables
1340 AvatarWearable[] wearables = ava.Wearables;
1341 for (int i=0; i<wearables.Length; i++)
1342 {
1343 if (imap.ContainsKey(wearables[i].ItemID))
1344 {
1345 AvatarWearable dw = new AvatarWearable();
1346 dw.AssetID = wearables[i].AssetID;
1347 dw.ItemID = imap[wearables[i].ItemID];
1348 ava.SetWearable(i, dw);
1349 }
1350 }
1351
1352 }
1353 else
1354 {
1355 throw new Exception("Unable to load both inventories");
1356 }
1357 }
1358 catch (Exception e)
1359 {
1360 m_log.WarnFormat("[RADMIN] Error transferring inventory for {0} : {1}",
1361 dest, e.Message);
1362 return new AvatarAppearance();
1363 }
1364
1365 m_app.CommunicationsManager.AvatarService.UpdateUserAppearance(dest, ava);
1366 return ava;
1367
1368 }
1369
1370 ///<summary>
1371 /// This method is called if a given model avatar name can not be found. If the external
1372 /// file has already been loaded once, then control returns immediately. If not, then it
1373 /// looks for a default appearance file. This file contains XML definitions of zero or more named
1374 /// avatars, each avatar can specify zero or more "outfits". Each outfit is a collection
1375 /// of items that together, define a particular ensemble for the avatar. Each avatar should
1376 /// indicate which outfit is the default, and this outfit will be automatically worn. The
1377 /// other outfits are provided to allow "real" avatars a way to easily change their outfits.
1378 /// </summary>
1379
1380 private bool createDefaultAvatars()
1381 {
1382
1383 m_log.DebugFormat("[RADMIN] Creating default avatar entries");
1384
1385 // Only load once
1386
1387 if (daload)
1388 {
1389 return false;
1390 }
1391
1392 daload = true;
1393
1394 // Load processing starts here...
1395
1396 try
1397 {
1398
1399 string dafn = m_config.GetString("default_appearance", "default_appearance.xml");
1400
1401 if (File.Exists(dafn))
1402 {
1403
1404 XmlDocument doc = new XmlDocument();
1405 string name = "*unknown*";
1406 string email = "anon@anon";
1407 uint regX = 1000;
1408 uint regY = 1000;
1409 string passwd = UUID.Random().ToString(); // No requirement to sign-in.
1410 CachedUserInfo UI;
1411 UUID ID = UUID.Zero;
1412 AvatarAppearance mava;
1413 XmlNodeList avatars;
1414 XmlNodeList assets;
1415 XmlNode perms = null;
1416 bool include = false;
1417 bool select = false;
1418
1419 UICallback uic;
1420 IInventoryServices iserv = m_app.CommunicationsManager.InventoryService;
1421 IAssetCache aserv = m_app.CommunicationsManager.AssetCache;
1422
1423 doc.LoadXml(File.ReadAllText(dafn));
1424
1425 // Load up any included assets. Duplicates will be ignored
1426 assets = doc.GetElementsByTagName("RequiredAsset");
1427 foreach(XmlNode asset in assets)
1428 {
1429 AssetBase rass = new AssetBase();
1430 rass.FullID = UUID.Random();
1431 rass.Name = GetStringAttribute(asset,"name","");
1432 rass.Description = GetStringAttribute(asset,"desc","");
1433 rass.Type = SByte.Parse(GetStringAttribute(asset,"type",""));
1434 rass.Local = Boolean.Parse(GetStringAttribute(asset,"local",""));
1435 rass.Temporary = Boolean.Parse(GetStringAttribute(asset,"temporary",""));
1436 rass.Data = Convert.FromBase64String(asset.InnerText);
1437 aserv.AddAsset(rass);
1438 }
1439
1440 avatars = doc.GetElementsByTagName("Avatar");
1441
1442 // The document may contain multiple avatars
1443
1444 foreach (XmlElement avatar in avatars)
1445 {
1446 m_log.DebugFormat("[RADMIN] Loading appearance for {0}, gender = {1}",
1447 GetStringAttribute(avatar,"name","?"), GetStringAttribute(avatar,"gender","?"));
1448
1449 // Create the user identified by the avatar entry
1450
1451 try
1452 {
1453 // Only the name value is mandatory
1454 name = GetStringAttribute(avatar,"name",name);
1455 email = GetStringAttribute(avatar,"email",email);
1456 regX = GetUnsignedAttribute(avatar,"regx",regX);
1457 regY = GetUnsignedAttribute(avatar,"regy",regY);
1458 passwd = GetStringAttribute(avatar,"password",passwd);
1459
1460 string[] nomens = name.Split();
1461 UI = m_app.CommunicationsManager.UserProfileCacheService.GetUserDetails(nomens[0], nomens[1]);
1462 if (null == UI)
1463 {
1464 ID = m_app.CommunicationsManager.UserAdminService.AddUser(nomens[0], nomens[1],
1465 passwd, email, regX, regY);
1466 if (ID == UUID.Zero)
1467 {
1468 m_log.ErrorFormat("[RADMIN] Avatar {0} {1} was not created", nomens[0], nomens[1]);
1469 return false;
1470 }
1471 }
1472 else
1473 {
1474 ID = UI.UserProfile.ID;
1475 }
1476
1477 m_log.DebugFormat("[RADMIN] User {0}[{1}] created or retrieved", name, ID);
1478 include = true;
1479 }
1480 catch (Exception e)
1481 {
1482 m_log.DebugFormat("[RADMIN] Error creating user {0} : {1}", name, e.Message);
1483 include = false;
1484 }
1485
1486 // OK, User has been created OK, now we can install the inventory.
1487 // First retrieve the current inventory (the user may already exist)
1488 // Note that althought he inventory is retrieved, the hierarchy has
1489 // not been interpreted at all.
1490
1491 if (include)
1492 {
1493 uic = new UICallback();
1494 // Request the inventory
1495 iserv.RequestInventoryForUser(ID, uic.callback);
1496
1497 // While the inventory is being fetched, setup for appearance processing
1498 if ((mava = m_app.CommunicationsManager.AvatarService.GetUserAppearance(ID)) == null)
1499 {
1500 mava = new AvatarAppearance();
1501 }
1502
1503 {
1504 AvatarWearable[] wearables = mava.Wearables;
1505 for (int i=0; i<wearables.Length; i++)
1506 {
1507 wearables[i] = new AvatarWearable();
1508 }
1509 }
1510
1511 // Wait for the inventory to arrive
1512 uic.GetInventory();
1513
1514 // We can only get dresssed if an inventory is forthcoming
1515 if (uic.OK)
1516 try
1517 {
1518
1519 m_log.DebugFormat("[RADMIN] {0} folders, {1} items in inventory",
1520 uic.folders.Count, uic.items.Count);
1521
1522 InventoryFolderImpl cfolder = uic.root.FindFolderForType(5);
1523
1524 // This should *never* be the case
1525 if (cfolder == null)
1526 {
1527 cfolder = new InventoryFolderImpl();
1528 cfolder.Name = "Clothing";
1529 cfolder.Type = 5;
1530 cfolder.Version = 1;
1531 cfolder.Owner = ID;
1532 uic.root.AddChildFolder(cfolder); // make connection
1533 iserv.AddFolder(cfolder); // store base record
1534 m_log.ErrorFormat("[RADMIN] Created clothing folder for {0}/{1}", name, ID);
1535 }
1536
1537 // OK, now we have an inventory for the user, read in the outfits from the
1538 // default appearance XMl file.
1539
1540 XmlNodeList outfits = avatar.GetElementsByTagName("Ensemble");
1541 InventoryFolderImpl efolder;
1542 string oname;
1543 UUID assetid;
1544
1545 foreach (XmlElement outfit in outfits)
1546 {
1547
1548 m_log.DebugFormat("[RADMIN] Loading outfit {0} for {1}",
1549 GetStringAttribute(outfit,"name","?"), GetStringAttribute(avatar,"name","?"));
1550
1551 oname = GetStringAttribute(outfit,"name","");
1552 select = (GetStringAttribute(outfit,"default","no") == "yes");
1553 efolder = null;
1554
1555 // If the folder already exists, re-use it. The defaults may
1556 // change over time. Augment only.
1557 foreach (InventoryFolderImpl folder in uic.folders)
1558 {
1559 if (folder.Name == oname && folder.ParentID == cfolder.ID)
1560 {
1561 efolder = folder;
1562 break;
1563 }
1564 }
1565
1566 // Otherwise, we must create the folder.
1567 if (efolder == null)
1568 {
1569 m_log.DebugFormat("[RADMIN] Creating outfit folder {0} for {1}", oname, name);
1570 efolder = new InventoryFolderImpl();
1571 efolder.ID = UUID.Random();
1572 efolder.Name = oname;
1573 efolder.Type = 5;
1574 efolder.Version = 1;
1575 efolder.Owner = ID;
1576 cfolder.AddChildFolder(efolder); // make connection
1577 iserv.AddFolder(efolder); // store base record
1578 m_log.DebugFormat("[RADMIN] Adding outfile folder {0} to folder {1}", efolder.ID, cfolder.ID);
1579 }
1580
1581 // Now get the pieces that make up the outfit
1582 XmlNodeList items = outfit.GetElementsByTagName("Item");
1583
1584 foreach (XmlElement item in items)
1585 {
1586 assetid = UUID.Zero;
1587 XmlNodeList children = item.ChildNodes;
1588 foreach (XmlNode child in children)
1589 {
1590 switch (child.Name)
1591 {
1592 case "Permissions" :
1593 m_log.DebugFormat("[RADMIN] Permissions specified");
1594 perms = child;
1595 break;
1596 case "Asset" :
1597 assetid = new UUID(child.InnerText);
1598 break;
1599 }
1600 }
1601
1602 InventoryItemBase iitem = null;
1603
1604 if ((iitem = efolder.FindAsset(assetid)) == null)
1605 {
1606 iitem = new InventoryItemBase();
1607 iitem.ID = UUID.Random();
1608 iitem.Name = GetStringAttribute(item,"name","");
1609 iitem.Description = GetStringAttribute(item,"desc","");
1610 iitem.InvType = GetIntegerAttribute(item,"invtype",-1);
1611 iitem.AssetType = GetIntegerAttribute(item,"assettype",-1);
1612 iitem.Flags = GetUnsignedAttribute(item,"flags",0);
1613 iitem.AssetID = assetid; // associated asset
1614 iitem.Folder = efolder.ID; // Parent folder
1615 iitem.Owner = ID; // Agent ID
1616 iitem.BasePermissions = GetUnsignedAttribute(perms,"base",0x7fffffff);
1617 iitem.NextPermissions = GetUnsignedAttribute(perms,"next",0x7fffffff);
1618 iitem.CurrentPermissions = GetUnsignedAttribute(perms,"current",0x7fffffff);
1619 iitem.GroupPermissions = GetUnsignedAttribute(perms,"group",0x7fffffff);
1620 iitem.EveryOnePermissions = GetUnsignedAttribute(perms,"everyone",0x7fffffff);
1621 m_log.DebugFormat("[RADMIN] Adding item {0} to folder {1}", iitem.ID, efolder.ID);
1622 iserv.AddItem(iitem);
1623 }
1624 // Record whether or not the item is to be initially worn
1625 try
1626 {
1627 if (select && (GetStringAttribute(item, "wear", "false") == "true"))
1628 {
1629 mava.Wearables[iitem.Flags].ItemID = iitem.ID;
1630 mava.Wearables[iitem.Flags].AssetID = iitem.AssetID;
1631 }
1632 }
1633 catch {}
1634 } // foreach item in outfit
1635 m_log.DebugFormat("[RADMIN] Outfit {0} load completed", oname);
1636 } // foreach outfit
1637 m_log.DebugFormat("[RADMIN] Inventory update complete for {0}", name);
1638 m_app.CommunicationsManager.AvatarService.UpdateUserAppearance(ID, mava);
1639 }
1640 catch (Exception e)
1641 {
1642 m_log.WarnFormat("[RADMIN] Inventory processing incomplete for user {0} : {1}",
1643 name, e.Message);
1644 }
1645 else
1646 {
1647 m_log.WarnFormat("[RADMIN] Unable to retrieve inventory for {0}[{1}]",
1648 name, ID);
1649 // continue to next avatar
1650 }
1651 } // End of include
1652 }
1653 m_log.DebugFormat("[RADMIN] Default avatar loading complete");
1654 }
1655 else
1656 {
1657 m_log.DebugFormat("[RADMIN] No default avatar information available");
1658 return false;
1659 }
1660 }
1661 catch (Exception e)
1662 {
1663 m_log.WarnFormat("[RADMIN] Exception whilst loading default avatars ; {0}", e.Message);
1664 return false;
1665 }
1666
1667 return true;
1668
1669 }
1670
1671 /// <summary>
1260 /// Load an OAR file into a region.. 1672 /// Load an OAR file into a region..
1261 /// <summary> 1673 /// <summary>
1262 /// <param name="request">incoming XML RPC request</param> 1674 /// <param name="request">incoming XML RPC request</param>
@@ -1809,13 +2221,17 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1809 Scene s = m_app.SceneManager.CurrentScene; 2221 Scene s = m_app.SceneManager.CurrentScene;
1810 Hashtable users = (Hashtable) requestData["users"]; 2222 Hashtable users = (Hashtable) requestData["users"];
1811 List<UUID> uuids = new List<UUID>(); 2223 List<UUID> uuids = new List<UUID>();
1812 foreach (string name in users.Values) 2224 foreach (string name in users.Values)
1813 { 2225 {
1814 string[] parts = name.Split(); 2226 string[] parts = name.Split();
1815 uuids.Add(ups.GetUserDetails(parts[0],parts[1]).UserProfile.ID); 2227 CachedUserInfo udata = ups.GetUserDetails(parts[0],parts[1]);
2228 if (udata != null)
2229 {
2230 uuids.Add(udata.UserProfile.ID);
2231 }
1816 } 2232 }
1817 List<UUID> acl = new List<UUID>(s.RegionInfo.EstateSettings.EstateAccess); 2233 List<UUID> acl = new List<UUID>(s.RegionInfo.EstateSettings.EstateAccess);
1818 foreach (UUID uuid in uuids) 2234 foreach (UUID uuid in uuids)
1819 { 2235 {
1820 if (!acl.Contains(uuid)) 2236 if (!acl.Contains(uuid))
1821 { 2237 {
@@ -1891,7 +2307,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1891 foreach (string name in users.Values) 2307 foreach (string name in users.Values)
1892 { 2308 {
1893 string[] parts = name.Split(); 2309 string[] parts = name.Split();
1894 uuids.Add(ups.GetUserDetails(parts[0],parts[1]).UserProfile.ID); 2310 CachedUserInfo udata = ups.GetUserDetails(parts[0],parts[1]);
2311 if (udata != null)
2312 {
2313 uuids.Add(udata.UserProfile.ID);
2314 }
1895 } 2315 }
1896 List<UUID> acl = new List<UUID>(s.RegionInfo.EstateSettings.EstateAccess); 2316 List<UUID> acl = new List<UUID>(s.RegionInfo.EstateSettings.EstateAccess);
1897 foreach (UUID uuid in uuids) 2317 foreach (UUID uuid in uuids)
@@ -1964,10 +2384,13 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1964 UUID[] acl = s.RegionInfo.EstateSettings.EstateAccess; 2384 UUID[] acl = s.RegionInfo.EstateSettings.EstateAccess;
1965 Hashtable users = new Hashtable(); 2385 Hashtable users = new Hashtable();
1966 2386
1967 foreach (UUID user in acl) 2387 foreach (UUID user in acl)
1968 { 2388 {
1969 users[user.ToString()] = 2389 CachedUserInfo udata = m_app.CommunicationsManager.UserProfileCacheService.GetUserDetails(user);
1970 m_app.CommunicationsManager.UserProfileCacheService.GetUserDetails(user).UserProfile.Name; 2390 if (udata != null)
2391 {
2392 users[user.ToString()] = udata.UserProfile.Name;
2393 }
1971 } 2394 }
1972 2395
1973 responseData["users"] = users; 2396 responseData["users"] = users;
@@ -1990,9 +2413,153 @@ namespace OpenSim.ApplicationPlugins.RemoteController
1990 return response; 2413 return response;
1991 } 2414 }
1992 2415
2416 private static void checkStringParameters(XmlRpcRequest request, string[] param)
2417 {
2418 Hashtable requestData = (Hashtable) request.Params[0];
2419 foreach (string p in param)
2420 {
2421 if (!requestData.Contains(p))
2422 throw new Exception(String.Format("missing string parameter {0}", p));
2423 if (String.IsNullOrEmpty((string) requestData[p]))
2424 throw new Exception(String.Format("parameter {0} is empty", p));
2425 }
2426 }
2427
2428 private static void checkIntegerParams(XmlRpcRequest request, string[] param)
2429 {
2430 Hashtable requestData = (Hashtable) request.Params[0];
2431 foreach (string p in param)
2432 {
2433 if (!requestData.Contains(p))
2434 throw new Exception(String.Format("missing integer parameter {0}", p));
2435 }
2436 }
2437
2438 private bool getBoolean(Hashtable requestData, string tag, bool defv)
2439 {
2440 // If an access value has been provided, apply it.
2441 if (requestData.Contains(tag))
2442 {
2443 switch (((string)requestData[tag]).ToLower())
2444 {
2445 case "true" :
2446 case "t" :
2447 case "1" :
2448 return true;
2449 case "false" :
2450 case "f" :
2451 case "0" :
2452 return false;
2453 default :
2454 return defv;
2455 }
2456 }
2457 else
2458 return defv;
2459 }
2460
2461 private int GetIntegerAttribute(XmlNode node, string attr, int dv)
2462 {
2463 try { return Convert.ToInt32(node.Attributes[attr].Value); } catch{}
2464 return dv;
2465 }
2466
2467 private uint GetUnsignedAttribute(XmlNode node, string attr, uint dv)
2468 {
2469 try { return Convert.ToUInt32(node.Attributes[attr].Value); } catch{}
2470 return dv;
2471 }
2472
2473 private string GetStringAttribute(XmlNode node, string attr, string dv)
2474 {
2475 try { return node.Attributes[attr].Value; } catch{}
2476 return dv;
2477 }
2478
1993 public void Dispose() 2479 public void Dispose()
1994 { 2480 {
1995 } 2481 }
2482
2483 }
2484
2485 class UICallback
2486 {
2487
2488 private Object uilock = new Object();
2489 internal InventoryFolderImpl root = null;
2490 internal List<InventoryFolderImpl> folders;
2491 internal List<InventoryItemBase> items;
2492 internal bool OK = false;
2493
2494 public void callback(ICollection<InventoryFolderImpl> p_folders, ICollection<InventoryItemBase> p_items)
2495 {
2496 lock (uilock)
2497 {
2498 folders = (List<InventoryFolderImpl>) p_folders;
2499 items = (List<InventoryItemBase>) p_items;
2500 OK = true;
2501 System.Threading.Monitor.Pulse(uilock);
2502 }
2503 }
2504
2505 public void GetInventory()
2506 {
2507
2508 Dictionary<UUID, InventoryFolderImpl> fmap = new Dictionary<UUID, InventoryFolderImpl>();
2509
2510 if (OK == false)
2511 {
2512 lock (uilock)
2513 {
2514 if (OK == false)
2515 System.Threading.Monitor.Wait(uilock);
2516 }
2517 }
2518
2519 // Got the inventory OK. So now merge the content of the default appearance
2520 // file with whatever we already have in-world. For convenience we initialize
2521 // the inventory hierarchy.
2522
2523 // Find root and build an index
2524
2525 foreach (InventoryFolderImpl folder in folders)
2526 {
2527 if (folder.ParentID == UUID.Zero)
2528 {
2529 if (root == null)
2530 {
2531 root = folder;
2532 }
2533 else
2534 {
2535 throw new Exception("Multiple root folders found");
2536 }
2537 }
2538 fmap.Add(folder.ID, folder);
2539 }
2540
2541 // Hard to continue if the root folder is not there
2542 if (root == null)
2543 {
2544 throw new Exception("Root folder not found");
2545 }
2546
2547 // Construct the folder hierarchy
2548 foreach (InventoryFolderImpl folder in folders)
2549 {
2550 if (folder.ID != root.ID)
2551 {
2552 fmap[folder.ParentID].AddChildFolder(folder);
2553 }
2554 }
2555
2556 // Find a home for every pre-existing item
2557 foreach (InventoryItemBase item in items)
2558 {
2559 fmap[item.Folder].Items.Add(item.ID, item);
2560 }
2561
2562 }
1996 } 2563 }
1997 2564
1998} 2565}