aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Framework/IClientAPI.cs7
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs40
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs200
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs56
-rw-r--r--OpenSim/Region/Framework/Interfaces/ILandObject.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs14
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs2
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs88
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs2
11 files changed, 244 insertions, 181 deletions
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index f8be9ad..1a59cf4 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -174,9 +174,10 @@ namespace OpenSim.Framework
174 public delegate void ParcelAccessListRequest( 174 public delegate void ParcelAccessListRequest(
175 UUID agentID, UUID sessionID, uint flags, int sequenceID, int landLocalID, IClientAPI remote_client); 175 UUID agentID, UUID sessionID, uint flags, int sequenceID, int landLocalID, IClientAPI remote_client);
176 176
177 public delegate void ParcelAccessListUpdateRequest( 177 public delegate void ParcelAccessListUpdateRequest(UUID agentID, uint flags,
178 UUID agentID, UUID sessionID, uint flags, int landLocalID, List<ParcelManager.ParcelAccessEntry> entries, 178 int landLocalID, UUID transactionID, int sequenceID,
179 IClientAPI remote_client); 179 int sections, List<ParcelManager.ParcelAccessEntry> entries,
180 IClientAPI remote_client);
180 181
181 public delegate void ParcelPropertiesRequest( 182 public delegate void ParcelPropertiesRequest(
182 int start_x, int start_y, int end_x, int end_y, int sequence_id, bool snap_selection, IClientAPI remote_client); 183 int start_x, int start_y, int end_x, int end_y, int sequence_id, bool snap_selection, IClientAPI remote_client);
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 246aaf0..612c0d9 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -8298,7 +8298,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8298 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); 8298 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
8299 entry.AgentID = block.ID; 8299 entry.AgentID = block.ID;
8300 entry.Flags = (AccessList)block.Flags; 8300 entry.Flags = (AccessList)block.Flags;
8301 entry.Time = new DateTime(); 8301 entry.Time = Util.ToDateTime(block.Time);
8302 entries.Add(entry); 8302 entries.Add(entry);
8303 } 8303 }
8304 8304
@@ -8306,8 +8306,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8306 if (handlerParcelAccessListUpdateRequest != null) 8306 if (handlerParcelAccessListUpdateRequest != null)
8307 { 8307 {
8308 handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID, 8308 handlerParcelAccessListUpdateRequest(updatePacket.AgentData.AgentID,
8309 updatePacket.AgentData.SessionID, updatePacket.Data.Flags, 8309 updatePacket.Data.Flags,
8310 updatePacket.Data.LocalID, entries, this); 8310 updatePacket.Data.LocalID,
8311 updatePacket.Data.TransactionID,
8312 updatePacket.Data.SequenceID,
8313 updatePacket.Data.Sections,
8314 entries, this);
8311 } 8315 }
8312 return true; 8316 return true;
8313 } 8317 }
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 2554995..8449cc1 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -167,7 +167,7 @@ namespace OpenSim.Region.CoreModules.World.Land
167 client.OnParcelSelectObjects += ClientOnParcelSelectObjects; 167 client.OnParcelSelectObjects += ClientOnParcelSelectObjects;
168 client.OnParcelObjectOwnerRequest += ClientOnParcelObjectOwnerRequest; 168 client.OnParcelObjectOwnerRequest += ClientOnParcelObjectOwnerRequest;
169 client.OnParcelAccessListRequest += ClientOnParcelAccessListRequest; 169 client.OnParcelAccessListRequest += ClientOnParcelAccessListRequest;
170 client.OnParcelAccessListUpdateRequest += ClientOnParcelAccessUpdateListRequest; 170 client.OnParcelAccessListUpdateRequest += ClientOnParcelAccessListUpdateRequest;
171 client.OnParcelAbandonRequest += ClientOnParcelAbandonRequest; 171 client.OnParcelAbandonRequest += ClientOnParcelAbandonRequest;
172 client.OnParcelGodForceOwner += ClientOnParcelGodForceOwner; 172 client.OnParcelGodForceOwner += ClientOnParcelGodForceOwner;
173 client.OnParcelReclaim += ClientOnParcelReclaim; 173 client.OnParcelReclaim += ClientOnParcelReclaim;
@@ -516,14 +516,22 @@ namespace OpenSim.Region.CoreModules.World.Land
516 516
517 if (land != null) 517 if (land != null)
518 { 518 {
519 m_landList[landLocalID].SendAccessList(agentID, sessionID, flags, sequenceID, remote_client); 519 land.SendAccessList(agentID, sessionID, flags, sequenceID, remote_client);
520 } 520 }
521 } 521 }
522 522
523 public void ClientOnParcelAccessUpdateListRequest(UUID agentID, UUID sessionID, uint flags, int landLocalID, 523 public void ClientOnParcelAccessListUpdateRequest(UUID agentID,
524 List<ParcelManager.ParcelAccessEntry> entries, 524 uint flags, int landLocalID, UUID transactionID, int sequenceID,
525 IClientAPI remote_client) 525 int sections, List<ParcelManager.ParcelAccessEntry> entries,
526 IClientAPI remote_client)
526 { 527 {
528 // Flags is the list to update, it can mean either the ban or
529 // the access list (WTH is a pass list? Mentioned in ParcelFlags)
530 //
531 // There may be multiple packets, because these can get LONG.
532 // Use transactionID to determine a new chain of packets since
533 // packets may have come in out of sequence and that would be
534 // a big mess if using the sequenceID
527 ILandObject land; 535 ILandObject land;
528 lock (m_landList) 536 lock (m_landList)
529 { 537 {
@@ -532,9 +540,15 @@ namespace OpenSim.Region.CoreModules.World.Land
532 540
533 if (land != null) 541 if (land != null)
534 { 542 {
535 if (agentID == land.LandData.OwnerID) 543 GroupPowers requiredPowers = GroupPowers.LandManageAllowed;
544 if (flags == (uint)AccessList.Ban)
545 requiredPowers = GroupPowers.LandManageBanned;
546
547 if (m_scene.Permissions.CanEditParcelProperties(agentID,
548 land, requiredPowers))
536 { 549 {
537 land.UpdateAccessList(flags, entries, remote_client); 550 land.UpdateAccessList(flags, transactionID, sequenceID,
551 sections, entries, remote_client);
538 } 552 }
539 } 553 }
540 else 554 else
@@ -862,7 +876,7 @@ namespace OpenSim.Region.CoreModules.World.Land
862 876
863 //If we are still here, then they are subdividing within one piece of land 877 //If we are still here, then they are subdividing within one piece of land
864 //Check owner 878 //Check owner
865 if (!m_scene.Permissions.CanEditParcel(attempting_user_id, startLandObject)) 879 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, startLandObject, GroupPowers.LandDivideJoin))
866 { 880 {
867 return; 881 return;
868 } 882 }
@@ -930,7 +944,7 @@ namespace OpenSim.Region.CoreModules.World.Land
930 { 944 {
931 return; 945 return;
932 } 946 }
933 if (!m_scene.Permissions.CanEditParcel(attempting_user_id, masterLandObject)) 947 if (!m_scene.Permissions.CanEditParcelProperties(attempting_user_id, masterLandObject, GroupPowers.LandDivideJoin))
934 { 948 {
935 return; 949 return;
936 } 950 }
@@ -1595,7 +1609,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1595 1609
1596 if (land == null) return; 1610 if (land == null) return;
1597 1611
1598 if (!m_scene.Permissions.CanEditParcel(remoteClient.AgentId, land)) 1612 if (!m_scene.Permissions.CanEditParcelProperties(remoteClient.AgentId, land, GroupPowers.LandOptions))
1599 return; 1613 return;
1600 1614
1601 land.LandData.OtherCleanTime = otherCleanTime; 1615 land.LandData.OtherCleanTime = otherCleanTime;
@@ -1695,7 +1709,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1695 if (targetAvatar.UserLevel == 0) 1709 if (targetAvatar.UserLevel == 0)
1696 { 1710 {
1697 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); 1711 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1698 if (!((Scene)client.Scene).Permissions.CanEditParcel(client.AgentId, land)) 1712 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1699 return; 1713 return;
1700 if (flags == 0) 1714 if (flags == 0)
1701 { 1715 {
@@ -1740,7 +1754,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1740 if (targetAvatar.UserLevel == 0) 1754 if (targetAvatar.UserLevel == 0)
1741 { 1755 {
1742 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); 1756 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1743 if (!((Scene)client.Scene).Permissions.CanEditParcel(client.AgentId, land)) 1757 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1744 return; 1758 return;
1745 1759
1746 Vector3 position = new Vector3(0, 0, 0); 1760 Vector3 position = new Vector3(0, 0, 0);
@@ -1819,7 +1833,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1819 if (targetAvatar.UserLevel == 0) 1833 if (targetAvatar.UserLevel == 0)
1820 { 1834 {
1821 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); 1835 ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y);
1822 if (!((Scene)client.Scene).Permissions.CanEditParcel(client.AgentId, land)) 1836 if (!((Scene)client.Scene).Permissions.CanEditParcelProperties(client.AgentId, land, GroupPowers.LandEjectAndFreeze))
1823 return; 1837 return;
1824 1838
1825 Vector3 position = new Vector3(0, 0, 0); 1839 Vector3 position = new Vector3(0, 0, 0);
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index d596887..8483e32 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -54,6 +54,7 @@ namespace OpenSim.Region.CoreModules.World.Land
54 protected LandData m_landData = new LandData(); 54 protected LandData m_landData = new LandData();
55 protected Scene m_scene; 55 protected Scene m_scene;
56 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>(); 56 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
57 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
57 58
58 public bool[,] LandBitmap 59 public bool[,] LandBitmap
59 { 60 {
@@ -199,36 +200,81 @@ namespace OpenSim.Region.CoreModules.World.Land
199 200
200 public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) 201 public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client)
201 { 202 {
202 if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this)) 203 //Needs later group support
204 bool snap_selection = false;
205 LandData newData = LandData.Copy();
206
207 uint allowedDelta = 0;
208
209 // These two are always blocked as no client can set them anyway
210 // ParcelFlags.ForSaleObjects
211 // ParcelFlags.LindenHome
212
213 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
203 { 214 {
204 //Needs later group support 215 allowedDelta |= (uint)(ParcelFlags.AllowLandmark |
205 bool snap_selection = false; 216 ParcelFlags.AllowTerraform |
206 LandData newData = LandData.Copy(); 217 ParcelFlags.AllowDamage |
218 ParcelFlags.CreateObjects |
219 ParcelFlags.RestrictPushObject |
220 ParcelFlags.AllowGroupScripts |
221 ParcelFlags.CreateGroupObjects |
222 ParcelFlags.AllowAPrimitiveEntry |
223 ParcelFlags.AllowGroupObjectEntry);
224 }
207 225
208 if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice) 226 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandSetSale))
227 {
228 if (args.AuthBuyerID != newData.AuthBuyerID ||
229 args.SalePrice != newData.SalePrice)
209 { 230 {
210 if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this)) 231 snap_selection = true;
211 { 232 }
212 newData.AuthBuyerID = args.AuthBuyerID; 233
213 newData.SalePrice = args.SalePrice; 234 newData.AuthBuyerID = args.AuthBuyerID;
214 snap_selection = true; 235 newData.SalePrice = args.SalePrice;
215 } 236
237 if (!LandData.IsGroupOwned)
238 {
239 newData.GroupID = args.GroupID;
240
241 allowedDelta |= (uint)(ParcelFlags.AllowDeedToGroup |
242 ParcelFlags.ContributeWithDeed |
243 ParcelFlags.SellParcelObjects);
216 } 244 }
245
246 allowedDelta |= (uint)ParcelFlags.ForSale;
247 }
248
249 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.FindPlaces))
250 {
217 newData.Category = args.Category; 251 newData.Category = args.Category;
252
253 allowedDelta |= (uint)(ParcelFlags.ShowDirectory |
254 ParcelFlags.AllowPublish |
255 ParcelFlags.MaturePublish);
256 }
257
258 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandChangeIdentity))
259 {
218 newData.Description = args.Desc; 260 newData.Description = args.Desc;
219 newData.GroupID = args.GroupID; 261 newData.Name = args.Name;
262 newData.SnapshotID = args.SnapshotID;
263 }
264
265 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.SetLandingPoint))
266 {
220 newData.LandingType = args.LandingType; 267 newData.LandingType = args.LandingType;
268 newData.UserLocation = args.UserLocation;
269 newData.UserLookAt = args.UserLookAt;
270 }
271
272 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.ChangeMedia))
273 {
221 newData.MediaAutoScale = args.MediaAutoScale; 274 newData.MediaAutoScale = args.MediaAutoScale;
222 newData.MediaID = args.MediaID; 275 newData.MediaID = args.MediaID;
223 newData.MediaURL = args.MediaURL; 276 newData.MediaURL = args.MediaURL;
224 newData.MusicURL = args.MusicURL; 277 newData.MusicURL = args.MusicURL;
225 newData.Name = args.Name;
226 newData.Flags = args.ParcelFlags;
227 newData.PassHours = args.PassHours;
228 newData.PassPrice = args.PassPrice;
229 newData.SnapshotID = args.SnapshotID;
230 newData.UserLocation = args.UserLocation;
231 newData.UserLookAt = args.UserLookAt;
232 newData.MediaType = args.MediaType; 278 newData.MediaType = args.MediaType;
233 newData.MediaDescription = args.MediaDescription; 279 newData.MediaDescription = args.MediaDescription;
234 newData.MediaWidth = args.MediaWidth; 280 newData.MediaWidth = args.MediaWidth;
@@ -237,10 +283,40 @@ namespace OpenSim.Region.CoreModules.World.Land
237 newData.ObscureMusic = args.ObscureMusic; 283 newData.ObscureMusic = args.ObscureMusic;
238 newData.ObscureMedia = args.ObscureMedia; 284 newData.ObscureMedia = args.ObscureMedia;
239 285
240 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 286 allowedDelta |= (uint)(ParcelFlags.SoundLocal |
287 ParcelFlags.UrlWebPage |
288 ParcelFlags.UrlRawHtml |
289 ParcelFlags.AllowVoiceChat |
290 ParcelFlags.UseEstateVoiceChan);
291 }
292
293 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses))
294 {
295 newData.PassHours = args.PassHours;
296 newData.PassPrice = args.PassPrice;
297
298 allowedDelta |= (uint)ParcelFlags.UsePassList;
299 }
300
301 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageAllowed))
302 {
303 allowedDelta |= (uint)(ParcelFlags.UseAccessGroup |
304 ParcelFlags.UseAccessList);
305 }
241 306
242 SendLandUpdateToAvatarsOverMe(snap_selection); 307 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandManageBanned))
308 {
309 allowedDelta |= (uint)(ParcelFlags.UseBanList |
310 ParcelFlags.DenyAnonymous |
311 ParcelFlags.DenyAgeUnverified);
243 } 312 }
313
314 uint preserve = LandData.Flags & ~allowedDelta;
315 newData.Flags = preserve | (args.ParcelFlags & allowedDelta);
316
317 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
318
319 SendLandUpdateToAvatarsOverMe(snap_selection);
244 } 320 }
245 321
246 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) 322 public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area)
@@ -326,14 +402,14 @@ namespace OpenSim.Region.CoreModules.World.Land
326 402
327 if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) 403 if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0)
328 { 404 {
329 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); 405 if (LandData.ParcelAccessList.FindIndex(
330 entry.AgentID = avatar; 406 delegate(ParcelManager.ParcelAccessEntry e)
331 entry.Flags = AccessList.Ban; 407 {
332 entry.Time = new DateTime(); 408 if (e.AgentID == avatar && e.Flags == AccessList.Ban)
333 //See if they are on the list, but make sure the owner isn't banned 409 return true;
334 if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) 410 return false;
411 }) != -1 && LandData.OwnerID != avatar)
335 { 412 {
336 //They are banned, so lets send them a notice about this parcel
337 return true; 413 return true;
338 } 414 }
339 } 415 }
@@ -347,17 +423,16 @@ namespace OpenSim.Region.CoreModules.World.Land
347 423
348 if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) 424 if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0)
349 { 425 {
350 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); 426 if (LandData.ParcelAccessList.FindIndex(
351 entry.AgentID = avatar; 427 delegate(ParcelManager.ParcelAccessEntry e)
352 entry.Flags = AccessList.Access; 428 {
353 entry.Time = new DateTime(); 429 if (e.AgentID == avatar && e.Flags == AccessList.Access)
354 430 return true;
355 //If they are not on the access list and are not the owner 431 return false;
356 if (!LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) 432 }) == -1 && LandData.OwnerID != avatar)
357 { 433 {
358 if (!HasGroupAccess(avatar)) 434 if (!HasGroupAccess(avatar))
359 { 435 {
360 //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel
361 return true; 436 return true;
362 } 437 }
363 } 438 }
@@ -456,39 +531,50 @@ namespace OpenSim.Region.CoreModules.World.Land
456 } 531 }
457 } 532 }
458 533
459 public void UpdateAccessList(uint flags, List<ParcelManager.ParcelAccessEntry> entries, IClientAPI remote_client) 534 public void UpdateAccessList(uint flags, UUID transactionID,
535 int sequenceID, int sections,
536 List<ParcelManager.ParcelAccessEntry> entries,
537 IClientAPI remote_client)
460 { 538 {
461 LandData newData = LandData.Copy(); 539 LandData newData = LandData.Copy();
462 540
463 if (entries.Count == 1 && entries[0].AgentID == UUID.Zero) 541 if ((!m_listTransactions.ContainsKey(flags)) ||
542 m_listTransactions[flags] != transactionID)
464 { 543 {
465 entries.Clear(); 544 m_listTransactions[flags] = transactionID;
466 }
467 545
468 List<ParcelManager.ParcelAccessEntry> toRemove = new List<ParcelManager.ParcelAccessEntry>(); 546 List<ParcelManager.ParcelAccessEntry> toRemove =
469 foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList) 547 new List<ParcelManager.ParcelAccessEntry>();
470 { 548
471 if (entry.Flags == (AccessList)flags) 549 foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList)
472 { 550 {
473 toRemove.Add(entry); 551 if (entry.Flags == (AccessList)flags)
552 toRemove.Add(entry);
474 } 553 }
475 }
476 554
477 foreach (ParcelManager.ParcelAccessEntry entry in toRemove) 555 foreach (ParcelManager.ParcelAccessEntry entry in toRemove)
478 { 556 {
479 newData.ParcelAccessList.Remove(entry); 557 newData.ParcelAccessList.Remove(entry);
558 }
559
560 // Checked here because this will always be the first
561 // and only packet in a transaction
562 if (entries.Count == 1 && entries[0].AgentID == UUID.Zero)
563 {
564 return;
565 }
480 } 566 }
567
481 foreach (ParcelManager.ParcelAccessEntry entry in entries) 568 foreach (ParcelManager.ParcelAccessEntry entry in entries)
482 { 569 {
483 ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry(); 570 ParcelManager.ParcelAccessEntry temp =
571 new ParcelManager.ParcelAccessEntry();
572
484 temp.AgentID = entry.AgentID; 573 temp.AgentID = entry.AgentID;
485 temp.Time = new DateTime(); //Pointless? Yes. 574 temp.Time = entry.Time;
486 temp.Flags = (AccessList)flags; 575 temp.Flags = (AccessList)flags;
487 576
488 if (!newData.ParcelAccessList.Contains(temp)) 577 newData.ParcelAccessList.Add(temp);
489 {
490 newData.ParcelAccessList.Add(temp);
491 }
492 } 578 }
493 579
494 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); 580 m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData);
@@ -746,7 +832,7 @@ namespace OpenSim.Region.CoreModules.World.Land
746 832
747 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client) 833 public void SendForceObjectSelect(int local_id, int request_type, List<UUID> returnIDs, IClientAPI remote_client)
748 { 834 {
749 if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) 835 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
750 { 836 {
751 List<uint> resultLocalIDs = new List<uint>(); 837 List<uint> resultLocalIDs = new List<uint>();
752 try 838 try
@@ -796,7 +882,7 @@ namespace OpenSim.Region.CoreModules.World.Land
796 /// </param> 882 /// </param>
797 public void SendLandObjectOwners(IClientAPI remote_client) 883 public void SendLandObjectOwners(IClientAPI remote_client)
798 { 884 {
799 if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) 885 if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId, this, GroupPowers.LandOptions))
800 { 886 {
801 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>(); 887 Dictionary<UUID, int> primCount = new Dictionary<UUID, int>();
802 List<UUID> groups = new List<UUID>(); 888 List<UUID> groups = new List<UUID>();
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 289741f..f9b2384 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -37,56 +37,6 @@ using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
39 39
40// Temporary fix of wrong GroupPowers constants in OpenMetaverse library
41enum GroupPowers : long
42 {
43 None = 0,
44 LandEjectAndFreeze = 1,
45 Invite = 2,
46 ReturnGroupSet = 2,
47 Eject = 4,
48 ReturnNonGroup = 4,
49 ChangeOptions = 8,
50 LandGardening = 8,
51 CreateRole = 16,
52 DeedObject = 16,
53 ModerateChat = 32,
54 DeleteRole = 32,
55 RoleProperties = 64,
56 ObjectManipulate = 64,
57 ObjectSetForSale = 128,
58 AssignMemberLimited = 128,
59 AssignMember = 256,
60 Accountable = 256,
61 RemoveMember = 512,
62 SendNotices = 1024,
63 ChangeActions = 1024,
64 ChangeIdentity = 2048,
65 ReceiveNotices = 2048,
66 StartProposal = 4096,
67 LandDeed = 4096,
68 VoteOnProposal = 8192,
69 LandRelease = 8192,
70 LandSetSale = 16384,
71 LandDivideJoin = 32768,
72 ReturnGroupOwned = 65536,
73 JoinChat = 65536,
74 FindPlaces = 131072,
75 LandChangeIdentity = 262144,
76 SetLandingPoint = 524288,
77 ChangeMedia = 1048576,
78 LandEdit = 2097152,
79 LandOptions = 4194304,
80 AllowEditLand = 8388608,
81 AllowFly = 16777216,
82 AllowRez = 33554432,
83 AllowLandmark = 67108864,
84 AllowVoiceChat = 134217728,
85 AllowSetHome = 268435456,
86 LandManageAllowed = 536870912,
87 LandManageBanned = 1073741824
88 }
89
90namespace OpenSim.Region.CoreModules.World.Permissions 40namespace OpenSim.Region.CoreModules.World.Permissions
91{ 41{
92 public class PermissionsModule : IRegionModule 42 public class PermissionsModule : IRegionModule
@@ -214,7 +164,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
214 m_scene.Permissions.OnDuplicateObject += CanDuplicateObject; 164 m_scene.Permissions.OnDuplicateObject += CanDuplicateObject;
215 m_scene.Permissions.OnDeleteObject += CanDeleteObject; //MAYBE FULLY IMPLEMENTED 165 m_scene.Permissions.OnDeleteObject += CanDeleteObject; //MAYBE FULLY IMPLEMENTED
216 m_scene.Permissions.OnEditObject += CanEditObject; //MAYBE FULLY IMPLEMENTED 166 m_scene.Permissions.OnEditObject += CanEditObject; //MAYBE FULLY IMPLEMENTED
217 m_scene.Permissions.OnEditParcel += CanEditParcel; //MAYBE FULLY IMPLEMENTED 167 m_scene.Permissions.OnEditParcelProperties += CanEditParcelProperties; //MAYBE FULLY IMPLEMENTED
218 m_scene.Permissions.OnInstantMessage += CanInstantMessage; 168 m_scene.Permissions.OnInstantMessage += CanInstantMessage;
219 m_scene.Permissions.OnInventoryTransfer += CanInventoryTransfer; //NOT YET IMPLEMENTED 169 m_scene.Permissions.OnInventoryTransfer += CanInventoryTransfer; //NOT YET IMPLEMENTED
220 m_scene.Permissions.OnIssueEstateCommand += CanIssueEstateCommand; //FULLY IMPLEMENTED 170 m_scene.Permissions.OnIssueEstateCommand += CanIssueEstateCommand; //FULLY IMPLEMENTED
@@ -1005,12 +955,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions
1005 return GenericObjectPermission(editorID, objectID, false); 955 return GenericObjectPermission(editorID, objectID, false);
1006 } 956 }
1007 957
1008 private bool CanEditParcel(UUID user, ILandObject parcel, Scene scene) 958 private bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, Scene scene)
1009 { 959 {
1010 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); 960 DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name);
1011 if (m_bypassPermissions) return m_bypassPermissionsValue; 961 if (m_bypassPermissions) return m_bypassPermissionsValue;
1012 962
1013 return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandDivideJoin); 963 return GenericParcelOwnerPermission(user, parcel, (ulong)p);
1014 } 964 }
1015 965
1016 /// <summary> 966 /// <summary>
diff --git a/OpenSim/Region/Framework/Interfaces/ILandObject.cs b/OpenSim/Region/Framework/Interfaces/ILandObject.cs
index 084184f..585eb00 100644
--- a/OpenSim/Region/Framework/Interfaces/ILandObject.cs
+++ b/OpenSim/Region/Framework/Interfaces/ILandObject.cs
@@ -57,7 +57,7 @@ namespace OpenSim.Region.Framework.Interfaces
57 void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client); 57 void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client);
58 List<UUID> CreateAccessListArrayByFlag(AccessList flag); 58 List<UUID> CreateAccessListArrayByFlag(AccessList flag);
59 void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID, IClientAPI remote_client); 59 void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID, IClientAPI remote_client);
60 void UpdateAccessList(uint flags, List<ParcelManager.ParcelAccessEntry> entries, IClientAPI remote_client); 60 void UpdateAccessList(uint flags, UUID transactionID, int sequenceID, int sections, List<ParcelManager.ParcelAccessEntry> entries, IClientAPI remote_client);
61 void UpdateLandBitmapByteArray(); 61 void UpdateLandBitmapByteArray();
62 void SetLandBitmapFromByteArray(); 62 void SetLandBitmapFromByteArray();
63 bool[,] GetLandBitmap(); 63 bool[,] GetLandBitmap();
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index ab0eed8..1295e58 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -722,20 +722,6 @@ namespace OpenSim.Region.Framework.Scenes
722 #endregion 722 #endregion
723 723
724 #region EDIT PARCEL 724 #region EDIT PARCEL
725 public bool CanEditParcel(UUID user, ILandObject parcel)
726 {
727 EditParcelHandler handler = OnEditParcel;
728 if (handler != null)
729 {
730 Delegate[] list = handler.GetInvocationList();
731 foreach (EditParcelHandler h in list)
732 {
733 if (h(user, parcel, m_scene) == false)
734 return false;
735 }
736 }
737 return true;
738 }
739 725
740 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p) 726 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p)
741 { 727 {
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index d854176..3edc3a2 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -919,7 +919,7 @@ namespace OpenSim.Region.RegionCombinerModule
919 VirtualRegion.Permissions.OnDuplicateObject += BigRegion.PermissionModule.CanDuplicateObject; 919 VirtualRegion.Permissions.OnDuplicateObject += BigRegion.PermissionModule.CanDuplicateObject;
920 VirtualRegion.Permissions.OnDeleteObject += BigRegion.PermissionModule.CanDeleteObject; //MAYBE FULLY IMPLEMENTED 920 VirtualRegion.Permissions.OnDeleteObject += BigRegion.PermissionModule.CanDeleteObject; //MAYBE FULLY IMPLEMENTED
921 VirtualRegion.Permissions.OnEditObject += BigRegion.PermissionModule.CanEditObject; //MAYBE FULLY IMPLEMENTED 921 VirtualRegion.Permissions.OnEditObject += BigRegion.PermissionModule.CanEditObject; //MAYBE FULLY IMPLEMENTED
922 VirtualRegion.Permissions.OnEditParcel += BigRegion.PermissionModule.CanEditParcel; //MAYBE FULLY IMPLEMENTED 922 VirtualRegion.Permissions.OnEditParcelProperties += BigRegion.PermissionModule.CanEditParcelProperties; //MAYBE FULLY IMPLEMENTED
923 VirtualRegion.Permissions.OnInstantMessage += BigRegion.PermissionModule.CanInstantMessage; 923 VirtualRegion.Permissions.OnInstantMessage += BigRegion.PermissionModule.CanInstantMessage;
924 VirtualRegion.Permissions.OnInventoryTransfer += BigRegion.PermissionModule.CanInventoryTransfer; //NOT YET IMPLEMENTED 924 VirtualRegion.Permissions.OnInventoryTransfer += BigRegion.PermissionModule.CanInventoryTransfer; //NOT YET IMPLEMENTED
925 VirtualRegion.Permissions.OnIssueEstateCommand += BigRegion.PermissionModule.CanIssueEstateCommand; //FULLY IMPLEMENTED 925 VirtualRegion.Permissions.OnIssueEstateCommand += BigRegion.PermissionModule.CanIssueEstateCommand; //FULLY IMPLEMENTED
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs
index 393322d..7c662c9 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs
@@ -105,9 +105,9 @@ namespace OpenSim.Region.RegionCombinerModule
105 return m_rootScene.Permissions.CanEditObject(objectid, editorid); 105 return m_rootScene.Permissions.CanEditObject(objectid, editorid);
106 } 106 }
107 107
108 public bool CanEditParcel(UUID user, ILandObject parcel, Scene scene) 108 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers g, Scene scene)
109 { 109 {
110 return m_rootScene.Permissions.CanEditParcel(user, parcel); 110 return m_rootScene.Permissions.CanEditParcelProperties(user, parcel, g);
111 } 111 }
112 112
113 public bool CanInstantMessage(UUID user, UUID target, Scene startscene) 113 public bool CanInstantMessage(UUID user, UUID target, Scene startscene)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 05a4170..835f274 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -6653,16 +6653,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6653 { 6653 {
6654 m_host.AddScriptLPS(1); 6654 m_host.AddScriptLPS(1);
6655 UUID key; 6655 UUID key;
6656 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData; 6656 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
6657 if (land.OwnerID == m_host.OwnerID) 6657 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed))
6658 { 6658 {
6659 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); 6659 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
6660 if (UUID.TryParse(avatar, out key)) 6660 if (UUID.TryParse(avatar, out key))
6661 { 6661 {
6662 entry.AgentID = key; 6662 if (land.LandData.ParcelAccessList.FindIndex(
6663 entry.Flags = AccessList.Access; 6663 delegate(ParcelManager.ParcelAccessEntry e)
6664 entry.Time = DateTime.Now.AddHours(hours); 6664 {
6665 land.ParcelAccessList.Add(entry); 6665 if (e.AgentID == key && e.Flags == AccessList.Access)
6666 return true;
6667 return false;
6668 }) == -1)
6669 {
6670 entry.AgentID = key;
6671 entry.Flags = AccessList.Access;
6672 entry.Time = DateTime.Now.AddHours(hours);
6673 land.LandData.ParcelAccessList.Add(entry);
6674 }
6666 } 6675 }
6667 } 6676 }
6668 ScriptSleep(100); 6677 ScriptSleep(100);
@@ -9493,7 +9502,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9493 // according to the docs, this command only works if script owner and land owner are the same 9502 // according to the docs, this command only works if script owner and land owner are the same
9494 // lets add estate owners and gods, too, and use the generic permission check. 9503 // lets add estate owners and gods, too, and use the generic permission check.
9495 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 9504 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
9496 if (!World.Permissions.CanEditParcel(m_host.OwnerID, landObject)) return; 9505 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return;
9497 9506
9498 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? 9507 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
9499 byte loop = 0; 9508 byte loop = 0;
@@ -9957,16 +9966,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9957 { 9966 {
9958 m_host.AddScriptLPS(1); 9967 m_host.AddScriptLPS(1);
9959 UUID key; 9968 UUID key;
9960 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData; 9969 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
9961 if (land.OwnerID == m_host.OwnerID) 9970 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned))
9962 { 9971 {
9963 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); 9972 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
9964 if (UUID.TryParse(avatar, out key)) 9973 if (UUID.TryParse(avatar, out key))
9965 { 9974 {
9966 entry.AgentID = key; 9975 if (land.LandData.ParcelAccessList.FindIndex(
9967 entry.Flags = AccessList.Ban; 9976 delegate(ParcelManager.ParcelAccessEntry e)
9968 entry.Time = DateTime.Now.AddHours(hours); 9977 {
9969 land.ParcelAccessList.Add(entry); 9978 if (e.AgentID == key && e.Flags == AccessList.Ban)
9979 return true;
9980 return false;
9981 }) == -1)
9982 {
9983 entry.AgentID = key;
9984 entry.Flags = AccessList.Ban;
9985 entry.Time = DateTime.Now.AddHours(hours);
9986 land.LandData.ParcelAccessList.Add(entry);
9987 }
9970 } 9988 }
9971 } 9989 }
9972 ScriptSleep(100); 9990 ScriptSleep(100);
@@ -9976,19 +9994,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9976 { 9994 {
9977 m_host.AddScriptLPS(1); 9995 m_host.AddScriptLPS(1);
9978 UUID key; 9996 UUID key;
9979 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData; 9997 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
9980 if (land.OwnerID == m_host.OwnerID) 9998 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed))
9981 { 9999 {
9982 if (UUID.TryParse(avatar, out key)) 10000 if (UUID.TryParse(avatar, out key))
9983 { 10001 {
9984 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList) 10002 int idx = land.LandData.ParcelAccessList.FindIndex(
9985 { 10003 delegate(ParcelManager.ParcelAccessEntry e)
9986 if (entry.AgentID == key && entry.Flags == AccessList.Access) 10004 {
9987 { 10005 if (e.AgentID == key && e.Flags == AccessList.Access)
9988 land.ParcelAccessList.Remove(entry); 10006 return true;
9989 break; 10007 return false;
9990 } 10008 });
9991 } 10009
10010 if (idx != -1)
10011 land.LandData.ParcelAccessList.RemoveAt(idx);
9992 } 10012 }
9993 } 10013 }
9994 ScriptSleep(100); 10014 ScriptSleep(100);
@@ -9998,19 +10018,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9998 { 10018 {
9999 m_host.AddScriptLPS(1); 10019 m_host.AddScriptLPS(1);
10000 UUID key; 10020 UUID key;
10001 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData; 10021 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
10002 if (land.OwnerID == m_host.OwnerID) 10022 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned))
10003 { 10023 {
10004 if (UUID.TryParse(avatar, out key)) 10024 if (UUID.TryParse(avatar, out key))
10005 { 10025 {
10006 foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList) 10026 int idx = land.LandData.ParcelAccessList.FindIndex(
10007 { 10027 delegate(ParcelManager.ParcelAccessEntry e)
10008 if (entry.AgentID == key && entry.Flags == AccessList.Ban) 10028 {
10009 { 10029 if (e.AgentID == key && e.Flags == AccessList.Ban)
10010 land.ParcelAccessList.Remove(entry); 10030 return true;
10011 break; 10031 return false;
10012 } 10032 });
10013 } 10033
10034 if (idx != -1)
10035 land.LandData.ParcelAccessList.RemoveAt(idx);
10014 } 10036 }
10015 } 10037 }
10016 ScriptSleep(100); 10038 ScriptSleep(100);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index ecd2d6f..712648d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -1342,7 +1342,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1342 return; 1342 return;
1343 } 1343 }
1344 1344
1345 if (! World.Permissions.CanEditParcel(m_host.OwnerID, startLandObject)) 1345 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, startLandObject, GroupPowers.LandOptions))
1346 { 1346 {
1347 OSSLShoutError("You do not have permission to modify the parcel"); 1347 OSSLShoutError("You do not have permission to modify the parcel");
1348 return; 1348 return;