clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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.Generic;
30 using System.IO;
31 using System.Reflection;
32 using log4net;
33 using NDesk.Options;
34 using Nini.Config;
35 using OpenMetaverse;
36 using OpenSim.Framework;
37 using OpenSim.Framework.Communications;
38 using OpenSim.Framework.Console;
39 using OpenSim.Region.Framework.Interfaces;
40 using OpenSim.Region.Framework.Scenes;
41 using OpenSim.Services.Interfaces;
42 using Mono.Addins;
43  
44 namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
45 {
46 /// <summary>
47 /// This module loads and saves OpenSimulator inventory archives
48 /// </summary>
49 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "InventoryArchiverModule")]
50 public class InventoryArchiverModule : ISharedRegionModule, IInventoryArchiverModule
51 {
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53  
54 /// <value>
55 /// Enable or disable checking whether the iar user is actually logged in
56 /// </value>
57 // public bool DisablePresenceChecks { get; set; }
58  
59 public event InventoryArchiveSaved OnInventoryArchiveSaved;
60 public event InventoryArchiveLoaded OnInventoryArchiveLoaded;
61  
62 /// <summary>
63 /// The file to load and save inventory if no filename has been specified
64 /// </summary>
65 protected const string DEFAULT_INV_BACKUP_FILENAME = "user-inventory.iar";
66  
67 /// <value>
68 /// Pending save and load completions initiated from the console
69 /// </value>
70 protected List<UUID> m_pendingConsoleTasks = new List<UUID>();
71  
72 /// <value>
73 /// All scenes that this module knows about
74 /// </value>
75 private Dictionary<UUID, Scene> m_scenes = new Dictionary<UUID, Scene>();
76 private Scene m_aScene;
77  
78 private IUserAccountService m_UserAccountService;
79 protected IUserAccountService UserAccountService
80 {
81 get
82 {
83 if (m_UserAccountService == null)
84 // What a strange thing to do...
85 foreach (Scene s in m_scenes.Values)
86 {
87 m_UserAccountService = s.RequestModuleInterface<IUserAccountService>();
88 break;
89 }
90  
91 return m_UserAccountService;
92 }
93 }
94  
95  
96 public InventoryArchiverModule() {}
97  
98 // public InventoryArchiverModule(bool disablePresenceChecks)
99 // {
100 // DisablePresenceChecks = disablePresenceChecks;
101 // }
102  
103 #region ISharedRegionModule
104  
105 public void Initialise(IConfigSource source)
106 {
107 }
108  
109 public void AddRegion(Scene scene)
110 {
111 if (m_scenes.Count == 0)
112 {
113 scene.RegisterModuleInterface<IInventoryArchiverModule>(this);
114 OnInventoryArchiveSaved += SaveInvConsoleCommandCompleted;
115 OnInventoryArchiveLoaded += LoadInvConsoleCommandCompleted;
116  
117 scene.AddCommand(
118 "Archiving", this, "load iar",
119 "load iar [-m|--merge] <first> <last> <inventory path> <password> [<IAR path>]",
120 "Load user inventory archive (IAR).",
121 "-m|--merge is an option which merges the loaded IAR with existing inventory folders where possible, rather than always creating new ones"
122 + "<first> is user's first name." + Environment.NewLine
123 + "<last> is user's last name." + Environment.NewLine
124 + "<inventory path> is the path inside the user's inventory where the IAR should be loaded." + Environment.NewLine
125 + "<password> is the user's password." + Environment.NewLine
126 + "<IAR path> is the filesystem path or URI from which to load the IAR."
127 + string.Format(" If this is not given then the filename {0} in the current directory is used", DEFAULT_INV_BACKUP_FILENAME),
128 HandleLoadInvConsoleCommand);
129  
130 scene.AddCommand(
131 "Archiving", this, "save iar",
132 "save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]",
133 "Save user inventory archive (IAR).",
134 "<first> is the user's first name.\n"
135 + "<last> is the user's last name.\n"
136 + "<inventory path> is the path inside the user's inventory for the folder/item to be saved.\n"
137 + "<IAR path> is the filesystem path at which to save the IAR."
138 + string.Format(" If this is not given then the filename {0} in the current directory is used.\n", DEFAULT_INV_BACKUP_FILENAME)
139 + "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
140 + "-c|--creators preserves information about foreign creators.\n"
141 + "-e|--exclude=<name/uuid> don't save the inventory item in archive" + Environment.NewLine
142 + "-f|--excludefolder=<folder/uuid> don't save contents of the folder in archive" + Environment.NewLine
143 + "-v|--verbose extra debug messages.\n"
144 + "--noassets stops assets being saved to the IAR."
145 + "--perm=<permissions> stops items with insufficient permissions from being saved to the IAR.\n"
146 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer, \"M\" = Modify.\n",
147 HandleSaveInvConsoleCommand);
148  
149 m_aScene = scene;
150 }
151  
152 m_scenes[scene.RegionInfo.RegionID] = scene;
153 }
154  
155 public void RemoveRegion(Scene scene)
156 {
157 }
158  
159 public void Close() {}
160  
161 public void RegionLoaded(Scene scene)
162 {
163 }
164  
165 public void PostInitialise()
166 {
167 }
168  
169 public Type ReplaceableInterface
170 {
171 get { return null; }
172 }
173  
174 public string Name { get { return "Inventory Archiver Module"; } }
175  
176 #endregion
177  
178 /// <summary>
179 /// Trigger the inventory archive saved event.
180 /// </summary>
181 protected internal void TriggerInventoryArchiveSaved(
182 UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream,
183 Exception reportedException, int SaveCount, int FilterCount)
184 {
185 InventoryArchiveSaved handlerInventoryArchiveSaved = OnInventoryArchiveSaved;
186 if (handlerInventoryArchiveSaved != null)
187 handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException, SaveCount , FilterCount);
188 }
189  
190 /// <summary>
191 /// Trigger the inventory archive loaded event.
192 /// </summary>
193 protected internal void TriggerInventoryArchiveLoaded(
194 UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream loadStream,
195 Exception reportedException, int LoadCount)
196 {
197 InventoryArchiveLoaded handlerInventoryArchiveLoaded = OnInventoryArchiveLoaded;
198 if (handlerInventoryArchiveLoaded != null)
199 handlerInventoryArchiveLoaded(id, succeeded, userInfo, invPath, loadStream, reportedException, LoadCount);
200 }
201  
202 public bool ArchiveInventory(
203 UUID id, string firstName, string lastName, string invPath, string pass, Stream saveStream)
204 {
205 return ArchiveInventory(id, firstName, lastName, invPath, pass, saveStream, new Dictionary<string, object>());
206 }
207  
208 public bool ArchiveInventory(
209 UUID id, string firstName, string lastName, string invPath, string pass, Stream saveStream,
210 Dictionary<string, object> options)
211 {
212 if (m_scenes.Count > 0)
213 {
214 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
215  
216 if (userInfo != null)
217 {
218 // if (CheckPresence(userInfo.PrincipalID))
219 // {
220 try
221 {
222 new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream).Execute(options, UserAccountService);
223 }
224 catch (EntryPointNotFoundException e)
225 {
226 m_log.ErrorFormat(
227 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
228 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
229 m_log.Error(e);
230  
231 return false;
232 }
233  
234 return true;
235 // }
236 // else
237 // {
238 // m_log.ErrorFormat(
239 // "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
240 // userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
241 // }
242 }
243 }
244  
245 return false;
246 }
247  
248 public bool ArchiveInventory(
249 UUID id, string firstName, string lastName, string invPath, string pass, string savePath,
250 Dictionary<string, object> options)
251 {
252 // if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath))
253 // return false;
254  
255 if (m_scenes.Count > 0)
256 {
257 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
258  
259 if (userInfo != null)
260 {
261 // if (CheckPresence(userInfo.PrincipalID))
262 // {
263 try
264 {
265 new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath).Execute(options, UserAccountService);
266 }
267 catch (EntryPointNotFoundException e)
268 {
269 m_log.ErrorFormat(
270 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
271 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
272 m_log.Error(e);
273  
274 return false;
275 }
276  
277 return true;
278 // }
279 // else
280 // {
281 // m_log.ErrorFormat(
282 // "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
283 // userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
284 // }
285 }
286 }
287  
288 return false;
289 }
290  
291 public bool DearchiveInventory(UUID id, string firstName, string lastName, string invPath, string pass, Stream loadStream)
292 {
293 return DearchiveInventory(id, firstName, lastName, invPath, pass, loadStream, new Dictionary<string, object>());
294 }
295  
296 public bool DearchiveInventory(
297 UUID id, string firstName, string lastName, string invPath, string pass, Stream loadStream,
298 Dictionary<string, object> options)
299 {
300 if (m_scenes.Count > 0)
301 {
302 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
303  
304 if (userInfo != null)
305 {
306 // if (CheckPresence(userInfo.PrincipalID))
307 // {
308 InventoryArchiveReadRequest request;
309 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
310  
311 try
312 {
313 request = new InventoryArchiveReadRequest(id, m_aScene.InventoryService, this, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadStream, merge);
314 }
315 catch (EntryPointNotFoundException e)
316 {
317 m_log.ErrorFormat(
318 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
319 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
320 m_log.Error(e);
321  
322 return false;
323 }
324  
325 UpdateClientWithLoadedNodes(userInfo, request.Execute());
326  
327 return true;
328 // }
329 // else
330 // {
331 // m_log.ErrorFormat(
332 // "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
333 // userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
334 // }
335 }
336 else
337 m_log.ErrorFormat("[INVENTORY ARCHIVER]: User {0} {1} not found",
338 firstName, lastName);
339 }
340  
341 return false;
342 }
343  
344 public bool DearchiveInventory(
345 UUID id, string firstName, string lastName, string invPath, string pass, string loadPath,
346 Dictionary<string, object> options)
347 {
348 if (m_scenes.Count > 0)
349 {
350 UserAccount userInfo = GetUserInfo(firstName, lastName, pass);
351  
352 if (userInfo != null)
353 {
354 // if (CheckPresence(userInfo.PrincipalID))
355 // {
356 InventoryArchiveReadRequest request;
357 bool merge = (options.ContainsKey("merge") ? (bool)options["merge"] : false);
358  
359 try
360 {
361 request = new InventoryArchiveReadRequest(id, m_aScene.InventoryService, this, m_aScene.AssetService, m_aScene.UserAccountService, userInfo, invPath, loadPath, merge);
362 }
363 catch (EntryPointNotFoundException e)
364 {
365 m_log.ErrorFormat(
366 "[INVENTORY ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream."
367 + "If you've manually installed Mono, have you appropriately updated zlib1g as well?");
368 m_log.Error(e);
369  
370 return false;
371 }
372  
373 UpdateClientWithLoadedNodes(userInfo, request.Execute());
374  
375 return true;
376 // }
377 // else
378 // {
379 // m_log.ErrorFormat(
380 // "[INVENTORY ARCHIVER]: User {0} {1} {2} not logged in to this region simulator",
381 // userInfo.FirstName, userInfo.LastName, userInfo.PrincipalID);
382 // }
383 }
384 }
385  
386 return false;
387 }
388  
389 /// <summary>
390 /// Load inventory from an inventory file archive
391 /// </summary>
392 /// <param name="cmdparams"></param>
393 protected void HandleLoadInvConsoleCommand(string module, string[] cmdparams)
394 {
395 try
396 {
397 UUID id = UUID.Random();
398  
399 Dictionary<string, object> options = new Dictionary<string, object>();
400 OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; });
401  
402 List<string> mainParams = optionSet.Parse(cmdparams);
403  
404 if (mainParams.Count < 6)
405 {
406 m_log.Error(
407 "[INVENTORY ARCHIVER]: usage is load iar [-m|--merge] <first name> <last name> <inventory path> <user password> [<load file path>]");
408 return;
409 }
410  
411 string firstName = mainParams[2];
412 string lastName = mainParams[3];
413 string invPath = mainParams[4];
414 string pass = mainParams[5];
415 string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME);
416  
417 m_log.InfoFormat(
418 "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}",
419 loadPath, invPath, firstName, lastName);
420  
421 lock (m_pendingConsoleTasks)
422 m_pendingConsoleTasks.Add(id);
423  
424 DearchiveInventory(id, firstName, lastName, invPath, pass, loadPath, options);
425 }
426 catch (InventoryArchiverException e)
427 {
428 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message);
429 }
430 }
431  
432 /// <summary>
433 /// Save inventory to a file archive
434 /// </summary>
435 /// <param name="cmdparams"></param>
436 protected void HandleSaveInvConsoleCommand(string module, string[] cmdparams)
437 {
438 UUID id = UUID.Random();
439  
440 Dictionary<string, object> options = new Dictionary<string, object>();
441  
442 OptionSet ops = new OptionSet();
443 //ops.Add("v|version=", delegate(string v) { options["version"] = v; });
444 ops.Add("h|home=", delegate(string v) { options["home"] = v; });
445 ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; });
446 ops.Add("c|creators", delegate(string v) { options["creators"] = v; });
447 ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
448 ops.Add("e|exclude=", delegate(string v)
449 {
450 if (!options.ContainsKey("exclude"))
451 options["exclude"] = new List<String>();
452 ((List<String>)options["exclude"]).Add(v);
453 });
454 ops.Add("f|excludefolder=", delegate(string v)
455 {
456 if (!options.ContainsKey("excludefolders"))
457 options["excludefolders"] = new List<String>();
458 ((List<String>)options["excludefolders"]).Add(v);
459 });
460 ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
461  
462 List<string> mainParams = ops.Parse(cmdparams);
463  
464 try
465 {
466 if (mainParams.Count < 6)
467 {
468 m_log.Error(
469 "[INVENTORY ARCHIVER]: save iar [-h|--home=<url>] [--noassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]");
470 return;
471 }
472  
473 if (options.ContainsKey("home"))
474 m_log.WarnFormat("[INVENTORY ARCHIVER]: Please be aware that inventory archives with creator information are not compatible with OpenSim 0.7.0.2 and earlier. Do not use the -home option if you want to produce a compatible IAR");
475  
476 string firstName = mainParams[2];
477 string lastName = mainParams[3];
478 string invPath = mainParams[4];
479 string pass = mainParams[5];
480 string savePath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME);
481  
482 m_log.InfoFormat(
483 "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}",
484 savePath, invPath, firstName, lastName);
485  
486 lock (m_pendingConsoleTasks)
487 m_pendingConsoleTasks.Add(id);
488  
489 ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, options);
490 }
491 catch (InventoryArchiverException e)
492 {
493 m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message);
494 }
495 }
496  
497 private void SaveInvConsoleCommandCompleted(
498 UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream,
499 Exception reportedException, int SaveCount, int FilterCount)
500 {
501 lock (m_pendingConsoleTasks)
502 {
503 if (m_pendingConsoleTasks.Contains(id))
504 m_pendingConsoleTasks.Remove(id);
505 else
506 return;
507 }
508  
509 if (succeeded)
510 {
511 // Report success and include item count and filter count (Skipped items due to --perm or --exclude switches)
512 if(FilterCount == 0)
513 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive with {0} items for {1} {2}", SaveCount, userInfo.FirstName, userInfo.LastName);
514 else
515 m_log.InfoFormat("[INVENTORY ARCHIVER]: Saved archive with {0} items for {1} {2}. Skipped {3} items due to exclude and/or perm switches", SaveCount, userInfo.FirstName, userInfo.LastName, FilterCount);
516 }
517 else
518 {
519 m_log.ErrorFormat(
520 "[INVENTORY ARCHIVER]: Archive save for {0} {1} failed - {2}",
521 userInfo.FirstName, userInfo.LastName, reportedException.Message);
522 }
523 }
524  
525 private void LoadInvConsoleCommandCompleted(
526 UUID id, bool succeeded, UserAccount userInfo, string invPath, Stream loadStream,
527 Exception reportedException, int LoadCount)
528 {
529 lock (m_pendingConsoleTasks)
530 {
531 if (m_pendingConsoleTasks.Contains(id))
532 m_pendingConsoleTasks.Remove(id);
533 else
534 return;
535 }
536  
537 if (succeeded)
538 {
539 m_log.InfoFormat("[INVENTORY ARCHIVER]: Loaded {0} items from archive {1} for {2} {3}", LoadCount, invPath, userInfo.FirstName, userInfo.LastName);
540 }
541 else
542 {
543 m_log.ErrorFormat(
544 "[INVENTORY ARCHIVER]: Archive load for {0} {1} failed - {2}",
545 userInfo.FirstName, userInfo.LastName, reportedException.Message);
546 }
547 }
548  
549 /// <summary>
550 /// Get user information for the given name.
551 /// </summary>
552 /// <param name="firstName"></param>
553 /// <param name="lastName"></param>
554 /// <param name="pass">User password</param>
555 /// <returns></returns>
556 protected UserAccount GetUserInfo(string firstName, string lastName, string pass)
557 {
558 UserAccount account
559 = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, firstName, lastName);
560  
561 if (null == account)
562 {
563 m_log.ErrorFormat(
564 "[INVENTORY ARCHIVER]: Failed to find user info for {0} {1}",
565 firstName, lastName);
566 return null;
567 }
568  
569 try
570 {
571 string encpass = Util.Md5Hash(pass);
572 if (m_aScene.AuthenticationService.Authenticate(account.PrincipalID, encpass, 1) != string.Empty)
573 {
574 return account;
575 }
576 else
577 {
578 m_log.ErrorFormat(
579 "[INVENTORY ARCHIVER]: Password for user {0} {1} incorrect. Please try again.",
580 firstName, lastName);
581 return null;
582 }
583 }
584 catch (Exception e)
585 {
586 m_log.ErrorFormat("[INVENTORY ARCHIVER]: Could not authenticate password, {0}", e);
587 return null;
588 }
589 }
590  
591 /// <summary>
592 /// Notify the client of loaded nodes if they are logged in
593 /// </summary>
594 /// <param name="loadedNodes">Can be empty. In which case, nothing happens</param>
595 private void UpdateClientWithLoadedNodes(UserAccount userInfo, HashSet<InventoryNodeBase> loadedNodes)
596 {
597 if (loadedNodes.Count == 0)
598 return;
599  
600 foreach (Scene scene in m_scenes.Values)
601 {
602 ScenePresence user = scene.GetScenePresence(userInfo.PrincipalID);
603  
604 if (user != null && !user.IsChildAgent)
605 {
606 foreach (InventoryNodeBase node in loadedNodes)
607 {
608 // m_log.DebugFormat(
609 // "[INVENTORY ARCHIVER]: Notifying {0} of loaded inventory node {1}",
610 // user.Name, node.Name);
611  
612 user.ControllingClient.SendBulkUpdateInventory(node);
613 }
614  
615 break;
616 }
617 }
618 }
619  
620 // /// <summary>
621 // /// Check if the given user is present in any of the scenes.
622 // /// </summary>
623 // /// <param name="userId">The user to check</param>
624 // /// <returns>true if the user is in any of the scenes, false otherwise</returns>
625 // protected bool CheckPresence(UUID userId)
626 // {
627 // if (DisablePresenceChecks)
628 // return true;
629 //
630 // foreach (Scene scene in m_scenes.Values)
631 // {
632 // ScenePresence p;
633 // if ((p = scene.GetScenePresence(userId)) != null)
634 // {
635 // p.ControllingClient.SendAgentAlertMessage("Inventory operation has been started", false);
636 // return true;
637 // }
638 // }
639 //
640 // return false;
641 // }
642 }
643 }