Compare commits

...

197 Commits

Author SHA1 Message Date
8f04e73d70 Update flavour 2026-03-01 08:08:55 +01:00
78ba26088a Merge branch 'master' into lotix 2026-03-01 05:47:46 +01:00
b8f87a029c Merge branch 'master' into lickx 2026-02-27 04:48:39 +01:00
2b5ba52e5d Put these two 'using' back 2026-02-26 20:04:52 +01:00
¡Cinder! ㊝
710bcbb2a0 A few unmistakable bugs I saw while poking (#140)
* Invalid comparison (map to bool/int) Check for null and count properly

* Fix a bad comparison. Good thing OpenSim doesn't support oblong regions.

* Assuming this should throw being that an exception is being created and all...

* ServerReleaseNotesModule.Initialize() returns unless capURL equals "localhost", which is almost certainly unintended.

* Same for EstateAccess

* Harden MapImageServicesConnector a lil bit.
2026-02-26 19:58:01 +01:00
e428722cba Merge branch 'master' into lickx 2026-02-26 19:22:59 +01:00
d0471554aa Merge branch 'master' into lickx 2026-02-26 07:47:37 +01:00
2e933108c4 Suggestions for startup/shutdown_commands.txt.example 2026-02-26 07:45:08 +01:00
lickx
b72fda435b Make denied message customizable 2026-02-22 05:05:51 +01:00
lickx
e838953db8 Merge branch 'master' into lickx 2026-02-18 05:06:57 +01:00
lickx
5d58ca3074 Post-rebase fixes 2026-02-15 13:13:45 +01:00
lickx
ec3388dcce Add sqlite for arm64 linux 2026-02-08 10:17:14 +01:00
lickx
d69bf27629 Extra check verifying local grid user 2026-02-07 15:47:11 +01:00
lickx
2ae41550fe Take name from UserAgentService response
For possible avi name changes, this time proper HG formatted.
Not sure if this is used tho, and no way to test (don't have two grids).
2026-02-07 15:47:11 +01:00
lickx
7adc5b6b51 Default to preserving creator information in IARs
Where --nocreators will not save it
2026-02-07 15:47:11 +01:00
lickx
92fa5975bf Revert "Take firstname and lastname from UserAgentService response"
This reverts commit de00d96c9b.
2026-02-07 15:47:11 +01:00
lickx
425cdb420e Take firstname and lastname from UserAgentService response 2026-02-07 15:47:11 +01:00
lickx
3f42069f42 Revert to regular version string, but with Lickx as flavour
For better compatibility with scripts that check for a minimum OpenSim version
2026-02-07 15:47:11 +01:00
lickx
6061e48d09 Verify avatar name taking into account name changes 2026-02-07 15:47:11 +01:00
lickx
e950829c94 Now does allow GridService from other instance 2026-02-07 15:47:11 +01:00
lickx
20492ac080 Partial revert commit aed3df84a7
Can't assume GridService runs within same instance as GridInfoService
2026-02-07 15:47:11 +01:00
lickx
624775f5f4 Mantis 9199: Add new (to be) hg friends to GridUser table
Now after confirming friendship on the homegrid, immediately instant
messages can be exchanged, without the foreign friend ever having to
have visited our grid before.
2026-02-07 15:47:11 +01:00
lickx
9a0de63ae7 Cleanup a bit for mantis 8366 2026-02-07 15:47:11 +01:00
lickx
5dcc178ea3 Correct exclusion for making zips 2026-02-07 15:47:11 +01:00
lickx
88ea8915a4 Exclude Opensim.Modules.Currency.* from main zip 2026-02-07 15:47:11 +01:00
lickx
81afed722b Include economy section example 2026-02-07 15:47:11 +01:00
lickx
6d0c6c00f8 Synchronize with OpenSimSearch-lickx 2026-02-07 15:47:11 +01:00
lickx
b2d37a7129 Re-introduce ForceViewersUpdateName
To see if this will help name changes propagate
2026-02-07 15:47:11 +01:00
lickx
7f63b6fabc Synchronise with OpenSimSearch-lickx 2026-02-07 15:47:11 +01:00
lickx
6f1dd37bd4 Use ILIKE where applicable 2026-02-07 15:47:07 +01:00
lickx
724a447b68 Update mkdist -- copy auxiliary opensim.currency files 2026-02-07 15:43:59 +01:00
lickx
a1681f2247 Update DeniedClients suggestion 2026-02-07 15:43:59 +01:00
lickx
8e5524d412 Include slightly modified economy helper
Original by https://github.com/magicoli/opensim-helpers which may
provide more functionality for other things
2026-02-07 15:43:59 +01:00
lickx
4cd1faab46 Update mkdist 2026-02-07 15:43:59 +01:00
lickx
67700ea1ed Put back a comment about permission control 2026-02-07 15:43:59 +01:00
lickx
cbd586792b forceGridAdminsOnly and forceGridGodsOnly is no longer needed 2026-02-07 15:43:59 +01:00
lickx
115887fc10 Remove godmode for region owners+admins
From now on only possible for user level >= 200
2026-02-07 15:43:59 +01:00
lickx
333d837da6 Reapply "remove option ClampNegativeZ"
This reverts commit 667695b393.
2026-02-07 15:43:59 +01:00
lickx
8d8217951d Reapply "mantis 9133 replace some z < 0 checks by < Constants.MinSimulationHeight (-100)"
This reverts commit cb1bde70db.
2026-02-07 15:43:59 +01:00
lickx
e1459301af Reapply "a few more changes on terrain"
This reverts commit ce1f31864f.
2026-02-07 15:43:59 +01:00
lickx
06c1c683e5 Reapply "Fix SmoothArea to be uniform again"
This reverts commit 1d92dee88c.
2026-02-07 15:43:59 +01:00
lickx
67bb7ab857 Reapply "try to fix some terrain issues, Add some more locking"
This reverts commit 103e21f3ed.
2026-02-07 15:43:55 +01:00
lickx
14d4d4e138 Comment out debug message for animation overrides 2026-02-07 15:43:06 +01:00
lickx
79d20b92fb Only work on imap when connected 2026-02-07 15:43:05 +01:00
lickx
328d9b51a7 Add crontab example, update a readme for mutes 2026-02-07 15:43:05 +01:00
lickx
0aebf3fbdf Revert "try to fix some terrain issues, Add some more locking"
This reverts commit e5d10bf127.
2026-02-07 15:43:02 +01:00
lickx
9a1a56bec8 Revert "Fix SmoothArea to be uniform again"
This reverts commit b1a2773de9.
2026-02-07 15:38:47 +01:00
lickx
7a1c2fe908 Revert "a few more changes on terrain"
This reverts commit 9a02b55bf2.
2026-02-07 15:38:47 +01:00
lickx
de1ea30ad3 Revert "mantis 9133 replace some z < 0 checks by < Constants.MinSimulationHeight (-100)"
This reverts commit f2379dc785.
2026-02-07 15:38:47 +01:00
lickx
49101a579d Revert "remove option ClampNegativeZ"
This reverts commit 9a92d94e99.
2026-02-07 15:38:47 +01:00
lickx
04962f9050 Add administrator check in HGEntityTransferModule 2026-02-07 15:38:47 +01:00
lickx
f2110c6505 Add support files for search and mutelist module 2026-02-07 15:38:47 +01:00
lickx
3ff7d53339 Name zip opensimcurrency instead of moneymodule
But really i use a seperate mkdist for packing opensim.currency
which also includes working helper scripts
2026-02-07 15:38:47 +01:00
lickx
a596034fb7 Make the finished loading message more useful 2026-02-07 15:38:47 +01:00
lickx
2d1573fc4f Set attachments to group and resume scripts for XmlRpcGroups 2026-02-07 15:38:40 +01:00
lickx
bb6cf5e9fe Add opensim.currency support to mkdist 2026-02-07 15:38:40 +01:00
lickx
23dd51c733 Also update grouptag for XmlRpcGroups 2026-02-07 15:38:40 +01:00
lickx
fa0619a15f Fix grouptag not updating after active role change 2026-02-07 15:38:40 +01:00
lickx
cf42b9925f Correct version string length 2026-02-07 15:38:40 +01:00
lickx
e42cf9730f compile.* will be generated by prebuild 2026-02-07 15:38:40 +01:00
lickx
dd059866d9 Add save oar --tenant= option for saving stuff
This is mainly useful for multi tenancy sims where a user requests an oar
of their stuff, and where you don't want to pass out other people's stuff.
2026-02-07 15:38:40 +01:00
lickx
db8ba76c1e Make default slurl prefix more opensim-like
While still remaining compatible with declined RLVa inventory offers
2026-02-07 15:38:36 +01:00
lickx
08e5fa095d null check, not everyone runs with a group module 2026-02-07 15:37:08 +01:00
lickx
1cd2361936 Revert folder version to ushort as in upstream
A signed int was a bad idea because of rollover
into the negative -sizeof(int)

To illustrate, my 'Current Outfits' folder version
is now, about 1 year after born, version 33000
2026-02-07 15:37:08 +01:00
lickx
7a6b3b3bf2 Correct offset clamp for PRIM_NORMAL 2026-02-07 15:37:08 +01:00
lickx
d5e41cee02 Do include *.pdb files in zips 2026-02-07 15:37:07 +01:00
lickx
b19f50904e Make cache an option, for issue #25 2026-02-07 15:37:04 +01:00
lickx
68eb1595ac Re-introduce SIGTERM signal handling
According to the .NET 6/8 docs, this is handled on Windows as well
2026-02-07 15:34:52 +01:00
lickx
825b1f7f98 Rework incoming attachments (HGEntityTransfer)
Avatar will progressively load now instead of waiting until all attached
assets are complete. Also optimize, cleanup etc.
2026-02-07 15:34:47 +01:00
lickx
e651278a54 llGetTimeOfDay() and llGetRegionTimeOfDay based on Environment
llGetTimeOfDay() is based on the current parcel environment, while
llGetRegionTimeOfDay() is based on the region environment

With a fallback on the hardcoded way we did this if no environment module
is active
2026-02-07 15:30:31 +01:00
lickx
3f658e414b Allow defining path where to store generated MAP-uuid.png
Defaults to the folder containing OpenSim.dll/.exe for legacy compatibility
2026-02-07 15:30:31 +01:00
lickx
f569e656d5 Use the shorthand 'mailname' from now on
objectmail_hostname will be deprecated but will still work
2026-02-07 15:30:31 +01:00
lickx
1b604f90bc Revert "some changes to PresenceServerPostHandler"
This reverts commit 81cfd6e956.
2026-02-07 15:30:09 +01:00
lickx
3085953ce5 Add examples of bad viewers in line with the Wiki 2026-02-07 15:30:09 +01:00
lickx
9090af50ec Always allow http requests to prim webservers 2026-02-07 15:30:09 +01:00
user
79b232ef60 Update build files 2026-02-07 15:30:08 +01:00
user
16059f43e2 Simplify loading attachments message 2026-02-07 15:30:08 +01:00
lickx
f15b058aa2 Fix mkdist.sh for OpenSimMutelist 2026-02-07 15:30:08 +01:00
lickx
2a00fd45ae Add scripts to make binary zips for distribution 2026-02-07 15:30:08 +01:00
lickx
f375db2f50 Add OpenSimSearch to the addons
It is used by nearly everyone
2026-02-07 15:30:08 +01:00
lickx
e2fa62623b Reject hypergrid visitors with just an IP address as homeURI 2026-02-07 15:28:02 +01:00
lickx
8f5cc78c74 Properly update lastowner info
In that Other Grid, it used to be done on inventory detach too, but that
seems no longer to be the case.
2026-02-07 15:28:02 +01:00
lickx
6f5083e5c7 Implement lxGetAgentViewer
This was an old request
2026-02-07 15:27:55 +01:00
lickx
02c088de00 Revert DefaultWater
I forgot my motivation I once had to modify it, but with the master
version I can create AND open a new Water setting in my inv again.

You might have to issue 'fcache deletedefaultassets' in your simulator,
AND clear your viewer cache.
2026-02-07 15:27:55 +01:00
lickx
69d8b70bba Enable sim-local mail by default
This is safe. With this setup mail addressed to outside destinations
(any address not ending in internal_object_host) is silently discarded.
By default the internal_object_host is defined as lsl.opensim.local
2026-02-07 15:27:55 +01:00
lickx
b97cacc712 Add "objectmail_hostname" to llGetEnv()
It returns the part after the @ for an object's email address
2026-02-07 15:27:55 +01:00
lickx
b218c303c5 Addressing an force-tp edge case, closes #22 2026-02-07 15:11:38 +01:00
lickx
dca12b5427 SMTPConfig -> EmailConfig 2026-02-07 15:11:38 +01:00
lickx
1b2d0d2ddc Change SMTP section to the more descriptive Email 2026-02-07 15:11:38 +01:00
lickx
174da88c88 Implement "region_rating" and "grid" in llGetEnv() 2026-02-07 15:11:38 +01:00
lickx
140ac4d19e Make this work correctly 2026-02-07 15:11:38 +01:00
lickx
b4e36ca262 Remove feature for now
This caused land sales for more than 0L to not work for local users,
at least with Gloebit. This check will probably need to happen elsewhere
but idk where yet
2026-02-07 15:11:38 +01:00
lickx
916f22ba67 Neater 2026-02-07 15:11:38 +01:00
lickx
d3433c1bc1 Revert "Only allow local residents to create groups"
This reverts commit df59617648.
Duplicate code, see CreateGroup() in GroupsServiceHGConnectorModule.cs
2026-02-07 15:11:38 +01:00
lickx
0e935cd69f Implement a request for a custom ban message 2026-02-07 15:11:38 +01:00
lickx
dc2ea0fc9b Unbreak 18+/PIOF access restrictions for parcels
(Was already OK for estates)
2026-02-07 15:11:38 +01:00
lickx
f05f84ce9f Add the PAYMENT_* constants as well 2026-02-07 15:11:34 +01:00
lickx
bac614f7cf Make ALL llRequestAgentData requests working
Before, only DATA_ONLINE worked and DATA_PAYINFO wasn't implemented
2026-02-07 15:10:17 +01:00
lickx
172c5947af Check for the full address, not just the key 2026-02-07 15:00:39 +01:00
lickx
0e005da8d9 Clean up a bit 2026-02-07 15:00:39 +01:00
lickx
6cdaf25a24 Syntax 2026-02-07 15:00:38 +01:00
lickx
41af43f591 Avoid double messages 2026-02-07 15:00:38 +01:00
lickx
ab99c42f25 Fix filtered e-mail search 2026-02-07 15:00:38 +01:00
lickx
70c9172f2c Comment typo in the new IMAP config 2026-02-07 15:00:38 +01:00
lickx
79feac5698 Implement intersim object2object e-mail for LSL 2026-02-07 15:00:38 +01:00
lickx
e27aecf254 One oops 2026-02-07 15:00:38 +01:00
lickx
c62e66863f This is a better place for it 2026-02-07 14:59:56 +01:00
lickx
d39e3fcd69 Mantis 8366: logins have GotAttachmentsData true 2026-02-07 14:57:36 +01:00
lickx
6afca908c7 Fixes #14 2026-02-07 14:56:11 +01:00
lickx
bf9449b3fe Revert "Description column should be 127 bytes UTF-8 string"
This reverts commit 27e0684cbc.
2026-02-07 14:55:01 +01:00
lickx
fc311fe4f3 Revert "Update MAX_ASSET_DESC also"
This reverts commit 25ff65ae05.
2026-02-07 14:55:01 +01:00
lickx
a543e6a2c6 Only attempt to resume scripts when they exist 2026-02-07 14:42:55 +01:00
lickx
b5fb4ed393 Stop resume scripts if HG user left the scene early 2026-02-07 14:40:36 +01:00
lickx
44c88b7258 Remove an unused optional feature for code clarity 2026-02-07 14:38:24 +01:00
lickx
a3ca1ed98f Update MAX_ASSET_DESC also 2026-02-07 14:30:29 +01:00
lickx
6b223bb913 Description column should be 127 bytes UTF-8 string 2026-02-07 14:30:29 +01:00
lickx
92acfc91fb More informative message to HG visitors, closes #20 2026-02-07 14:24:16 +01:00
lickx
0b209d31c8 Inform foreign visitors the HGTP is complete
And thus their avi should be fully rezzed, and attachments working
2026-02-07 14:24:16 +01:00
lickx
053cf1066b Re-implement per-friend notifications, closes #19
Slightly less performant than per-domain, but it works well
2026-02-07 14:24:16 +01:00
lickx
d733e45971 Use groupname if the abandoned parcel was group-owned 2026-02-07 14:24:16 +01:00
lickx
b53db82072 Improve new take_copy_restricted functionality 2026-02-07 14:24:11 +01:00
lickx
9110cfd111 Revert "Addendum to 7a6e51552eac81ca5c527f2749c74e983276ab1b"
This reverts commit c5b3697eaa.
2026-02-07 14:22:17 +01:00
lickx
91907c428f Addendum to 7a6e51552e 2026-02-07 14:22:17 +01:00
lickx
aad0041cbe Do away with cache
It doesn't work well with multiple instances behind a proxy
2026-02-07 14:22:17 +01:00
lickx
bc6cb895f9 This is a better place for it 2026-02-07 14:22:17 +01:00
lickx
4b7ad320c0 Implement functional per-domain status notifications
See commit
2026-02-07 14:22:13 +01:00
lickx
04b2365607 Use per- HG friend notify for now in HGStatusNotifier
The domain based Notify never worked; It would notify the wrong grids.
Will look later if the domain based notify can be fixed somehow, since
it would save overhead.

Also, revert most of Nani's friendmodules changes back to upstream since
that is not where the culprit was.

So yay, we have working online/offline notifications for HG friends!
2026-02-07 14:20:45 +01:00
lickx
26c366e81f Mantis 8366: logins have GotAttachmentsData true 2026-02-07 14:20:45 +01:00
lickx
3682b9ab8a Addendum to 7a9c591f99 2026-02-07 14:20:45 +01:00
lickx
9a43983e0c Fixes #14 2026-02-07 14:20:45 +01:00
lickx
4941818556 Revert "Description column should be 127 bytes UTF-8 string"
This reverts commit 4e3b0129fe.
2026-02-07 14:20:45 +01:00
lickx
f677811a63 Revert "Update MAX_ASSET_DESC also"
This reverts commit d98b77a229.
2026-02-07 14:20:45 +01:00
lickx
48b6782b83 Update comment info on texture asset 2026-02-07 14:20:44 +01:00
lickx
3fbea2622f Use FireAndForget with logout, be less verbose on login
Again, all credits to Nani
2026-02-07 14:20:44 +01:00
lickx
d40fc991d6 More work from Nani on HG friends notifications 2026-02-07 14:20:44 +01:00
lickx
3e57932370 Shorten expiry time 2026-02-07 14:20:44 +01:00
lickx
f7178a3a1d Correct IMG_BLOOM1 2026-02-07 14:20:44 +01:00
lickx
07e13760c8 Provide detailed info in abandoned land desc..
..which is handy for estate owner/managers and their land administration

Also set back autoreturn to 0 on reclaimed land, because in this case
the estate owner/manager will manually deal with the cleanup themselves
and might decide to leave (some) objects of the previous owner rezzed out.
2026-02-07 14:20:40 +01:00
lickx
81bfcb7578 Make allowing HG residents to buy parcels an option
By default this option is true (like in vanilla OpenSim)
2026-02-07 14:20:40 +01:00
lickx
db0378e288 Only allow local residents to create groups 2026-02-07 14:20:40 +01:00
lickx
755ed260af Mark version as being from our repo, to avoid confusion 2026-02-07 14:20:30 +01:00
lickx
65eb015e0c Add to help the new bit about parcels for --default-user 2026-02-07 14:20:26 +01:00
lickx
ee0393228b Safe perms for abandoned and reclaimed land 2026-02-07 14:19:01 +01:00
lickx
286ed354af Besides objects, also let default user be parcel owner
Because parcel owner and estate owner may differ
2026-02-07 14:18:34 +01:00
lickx
11583534a6 Convert category to int from classifieds
Thanks OpenSim-NGC
2026-02-07 14:18:34 +01:00
lickx
7b330504b3 Testing code from nani 2026-02-07 14:18:34 +01:00
lickx
b923c9e5bc Lowercase some asset UUID's, include water texture in setting 2026-02-07 14:17:55 +01:00
lickx
0a28fda92e Remove obsolete map throttle for FS
That was for one specific very old Firestorm, which is no longer allowed on OsGrid and other grids
2026-02-07 14:17:55 +01:00
lickx
f456192e93 One more check 2026-02-07 14:17:55 +01:00
lickx
7b3c2382f7 Only attempt to resume scripts when they exist 2026-02-07 14:17:55 +01:00
lickx
664cb64de7 Apply revert again, it is needed to unbreak scripted objects
That change causes more breakage! So we undo it.
Expect some mantises from people on that one lol
2026-02-07 14:17:55 +01:00
lickx
5a77847e21 Revert "Revert an upstream change"
This reverts commit c971a55f48.

The issue that the revert solved, was caused by a bad script
2026-02-07 14:17:55 +01:00
lickx
515d55a497 Stop resume scripts if HG user left the scene early 2026-02-07 14:17:55 +01:00
lickx
16e884d467 Revert "Revert "change lsl integer parsing""
This reverts commit b1f64a2dd0.
2026-02-07 14:17:55 +01:00
lickx
6a413bfd0b Revert "change lsl integer parsing"
This reverts commit 92e25a9377.
2026-02-07 14:17:51 +01:00
lickx
8a4c0a9b0e Move incoming agent from debug to info logging 2026-02-07 14:14:08 +01:00
lickx
4c507e8ee4 There is no classifieds datastore 2026-02-07 14:14:08 +01:00
lickx
f3dbaae928 Add missing classifieds table 2026-02-07 14:14:08 +01:00
lickx
95e79136cc Revert an upstream change
That caused issues with button positioning on HUDs and possibly
other objects
2026-02-07 14:14:04 +01:00
lickx
0f9690d8a3 XEngine is no longer an option, so remove config 2026-02-07 14:12:35 +01:00
lickx
fb412ddfdf Remove an unused optional feature for code clarity 2026-02-07 14:11:38 +01:00
lickx
03c9e20c82 Also set attachments to group on HG entity transfer
(We already sorted starting their scripts in another patch, mantis 8366)
2026-02-07 14:10:28 +01:00
lickx
818e201f54 Change attachments group and start scripts on group change 2026-02-07 14:10:28 +01:00
lickx
1b4ad7326f Update MAX_ASSET_DESC also 2026-02-07 14:10:28 +01:00
lickx
e9148bb4d9 Description column should be 127 bytes UTF-8 string 2026-02-07 14:10:28 +01:00
lickx
cda9718013 Better (safer) land defaults 2026-02-07 14:10:24 +01:00
lickx
cef10eaf8e Make llGiveInventory work for HG receipants 2026-02-07 14:09:02 +01:00
lickx
89c04491cc Update log strings 2026-02-07 14:05:41 +01:00
lickx
3b4ff99c66 Put back god stuff in OpenSim.ini
Note that on our branch region_owner_is_god defaults to false,
so it will only be enabled by setting that line to true in the ini!
2026-02-07 14:05:41 +01:00
lickx
7197e1458e No that didn't work for the Bento issue 2026-02-07 14:00:41 +01:00
lickx
870e7d09db Try this the old way 2026-02-07 13:59:44 +01:00
lickx
ff445c9434 Revert "Revert "mantis 9025: reduce latency a bit""
This reverts commit 5670b03208.
2026-02-07 13:58:36 +01:00
lickx
1b20e27f47 Revert "Revert "a few changes to local console; add pooling of Console.KeyAvailable instead of waiting on keyread, that has treading issues. Thanks ALicia for some ideas on this""
This reverts commit 752d871e44.
2026-02-07 13:58:29 +01:00
lickx
e6c7be8ca6 Revert "a few changes to local console; add pooling of Console.KeyAvailable instead of waiting on keyread, that has treading issues. Thanks ALicia for some ideas on this"
This reverts commit 87ba2d7b43.
2026-02-07 13:52:14 +01:00
lickx
c98fc5cade Revert "mantis 9025: reduce latency a bit"
This reverts commit 086fcc7ff7.
2026-02-07 13:48:24 +01:00
lickx
e23eeabd26 Change release notes link 2026-02-07 13:46:25 +01:00
lickx
accaa74344 Add pre-EEP sun, issue 2 2026-02-07 13:45:54 +01:00
lickx
154750c31d Upgrade ground textures, closes #1 2026-02-07 13:45:50 +01:00
lickx
1eb6f8fed9 Add missing assets, closes #2 2026-02-07 13:44:25 +01:00
lickx
e3c61b77e9 Try to fix mousewalk 2026-02-07 13:44:25 +01:00
lickx
9e399f51b0 Preserve formatting from master, for cleaner diffs
Also rephrase the slurl stuff
2026-02-07 13:44:22 +01:00
lickx
fdb7b13016 More sane godmode defaults 2026-02-07 13:43:50 +01:00
lickx
7999dce95e Line endings... 2026-02-07 13:43:47 +01:00
lickx
2dc7a7cf16 Less drastic, but still ethical defaults 2026-02-07 13:42:40 +01:00
lickx
4de6df9c6b Discourage god mode in the example config 2026-02-07 13:41:04 +01:00
lickx
efb9370527 No god mode for region owners by default 2026-02-07 13:41:04 +01:00
lickx
9bff1e873e Always return empty string for osGetAgentIP 2026-02-07 13:40:59 +01:00
lickx
221c43b6d1 Faster vector checking 2026-02-07 13:38:59 +01:00
lickx
328c5b3692 Add hardened permissions option 2026-02-07 13:38:18 +01:00
lickx
504ab61fab Make viewer allow/ban list work for sims 2026-02-07 13:35:24 +01:00
lickx
2c5df5ea6a Use int for folder versions 2026-02-07 13:34:05 +01:00
lickx
72abced38d Unicode profiles and picks 2026-02-07 13:34:05 +01:00
lickx
c9940aa509 Mantis 8539 2026-02-07 13:34:05 +01:00
lickx
a0ffcd98a1 Use avatar rotation for attachments with local=true
Signed-off-by: lickx <sinesurfer@gmail.com>
2026-02-07 13:34:05 +01:00
lickx
d0b5c47088 Mantis 8366
Signed-off-by: lickx <sinesurfer@gmail.com>
2026-02-07 13:34:00 +01:00
lickx
7624dda74c Improve MoveToTarget for Mantis 8250
Signed-off-by: lickx <sinesurfer@gmail.com>
2026-02-07 13:32:49 +01:00
lickx
4fd189776a Mantis 6311
Signed-off-by: lickx <sinesurfer@gmail.com>
2026-02-07 13:32:12 +01:00
116 changed files with 5923 additions and 710 deletions

View File

@@ -706,6 +706,21 @@ namespace OpenSim.Groups
m_groupData.SetAgentActiveGroup(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID);
ScenePresence sp = ((Scene)(remoteClient.Scene)).GetScenePresence(remoteClient.AgentId);
List<SceneObjectGroup> attachments = sp.GetAttachments();
foreach(SceneObjectGroup so in attachments)
{
//m_log.DebugFormat("[GROUPS MODULE]: Setting new group and checking scripts to run in attachment {0} for {1}", so.Name, so.OwnerID);
so.SetGroup(groupID, remoteClient);
if (so.ContainsScripts() && so.RunningScriptCount() == 0)
{
so.RootPart.ParentGroup.CreateScriptInstances(
0, false, sp.Scene.DefaultScriptEngine, sp.GetStateSource());
so.ResumeScripts();
}
}
// Changing active group changes title, active powers, all kinds of things
// anyone who is in any region that can see this client, should probably be
// updated with new group info. At a minimum, they should get ScenePresence
@@ -981,11 +996,16 @@ namespace OpenSim.Groups
{
if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
m_groupData.SetAgentActiveGroupRole(GetRequestingAgentIDStr(remoteClient), GetRequestingAgentIDStr(remoteClient), groupID, titleRoleID);
UUID agentID = remoteClient.AgentId;
m_groupData.SetAgentActiveGroupRole(agentID.ToString(), agentID.ToString(), groupID, titleRoleID);
// TODO: Not sure what all is needed here, but if the active group role change is for the group
// the client currently has set active, then we need to do a scene presence update too
// if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID)
// If the active group role change is for the group
// the client currently has set active, then we need to
// set the active group again for the tag to update
if (m_groupData.GetAgentActiveMembership(agentID.ToString(), agentID.ToString()).GroupID == groupID)
{
m_groupData.SetAgentActiveGroup(agentID.ToString(), agentID.ToString(), groupID);
}
SendDataUpdate(remoteClient, true);
}

View File

@@ -84,3 +84,14 @@ CREATE TABLE IF NOT EXISTS `usersettings` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
commit;
:VERSION 6 # Unicode profiles
ALTER TABLE classifieds CONVERT TO CHARACTER SET utf8;
ALTER TABLE usernotes CONVERT TO CHARACTER SET utf8;
ALTER TABLE userpicks CONVERT TO CHARACTER SET utf8;
ALTER TABLE userprofile CONVERT TO CHARACTER SET utf8;
ALTER TABLE userdata CONVERT TO CHARACTER SET utf8;
commit;

View File

@@ -192,7 +192,7 @@ namespace OpenSim.Data.Null
foreach (RegionData r in m_regionData.Values)
{
if (r.posX + r.sizeX > startX && r.posX <= endX
&& r.posY + r.sizeX > startY && r.posY <= endY)
&& r.posY + r.sizeY > startY && r.posY <= endY)
ret.Add(r);
}
}

View File

@@ -61,7 +61,7 @@ namespace OpenSim.Data.PGSQL
public GridUserData[] GetAll(string userID)
{
return base.Get(String.Format("\"UserID\" LIKE '{0}%'", userID));
return base.Get(String.Format("\"UserID\" ILIKE '{0}%'", userID));
}
}

View File

@@ -92,7 +92,7 @@ namespace OpenSim.Data.PGSQL
}
else
{
pattern = " \"ShowInList\" = 1 AND lower(\"Name\") LIKE lower('%" + pattern + "%')";
pattern = " \"ShowInList\" = 1 AND \"Name\" ILIKE '%" + pattern + "%'";
return m_Groups.Get(pattern, new NpgsqlParameter("pattern", pattern));
}

View File

@@ -98,7 +98,7 @@ namespace OpenSim.Data.PGSQL
public List<RegionData> Get(string regionName, UUID scopeID)
{
string sql = "select * from "+m_Realm+" where lower(\"regionName\") like lower(:regionName) ";
string sql = "select * from "+m_Realm+" where \"regionName\" ILIKE :regionName ";
if (!scopeID.IsZero())
sql += " and \"ScopeID\" = :scopeID";
sql += " order by lower(\"regionName\")";

View File

@@ -298,14 +298,14 @@ namespace OpenSim.Data.PGSQL
{
if (words.Length == 1)
{
sql = String.Format(@"select * from {0} where (""ScopeID""=:ScopeID or ""ScopeID""=:UUIDZero) and (LOWER(""FirstName"" COLLATE ""en_US.utf8"") like LOWER(:search) or LOWER(""LastName"" COLLATE ""en_US.utf8"") like LOWER(:search))", m_Realm);
sql = String.Format(@"select * from {0} where (""ScopeID""=:ScopeID or ""ScopeID""=:UUIDZero) and (""FirstName"" COLLATE ""en_US.utf8"" ILIKE :search or ""LastName"" COLLATE ""en_US.utf8"" ILIKE :search)", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("ScopeID", scopeID));
cmd.Parameters.Add (m_database.CreateParameter("UUIDZero", UUID.Zero));
cmd.Parameters.Add(m_database.CreateParameter("search", "%" + words[0] + "%"));
}
else
{
sql = String.Format(@"select * from {0} where (""ScopeID""=:ScopeID or ""ScopeID""=:UUIDZero) and (LOWER(""FirstName"" COLLATE ""en_US.utf8"") like LOWER(:searchFirst) or LOWER(""LastName"" COLLATE ""en_US.utf8"") like LOWER(:searchLast))", m_Realm);
sql = String.Format(@"select * from {0} where (""ScopeID""=:ScopeID or ""ScopeID""=:UUIDZero) and (""FirstName"" COLLATE ""en_US.utf8"" ILIKE :searchFirst or ""LastName"" COLLATE ""en_US.utf8"" ILIKE :searchLast)", m_Realm);
cmd.Parameters.Add(m_database.CreateParameter("searchFirst", "%" + words[0] + "%"));
cmd.Parameters.Add(m_database.CreateParameter("searchLast", "%" + words[1] + "%"));
cmd.Parameters.Add (m_database.CreateParameter("UUIDZero", UUID.Zero));

View File

@@ -63,7 +63,7 @@ namespace OpenSim.Framework
private uint _flags = (uint)ParcelFlags.AllowFly | (uint)ParcelFlags.AllowLandmark |
(uint)ParcelFlags.AllowAPrimitiveEntry |
(uint)ParcelFlags.AllowDeedToGroup |
(uint)ParcelFlags.CreateObjects | (uint)ParcelFlags.AllowOtherScripts |
(uint)ParcelFlags.AllowOtherScripts |
(uint)ParcelFlags.AllowVoiceChat;
private byte _landingType = (byte)OpenMetaverse.LandingType.Direct;
@@ -84,7 +84,7 @@ namespace OpenSim.Framework
private UUID _snapshotID = UUID.Zero;
private Vector3 _userLocation = new();
private Vector3 _userLookAt = new();
private int _otherCleanTime = 0;
private int _otherCleanTime = 5;
private string _mediaType = "none/none";
private string _mediaDescription = "";
private int _mediaHeight = 0;

View File

@@ -240,10 +240,12 @@ namespace OpenSim.Framework
// m_log.DebugFormat("[OUTBOUND URL FILTER]: Found [{0}] in blacklist for {1}", url, Name);
// Check blacklist exceptions
allowed
= OutboundUrlFilter.IsInNetwork(
addr, url.Port, m_blacklistExceptionNetworks, m_blacklistExceptionEndPoints, Name);
if (!url.AbsolutePath.StartsWith("/lslhttp/"))
{
allowed
= OutboundUrlFilter.IsInNetwork(
addr, url.Port, m_blacklistExceptionNetworks, m_blacklistExceptionEndPoints, Name);
}
// if (allowed)
// m_log.DebugFormat("[OUTBOUND URL FILTER]: Found [{0}] in whitelist for {1}", url, Name);
}

View File

@@ -110,10 +110,10 @@ namespace OpenSim.Framework
/// <value>
/// These appear to be terrain textures that are shipped with the client.
/// </value>
public static readonly UUID DEFAULT_TERRAIN_TEXTURE_1 = new("b8d3965a-ad78-bf43-699b-bff8eca6c975");
public static readonly UUID DEFAULT_TERRAIN_TEXTURE_2 = new("abb783e6-3e93-26c0-248a-247666855da3");
public static readonly UUID DEFAULT_TERRAIN_TEXTURE_3 = new("179cdabd-398a-9b6b-1391-4dc333ba321f");
public static readonly UUID DEFAULT_TERRAIN_TEXTURE_4 = new("beb169c7-11ea-fff2-efe5-0f24dc881df2");
public static readonly UUID DEFAULT_TERRAIN_TEXTURE_1 = new("0bc58228-74a0-7e83-89bc-5c23464bcec5");
public static readonly UUID DEFAULT_TERRAIN_TEXTURE_2 = new("63338ede-0037-c4fd-855b-015d77112fc8");
public static readonly UUID DEFAULT_TERRAIN_TEXTURE_3 = new("303cd381-8560-7579-23f1-f0a880799740");
public static readonly UUID DEFAULT_TERRAIN_TEXTURE_4 = new("53a2f406-4895-1d13-d541-d2e3b86bc19c");
public static readonly UUID DEFAULT_TERRAIN_PBR_1 = new("b8d3965a-ad78-bf43-699b-bff8eca6c975");
public static readonly UUID DEFAULT_TERRAIN_PBR_2 = new("abb783e6-3e93-26c0-248a-247666855da3");

View File

@@ -281,7 +281,7 @@ namespace OpenSim.Framework.Serialization.External
writer.WriteStartElement("GroupOwned");
writer.WriteString(inventoryItem.GroupOwned.ToString());
writer.WriteEndElement();
if (options.ContainsKey("creators") && !string.IsNullOrEmpty(inventoryItem.CreatorData))
if (!options.ContainsKey("nocreators") && !string.IsNullOrEmpty(inventoryItem.CreatorData))
writer.WriteElementString("CreatorData", inventoryItem.CreatorData);
else if (options.ContainsKey("home"))
{

View File

@@ -32,7 +32,7 @@ namespace OpenSim
public const string VersionNumber = "0.9.3.1";
public const string AssemblyVersionNumber = "0.9.3.1";
public const Flavour VERSION_FLAVOUR = Flavour.Dev;
public const Flavour VERSION_FLAVOUR = Flavour.Lotix;
public enum Flavour
{
@@ -43,7 +43,8 @@ namespace OpenSim
RC3,
Release,
Post_Fixes,
Extended
Extended,
Lotix
}
public static string Version
@@ -57,7 +58,7 @@ namespace OpenSim
return versionString.PadRight(VERSIONINFO_VERSION_LENGTH);
}
public const int VERSIONINFO_VERSION_LENGTH = 27;
public const int VERSIONINFO_VERSION_LENGTH = 29;
/// <value>
/// This is the external interface version. It is separate from the OpenSimulator project version.

View File

@@ -38,6 +38,7 @@ using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
using System.Net;
using System.Runtime.InteropServices;
using log4net;
using NDesk.Options;
using Nini.Config;
@@ -79,6 +80,7 @@ namespace OpenSim
private string m_timedScript = "disabled";
private int m_timeInterval = 1200;
private System.Timers.Timer m_scriptTimer;
private PosixSignalRegistration m_signalReg;
public OpenSim(IConfigSource configSource) : base(configSource)
{
@@ -132,6 +134,12 @@ namespace OpenSim
m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod);
m_log.InfoFormat("[OPENSIM MAIN] Running GC in {0} mode", GCSettings.IsServerGC ? "server":"workstation");
m_signalReg = PosixSignalRegistration.Create(PosixSignal.SIGTERM, context =>
{
m_log.Info("Received SIGTERM, shutting down");
MainConsole.Instance.RunCommand("shutdown");
});
}
/// <summary>
@@ -301,9 +309,9 @@ namespace OpenSim
+ "--skip-assets will load the OAR but ignore the assets it contains.\n"
+ "--force-assets will load the OAR and try to upload the assets it contains.\n"
+ " it will REPLACE those assets on local region cache\n"
+ " it will also try to upload them to service, but that only work if they are not present"
+ " Avoid using this except for some recovery attempts"
+ "--default-user will use this user for any objects with an owner whose UUID is not found in the grid.\n"
+ " it will also try to upload them to service, but that only work if they are not present\n"
+ " Avoid using this except for some recovery attempts\n"
+ "--default-user will use this user for any objects and parcels with an owner whose UUID is not found in the grid.\n"
+ "--no-objects suppresses the addition of any objects (good for loading only the terrain).\n"
+ "--rotation specified rotation to be applied to the oar. Specified in degrees.\n"
+ "--bounding-origin will only place objects that after displacement and rotation fall within the bounding cube who's position starts at <x,y,z>. Defaults to <0,0,0>.\n"
@@ -321,7 +329,7 @@ namespace OpenSim
m_console.Commands.AddCommand("Archiving", false, "save oar",
//"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
"save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [--all] [<OAR path>]",
"save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [--all] [--tenant=<uuid>] [<OAR path>]",
"Save a region's data to an OAR archive.",
// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
"-h|--home=<url> adds the url of the profile service to the saved user information.\n"
@@ -331,6 +339,7 @@ namespace OpenSim
+ " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n"
+ "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n"
+ " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n"
+ "--tenant=<uuid> only save objects owned by tenant with uuid.\n"
+ "--all saves all the regions in the simulator, instead of just the current region.\n"
+ "The OAR path must be a filesystem path."
+ " If this is not given then the oar is saved to region.oar in the current directory.",
@@ -1520,5 +1529,7 @@ namespace OpenSim
result = result.TrimEnd(' ');
return result;
}
}
}

View File

@@ -31,7 +31,8 @@ namespace OpenSim.Region.ClientStack.Linden
return;
}
if(map == map.Count < 3)
// Ensure we have a valid map with the expected minimum number of entries
if (map == null || map.Count < 3)
{
response.StatusCode = (int)HttpStatusCode.BadRequest;
return;

View File

@@ -65,8 +65,13 @@ namespace OpenSim.Region.ClientStack.Linden
return;
m_capUrl = config.GetString("Cap_EstateAccess", string.Empty);
if (!String.IsNullOrEmpty(m_capUrl) && m_capUrl.Equals("localhost"))
// enable when configured (non-empty and not explicitly false/0)
if (!String.IsNullOrEmpty(m_capUrl) &&
!m_capUrl.Equals("false", StringComparison.OrdinalIgnoreCase) &&
m_capUrl != "0")
{
m_Enabled = true;
}
}
public void AddRegion(Scene scene)

View File

@@ -67,8 +67,14 @@ namespace OpenSim.Region.ClientStack.LindenCaps
return;
string capURL = config.GetString("Cap_ServerReleaseNotes", string.Empty);
if (string.IsNullOrEmpty(capURL) || capURL != "localhost")
// If capability not configured or explicitly turned off, leave disabled
if (string.IsNullOrEmpty(capURL) ||
capURL.Equals("false", StringComparison.OrdinalIgnoreCase) ||
capURL == "0")
{
m_log.DebugFormat("[ServerReleaseNotesModule]: Cap_ServerReleaseNotes not enabled in config");
return;
}
config = source.Configs["ServerReleaseNotes"];
if (config == null)
@@ -76,16 +82,19 @@ namespace OpenSim.Region.ClientStack.LindenCaps
m_ServerReleaseNotesURL = config.GetString("ServerReleaseNotesURL", m_ServerReleaseNotesURL);
if (string.IsNullOrEmpty(m_ServerReleaseNotesURL))
return;
Uri dummy;
if(!Uri.TryCreate(m_ServerReleaseNotesURL,UriKind.Absolute, out dummy))
{
m_log.Error("[Cap_ServerReleaseNotes]: Invalid ServerReleaseNotesURL. Cap Disabled");
m_log.Error("[ServerReleaseNotesModule]: ServerReleaseNotesURL not configured. Cap disabled.");
return;
}
if (!Uri.IsWellFormedUriString(m_ServerReleaseNotesURL, UriKind.Absolute))
{
m_log.ErrorFormat("[ServerReleaseNotesModule]: Invalid ServerReleaseNotesURL '{0}'. Cap Disabled", m_ServerReleaseNotesURL);
return;
}
m_enabled = true;
m_log.InfoFormat("[ServerReleaseNotesModule]: Enabled. Redirecting ServerReleaseNotes cap to {0}", m_ServerReleaseNotesURL);
}
public void AddRegion(Scene scene)

View File

@@ -381,7 +381,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
ad.AttachmentObjectStates = null;
if (attachments.Count > 0)
m_scene.IncomingAttechments(sp, attachments);
m_scene.IncomingAttachments(sp, attachments);
else
sp.GotAttachmentsData = true;
}

View File

@@ -263,10 +263,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
{
//m_log.DebugFormat("[HGFRIENDS MODULE]: Entering StatusNotify for {0}", userID);
// First, let's divide the friends on a per-domain basis
List<FriendInfo> locallst = new(friendList.Count);
List<UUID> hglst = new();
Dictionary<string, List<FriendInfo>> friendsPerDomain = new Dictionary<string, List<FriendInfo>>();
foreach (FriendInfo friend in friendList)
{
if (UUID.TryParse(friend.Friend, out UUID friendID))
@@ -284,12 +283,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
if (LocalStatusNotification(userID, friendID, online))
continue;
if (!friendsPerDomain.TryGetValue(url, out List<FriendInfo> lst))
{
lst = new List<FriendInfo>();
friendsPerDomain[url] = lst;
}
lst.Add(friend);
hglst.Add(friendID);
}
}
}
@@ -299,8 +293,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
if (locallst.Count > 0)
base.StatusNotify(locallst, userID, online);
if(friendsPerDomain.Count > 0)
m_StatusNotifier.Notify(userID, friendsPerDomain, online);
if(hglst.Count > 0)
m_StatusNotifier.Notify(userID, hglst, online);
//m_log.DebugFormat("[HGFRIENDS MODULE]: Exiting StatusNotify for {0}", userID);
}

View File

@@ -26,6 +26,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
m_FriendsModule = friendsModule;
}
// Currently unused
/*
public void Notify(UUID userID, Dictionary<string, List<FriendInfo>> friendsPerDomain, bool online)
{
if(m_FriendsModule is null)
@@ -33,41 +35,84 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
foreach (KeyValuePair<string, List<FriendInfo>> kvp in friendsPerDomain)
{
// For the others, call the user agent service
List<string> ids = new(kvp.Value.Count);
foreach (FriendInfo f in kvp.Value)
ids.Add(f.Friend);
if (ids.Count == 0)
if (kvp.Value.Count == 0)
continue; // no one to notify. caller don't do this
//m_log.DebugFormat("[HG STATUS NOTIFIER]: Notifying {0} friends in {1}", ids.Count, kvp.Key);
// ASSUMPTION: we assume that all users for one home domain
// have exactly the same set of service URLs.
// If this is ever not true, we need to change this.
if (Util.ParseUniversalUserIdentifier(ids[0], out UUID friendID))
FriendInfo id0Info = kvp.Value[0];
string id0 = id0Info.Friend; // the hgname of the first friend
if (Util.ParseUniversalUserIdentifier(id0, out UUID firstID))
{
string friendsServerURI = m_FriendsModule.UserManagementModule.GetUserServerURL(friendID, "FriendsServerURI");
if (!string.IsNullOrEmpty(friendsServerURI))
{
HGFriendsServicesConnector fConn = new(friendsServerURI);
string friendsServerURI = m_FriendsModule.UserManagementModule.GetUserServerURL(firstID, "FriendsServerURI");
if (string.IsNullOrEmpty(friendsServerURI))
continue;
List<UUID> friendsOnline = fConn.StatusNotification(ids, userID, online);
if (friendsOnline.Count > 0)
HGFriendsServicesConnector fConn = new(friendsServerURI);
List<string> ids = new(kvp.Value.Count);
foreach (FriendInfo f in kvp.Value)
{
if (Util.ParseUniversalUserIdentifier(f.Friend, out UUID friendID))
ids.Add(friendID.ToString());
}
if (ids.Count == 0)
continue;
// Note: first argument in StatusNotification needs to be
// a List<string> of UUIDs, not a List<string> of hgnames!
List<UUID> friendsOnline = fConn.StatusNotification(ids, userID, online);
if (friendsOnline.Count == 0)
continue;
IClientAPI client = m_FriendsModule.LocateClientObject(userID);
if(client is not null)
{
m_log.DebugFormat("[HG STATUS NOTIFIER]: Notifying {0} friends in {1}", friendsOnline.Count, kvp.Key);
m_FriendsModule.CacheFriendsOnline(userID, friendsOnline, online);
if(online)
client?.SendAgentOnline(friendsOnline.ToArray());
else
client?.SendAgentOffline(friendsOnline.ToArray());
}
}
}
}
*/
public void Notify(UUID userID, List<UUID>friendIds, bool online)
{
if(m_FriendsModule is null)
return;
if (friendIds.Count == 0)
return; // no one to notify. caller don't do this
m_log.DebugFormat("[HG STATUS NOTIFIER]: Notifying {0} foreign friends", friendIds.Count);
foreach (UUID friendID in friendIds)
{
string friendsServerURI = m_FriendsModule.UserManagementModule.GetUserServerURL(friendID, "FriendsServerURI");
if (!string.IsNullOrEmpty(friendsServerURI))
{
HGFriendsServicesConnector fConn = new(friendsServerURI);
List<UUID> friendsOnline = fConn.StatusNotification(new List<string> { friendID.ToString() }, userID, online);
if (friendsOnline.Count > 0)
{
IClientAPI client = m_FriendsModule.LocateClientObject(userID);
if(client is not null)
{
IClientAPI client = m_FriendsModule.LocateClientObject(userID);
if(client is not null)
{
m_FriendsModule.CacheFriendsOnline(userID, friendsOnline, online);
if(online)
client?.SendAgentOnline(friendsOnline.ToArray());
else
client?.SendAgentOffline(friendsOnline.ToArray());
}
m_FriendsModule.CacheFriendsOnline(userID, friendsOnline, online);
if(online)
client?.SendAgentOnline(friendsOnline.ToArray());
else
client?.SendAgentOffline(friendsOnline.ToArray());
}
}
}
}
}
}
}

View File

@@ -128,7 +128,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
scene.AddCommand(
"Archiving", this, "save iar",
"save iar [-h|--home=<url>] [--noassets | --skipbadassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]",
"save iar [-h|--home=<url>] [--noassets | --skipbadassets] <first> <last> <inventory path> <password> [<IAR path>] [--nocreators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]",
"Save user inventory archive (IAR).",
"<first> is the user's first name.\n"
+ "<last> is the user's last name.\n"
@@ -136,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
+ "<IAR path> is the filesystem path at which to save the IAR."
+ string.Format(" If this is not given then the filename {0} in the current directory is used.\n", DEFAULT_INV_BACKUP_FILENAME)
+ "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
+ "-c|--creators preserves information about foreign creators.\n"
+ " --nocreators stops saving information about foreign creators.\n"
+ "-e|--exclude=<name/uuid> don't save the inventory item in archive" + Environment.NewLine
+ "-f|--excludefolder=<folder/uuid> don't save contents of the folder in archive" + Environment.NewLine
+ "-v|--verbose extra debug messages.\n"
@@ -445,7 +445,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
//ops.Add("v|version=", delegate(string v) { options["version"] = v; });
ops.Add("h|home=", delegate(string v) { options["home"] = v; });
ops.Add("v|verbose", delegate(string v) { options["verbose"] = v; });
ops.Add("c|creators", delegate(string v) { options["creators"] = v; });
ops.Add("c|creators", delegate(string v) { });
ops.Add("nocreators", delegate(string v) { options["nocreators"] = v; });
ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
ops.Add("skipbadassets", delegate(string v) { options["skipbadassets"] = v != null; });
ops.Add("e|exclude=", delegate(string v)
@@ -469,7 +470,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
if (mainParams.Count < 6)
{
m_log.Error(
"[INVENTORY ARCHIVER]: save iar [-h|--home=<url>] [--noassets | --skipbadassets] <first> <last> <inventory path> <password> [<IAR path>] [-c|--creators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]");
"[INVENTORY ARCHIVER]: save iar [-h|--home=<url>] [--noassets | --skipbadassets] <first> <last> <inventory path> <password> [<IAR path>] [--nocreators] [-e|--exclude=<name/uuid>] [-f|--excludefolder=<foldername/uuid>] [-v|--verbose]");
return;
}

View File

@@ -1862,6 +1862,9 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles
return false;
account = new UserAccount();
if (info.ContainsKey("user_firstname") && info.ContainsKey("user_lastname"))
account.FirstName = info["user_firstname"] + "." + info["user_lastname"];
if (info.ContainsKey("user_flags"))
account.UserFlags = (int)info["user_flags"];

View File

@@ -1319,6 +1319,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, EntityTransferContext ctx, out string reason, out bool logout)
{
if (!sp.GotAttachmentsData)
{
logout = false;
reason = "Cannot leave region yet, attachments are still loading";
return false;
}
GridRegion source = new(m_sceneRegionInfo)
{
RawServerURI = m_thisGridInfo.GateKeeperURL
@@ -2854,7 +2861,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
return true;
}
private int GetStateSource(SceneObjectGroup sog)
public int GetStateSource(SceneObjectGroup sog)
{
ScenePresence sp = m_scene.GetScenePresence(sog.OwnerID);

View File

@@ -651,17 +651,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (OwnerID.IsZero())
{
m_log.DebugFormat(
"[HG TRANSFER MODULE]: Denied object {0}({1}) entry into {2} because ownerID is zero",
"[HG ENTITY TRANSFER MODULE]: Denied object {0}({1}) entry into {2} because ownerID is zero",
so.Name, so.UUID, m_sceneName);
return false;
}
if (m_sceneRegionInfo.EstateSettings.IsBanned(OwnerID))
if (!m_scene.Permissions.IsAdministrator(so.OwnerID) && m_sceneRegionInfo.EstateSettings.IsBanned(OwnerID))
{
m_log.DebugFormat(
"[HG TRANSFER MODULE]: Denied prim crossing of {0} {1} into {2} for banned avatar {3}",
so.Name, so.UUID, m_sceneName, so.OwnerID);
$"[HG ENTITY TRANSFER MODULE]: Denied {so.Name} {so.UUID} into { m_sceneName} of banned owner {so.OwnerID}");
return false;
}
@@ -676,8 +674,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
if (m_scene.GetScenePresence(OwnerID) == null)
{
m_log.DebugFormat(
"[HG TRANSFER MODULE]: Denied attachment {0}({1}) owner {2} not in region {3}",
so.Name, so.UUID, OwnerID, m_sceneName);
$"[HG ENTITY TRANSFER MODULE]: Denied attachment {so.Name}({so.UUID}) owner {so.OwnerID} not in region {m_sceneName}");
return false;
}
@@ -803,72 +800,115 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
}
else
{
if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
// Upstream does let the avi in, even if their assetserver can't be reached
// The visitor will obviously be without visible attachments in this case
if (aCircuit.ServiceURLs == null || !aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
{
ScenePresence defsp = sp;
List<SceneObjectGroup> deftatt = attachments;
List<SceneObjectGroup> toadd = new List<SceneObjectGroup>(deftatt.Count);
m_incomingSceneObjectEngine.QueueJob(
string.Format("HG UUID Gather attachments {0}", defsp.Name), () =>
sp.GotAttachmentsData = true;
return true;
}
ScenePresence defsp = sp;
List<SceneObjectGroup> deftatt = new(attachments.Count);
List<SceneObjectGroup> defhuds = new();
int requestStartTick = Environment.TickCount;
// Prioritize non-HUDS, as AOs, dance huds etc can hold a lot of assets
foreach (SceneObjectGroup sog in attachments)
{
if (sog.AttachmentPoint >= 31 && sog.AttachmentPoint <= 38)
{
defhuds.Add(sog);
}
else
{
deftatt.Add(sog);
}
}
deftatt.AddRange(defhuds);
IClientAPI remoteClient = sp.ControllingClient;
UUID groupID = remoteClient.ActiveGroupId;
m_incomingSceneObjectEngine.QueueJob(
string.Format("HG UUID Gather attachments {0}", defsp.Name), () =>
{
string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
IDictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, url, ids);
foreach (SceneObjectGroup sog in deftatt)
{
string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
IDictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, url, ids);
foreach (SceneObjectGroup defso in deftatt)
if(sog.OwnerID.NotEqual(defsp.UUID))
{
if(defso.OwnerID.NotEqual(defsp.UUID))
{
m_log.ErrorFormat(
"[HG TRANSFER MODULE] attachment {0}({1} owner {2} does not match HG avatarID {3}",
defso.Name, defso.UUID, defso.OwnerID, defsp.UUID);
continue;
}
uuidGatherer.AddForInspection(defso);
while (!uuidGatherer.Complete)
{
if (sp.IsDeleted)
{
deftatt = null;
defsp = null;
uuidGatherer = null;
toadd = null;
return;
}
uuidGatherer.GatherNext();
}
toadd.Add(defso);
m_log.ErrorFormat(
"[HG ENTITY TRANSFER] Owner ({0}) of attachment '{1}' does not match HG visitor's ID ({2})",
sog.OwnerID, sog.Name, defsp.UUID);
continue;
}
deftatt = null;
// get asset uuids for scene object
uuidGatherer.AddForInspection(sog);
while (!uuidGatherer.Complete)
{
if (sp.IsDeleted)
{
deftatt = null;
defsp = null;
uuidGatherer = null;
return;
}
uuidGatherer.GatherNext();
}
// fetch assets for scene object
foreach (UUID id in ids.Keys)
{
int tickStart = Util.EnvironmentTickCount();
uuidGatherer.FetchAsset(id);
int ticksElapsed = Util.EnvironmentTickCountSubtract(tickStart);
if (sp.IsDeleted || ticksElapsed > 30000)
{
m_log.WarnFormat(
"[HG ENTITY TRANSFER]: Aborting fetch attachments assets for HG user {0}", sp.Name);
"[HG ENTITY TRANSFER]: Aborting fetching assets for for HG visitor {0}", defsp.Name);
deftatt = null;
defsp = null;
uuidGatherer = null;
toadd = null;
return;
}
}
ids.Clear(); // this scene object is done fetching
base.HandleIncomingAttachments(sp, toadd);
// add scene object
if (!m_scene.AddSceneObject(sog))
{
m_log.DebugFormat(
"[HG ENTITY TRANSFER]: Could not add attachment '{0}' for HG visitor {1}",
sog.Name, defsp.Name);
} else {
sog.SetGroup(groupID, remoteClient);
if (sog.ContainsScripts())
{
sog.RootPart.ParentGroup.CreateScriptInstances(
0, false, Scene.DefaultScriptEngine, GetStateSource(sog));
sog.aggregateScriptEvents();
sog.ResumeScripts();
}
}
}
defsp = null;
uuidGatherer = null;
toadd = null;
},
OwnerID.ToString());
}
deftatt = null;
defsp = null;
uuidGatherer = null;
sp.GotAttachmentsData = true;
string loadtime = Convert.ToString(Environment.TickCount - requestStartTick);
m_log.DebugFormat(
"[HG TRANSFER MODULE]: Attachments of avatar {0} took {1}ms. to load", sp.Name, loadtime);
// at this point the job engine is done
},
OwnerID.ToString());
}
}

View File

@@ -1214,11 +1214,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
{
if (m_thisGridInfo.IsLocalGrid(homeuri.URL) == 1) // local
{
oldUser.FirstName = firstname;
oldUser.LastName = lastname;
oldUser.IsLocal = true;
oldUser.HomeURL = string.Empty;
oldUser.HasGridUserTried = true;
UserAccount account = m_userAccountService.GetUserAccount(UUID.Zero, firstname, lastname);
if (account != null)
{
oldUser.FirstName = firstname;
oldUser.LastName = lastname;
oldUser.IsLocal = true;
oldUser.HomeURL = string.Empty;
oldUser.HasGridUserTried = true;
}
else return;
}
else
{
@@ -1232,11 +1237,16 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
{
if (string.IsNullOrEmpty(homeuri.Host)) // take this as local
{
oldUser.FirstName = firstname;
oldUser.LastName = lastname;
oldUser.IsLocal = true;
oldUser.HomeURL = string.Empty;
oldUser.HasGridUserTried = true;
UserAccount account = m_userAccountService.GetUserAccount(UUID.Zero, firstname, lastname);
if (account != null && account.PrincipalID == id)
{
oldUser.FirstName = firstname;
oldUser.LastName = lastname;
oldUser.IsLocal = true;
oldUser.HomeURL = string.Empty;
oldUser.HasGridUserTried = true;
}
else return;
}
else
{

View File

@@ -32,7 +32,9 @@ using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using log4net;
using MailKit;
using MailKit.Net.Imap;
using MailKit.Net.Smtp;
using MailKit.Search;
using MimeKit;
using Nini.Config;
using OpenMetaverse;
@@ -40,6 +42,7 @@ using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using Mono.Addins;
using System.Security.Cryptography;
namespace OpenSim.Region.CoreModules.Scripting.EmailModules
{
@@ -68,8 +71,14 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
private string SMTP_SERVER_LOGIN = null;
private string SMTP_SERVER_PASSWORD = null;
private bool m_enableEmailToExternalObjects = true;
private bool m_enableEmailToSMTP = true;
private bool IMAP_SERVER_TLS = false;
private string IMAP_SERVER_HOSTNAME = null;
private int IMAP_SERVER_PORT = 143;
private string IMAP_SERVER_LOGIN = null;
private string IMAP_SERVER_PASSWORD = null;
private bool m_enableEmailToExternalObjects = false;
private bool m_enableEmailToSMTP = false;
private ParserOptions m_mailParseOptions;
@@ -102,6 +111,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
private int m_MaxEmailSize = 4096; // largest email allowed by default, as per lsl docs.
private static SslPolicyErrors m_SMTP_SslPolicyErrorsMask;
private static SslPolicyErrors m_IMAP_SslPolicyErrorsMask;
private bool m_checkSpecName;
private object m_queuesLock = new object();
@@ -123,22 +133,22 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
if(startupConfig.GetString("emailmodule", "DefaultEmailModule") != "DefaultEmailModule")
return;
//Load SMTP SERVER config
//Load Email config
try
{
IConfig SMTPConfig = config.Configs["SMTP"];
if (SMTPConfig == null)
IConfig EmailConfig = config.Configs["Email"];
if (EmailConfig == null)
return;
if(!SMTPConfig.GetBoolean("enabled", false))
if(!EmailConfig.GetBoolean("enabled", true))
return;
m_enableEmailToExternalObjects = SMTPConfig.GetBoolean("enableEmailToExternalObjects", m_enableEmailToExternalObjects);
m_enableEmailToSMTP = SMTPConfig.GetBoolean("enableEmailToSMTP", m_enableEmailToSMTP);
m_enableEmailToExternalObjects = EmailConfig.GetBoolean("enableEmailToExternalObjects", m_enableEmailToExternalObjects);
m_enableEmailToSMTP = EmailConfig.GetBoolean("enableEmailToSMTP", m_enableEmailToSMTP);
m_MailsToPrimAddressPerHour = SMTPConfig.GetInt("MailsToPrimAddressPerHour", m_MailsToPrimAddressPerHour);
m_MailsToPrimAddressPerHour = EmailConfig.GetInt("MailsToPrimAddressPerHour", m_MailsToPrimAddressPerHour);
m_MailsToPrimAddressRate = m_MailsToPrimAddressPerHour / 3600.0;
m_MailsFromOwnerPerHour = SMTPConfig.GetInt("MailsFromOwnerPerHour", m_MailsFromOwnerPerHour);
m_MailsFromOwnerPerHour = EmailConfig.GetInt("MailsFromOwnerPerHour", m_MailsFromOwnerPerHour);
m_MailsFromOwnerRate = m_MailsFromOwnerPerHour / 3600.0;
m_mailParseOptions = new ParserOptions()
@@ -146,17 +156,17 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
AllowAddressesWithoutDomain = false,
};
m_InterObjectHostname = SMTPConfig.GetString("internal_object_host", m_InterObjectHostname);
m_InterObjectHostname = EmailConfig.GetString("internal_object_host", m_InterObjectHostname);
m_checkSpecName = !m_InterObjectHostname.Equals("lsl.secondlife.com");
if (m_enableEmailToSMTP)
{
m_SMTP_MailsPerDay = SMTPConfig.GetInt("SMTP_MailsPerDay", m_SMTP_MailsPerDay);
m_SMTP_MailsPerDay = EmailConfig.GetInt("SMTP_MailsPerDay", m_SMTP_MailsPerDay);
m_SMTP_MailsRate = m_SMTP_MailsPerDay / 86400.0;
m_MailsToSMTPAddressPerHour = SMTPConfig.GetInt("MailsToSMTPAddressPerHour", m_MailsToPrimAddressPerHour);
m_MailsToSMTPAddressPerHour = EmailConfig.GetInt("MailsToSMTPAddressPerHour", m_MailsToPrimAddressPerHour);
m_MailsToSMTPAddressRate = m_MailsToPrimAddressPerHour / 3600.0;
SMTP_SERVER_HOSTNAME = SMTPConfig.GetString("SMTP_SERVER_HOSTNAME", SMTP_SERVER_HOSTNAME);
SMTP_SERVER_HOSTNAME = EmailConfig.GetString("SMTP_SERVER_HOSTNAME", SMTP_SERVER_HOSTNAME);
OSHHTPHost hosttmp = new OSHHTPHost(SMTP_SERVER_HOSTNAME, true);
if(!hosttmp.IsResolvedHost)
{
@@ -164,22 +174,22 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
return;
}
SMTP_SERVER_PORT = SMTPConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT);
SMTP_SERVER_TLS = SMTPConfig.GetBoolean("SMTP_SERVER_TLS", SMTP_SERVER_TLS);
SMTP_SERVER_PORT = EmailConfig.GetInt("SMTP_SERVER_PORT", SMTP_SERVER_PORT);
SMTP_SERVER_TLS = EmailConfig.GetBoolean("SMTP_SERVER_TLS", SMTP_SERVER_TLS);
string smtpfrom = SMTPConfig.GetString("SMTP_SERVER_FROM", string.Empty);
m_HostName = SMTPConfig.GetString("host_domain_header_from", m_HostName);
string smtpfrom = EmailConfig.GetString("SMTP_SERVER_FROM", string.Empty);
m_HostName = EmailConfig.GetString("host_domain_header_from", m_HostName);
if (!string.IsNullOrEmpty(smtpfrom) && !MailboxAddress.TryParse(m_mailParseOptions, smtpfrom, out SMTP_MAIL_FROM))
{
m_log.ErrorFormat("[EMAIL]: Invalid SMTP_SERVER_FROM {0}", smtpfrom);
return;
}
SMTP_SERVER_LOGIN = SMTPConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN);
SMTP_SERVER_PASSWORD = SMTPConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD);
SMTP_SERVER_LOGIN = EmailConfig.GetString("SMTP_SERVER_LOGIN", SMTP_SERVER_LOGIN);
SMTP_SERVER_PASSWORD = EmailConfig.GetString("SMTP_SERVER_PASSWORD", SMTP_SERVER_PASSWORD);
bool VerifyCertChain = SMTPConfig.GetBoolean("SMTP_VerifyCertChain", true);
bool VerifyCertNames = SMTPConfig.GetBoolean("SMTP_VerifyCertNames", true);
bool VerifyCertChain = EmailConfig.GetBoolean("SMTP_VerifyCertChain", true);
bool VerifyCertNames = EmailConfig.GetBoolean("SMTP_VerifyCertNames", true);
m_SMTP_SslPolicyErrorsMask = VerifyCertChain ? 0 : SslPolicyErrors.RemoteCertificateChainErrors;
if (!VerifyCertNames)
m_SMTP_SslPolicyErrorsMask |= SslPolicyErrors.RemoteCertificateNameMismatch;
@@ -191,7 +201,35 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
m_log.Warn("[EMAIL]: SMTP disabled, set enableEmailSMTP to enable");
}
m_MaxEmailSize = SMTPConfig.GetInt("email_max_size", m_MaxEmailSize);
if (m_enableEmailToExternalObjects)
{
IMAP_SERVER_HOSTNAME = EmailConfig.GetString("IMAP_SERVER_HOSTNAME", IMAP_SERVER_HOSTNAME);
OSHHTPHost hosttmp = new OSHHTPHost(IMAP_SERVER_HOSTNAME, true);
if(!hosttmp.IsResolvedHost)
{
m_log.ErrorFormat("[EMAIL]: could not resolve IMAP_SERVER_HOSTNAME {0}", IMAP_SERVER_HOSTNAME);
return;
}
IMAP_SERVER_PORT = EmailConfig.GetInt("IMAP_SERVER_PORT", IMAP_SERVER_PORT);
IMAP_SERVER_TLS = EmailConfig.GetBoolean("IMAP_SERVER_TLS", IMAP_SERVER_TLS);
IMAP_SERVER_LOGIN = EmailConfig.GetString("IMAP_SERVER_LOGIN", IMAP_SERVER_LOGIN);
IMAP_SERVER_PASSWORD = EmailConfig.GetString("IMAP_SERVER_PASSWORD", IMAP_SERVER_PASSWORD);
bool VerifyCertChain = EmailConfig.GetBoolean("IMAP_VerifyCertChain", true);
bool VerifyCertNames = EmailConfig.GetBoolean("IMAP_VerifyCertNames", true);
m_IMAP_SslPolicyErrorsMask = VerifyCertChain ? 0 : SslPolicyErrors.RemoteCertificateChainErrors;
if (!VerifyCertNames)
m_IMAP_SslPolicyErrorsMask |= SslPolicyErrors.RemoteCertificateNameMismatch;
m_IMAP_SslPolicyErrorsMask = ~m_IMAP_SslPolicyErrorsMask;
}
else
{
m_IMAP_SslPolicyErrorsMask = ~SslPolicyErrors.None;
m_log.Warn("[EMAIL]: IMAP disabled, set enableEmailToExternalObjects to enable");
}
m_MaxEmailSize = EmailConfig.GetInt("email_max_size", m_MaxEmailSize);
if(m_MaxEmailSize < 256 || m_MaxEmailSize > 1000000)
{
m_log.Warn("[EMAIL]: email_max_size out of range [256, 1000000], Changed to default 4096");
@@ -369,6 +407,11 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
{
return (sslPolicyErrors & m_SMTP_SslPolicyErrorsMask) == SslPolicyErrors.None;
}
public static bool imapValidateServerCertificate(object sender, X509Certificate certificate,
X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return (sslPolicyErrors & m_IMAP_SslPolicyErrorsMask) == SslPolicyErrors.None;
}
/// <summary>
/// SendMail function utilized by llEMail
@@ -500,7 +543,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
client.Connect(SMTP_SERVER_HOSTNAME, SMTP_SERVER_PORT, MailKit.Security.SecureSocketOptions.StartTls);
}
else
client.Connect(SMTP_SERVER_HOSTNAME, SMTP_SERVER_PORT);
client.Connect(SMTP_SERVER_HOSTNAME, SMTP_SERVER_PORT, MailKit.Security.SecureSocketOptions.None);
if (!string.IsNullOrEmpty(SMTP_SERVER_LOGIN) && !string.IsNullOrEmpty(SMTP_SERVER_PASSWORD))
client.Authenticate(SMTP_SERVER_LOGIN, SMTP_SERVER_PASSWORD);
@@ -549,25 +592,60 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
if (!UUID.TryParse(address.Substring(0, indx), out UUID toID))
return;
Email email = new Email();
email.time = Util.UnixTimeSinceEpoch().ToString();
email.subject = subject;
email.sender = objectID.ToString() + "@" + m_InterObjectHostname;
email.message = "Object-Name: " + LastObjectName +
"\nRegion: " + LastObjectRegionName + "\nLocal-Position: " +
LastObjectPosition + "\n\n" + body;
if (IsLocal(toID))
{
// object in this instance
Email email = new Email();
email.time = Util.UnixTimeSinceEpoch().ToString();
email.subject = subject;
email.sender = objectID.ToString() + "@" + m_InterObjectHostname;
email.message = "Object-Name: " + LastObjectName +
"\nRegion: " + LastObjectRegionName + "\nLocal-Position: " +
LastObjectPosition + "\n\n" + body;
InsertEmail(toID, email);
}
else
{
// object on another region
if (!m_enableEmailToExternalObjects)
return;
// object on another region
// TODO FIX
// Insert mail into IMAP inbox
using (var client = new ImapClient ()) {
if (IMAP_SERVER_TLS)
{
client.ServerCertificateValidationCallback = imapValidateServerCertificate;
client.Connect(IMAP_SERVER_HOSTNAME, IMAP_SERVER_PORT, MailKit.Security.SecureSocketOptions.StartTls);
}
else
client.Connect(IMAP_SERVER_HOSTNAME, IMAP_SERVER_PORT, MailKit.Security.SecureSocketOptions.None);
if (client.IsConnected && !string.IsNullOrEmpty(IMAP_SERVER_LOGIN) && !string.IsNullOrEmpty(IMAP_SERVER_PASSWORD))
{
client.Authenticate(IMAP_SERVER_LOGIN, IMAP_SERVER_PASSWORD);
client.Inbox.Open(FolderAccess.ReadWrite);
var builder = new BodyBuilder();
builder.TextBody = "Object-Name: " + LastObjectName +
"\nRegion: " + LastObjectRegionName +
"\nLocal-Position: " + LastObjectPosition +
"\n\n" + body;
MimeMessage email = new()
{
Date = DateTimeOffset.UtcNow,
Subject = subject,
Sender = new MailboxAddress(LastObjectName, objectID.ToString() + "@" + m_InterObjectHostname),
Body = builder.ToMessageBody()
};
email.To.Add(MailboxAddress.Parse(address));
client.Inbox.Append(email);
client.Disconnect(true);
}
}
}
}
}
@@ -637,6 +715,50 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules
}
}
// Fetch mail from imap inbox here
if (m_enableEmailToExternalObjects) {
using (var client = new ImapClient ()) {
if (IMAP_SERVER_TLS)
{
client.ServerCertificateValidationCallback = imapValidateServerCertificate;
client.Connect(IMAP_SERVER_HOSTNAME, IMAP_SERVER_PORT, MailKit.Security.SecureSocketOptions.StartTls);
}
else
client.Connect(IMAP_SERVER_HOSTNAME, IMAP_SERVER_PORT, MailKit.Security.SecureSocketOptions.None);
if (client.IsConnected && !string.IsNullOrEmpty(IMAP_SERVER_LOGIN) && !string.IsNullOrEmpty(IMAP_SERVER_PASSWORD))
{
client.Authenticate(IMAP_SERVER_LOGIN, IMAP_SERVER_PASSWORD);
client.Inbox.Open(FolderAccess.ReadWrite);
SearchQuery query = SearchQuery.ToContains(objectID.ToString()+"@"+m_InterObjectHostname).And(SearchQuery.NotDeleted);
if (!string.IsNullOrEmpty(sender))
query = query.And(SearchQuery.FromContains(sender));
if (!string.IsNullOrEmpty(subject))
query = query.And(SearchQuery.SubjectContains(subject));
var uids = client.Inbox.Search(query);
foreach (var uid in uids)
{
var message = client.Inbox.GetMessage(uid);
Email email = new()
{
time = message.Date.ToString(),
subject = message.Subject,
sender = message.From.ToString(),
message = message.GetTextBody(MimeKit.Text.TextFormat.Plain)
};
InsertEmail(objectID, email);
client.Inbox.AddFlags(uid, MessageFlags.Deleted, true);
}
client.Inbox.Expunge();
client.Disconnect(true);
}
}
}
lock (m_queuesLock)
{
m_LastGetEmailCall[objectID] = now + m_QueueTimeout;

View File

@@ -951,7 +951,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{
if (parcel.GroupID.IsZero())
{
parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
parcel.OwnerID = m_defaultUser;
parcel.IsGroupOwned = false;
}
else
@@ -963,7 +963,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
else
{
if (!ResolveUserUuid(scene, parcel.OwnerID))
parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
parcel.OwnerID = m_defaultUser;
}
List<LandAccessEntry> accessList = new();

View File

@@ -155,7 +155,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if (options.TryGetValue("checkPermissions", out Object temp))
FilterContent = (string)temp;
// Find the regions to archive
ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
if (MultiRegionFormat)
@@ -189,7 +188,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver
scenesGroup.ForEachScene(delegate(Scene scene)
{
string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : "";
ArchiveOneRegion(scene, regionDir, assetUuids, failedIDs, uncertainAssetsUUIDs);
UUID userId = scene.RegionInfo.EstateSettings.EstateOwner;
if (options.TryGetValue("tenant", out Object temp))
{
if (!UUID.TryParse((string)temp, out userId) || userId.IsZero())
userId = scene.RegionInfo.EstateSettings.EstateOwner;
}
ArchiveOneRegion(scene, regionDir, assetUuids, failedIDs, uncertainAssetsUUIDs, userId);
});
// Archive the assets
@@ -227,7 +234,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
}
private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, sbyte> assetUuids,
HashSet<UUID> failedIDs, HashSet<UUID> uncertainAssetsUUIDs)
HashSet<UUID> failedIDs, HashSet<UUID> uncertainAssetsUUIDs, UUID userId)
{
m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name);
@@ -248,7 +255,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if (!sceneObject.IsDeleted && !sceneObject.IsAttachment && !sceneObject.IsTemporary && !sceneObject.inTransit)
{
if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule))
if (userId != scene.RegionInfo.EstateSettings.EstateOwner && sceneObject.OwnerID != userId)
{
// A tenant= option was specified, skip object if not owned by tenant with userid
++numObjectsSkippedPermissions;
}
else if (!CanUserArchiveObject(userId, sceneObject, FilterContent, permissionsModule))
{
// The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
++numObjectsSkippedPermissions;

View File

@@ -280,6 +280,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
ops.Add("publish", v => options["wipe-owners"] = v != null);
ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
ops.Add("all", delegate(string v) { options["all"] = v != null; });
ops.Add("tenant=", delegate(string v) { options["tenant"] = v; });
List<string> mainParams = ops.Parse(cmdparams);

View File

@@ -51,6 +51,8 @@ using OSDMap = OpenMetaverse.StructuredData.OSDMap;
using OSDArray = OpenMetaverse.StructuredData.OSDArray;
using Extension = Mono.Addins.ExtensionAttribute;
using System.Text.RegularExpressions;
namespace OpenSim.Region.CoreModules.World.Land
{
// used for caching
@@ -1694,10 +1696,28 @@ namespace OpenSim.Region.CoreModules.World.Land
if (m_scene.Permissions.CanAbandonParcel(remote_client.AgentId, land))
{
string LastOwnerName;
if (land.LandData.IsGroupOwned)
{
if (m_groupManager is not null)
{
GroupRecord groupRecord = m_groupManager.GetGroupRecord(land.LandData.OwnerID);
LastOwnerName = "group " + groupRecord.GroupName;
}
else
LastOwnerName = "a group";
}
else
LastOwnerName = m_userManager.GetUserName(land.LandData.OwnerID);
string date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
land.LandData.GroupID = UUID.Zero;
land.LandData.IsGroupOwned = false;
land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory | ParcelFlags.CreateObjects);
land.LandData.Name = "Abandoned Land";
land.LandData.OtherCleanTime = 5;
land.LandData.Description = "Land abandoned by " + LastOwnerName + " on " + date;
UpdateLandObject(land.LandData.LocalID, land.LandData);
m_scene.ForEachClient(SendParcelOverlay);
@@ -1725,7 +1745,9 @@ namespace OpenSim.Region.CoreModules.World.Land
land.LandData.SeeAVs = true;
land.LandData.AnyAVSounds = true;
land.LandData.GroupAVSounds = true;
land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory);
land.LandData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory | ParcelFlags.CreateObjects);
land.LandData.Name = "Reclaimed Land";
land.LandData.OtherCleanTime = 0;
UpdateLandObject(land.LandData.LocalID, land.LandData);
m_scene.ForEachClient(SendParcelOverlay);
land.SendLandUpdateToAvatars();

View File

@@ -860,9 +860,9 @@ namespace OpenSim.Region.CoreModules.World.Land
{
if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) == 0)
{
bool adults = m_estateSettings.DoDenyMinors &&
bool adults = m_estateSettings.DoDenyMinors ||
(m_estateSettings.DenyMinors || ((LandData.Flags & (uint)ParcelFlags.DenyAgeUnverified) != 0));
bool anonymous = m_estateSettings.DoDenyAnonymous &&
bool anonymous = m_estateSettings.DoDenyAnonymous ||
(m_estateSettings.DenyAnonymous || ((LandData.Flags & (uint)ParcelFlags.DenyAnonymous) != 0));
if(adults || anonymous)
{

View File

@@ -1003,6 +1003,12 @@ namespace OpenSim.Region.CoreModules.World.LightShare
return (float)Utils.Clamp(dayfrac, 0, 1);
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public float GetDayFractionTime(Vector3 pos)
{
return GetDayFractionTime(GetEnvironment(pos));
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public float GetRegionDayFractionTime()
{

View File

@@ -89,11 +89,9 @@ namespace OpenSim.Region.CoreModules.World.Permissions
private bool m_propagatePermissions = false;
private bool m_debugPermissions = false;
private bool m_allowGridAdmins = false;
private bool m_RegionOwnerIsAdmin = false;
private bool m_RegionManagerIsAdmin = false;
private bool m_forceGridAdminsOnly;
private bool m_forceAdminModeAlwaysOn;
private bool m_allowAdminActionsWithoutGodMode;
private bool m_takeCopyRestricted = false;
/// <value>
/// The set of users that are allowed to create scripts. This is only active if permissions are not being
@@ -160,19 +158,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions
string[] sections = new string[] { "Startup", "Permissions" };
m_allowGridAdmins = Util.GetConfigVarFromSections<bool>(config, "allow_grid_gods", sections, false);
m_allowGridAdmins = Util.GetConfigVarFromSections<bool>(config, "allow_grid_gods", sections, true);
m_bypassPermissions = !Util.GetConfigVarFromSections<bool>(config, "serverside_object_permissions", sections, true);
m_propagatePermissions = Util.GetConfigVarFromSections<bool>(config, "propagate_permissions", sections, true);
m_forceGridAdminsOnly = Util.GetConfigVarFromSections<bool>(config, "force_grid_gods_only", sections, false);
if(!m_forceGridAdminsOnly)
{
m_RegionOwnerIsAdmin = Util.GetConfigVarFromSections<bool>(config, "region_owner_is_god",sections, true);
m_RegionManagerIsAdmin = Util.GetConfigVarFromSections<bool>(config, "region_manager_is_god",sections, false);
}
else
m_allowGridAdmins = true;
m_forceAdminModeAlwaysOn = Util.GetConfigVarFromSections<bool>(config, "automatic_gods", sections, false);
m_allowAdminActionsWithoutGodMode = Util.GetConfigVarFromSections<bool>(config, "implicit_gods", sections, false);
if(m_allowAdminActionsWithoutGodMode)
@@ -188,6 +177,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
else
m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks");
m_takeCopyRestricted = Util.GetConfigVarFromSections<bool>(config, "take_copy_restricted", sections, false);
string grant = Util.GetConfigVarFromSections<string>(config, "GrantLSL",
new string[] { "Startup", "Permissions" }, string.Empty);
if (grant.Length > 0)
@@ -625,12 +616,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions
if (user.IsZero())
return false;
if (m_RegionOwnerIsAdmin && m_scene.RegionInfo.EstateSettings.EstateOwner.Equals(user))
return true;
if (m_RegionManagerIsAdmin && IsEstateManager(user))
return true;
if (IsGridAdministrator(user))
return true;
@@ -2022,6 +2007,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions
if(sog.OwnerID.NotEqual(sp.UUID) && (perms & (uint)PermissionMask.Transfer) == 0)
return false;
if (sog.OwnerID.NotEqual(sp.UUID) && !IsFriendWithPerms(sp.UUID, sog.OwnerID) && !sp.IsGod)
{
if (m_takeCopyRestricted)
return false;
}
return true;
}
@@ -2380,7 +2371,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
bool spNotOwner = sp.UUID.NotEqual(destsog.OwnerID);
// scripts can't be droped
// scripts can't be dropped
if(spNotOwner && item.InvType == (int)InventoryType.LSL)
return false;

View File

@@ -84,6 +84,8 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
private float m_renderMinHeight = -100f;
private float m_renderMaxHeight = 4096f;
private string m_tilesPath = ".";
private bool m_Enabled = false;
#region Region Module interface
@@ -132,6 +134,10 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
m_renderMinHeight = -100f;
else if (m_renderMinHeight > m_renderMaxHeight - 10f)
m_renderMinHeight = m_renderMaxHeight - 10f;
m_tilesPath = Util.GetConfigVarFromSections<string>(source, "GenTilesDirectory", configSections, m_tilesPath);
if (!Directory.Exists(m_tilesPath))
Directory.CreateDirectory(m_tilesPath);
}
public void AddRegion(Scene scene)
@@ -208,7 +214,7 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
Bitmap tile = GenImage();
// image may be reloaded elsewhere, so no compression format
string filename = "MAP-" + m_scene.RegionInfo.RegionID.ToString() + ".png";
string filename = System.IO.Path.Combine(m_tilesPath, "MAP-" + m_scene.RegionInfo.RegionID.ToString() + ".png");
tile.Save(filename,ImageFormat.Png);
m_primMesher = null;
return tile;

View File

@@ -77,6 +77,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
private string m_regionName;
private byte[] myMapImageJPEG;
private string m_tilesPath = ".";
protected volatile bool m_Enabled = false;
private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false);
@@ -158,6 +159,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
Util.GetConfigVarFromSections<bool>(config, "ExportMapAddRegionName", configSections, m_exportPrintRegionName);
m_localV1MapAssets =
Util.GetConfigVarFromSections<bool>(config, "LocalV1MapAssets", configSections, m_localV1MapAssets);
m_tilesPath =
Util.GetConfigVarFromSections<string>(config, "GenTilesDirectory", configSections, m_tilesPath);
if (!Directory.Exists(m_tilesPath))
Directory.CreateDirectory(m_tilesPath);
}
public virtual void AddRegion(Scene scene)
@@ -916,9 +921,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
}
private const double SPAMBLOCKTIMEms = 30000;
private Dictionary<UUID,double> spamBlocked = new Dictionary<UUID,double>();
/// <summary>
/// Requests map blocks in area of minX, maxX, minY, MaxY in world cordinates
/// </summary>
@@ -928,50 +930,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
/// <param name="maxY"></param>
public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag)
{
// anti spam because of FireStorm 4.7.7 absurd request repeat rates
// possible others
double now = Util.GetTimeStampMS();
UUID agentID = remoteClient.AgentId;
lock (m_mapBlockRequestEvent)
{
if(spamBlocked.ContainsKey(agentID))
{
if(spamBlocked[agentID] < now &&
(!m_mapBlockRequests.ContainsKey(agentID) ||
m_mapBlockRequests[agentID].Count == 0 ))
{
spamBlocked.Remove(agentID);
m_log.DebugFormat("[WoldMapModule] RequestMapBlocks release spammer {0}", agentID);
}
else
return;
}
else
{
// ugly slow expire spammers
if(spamBlocked.Count > 0)
{
UUID k = UUID.Zero;
bool expireone = false;
foreach(UUID k2 in spamBlocked.Keys)
{
if(spamBlocked[k2] < now &&
(!m_mapBlockRequests.ContainsKey(k2) ||
m_mapBlockRequests[k2].Count == 0 ))
{
m_log.DebugFormat("[WoldMapModule] RequestMapBlocks release spammer {0}", k2);
k = k2;
expireone = true;
}
break; // doing one at a time
}
if(expireone)
spamBlocked.Remove(k);
}
}
// m_log.DebugFormat("[WoldMapModule] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag);
MapBlockRequestData req = new MapBlockRequestData()
@@ -990,13 +952,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
agentq = new Queue<MapBlockRequestData>();
m_mapBlockRequests[agentID] = agentq;
}
if(agentq.Count < 150 )
agentq.Enqueue(req);
else
{
spamBlocked[agentID] = now + SPAMBLOCKTIMEms;
m_log.DebugFormat("[WoldMapModule] RequestMapBlocks blocking spammer {0} for {1} s",agentID, SPAMBLOCKTIMEms/1000.0);
}
agentq.Enqueue(req);
m_mapBlockRequestEvent.Set();
}
}
@@ -1338,7 +1294,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
startY--;
bool doneLocal = false;
string filename = "MAP-" + m_scene.RegionInfo.RegionID.ToString() + ".png";
string filename = Path.Combine(m_tilesPath, "MAP-" + m_scene.RegionInfo.RegionID.ToString() + ".png");
try
{
using(Image localMap = Bitmap.FromFile(filename))

View File

@@ -43,6 +43,7 @@ namespace OpenSim.Region.Framework.Interfaces
ViewerEnvironment GetRegionEnvironment();
float GetDayFractionTime(Vector3 pos);
float GetRegionDayFractionTime();
int GetRegionDayLength();
int GetRegionDayOffset();

View File

@@ -64,7 +64,7 @@ namespace OpenSim.Region.Framework.Scenes
return;
}
m_log.DebugFormat("Setting override for {0} to {1}", state, animID);
//m_log.DebugFormat("Setting override for {0} to {1}", state, animID);
lock (MAOLock)
m_overrides[state] = animID;

View File

@@ -87,7 +87,10 @@ namespace OpenSim.Region.Framework.Scenes
if (permissionToDelete)
{
foreach (SceneObjectGroup g in objectGroups)
{
g.LastOwnerID = g.OwnerID;
g.DeleteGroupFromScene(false);
}
}
if(Monitor.TryEnter(m_threadLock))

View File

@@ -46,9 +46,6 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence m_scenePresence;
Scene m_scene;
protected bool m_allowGridGods;
protected bool m_forceGridGodsOnly;
protected bool m_regionOwnerIsGod;
protected bool m_regionManagerIsGod;
protected bool m_forceGodModeAlwaysOn;
protected bool m_allowGodActionsWithoutGodMode;
@@ -76,29 +73,8 @@ namespace OpenSim.Region.Framework.Scenes
// gods are god everywhere.
m_allowGridGods =
Util.GetConfigVarFromSections<bool>(config,
"allow_grid_gods", sections, false);
"allow_grid_gods", sections, true);
// If grid gods are active, dont allow any other gods
m_forceGridGodsOnly =
Util.GetConfigVarFromSections<bool>(config,
"force_grid_gods_only", sections, false);
if(!m_forceGridGodsOnly)
{
// The owner of a region is a god in his region only.
m_regionOwnerIsGod =
Util.GetConfigVarFromSections<bool>(config,
"region_owner_is_god", sections, true);
// Region managers are gods in the regions they manage.
m_regionManagerIsGod =
Util.GetConfigVarFromSections<bool>(config,
"region_manager_is_god", sections, false);
}
else
m_allowGridGods = true; // reduce potencial user mistakes
// God mode should be turned on in the viewer whenever
// the user has god rights somewhere. They may choose
// to turn it off again, though.
@@ -140,18 +116,6 @@ namespace OpenSim.Region.Framework.Scenes
if (m_allowGridGods && m_userLevel >= 200)
level = m_userLevel;
if(m_forceGridGodsOnly || level >= (int)ImplicitGodLevels.RegionOwner)
return level;
if (m_regionOwnerIsGod && m_scene.RegionInfo.EstateSettings.IsEstateOwner(m_scenePresence.UUID))
level = (int)ImplicitGodLevels.RegionOwner;
if(level >= (int)ImplicitGodLevels.EstateManager)
return level;
if (m_regionManagerIsGod && m_scene.Permissions.IsEstateManager(m_scenePresence.UUID))
level = (int)ImplicitGodLevels.EstateManager;
return level;
}

View File

@@ -32,6 +32,7 @@ using System.IO;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Timers;
using Nini.Config;
@@ -267,8 +268,9 @@ namespace OpenSim.Region.Framework.Scenes
get { return m_minRegionViewDistance; }
}
private readonly List<string> m_AllowedViewers = new();
private readonly List<string> m_BannedViewers = new();
private static string m_AllowedViewers = string.Empty;
private static string m_BannedViewers = string.Empty;
private static string m_ViewerDeniedMsg = "Access denied, your viewer is banned";
// TODO: need to figure out how allow client agents but deny
// root agents when ACL denies access to root agent
@@ -1039,29 +1041,12 @@ namespace OpenSim.Region.Framework.Scenes
string[] possibleAccessControlConfigSections = new string[] { "Startup", "AccessControl"};
string grant = Util.GetConfigVarFromSections<string>(
config, "AllowedClients", possibleAccessControlConfigSections, string.Empty);
if (grant.Length > 0)
{
foreach (string viewer in grant.Split(','))
{
m_AllowedViewers.Add(viewer.Trim().ToLower());
}
}
grant = Util.GetConfigVarFromSections<string>(config, "DeniedClients", possibleAccessControlConfigSections, string.Empty);
// Deal with the mess of someone having used a different word at some point
if (string.IsNullOrWhiteSpace(grant))
grant = Util.GetConfigVarFromSections<string>(config, "BannedClients", possibleAccessControlConfigSections, string.Empty);
if (grant.Length > 0)
{
foreach (string viewer in grant.Split(','))
{
m_BannedViewers.Add(viewer.Trim().ToLower());
}
}
m_AllowedViewers = Util.GetConfigVarFromSections<string>(
config, "AllowedClients", possibleAccessControlConfigSections, string.Empty);
m_BannedViewers = Util.GetConfigVarFromSections<string>(
config, "DeniedClients", possibleAccessControlConfigSections, string.Empty);
m_ViewerDeniedMsg = Util.GetConfigVarFromSections<string>(
config, "ViewerDeniedMsg", possibleAccessControlConfigSections, m_ViewerDeniedMsg);
FrameTime = startupConfig.GetFloat( "FrameTime", FrameTime);
FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent);
@@ -2973,7 +2958,7 @@ namespace OpenSim.Region.Framework.Scenes
return true;
}
public bool IncomingAttechments(ScenePresence sp, List<SceneObjectGroup> attachments)
public bool IncomingAttachments(ScenePresence sp, List<SceneObjectGroup> attachments)
{
//m_log.DebugFormat(" >>> IncomingCreateObject(sog) <<< {0} deleted? {1} isAttach? {2}", ((SceneObjectGroup)sog).AbsolutePosition,
// ((SceneObjectGroup)sog).IsDeleted, ((SceneObjectGroup)sog).RootPart.IsAttachment);
@@ -3983,20 +3968,14 @@ namespace OpenSim.Region.Framework.Scenes
//Check if the viewer is banned or in the viewer access list
//We check if the substring is listed for higher flexebility
bool ViewerDenied = true;
string cV = null;
//Check if the specific viewer is listed in the allowed viewer list
if (m_AllowedViewers.Count > 0)
if (!String.IsNullOrWhiteSpace(m_AllowedViewers))
{
cV = curViewer.Trim().ToLower();
foreach (string viewer in m_AllowedViewers)
{
if (viewer == cV[..Math.Min(viewer.Length, curViewer.Length)])
{
ViewerDenied = false;
break;
}
}
Regex arx = new Regex(m_AllowedViewers);
Match am = arx.Match(curViewer);
if (am.Success) ViewerDenied = false;
}
else
{
@@ -4004,17 +3983,12 @@ namespace OpenSim.Region.Framework.Scenes
}
//Check if the viewer is in the banned list
if (m_BannedViewers.Count > 0)
if (!String.IsNullOrWhiteSpace(m_BannedViewers))
{
cV ??= curViewer.Trim().ToLower();
foreach (string viewer in m_BannedViewers)
{
if (viewer == cV[..Math.Min(viewer.Length, curViewer.Length)])
{
ViewerDenied = true;
break;
}
}
Regex drx = new Regex(m_BannedViewers);
Match dm = drx.Match(curViewer);
if (dm.Success) ViewerDenied = true;
}
if (ViewerDenied)
@@ -4022,7 +3996,7 @@ namespace OpenSim.Region.Framework.Scenes
m_log.DebugFormat(
"[SCENE]: Access denied for {0} {1} using {2}",
acd.firstname, acd.lastname, curViewer);
reason = "Access denied, your viewer is banned";
reason = m_ViewerDeniedMsg;
return false;
}

View File

@@ -712,10 +712,8 @@ namespace OpenSim.Region.Framework.Scenes
// now that position is changed tell it to scripts
if (triggerScriptEvent && (ScriptEvents & scriptEvents.changed) != 0)
{
foreach (SceneObjectPart part in parts)
{
part.TriggerScriptChangedEvent(Changed.POSITION);
}
// Only send this to the rootprim instead of all childprims
m_rootPart.TriggerScriptChangedEvent(Changed.POSITION);
}
Scene?.EventManager.TriggerParcelPrimCountTainted();

View File

@@ -2073,7 +2073,15 @@ namespace OpenSim.Region.Framework.Scenes
return;
if (localGlobalTF)
impulse *= GetWorldRotation();
{
if (ParentGroup.IsAttachment)
{
ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
if (sp != null)
impulse *= sp.GetWorldRotation();
} else
impulse *= GetWorldRotation();
}
ParentGroup.applyImpulse(impulse);
}
@@ -2084,9 +2092,6 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
return;
if (ParentGroup.IsAttachment)
return; // don't work on attachments (for now ??)
SceneObjectPart root = ParentGroup.RootPart;
if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
@@ -2098,7 +2103,16 @@ namespace OpenSim.Region.Framework.Scenes
return;
if (localGlobalTF)
pVel *= GetWorldRotation();
{
if (ParentGroup.IsAttachment)
{
ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
if (sp != null)
pVel *= sp.GetWorldRotation();
}
else
pVel *= GetWorldRotation();
}
ParentGroup.Velocity = pVel;
}
@@ -2109,9 +2123,6 @@ namespace OpenSim.Region.Framework.Scenes
if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
return;
if (ParentGroup.IsAttachment)
return; // don't work on attachments (for now ??)
SceneObjectPart root = ParentGroup.RootPart;
if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
@@ -2123,7 +2134,16 @@ namespace OpenSim.Region.Framework.Scenes
return;
if (localGlobalTF)
pAngVel *= GetWorldRotation();
{
if (ParentGroup.IsAttachment)
{
ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
if (sp != null)
pAngVel *= sp.GetWorldRotation();
}
else
pAngVel *= GetWorldRotation();
}
root.AngularVelocity = pAngVel;
}
@@ -2142,7 +2162,16 @@ namespace OpenSim.Region.Framework.Scenes
return;
if (localGlobalTF)
ParentGroup.ApplyAngularImpulse(impulse * GetWorldRotation());
{
if (ParentGroup.IsAttachment)
{
ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
if (sp != null)
ParentGroup.ApplyAngularImpulse(impulse * sp.GetWorldRotation());
}
else
ParentGroup.ApplyAngularImpulse(impulse * GetWorldRotation());
}
else
ParentGroup.ApplyAngularImpulse(impulse);
}
@@ -2161,7 +2190,16 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 torque = torquei;
if (localGlobalTF)
torque *= GetWorldRotation();
{
if (ParentGroup.IsAttachment)
{
ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
if (sp != null)
torque *= sp.GetWorldRotation();
}
else
torque *= GetWorldRotation();
}
Torque = torque;
}

View File

@@ -655,11 +655,17 @@ namespace OpenSim.Region.Framework.Scenes
public string Grouptitle
{
get { return m_groupTitle; }
get { return UseFakeGroupTitle ? "(Loading)" : m_groupTitle; }
set { m_groupTitle = value; }
}
private string m_groupTitle;
/// <summary>
/// When this is 'true', return a dummy group title instead of the real group title. This is
/// used as part of a hack to force viewers to update the displayed avatar name.
/// </summary>
public bool UseFakeGroupTitle { get; set; }
// Agent's Draw distance.
private float m_drawDistance = 255f;
public float DrawDistance
@@ -1075,7 +1081,7 @@ namespace OpenSim.Region.Framework.Scenes
// velocities
private const float AgentControlStopSlowVel = 0.2f * 4.096f;
public const float AgentControlMidVel = 0.6f * 4.096f;
public const float AgentControlMidVel = 1.0f * 4.096f;
public const float AgentControlNormalVel = 1.0f * 4.096f;
// old normal speed was tuned to match sl normal plus Fast modifiers
@@ -1590,9 +1596,12 @@ namespace OpenSim.Region.Framework.Scenes
// Resume scripts
foreach (SceneObjectGroup sog in attachments)
{
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
sog.ResumeScripts();
sog.ScheduleGroupForFullUpdate();
if (sog.ContainsScripts())
{
sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
sog.ResumeScripts();
sog.ScheduleGroupForFullUpdate();
}
}
}
@@ -1611,7 +1620,6 @@ namespace OpenSim.Region.Framework.Scenes
/// Group Title. So the following trick makes viewers update the avatar's name by briefly changing
/// the group title (to "(Loading)"), and then restoring it.
/// </remarks>
/*
public void ForceViewersUpdateName()
{
m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name);
@@ -1628,10 +1636,10 @@ namespace OpenSim.Region.Framework.Scenes
Thread.Sleep(5000);
UseFakeGroupTitle = false;
SendAvatarDataToAllClients(false);
SendAvatarDataToAllAgents();
}, null, "Scenepresence.ForceViewersUpdateName");
}
*/
public int GetStateSource()
{
return m_teleportFlags == TeleportFlags.Default ? 2 : 5; // StateSource.PrimCrossing : StateSource.Teleporting
@@ -2239,6 +2247,16 @@ namespace OpenSim.Region.Framework.Scenes
m_log.DebugFormat("[CompleteMovement]: Missing COF for {0} is {1}", client.AgentId, COF);
*/
}
if ((m_teleportFlags & TeleportFlags.ViaHGLogin) != 0)
{
// The avatar is arriving from another grid. This means that we may have changed the
// avatar's name to or from the special Hypergrid format ("First.Last @grid.example.com").
// Unfortunately, due to a viewer bug, viewers don't always show the new name.
// But we have a trick that can force them to update the name anyway.
ForceViewersUpdateName();
}
}
if (m_teleportFlags > 0)
@@ -2355,6 +2373,7 @@ namespace OpenSim.Region.Framework.Scenes
// attachments
if (IsNPC || IsRealLogin(m_teleportFlags))
{
GotAttachmentsData = true;
if (Scene.AttachmentsModule != null)
{
if(IsNPC)
@@ -3070,14 +3089,22 @@ namespace OpenSim.Region.Framework.Scenes
if(IsNPC)
{
if (!Flying)
shouldfly = !noFly && (pos.Z > terrainHeight + Appearance.AvatarHeight);
shouldfly = !noFly && (pos.Z > AbsolutePosition.Z + (Appearance.AvatarHeight*2));
LandAtTarget = landAtTarget && shouldfly;
}
else
{
// we have no control on viewer fly state
shouldfly = Flying || (pos.Z > terrainHeight + Appearance.AvatarHeight);
LandAtTarget = false;
if (pos.Z < AbsolutePosition.Z)
{
shouldfly = false;
LandAtTarget = false;
}
else
{
// we have no control on viewer fly state
shouldfly = Flying || (pos.Z > AbsolutePosition.Z + (Appearance.AvatarHeight*2));
LandAtTarget = false;
}
}
// m_log.DebugFormat("[SCENE PRESENCE]: Local vector to target is {0},[1}", localVectorToTarget3D.X,localVectorToTarget3D.Y);

View File

@@ -824,6 +824,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
UUID agentID = GetRequestingAgentID(remoteClient);
m_groupData.SetAgentActiveGroup(agentID, agentID, groupID);
ScenePresence sp = ((Scene)(remoteClient.Scene)).GetScenePresence(remoteClient.AgentId);
List<SceneObjectGroup> attachments = sp.GetAttachments();
foreach(SceneObjectGroup so in attachments)
{
//m_log.DebugFormat("[GROUPS MODULE]: Setting new group and checking scripts to run in attachment {0} for {1}", so.Name, so.OwnerID);
so.SetGroup(groupID, remoteClient);
if (so.ContainsScripts() && so.RunningScriptCount() == 0)
{
so.RootPart.ParentGroup.CreateScriptInstances(
0, false, sp.Scene.DefaultScriptEngine, sp.GetStateSource());
so.ResumeScripts();
}
}
// llClientView does this
SendAgentGroupDataUpdate(remoteClient, true);
}
@@ -1080,11 +1095,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
{
if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name);
m_groupData.SetAgentActiveGroupRole(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, titleRoleID);
UUID agentID = remoteClient.AgentId;
m_groupData.SetAgentActiveGroupRole(agentID, agentID, groupID, titleRoleID);
// TODO: Not sure what all is needed here, but if the active group role change is for the group
// the client currently has set active, then we need to do a scene presence update too
// if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID)
// If the active group role change is for the group
// the client currently has set active, then we need to
// set the active group again for the tag to update
if (m_groupData.GetAgentActiveMembership(agentID, agentID).GroupID == groupID)
{
m_groupData.SetAgentActiveGroup(agentID, agentID, groupID);
}
SendDataUpdate(remoteClient, true);
}

View File

@@ -118,6 +118,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected bool m_AllowGodFunctions;
protected double m_timer = Util.GetTimeStamp();
protected string m_SlurlPrefix = "http://slurl.opensim.local";
protected bool m_waitingForScriptAnswer = false;
protected bool m_automaticLinkPermission = false;
protected int m_notecardLineReadCharsMax = 255;
@@ -443,6 +445,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_recoilScaleFactor = seConfig.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
m_AllowGodFunctions = seConfig.GetBoolean("AllowGodFunctions", false);
m_SlurlPrefix = seConfig.GetString("SlurlPrefix", m_SlurlPrefix);
m_disable_underground_movement = seConfig.GetBoolean("DisableUndergroundMovement", true);
m_linksetDataLimit = seConfig.GetInt("LinksetDataLimit", m_linksetDataLimit);
@@ -516,7 +520,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay);
}
IConfig smtpConfig = seConfigSource.Configs["SMTP"];
IConfig smtpConfig = seConfigSource.Configs["Email"];
if (smtpConfig != null)
{
// there's an smtp config, so load in the snooze time.
@@ -525,7 +529,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost);
}
IConfig chatConfig = seConfigSource.Configs["SMTP"];
IConfig chatConfig = seConfigSource.Configs["Chat"];
if(chatConfig != null)
{
m_whisperdistance = chatConfig.GetInt("whisper_distance", m_whisperdistance);
@@ -2799,7 +2803,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Float llGetTimeOfDay()
{
return (double)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4));
if (m_envModule is null)
{
return (float)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4));
}
else
{
// Similar as osGetApparentTime(), taking into account parcel environment
float frac = m_envModule.GetDayFractionTime(m_host.GetWorldPosition());
return 86400 * frac;
}
}
public LSL_Float llGetRegionTimeOfDay()
{
if (m_envModule is null)
{
return (float)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4));
}
else
{
// Same as osGetApparentTime(), taking into account region environment
float frac = m_envModule.GetRegionDayFractionTime();
return 86400 * frac;
}
}
public LSL_Float llGetWallclock()
@@ -5035,7 +5062,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (account is null)
{
GridUserInfo info = World.GridUserService.GetGridUserInfo(destId.ToString());
if(info is null || info.Online == false)
if(info is null)
{
Error("llGiveInventory", "Can't find destination '" + destId.ToString() + "'");
return;
@@ -5237,7 +5264,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
else
{
if (data == 7)
if (data == 7 || data == 8)
reply = "0";
}
break;
@@ -6472,6 +6499,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case "shout_range":
return m_shoutdistance.ToString();
case "region_rating":
switch(World.RegionInfo.RegionSettings.Maturity)
{
case 0: return "PG";
case 1: return "MATURE";
case 2: return "ADULT";
default: return "UNKNOWN";
}
case "grid":
return World.SceneGridInfo == null ? string.Empty : World.SceneGridInfo.GridName;
case "objectmail_hostname":
goto case "mailname";
case "mailname":
if (m_emailModule is not null)
return m_internalObjectHost;
return "";
default:
return "";
}
@@ -8119,8 +8165,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
GridInstantMessage msg = new(World, m_host.OwnerID, m_host.Name, destID,
(byte)InstantMessageDialog.TaskInventoryOffered,
m_host.OwnerID.Equals(m_host.GroupID),
string.Format("'{0}'", category),
//string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z),
string.Format("'{0}' ( {1}/{2}/{3}/{4}/{5}/ )", category, m_SlurlPrefix, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), //string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z),
folderID, false, pos,
bucket, false);
@@ -10751,8 +10796,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
float repeatX = Math.Clamp((float)mnrepeat.x,-100.0f, 100.0f);
float repeatY = Math.Clamp((float)mnrepeat.y,-100.0f, 100.0f);
float offsetX = Math.Clamp((float)mnoffset.x, 0f, 1.0f);
float offsetY = Math.Clamp((float)mnoffset.y, 0f, 1.0f);
float offsetX = Math.Clamp((float)mnoffset.x, -1.0f, 1.0f);
float offsetY = Math.Clamp((float)mnoffset.y, -1.0f, 1.0f);
materialChanged |= SetMaterialNormalMap(part, face, mapID, repeatX, repeatY, offsetX, offsetY, mnrot);
break;

View File

@@ -0,0 +1,102 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using OpenMetaverse;
using Nini.Config;
using OpenSim;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.ScriptEngine.Shared;
using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
#pragma warning disable IDE1006
namespace OpenSim.Region.ScriptEngine.Shared.Api
{
[Serializable]
public class Lickx_Api : ILickx_Api, IScriptApi
{
internal IScriptEngine m_ScriptEngine;
internal SceneObjectPart m_host;
internal bool m_LickxFunctionsEnabled = true;
internal IScriptModuleComms m_comms = null;
public void Initialize(IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
{
m_ScriptEngine = scriptEngine;
m_host = host;
m_comms = m_ScriptEngine.World.RequestModuleInterface<IScriptModuleComms>();
if (m_comms == null)
m_LickxFunctionsEnabled = false;
}
public Scene World
{
get { return m_ScriptEngine.World; }
}
internal static void lxError(string msg)
{
throw new ScriptException("Lickx Runtime Error: " + msg);
}
/// <summary>
/// Get the viewer name of an agent
/// </summary>
/// <param name="avKey">The UUID of the target agent</param>
/// <returns>A string containing the viewer name</returns>
public LSL_String lxGetAgentViewer(LSL_Key avkey)
{
if (!UUID.TryParse(avkey.m_string, out UUID avId))
return string.Empty;
AgentCircuitData aCircuit = World.AuthenticateHandler.GetAgentCircuitData(avId);
if (aCircuit != null)
return Util.GetViewerName(aCircuit);
return String.Empty;
}
}
}

View File

@@ -1184,6 +1184,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if(!(World.Permissions.IsGod(m_host.OwnerID))) // user god always needed
return string.Empty;
/*
if(!UUID.TryParse(agent, out UUID avatarID))
return string.Empty;
@@ -1192,7 +1193,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
return target.ControllingClient.RemoteEndPoint.Address.ToString();
}
*/
return string.Empty;
}

View File

@@ -223,6 +223,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
LSL_Vector llGetTextureScale(int side);
LSL_Float llGetTime();
LSL_Float llGetTimeOfDay();
LSL_Float llGetRegionTimeOfDay();
LSL_String llGetTimestamp();
LSL_Vector llGetTorque();
LSL_Integer llGetUnixTime();

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma warning disable IDE1006
using System;
using System.Collections;
using OpenSim.Region.ScriptEngine.Interfaces;
using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
{
public interface ILickx_Api
{
LSL_String lxGetAgentViewer(LSL_Key avkey);
}
}

View File

@@ -1121,5 +1121,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int BEACON_MAP = 0x1;
public const int BEACON_SHOW_MAP = 0x1;
public const int BEACON_FOCUS_MAP = 0x2;
// returned by llRequestAgentData
public const int PAYMENT_INFO_ON_FILE = 1;
public const int PAYMENT_INFO_USED = 2;
}
}

View File

@@ -1040,6 +1040,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
return m_LSL_Functions.llGetTimeOfDay();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public LSL_Float llGetRegionTimeOfDay()
{
return m_LSL_Functions.llGetRegionTimeOfDay();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public LSL_String llGetTimestamp()
{

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Runtime.CompilerServices;
using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
#pragma warning disable IDE1006
namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
{
public partial class ScriptBaseClass
{
public ILickx_Api m_Lickx_Functions;
public void ApiTypeLickx(IScriptApi api)
{
if (api is ILickx_Api p)
m_Lickx_Functions = p;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public LSL_String lxGetAgentViewer(LSL_Key avkey)
{
return m_Lickx_Functions.lxGetAgentViewer(avkey);
}
}
}

View File

@@ -2568,88 +2568,29 @@ namespace OpenSim.Region.ScriptEngine.Shared
public LSLInteger(LSLString s) : this(MemoryExtensions.AsSpan(s.m_string)) { }
public LSLInteger(ReadOnlySpan<char> s)
{
value = 0;
if (s.Length == 0)
return;
int indx = 0;
char c;
bool neg = false;
int rc;
try
{
do
{
c = Unsafe.Add(ref MemoryMarshal.GetReference(s), indx);
if (c != ' ')
break;
}
while (++indx < s.Length);
if (c == '0')
{
if (++indx >= s.Length)
return;
c = Unsafe.Add(ref MemoryMarshal.GetReference(s), indx);
if (c == 'x' || c == 'X')
{
uint uvalue = 0;
while (++indx < s.Length)
{
c = Unsafe.Add(ref MemoryMarshal.GetReference(s), indx);
rc = Utils.HexNibbleWithChk(c);
if (rc < 0)
break;
checked
{
uvalue *= 16;
uvalue += (uint)rc;
}
}
value = (int)uvalue;
return;
}
}
else if (c == '+')
{
if (++indx >= s.Length)
return;
c = Unsafe.Add(ref MemoryMarshal.GetReference(s), indx);
}
else if (c == '-')
{
if (++indx >= s.Length)
return;
neg = true;
c = Unsafe.Add(ref MemoryMarshal.GetReference(s), indx);
}
while (c >= '0' && c <= '9')
{
rc = c - '0';
checked
{
value *= 10;
value += rc;
}
if(++indx >= s.Length)
break;
c = Unsafe.Add(ref MemoryMarshal.GetReference(s), indx);
}
if(neg)
value = -value;
return;
}
catch (OverflowException)
{
value = -1;
}
catch
{
value = 0;
}
else
{
try
{
s = s.TrimStart();
if (s.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
value = int.Parse(s[2..], NumberStyles.HexNumber);
else
value = int.Parse(s,NumberStyles.Integer);
}
catch (OverflowException)
{
value = -1;
}
catch
{
value = 0;
}
}
}
#endregion

View File

@@ -89,12 +89,13 @@ namespace OpenSim.Server.Handlers.Grid
if (stats_available)
{
stats_available = false;
string gridService = m_Config.Configs["GridService"].GetString("LocalServiceModule", string.Empty);
if(!string.IsNullOrEmpty(gridService))
string gridService = gridCfg.GetString("GridService", string.Empty);
if (!string.IsNullOrWhiteSpace(gridService))
{
m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, [m_Config]);
if(m_GridService != null)
{
object[] args = new object[] { configSource };
m_GridService = ServerUtils.LoadPlugin<IGridService>(gridService, args);
if (m_GridService != null)
{
IConfig dbConfig = configSource.Configs["DatabaseService"];
if (dbConfig is not null)
{
@@ -282,7 +283,7 @@ namespace OpenSim.Server.Handlers.Grid
try
{
// Fetch region data
if(m_GridService is not null)
if (m_GridService is not null)
{
List<GridRegion> regions = m_GridService.GetOnlineRegions(UUID.Zero, 0, 0, int.MaxValue);
foreach (GridRegion region in regions)

View File

@@ -69,24 +69,18 @@ namespace OpenSim.Server.Handlers.Presence
string method = string.Empty;
try
{
Dictionary<string, object> request = ServerUtils.ParseQueryString(body);
Dictionary<string, object> request =
ServerUtils.ParseQueryString(body);
if (!request.TryGetValue("METHOD", out object tmpobj) || tmpobj is not string)
if (!request.ContainsKey("METHOD"))
return FailureResult();
method = (string)tmpobj;
method = request["METHOD"].ToString();
switch (method)
{
case "login":
{
//return LoginAgent(request); this is ilegal
if (request.TryGetValue("UserID", out object uo) && uo is string user)
m_log.Debug($"[PRESENCE HANDLER]: ilegal login try from {httpRequest.RemoteIPEndPoint} for userID {user}");
else
m_log.Debug($"[PRESENCE HANDLER]: ilegal login try from {httpRequest.RemoteIPEndPoint} for unkown user");
return FailureResult();
}
return LoginAgent(request);
case "logout":
return LogoutAgent(request);
case "logoutregion":
@@ -98,11 +92,11 @@ namespace OpenSim.Server.Handlers.Presence
case "getagents":
return GetAgents(request);
}
m_log.Debug($"[PRESENCE HANDLER]: unknown method request: {method}");
m_log.DebugFormat("[PRESENCE HANDLER]: unknown method request: {0}", method);
}
catch (Exception e)
{
m_log.Debug($"[PRESENCE HANDLER]: Exception in method {method}: {e.Message}");
m_log.DebugFormat("[PRESENCE HANDLER]: Exception in method {0}: {1}", method, e);
}
return FailureResult();

View File

@@ -32,6 +32,7 @@ using System;
using System.IO;
using System.Net;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Collections.Generic;
using OpenSim.Framework;
@@ -50,6 +51,7 @@ namespace OpenSim.Server
protected static List<IServiceConnector> m_ServiceConnectors = new();
protected static PluginLoader loader;
private static PosixSignalRegistration m_signalReg;
private static bool m_NoVerifyCertChain = false;
private static bool m_NoVerifyCertHostname = false;
@@ -95,13 +97,20 @@ namespace OpenSim.Server
Culture.SetCurrentCulture();
Culture.SetDefaultCurrentCulture();
m_signalReg = PosixSignalRegistration.Create(PosixSignal.SIGTERM, context =>
{
m_log.Info("Received SIGTERM, shutting down");
m_Server?.Shutdown();
Util.StopThreadPool();
});
ServicePointManager.DefaultConnectionLimit = 64;
ServicePointManager.MaxServicePointIdleTime = 30000;
ServicePointManager.Expect100Continue = false;
ServicePointManager.UseNagleAlgorithm = false;
ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;
m_Server = new HttpServerBase("R.O.B.U.S.T.", args);
string registryLocation;

View File

@@ -28,19 +28,14 @@
using log4net;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reflection;
using Nini.Config;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.ServiceAuth;
using OpenSim.Server.Base;
using OpenSim.Services.Interfaces;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Services.Connectors
{
@@ -105,12 +100,12 @@ namespace OpenSim.Services.Connectors
}
else
{
// Do not include SCOPE when it's zero
reqString = ServerUtils.BuildQueryString(
new Dictionary<string, object>()
{
{"X" , x.ToString() },
{"Y" , y.ToString() },
{ "SCOPE" , scopeID.ToString() },
{"Y" , y.ToString() }
}
);
}
@@ -118,7 +113,7 @@ namespace OpenSim.Services.Connectors
try
{
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI + "/map", reqString, 10, null, false);
if (reply.Length > 0)
if (!string.IsNullOrEmpty(reply))
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if(replyData.TryGetValue("Result", out object resultobj))
@@ -133,17 +128,17 @@ namespace OpenSim.Services.Connectors
return true;
else if (res.Equals("failure", StringComparison.InvariantCultureIgnoreCase))
{
reason = replyData["Message"].ToString();
reason = replyData.TryGetValue("Message", out var value) ? value.ToString() : "";
m_log.DebugFormat("[MAP IMAGE CONNECTOR]: RemoveMapTile failed: {0}", reason);
return false;
}
m_log.DebugFormat("[MAP IMAGE CONNECTOR]: RemoveMapTile unknown result field contents");
return false;
}
}
else
{
m_log.DebugFormat("[MAP IMAGE CONNECTOR]: RemoveMapTile reply data does not contain result field");
else
{
m_log.DebugFormat("[MAP IMAGE CONNECTOR]: RemoveMapTile reply data does not contain result field");
}
}
}
catch (Exception e)
@@ -188,7 +183,7 @@ namespace OpenSim.Services.Connectors
try
{
string reply = SynchronousRestFormsRequester.MakeRequest("POST", m_ServerURI + "/map", reqString, 10, m_Auth, false);
if (reply.Length > 0)
if (!string.IsNullOrEmpty(reply))
{
Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(reply);
if (replyData.TryGetValue("Result", out object resultobj))
@@ -203,7 +198,7 @@ namespace OpenSim.Services.Connectors
return true;
else if (res.Equals("failure", StringComparison.InvariantCultureIgnoreCase))
{
reason = replyData["Message"].ToString();
reason = replyData.TryGetValue("Message", out var value) ? value.ToString() : "";
m_log.DebugFormat("[MAP IMAGE CONNECTOR]: AddMapTile failed: {0}", reason);
return false;
}
@@ -231,9 +226,7 @@ namespace OpenSim.Services.Connectors
public byte[] GetMapTile(string fileName, UUID scopeID, out string format)
{
format = string.Empty;
new Exception("GetMapTile method not Implemented");
return null;
throw new Exception("GetMapTile method not Implemented");
}
}
}

View File

@@ -65,6 +65,7 @@ namespace OpenSim.Services.HypergridService
private static bool m_ForeignAgentsAllowed = true;
private static readonly List<string> m_ForeignsAllowedExceptions = new();
private static readonly List<string> m_ForeignsDisallowedExceptions = new();
private static string m_DeniedMessage = "Destination does not allow visitors from your world";
private static UUID m_ScopeID;
private static bool m_AllowTeleportsToAnyRegion;
@@ -187,6 +188,8 @@ namespace OpenSim.Services.HypergridService
LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_ForeignsAllowedExceptions);
LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_ForeignsDisallowedExceptions);
m_DeniedMessage = serverConfig.GetString("DeniedMessage", m_DeniedMessage);
if (m_GridService is null || m_PresenceService is null || m_SimulationService is null)
throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function.");
@@ -432,12 +435,18 @@ namespace OpenSim.Services.HypergridService
if (m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsAllowedExceptions))
allowed = false;
string iponly = @"http\:\/\/\d+\.\d+\.\d+\.\d+\:\d+";
Regex r = new Regex(iponly, RegexOptions.IgnoreCase);
Match m = r.Match(aCircuit.ServiceURLs["HomeURI"].ToString());
if (m_ForeignAgentsAllowed && m.Success)
allowed = false; // HomeURI is an ip address, not a proper hostname
if (!m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsDisallowedExceptions))
allowed = true;
if (!allowed)
{
reason = "Destination does not allow visitors from your world";
reason = m_DeniedMessage;
m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agents are not permitted {0} {1} @ {2}. Refusing service.",
aCircuit.firstname, aCircuit.lastname, aCircuit.ServiceURLs["HomeURI"]);
return false;

View File

@@ -104,6 +104,11 @@ namespace OpenSim.Services.HypergridService
throw new Exception("No PresenceService in " + m_ConfigName);
m_PresenceService = ServerUtils.LoadPlugin<IPresenceService>(theService, args);
theService = serverConfig.GetString("GridUserService", string.Empty);
if (theService.Length == 0)
throw new Exception("No GridUserService in " + m_ConfigName);
m_GridUserService = ServerUtils.LoadPlugin<IGridUserService>(theService, args);
m_FriendsSimConnector = new FriendsSimConnector();
m_log.DebugFormat("[HGFRIENDS SERVICE]: Starting...");
@@ -133,6 +138,9 @@ namespace OpenSim.Services.HypergridService
m_log.DebugFormat("[HGFRIENDS SERVICE]: New friendship {0} {1} ({2})", friend.PrincipalID, friend.Friend, verified);
// Mantis 9199: Make sure the new HG friend is in the GridUser table
m_GridUserService?.LoggedIn(friendID.ToString()+";"+url+";"+first+" "+last);
// Does the friendship already exist?
FriendInfo[] finfos = m_FriendsService.GetFriends(friend.PrincipalID);
foreach (FriendInfo finfo in finfos)

View File

@@ -114,7 +114,7 @@ namespace OpenSim.Services.HypergridService
}
catch
{
m_log.WarnFormat("[HG IM SERVICE]: Unable to load PresenceService");
m_log.WarnFormat("[HG IM SERVICE]: Unable to load UserAgentService");
}
m_InGatekeeper = serverConfig.GetBoolean("InGatekeeper", false);
@@ -122,7 +122,7 @@ namespace OpenSim.Services.HypergridService
IConfig cnf = config.Configs["Messaging"];
if (cnf == null)
{
m_log.Debug("[HG IM SERVICE]: Starting (without [MEssaging])");
m_log.Debug("[HG IM SERVICE]: Starting (without [Messaging])");
return;
}

View File

@@ -11,11 +11,13 @@ namespace OpenSim.Services.HypergridService
{
public class UserAccountCache : IUserAccountService
{
private const double CACHE_EXPIRATION_SECONDS = 120000.0; // 33 hours!
private const double CACHE_ALIEN_EXPIRATION_SECONDS = 7200.0; // 2 hours
private const double CACHE_EXPIRATION_SECONDS = 3600; // 1 hour // 120000.0; // 33 hours!
private const double CACHE_NULL_EXPIRATION_SECONDS = 600; // 10 minutes
// private static readonly ILog m_log =
// LogManager.GetLogger(
// MethodBase.GetCurrentMethod().DeclaringType);
//private static readonly ILog m_log =
// LogManager.GetLogger(
// MethodBase.GetCurrentMethod().DeclaringType);
private ExpiringCache<UUID, UserAccount> m_UUIDCache;
@@ -40,7 +42,20 @@ namespace OpenSim.Services.HypergridService
public void Cache(UUID userID, UserAccount account)
{
// Cache even null accounts
m_UUIDCache.AddOrUpdate(userID, account, CACHE_EXPIRATION_SECONDS);
if (account is null)
{
m_UUIDCache.AddOrUpdate(userID, account, CACHE_NULL_EXPIRATION_SECONDS);
return;
}
if (account.LocalToGrid)
{
m_UUIDCache.AddOrUpdate(userID, account, CACHE_EXPIRATION_SECONDS);
return;
}
// Foreigners
m_UUIDCache.AddOrUpdate(userID, account, CACHE_ALIEN_EXPIRATION_SECONDS);
//m_log.DebugFormat("[USER CACHE]: cached user {0}", userID);
}

View File

@@ -44,6 +44,7 @@ namespace OpenSim.Services.PresenceService
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected bool m_allowDuplicatePresences = false;
protected bool m_useCache = true;
const int EXPIREMS = 300000;
static ExpiringCacheOS<UUID, PresenceData> BySessionCache = new ExpiringCacheOS<UUID, PresenceData>(60000);
static ExpiringCacheOS<string, PresenceData> ByUserCache = new ExpiringCacheOS<string, PresenceData>(60000);
@@ -57,23 +58,32 @@ namespace OpenSim.Services.PresenceService
if (presenceConfig != null)
{
m_allowDuplicatePresences = presenceConfig.GetBoolean("AllowDuplicatePresences", m_allowDuplicatePresences);
m_useCache = presenceConfig.GetBoolean("UseCache", m_useCache);
}
}
public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
{
bool inCache = ByUserCache.TryGetValue(userID, out PresenceData prevUser);
if (!inCache)
bool inCache = false;
PresenceData prevUser;
if (m_useCache)
{
PresenceData[] dataprv = m_Database.Get("UserID", userID);
if (dataprv.Length > 0)
prevUser = dataprv[0];
inCache = ByUserCache.TryGetValue(userID, out prevUser);
if (!inCache)
{
PresenceData[] dataprv = m_Database.Get("UserID", userID);
if (dataprv.Length > 0)
prevUser = dataprv[0];
}
}
else
prevUser = GetUser(userID);
if (!m_allowDuplicatePresences && (prevUser != null))
{
m_Database.Delete("UserID", userID.ToString());
if(inCache)
if(m_useCache && inCache)
{
BySessionCache.Remove(prevUser.SessionID);
ByUserCache.Remove(userID);
@@ -89,8 +99,11 @@ namespace OpenSim.Services.PresenceService
data.Data["SecureSessionID"] = secureSessionID.ToString();
m_Database.Store(data);
BySessionCache.Add(sessionID, data, EXPIREMS);
ByUserCache.Add(userID, data, EXPIREMS);
if (m_useCache)
{
BySessionCache.Add(sessionID, data, EXPIREMS);
ByUserCache.Add(userID, data, EXPIREMS);
}
string prevUserStr = "";
if (prevUser != null)
@@ -104,8 +117,16 @@ namespace OpenSim.Services.PresenceService
public bool LogoutAgent(UUID sessionID)
{
bool inCache = BySessionCache.TryGetValue(sessionID, out PresenceData presence);
if(!inCache)
bool inCache = false;
PresenceData presence;
if (m_useCache)
{
inCache = BySessionCache.TryGetValue(sessionID, out presence);
if(!inCache)
presence = m_Database.Get(sessionID);
}
else
presence = m_Database.Get(sessionID);
m_log.DebugFormat("[PRESENCE SERVICE]: LogoutAgent: session {0}, user {1}, region {2}",
@@ -114,7 +135,7 @@ namespace OpenSim.Services.PresenceService
(presence == null) ? null : presence.RegionID.ToString());
bool ret = m_Database.Delete("SessionID", sessionID.ToString());
if(inCache)
if(m_useCache && inCache)
{
BySessionCache.Remove(sessionID);
if(presence is not null)
@@ -126,15 +147,19 @@ namespace OpenSim.Services.PresenceService
public bool LogoutRegionAgents(UUID regionID)
{
PresenceData[] prevSessions = GetRegionAgents(regionID);
if ((prevSessions is null) || (prevSessions.Length == 0))
return true;
m_log.DebugFormat("[PRESENCE SERVICE]: Logout users in region {0}", regionID);
for (int i = 0; i < prevSessions.Length; ++i)
if (m_useCache)
{
PresenceData pd = prevSessions[i];
BySessionCache.Remove(pd.SessionID);
ByUserCache.Remove(pd.UserID);
for (int i = 0; i < prevSessions.Length; ++i)
{
PresenceData pd = prevSessions[i];
BySessionCache.Remove(pd.SessionID);
ByUserCache.Remove(pd.UserID);
}
}
// There's a small chance that LogoutRegionAgents() will logout different users than the
@@ -149,8 +174,16 @@ namespace OpenSim.Services.PresenceService
{
try
{
bool inCache = BySessionCache.TryGetValue(sessionID, out PresenceData presence);
if(!inCache)
bool inCache = false;
PresenceData presence;
if (m_useCache)
{
inCache = BySessionCache.TryGetValue(sessionID, out presence);
if(!inCache)
presence = m_Database.Get(sessionID);
}
else
presence = m_Database.Get(sessionID);
bool success;
@@ -164,16 +197,19 @@ namespace OpenSim.Services.PresenceService
sessionID, (presence == null) ? null : presence.UserID, regionID,
(presence == null) ? "not logged-in" : "region " + presence.RegionID);
if (success)
if (m_useCache)
{
presence.RegionID = regionID;
BySessionCache.Add(sessionID, presence, EXPIREMS); // lastseen seems unused
ByUserCache.Add(presence.UserID, presence, EXPIREMS); // lastseen seems unused
}
else if (inCache)
{
BySessionCache.Remove(sessionID);
ByUserCache.Remove(presence.UserID);
if (success)
{
presence.RegionID = regionID;
BySessionCache.Add(sessionID, presence, EXPIREMS); // lastseen seems unused
ByUserCache.Add(presence.UserID, presence, EXPIREMS); // lastseen seems unused
}
else if (inCache)
{
BySessionCache.Remove(sessionID);
ByUserCache.Remove(presence.UserID);
}
}
return success;
@@ -187,14 +223,24 @@ namespace OpenSim.Services.PresenceService
public PresenceInfo GetAgent(UUID sessionID)
{
if(!BySessionCache.TryGetValue(sessionID, out PresenceData data))
PresenceData data;
if (m_useCache)
{
if(!BySessionCache.TryGetValue(sessionID, out data))
data = m_Database.Get(sessionID);
}
else
data = m_Database.Get(sessionID);
if (data == null)
return null;
BySessionCache.Add(sessionID, data, EXPIREMS);
ByUserCache.Add(data.UserID, data, EXPIREMS);
if (m_useCache)
{
BySessionCache.Add(sessionID, data, EXPIREMS);
ByUserCache.Add(data.UserID, data, EXPIREMS);
}
var ret = new PresenceInfo()
{
@@ -210,8 +256,9 @@ namespace OpenSim.Services.PresenceService
PresenceInfo ret;
foreach (string userIDStr in userIDs)
{
if(ByUserCache.TryGetValue(userIDStr, out PresenceData pd))
if(m_useCache && ByUserCache.TryGetValue(userIDStr, out PresenceData pd))
{
// cache hit
ByUserCache.Add(pd.UserID, pd, EXPIREMS);
BySessionCache.Add(pd.SessionID, pd, EXPIREMS);
ret = new PresenceInfo()
@@ -223,12 +270,16 @@ namespace OpenSim.Services.PresenceService
}
else
{
// no cache used or cache miss
PresenceData[] data = m_Database.Get("UserID", userIDStr);
if(data.Length == 0)
continue;
PresenceData d = data[0];
ByUserCache.Add(d.UserID, d, EXPIREMS);
BySessionCache.Add(d.SessionID, d, EXPIREMS);
if (m_useCache)
{
ByUserCache.Add(d.UserID, d, EXPIREMS);
BySessionCache.Add(d.SessionID, d, EXPIREMS);
}
ret = new PresenceInfo()
{
UserID = d.UserID,
@@ -243,6 +294,18 @@ namespace OpenSim.Services.PresenceService
return info.ToArray();
}
/// <summary>
/// Return the user's Presence. This only really works well if !AllowDuplicatePresences, but that's the default.
/// </summary>
private PresenceData GetUser(string userID)
{
PresenceData[] data = m_Database.Get("UserID", userID);
if (data.Length > 0)
return data[0];
else
return null;
}
private PresenceData[] GetRegionAgents(UUID regionID)
{
return m_Database.Get("RegionID", regionID.ToString());

View File

@@ -44,6 +44,7 @@ namespace OpenSim.Services.UserAccountService
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static bool m_Initialized;
protected bool m_useCache = true;
public GridUserService(IConfigSource config) : base(config)
{
@@ -69,6 +70,13 @@ namespace OpenSim.Services.UserAccountService
"This number may not be accurate as a region may crash or not be cleanly shutdown and leave grid users shown as online\n."
+ "For this reason, users online for more than 5 days are not currently counted",
HandleShowGridUsersOnline);
IConfig griduserConfig = config.Configs["GridUserService"];
if (griduserConfig != null)
{
m_useCache = griduserConfig.GetBoolean("UseCache", m_useCache);
}
}
}
@@ -132,13 +140,13 @@ namespace OpenSim.Services.UserAccountService
if (userID.Length > 36)
userID = userID.Substring(0, 36);
if (cache.TryGetValue(userID, out GridUserData d))
return d;
if (m_useCache && cache.TryGetValue(userID, out GridUserData d))
return d;
GridUserData[] ds = m_Database.GetAll(userID);
if (ds == null || ds.Length == 0)
{
cache.Add(userID, null, 300000);
if (m_useCache) cache.Add(userID, null, 300000);
return null;
}
@@ -168,7 +176,7 @@ namespace OpenSim.Services.UserAccountService
}
catch { }
}
cache.Add(userID, d, 300000);
if (m_useCache) cache.Add(userID, d, 300000);
return d;
}
@@ -249,7 +257,7 @@ namespace OpenSim.Services.UserAccountService
d.Data["Login"] = Util.UnixTimeSinceEpoch().ToString();
m_Database.Store(d);
if (userID.Length >= 36)
if (m_useCache && userID.Length >= 36)
cache.Add(userID.Substring(0, 36), d, 300000);
return ToInfo(d);
@@ -275,7 +283,7 @@ namespace OpenSim.Services.UserAccountService
if(m_Database.Store(d))
{
if (userID.Length >= 36)
if (m_useCache && userID.Length >= 36)
cache.Add(userID.Substring(0, 36), d, 300000);
return true;
}
@@ -298,7 +306,7 @@ namespace OpenSim.Services.UserAccountService
if(m_Database.Store(d))
{
if (userID.Length >= 36)
if (m_useCache && userID.Length >= 36)
cache.Add(userID.Substring(0, 36), d, 300000);
return true;
}
@@ -323,7 +331,7 @@ namespace OpenSim.Services.UserAccountService
if(m_Database.Store(d))
{
if (userID.Length >= 36)
if (m_useCache && userID.Length >= 36)
cache.Add(userID.Substring(0, 36), d, 300000);
return true;
}

View File

@@ -0,0 +1,732 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Xml;
using OpenMetaverse;
using log4net;
using Nini.Config;
using Nwc.XmlRpc;
using OpenSim.Framework;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using OpenSim.Services.Interfaces;
using Mono.Addins;
using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags;
[assembly: Addin("OpenSimSearch", OpenSim.VersionInfo.VersionNumber + "0.4")]
[assembly: AddinDependency("OpenSim.Region.Framework", OpenSim.VersionInfo.VersionNumber)]
[assembly: AddinDescription("OpenSimSearch module.")]
[assembly: AddinAuthor("Unknown")]
namespace OpenSimSearch.Modules.OpenSearch
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "OpenSimSearch")]
public class OpenSearchModule : ISearchModule, ISharedRegionModule
{
//
// Log module
//
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
//
// Module vars
//
private List<Scene> m_Scenes = new();
private string m_SearchServer = "";
private bool m_Enabled = true;
#region IRegionModuleBase implementation
public void Initialise(IConfigSource config)
{
IConfig searchConfig = config.Configs["Search"];
if (searchConfig is null)
{
m_Enabled = false;
return;
}
if (searchConfig.GetString("Module", "OpenSimSearch") != "OpenSimSearch")
{
m_Enabled = false;
return;
}
m_SearchServer = searchConfig.GetString("SearchURL", "");
if (m_SearchServer == "")
{
m_Enabled = false;
return;
}
m_log.Info("[SEARCH] OpenSimSearch module is active");
m_Enabled = true;
}
public void AddRegion(Scene scene)
{
if (!m_Enabled)
return;
// Hook up events
scene.EventManager.OnNewClient += OnNewClient;
// Take ownership of the ISearchModule service
scene.RegisterModuleInterface<ISearchModule>(this);
// Add our scene to our list...
lock(m_Scenes)
{
m_Scenes.Add(scene);
}
}
public void RemoveRegion(Scene scene)
{
if (!m_Enabled)
return;
scene.UnregisterModuleInterface<ISearchModule>(this);
scene.EventManager.OnNewClient -= OnNewClient;
lock(m_Scenes)
{
m_Scenes.Remove(scene);
}
}
public void RegionLoaded(Scene scene)
{
}
public Type ReplaceableInterface
{
get { return null; }
}
public void PostInitialise()
{
}
public void Close()
{
}
public string Name
{
get { return "OpenSimSearch"; }
}
public static bool IsSharedModule
{
get { return true; }
}
#endregion
/// New Client Event Handler
private void OnNewClient(IClientAPI client)
{
// Subscribe to messages
client.OnDirPlacesQuery += DirPlacesQuery;
client.OnDirFindQuery += DirFindQuery;
client.OnDirPopularQuery += DirPopularQuery;
client.OnDirLandQuery += DirLandQuery;
client.OnDirClassifiedQuery += DirClassifiedQuery;
// Response after Directory Queries
client.OnEventInfoRequest += EventInfoRequest;
client.OnClassifiedInfoRequest += ClassifiedInfoRequest;
client.OnMapItemRequest += HandleMapItemRequest;
}
//
// Make external XMLRPC request
//
private Hashtable GenericXMLRPCRequest(Hashtable ReqParams, string method)
{
ArrayList SendParams = new()
{
ReqParams
};
// Send Request
XmlRpcResponse Resp;
try
{
XmlRpcRequest Req = new(method, SendParams);
Resp = Req.Send(m_SearchServer, 30000);
}
catch (WebException ex)
{
m_log.ErrorFormat("[SEARCH]: Unable to connect to Search " +
"Server {0}. Exception {1}", m_SearchServer, ex);
Hashtable ErrorHash = new()
{
["success"] = false,
["errorMessage"] = "Unable to search at this time. ",
["errorURI"] = ""
};
return ErrorHash;
}
catch (SocketException ex)
{
m_log.ErrorFormat(
"[SEARCH]: Unable to connect to Search Server {0}. " +
"Exception {1}", m_SearchServer, ex);
Hashtable ErrorHash = new()
{
["success"] = false,
["errorMessage"] = "Unable to search at this time. ",
["errorURI"] = ""
};
return ErrorHash;
}
catch (XmlException ex)
{
m_log.ErrorFormat(
"[SEARCH]: Unable to connect to Search Server {0}. " +
"Exception {1}", m_SearchServer, ex);
Hashtable ErrorHash = new()
{
["success"] = false,
["errorMessage"] = "Unable to search at this time. ",
["errorURI"] = ""
};
return ErrorHash;
}
if (Resp.IsFault)
{
Hashtable ErrorHash = new()
{
["success"] = false,
["errorMessage"] = "Unable to search at this time. ",
["errorURI"] = ""
};
return ErrorHash;
}
Hashtable RespData = (Hashtable)Resp.Value;
return RespData;
}
protected void DirPlacesQuery(IClientAPI remoteClient, UUID queryID,
string queryText, int queryFlags, int category, string simName,
int queryStart)
{
Hashtable ReqHash = new()
{
["text"] = queryText,
["flags"] = queryFlags.ToString(),
["category"] = category.ToString(),
["sim_name"] = simName,
["query_start"] = queryStart.ToString()
};
Hashtable result = GenericXMLRPCRequest(ReqHash, "dir_places_query");
if (!Convert.ToBoolean(result["success"]))
{
remoteClient.SendAgentAlertMessage(result["errorMessage"].ToString(), false);
return;
}
ArrayList dataArray = (ArrayList)result["data"];
int count = (dataArray.Count > 100) ? 101 : dataArray.Count;
DirPlacesReplyData[] data = new DirPlacesReplyData[count];
int i = 0;
foreach (Object o in dataArray)
{
Hashtable d = (Hashtable)o;
data[i] = new DirPlacesReplyData
{
parcelID = new UUID(d["parcel_id"].ToString()),
name = d["name"].ToString(),
forSale = Convert.ToBoolean(d["for_sale"]),
auction = Convert.ToBoolean(d["auction"]),
dwell = Convert.ToSingle(d["dwell"])
};
if (++i >= count)
break;
}
remoteClient.SendDirPlacesReply(queryID, data);
}
public void DirPopularQuery(IClientAPI remoteClient, UUID queryID, uint queryFlags)
{
Hashtable ReqHash = new()
{
["flags"] = queryFlags.ToString()
};
Hashtable result = GenericXMLRPCRequest(ReqHash, "dir_popular_query");
if (!Convert.ToBoolean(result["success"]))
{
remoteClient.SendAgentAlertMessage(result["errorMessage"].ToString(), false);
return;
}
ArrayList dataArray = (ArrayList)result["data"];
int count = (dataArray.Count > 100) ? 101 : dataArray.Count;
DirPopularReplyData[] data = new DirPopularReplyData[count];
int i = 0;
foreach (Object o in dataArray)
{
Hashtable d = (Hashtable)o;
data[i] = new DirPopularReplyData
{
parcelID = new UUID(d["parcel_id"].ToString()),
name = d["name"].ToString(),
dwell = Convert.ToSingle(d["dwell"])
};
if (++i >= count)
break;
}
remoteClient.SendDirPopularReply(queryID, data);
}
public void DirLandQuery(IClientAPI remoteClient, UUID queryID,
uint queryFlags, uint searchType, int price, int area,
int queryStart)
{
Hashtable ReqHash = new()
{
["flags"] = queryFlags.ToString(),
["type"] = searchType.ToString(),
["price"] = price.ToString(),
["area"] = area.ToString(),
["query_start"] = queryStart.ToString()
};
Hashtable result = GenericXMLRPCRequest(ReqHash, "dir_land_query");
if (!Convert.ToBoolean(result["success"]))
{
remoteClient.SendAgentAlertMessage(result["errorMessage"].ToString(), false);
return;
}
ArrayList dataArray = (ArrayList)result["data"];
int count = 0;
/* Count entries in dataArray with valid region name to */
/* prevent allocating data array with too many entries. */
foreach (Object o in dataArray)
{
Hashtable d = (Hashtable)o;
if (d["name"] is not null)
++count;
}
count = (count > 100) ? 101 : count;
DirLandReplyData[] data = new DirLandReplyData[count];
int i = 0;
foreach (Object o in dataArray)
{
Hashtable d = (Hashtable)o;
if (d["name"] is null)
continue;
data[i] = new DirLandReplyData
{
parcelID = new UUID(d["parcel_id"].ToString()),
name = d["name"].ToString(),
auction = Convert.ToBoolean(d["auction"]),
forSale = Convert.ToBoolean(d["for_sale"]),
salePrice = Convert.ToInt32(d["sale_price"]),
actualArea = Convert.ToInt32(d["area"])
};
if (++i >= count)
break;
}
remoteClient.SendDirLandReply(queryID, data);
}
public void DirFindQuery(IClientAPI remoteClient, UUID queryID,
string queryText, uint queryFlags, int queryStart)
{
if (((DirFindFlags)queryFlags & DirFindFlags.DateEvents) == DirFindFlags.DateEvents)
{
DirEventsQuery(remoteClient, queryID, queryText, queryFlags,
queryStart);
return;
}
}
public void DirEventsQuery(IClientAPI remoteClient, UUID queryID,
string queryText, uint queryFlags, int queryStart)
{
Hashtable ReqHash = new()
{
["text"] = queryText,
["flags"] = queryFlags.ToString(),
["query_start"] = queryStart.ToString()
};
Hashtable result = GenericXMLRPCRequest(ReqHash, "dir_events_query");
if (!Convert.ToBoolean(result["success"]))
{
remoteClient.SendAgentAlertMessage(result["errorMessage"].ToString(), false);
return;
}
ArrayList dataArray = (ArrayList)result["data"];
int count = (dataArray.Count > 100) ? 101 : dataArray.Count;
DirEventsReplyData[] data = new DirEventsReplyData[count];
int i = 0;
foreach (Object o in dataArray)
{
Hashtable d = (Hashtable)o;
data[i] = new DirEventsReplyData
{
ownerID = new UUID(d["owner_id"].ToString()),
name = d["name"].ToString(),
eventID = Convert.ToUInt32(d["event_id"]),
date = d["date"].ToString(),
unixTime = Convert.ToUInt32(d["unix_time"]),
eventFlags = Convert.ToUInt32(d["event_flags"])
};
if (++i >= count)
break;
}
remoteClient.SendDirEventsReply(queryID, data);
}
public void DirClassifiedQuery(IClientAPI remoteClient, UUID queryID,
string queryText, uint queryFlags, uint category,
int queryStart)
{
Hashtable ReqHash = new()
{
["text"] = queryText,
["flags"] = queryFlags.ToString(),
["category"] = category.ToString(),
["query_start"] = queryStart.ToString()
};
Hashtable result = GenericXMLRPCRequest(ReqHash, "dir_classified_query");
if (!Convert.ToBoolean(result["success"]))
{
remoteClient.SendAgentAlertMessage(result["errorMessage"].ToString(), false);
return;
}
ArrayList dataArray = (ArrayList)result["data"];
int count = (dataArray.Count > 100) ? 101 : dataArray.Count;
DirClassifiedReplyData[] data = new DirClassifiedReplyData[count];
int i = 0;
foreach (Object o in dataArray)
{
Hashtable d = (Hashtable)o;
data[i] = new DirClassifiedReplyData
{
classifiedID = new UUID(d["classifiedid"].ToString()),
name = d["name"].ToString(),
classifiedFlags = Convert.ToByte(d["classifiedflags"]),
creationDate = Convert.ToUInt32(d["creation_date"]),
expirationDate = Convert.ToUInt32(d["expiration_date"]),
price = Convert.ToInt32(d["priceforlisting"])
};
if (++i >= count)
break;
}
remoteClient.SendDirClassifiedReply(queryID, data);
}
public void EventInfoRequest(IClientAPI remoteClient, uint queryEventID)
{
Hashtable ReqHash = new()
{
["eventID"] = queryEventID.ToString()
};
Hashtable result = GenericXMLRPCRequest(ReqHash, "event_info_query");
if (!Convert.ToBoolean(result["success"]))
{
remoteClient.SendAgentAlertMessage(result["errorMessage"].ToString(), false);
return;
}
ArrayList dataArray = (ArrayList)result["data"];
if (dataArray.Count == 0)
{
// something bad happened here, if we could return an
// event after the search,
// we should be able to find it here
// TODO do some (more) sensible error-handling here
remoteClient.SendAgentAlertMessage("Couldn't find this event.",
false);
return;
}
Hashtable d = (Hashtable)dataArray[0];
EventData data = new()
{
eventID = Convert.ToUInt32(d["event_id"]),
creator = d["creator"].ToString(),
name = d["name"].ToString(),
category = d["category"].ToString(),
description = d["description"].ToString(),
date = d["date"].ToString(),
dateUTC = Convert.ToUInt32(d["dateUTC"]),
duration = Convert.ToUInt32(d["duration"]),
cover = Convert.ToUInt32(d["covercharge"]),
amount = Convert.ToUInt32(d["coveramount"]),
simName = d["simname"].ToString()
};
data.globalPos = (Vector3.TryParse(d["globalposition"].ToString(), out data.globalPos)) ? data.globalPos : new();
data.eventFlags = Convert.ToUInt32(d["eventflags"]);
remoteClient.SendEventInfoReply(data);
}
public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient)
{
Hashtable ReqHash = new()
{
["classifiedID"] = queryClassifiedID.ToString()
};
Hashtable result = GenericXMLRPCRequest(ReqHash, "classifieds_info_query");
if (!Convert.ToBoolean(result["success"]))
{
remoteClient.SendAgentAlertMessage(result["errorMessage"].ToString(), false);
return;
}
//The viewer seems to issue an info request even when it is
//creating a new classified which means the data hasn't been
//saved to the database yet so there is no info to find.
ArrayList dataArray = (ArrayList)result["data"];
if (dataArray.Count == 0)
{
// Something bad happened here if we could not return an
// event after the search. We should be able to find it here.
// TODO do some (more) sensible error-handling here
// remoteClient.SendAgentAlertMessage("Couldn't find data for classified ad.",
// false);
return;
}
Hashtable d = (Hashtable)dataArray[0];
Vector3 globalPos = (Vector3.TryParse(d["posglobal"].ToString(), out globalPos)) ? globalPos : new();
remoteClient.SendClassifiedInfoReply(
new UUID(d["classifieduuid"].ToString()),
new UUID(d["creatoruuid"].ToString()),
Convert.ToUInt32(d["creationdate"]),
Convert.ToUInt32(d["expirationdate"]),
Convert.ToUInt32(d["category"]),
d["name"].ToString(),
d["description"].ToString(),
new UUID(d["parceluuid"].ToString()),
Convert.ToUInt32(d["parentestate"]),
new UUID(d["snapshotuuid"].ToString()),
d["simname"].ToString(),
globalPos,
d["parcelname"].ToString(),
Convert.ToByte(d["classifiedflags"]),
Convert.ToInt32(d["priceforlisting"]));
}
public void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
uint EstateID, bool godlike,
uint itemtype, ulong regionhandle)
{
//The following constant appears to be from GridLayerType enum
//defined in OpenMetaverse/GridManager.cs of libopenmetaverse.
if (itemtype == (uint)OpenMetaverse.GridItemType.LandForSale)
{
Hashtable ReqHash = new()
{
//The flags are: SortAsc (1 << 15), PerMeterSort (1 << 17)
["flags"] = "163840",
["type"] = "4294967295", //This is -1 in 32 bits
["price"] = "0",
["area"] = "0",
["query_start"] = "0"
};
Hashtable result = GenericXMLRPCRequest(ReqHash, "dir_land_query");
if (!Convert.ToBoolean(result["success"]))
{
remoteClient.SendAgentAlertMessage(result["errorMessage"].ToString(), false);
return;
}
ArrayList dataArray = (ArrayList)result["data"];
List<mapItemReply> mapitems = new();
string ParcelRegionUUID;
string[] landingpoint;
foreach (Object o in dataArray)
{
Hashtable d = (Hashtable)o;
if (d["name"] is null)
continue;
mapItemReply mapitem = new();
ParcelRegionUUID = d["region_UUID"].ToString();
foreach (Scene scene in m_Scenes)
{
if (scene.RegionInfo.RegionID.ToString() == ParcelRegionUUID)
{
landingpoint = d["landing_point"].ToString().Split('/');
mapitem.x = (uint)((scene.RegionInfo.RegionLocX * 256) +
Convert.ToDecimal(landingpoint[0]));
mapitem.y = (uint)((scene.RegionInfo.RegionLocY * 256) +
Convert.ToDecimal(landingpoint[1]));
break;
}
}
mapitem.id = new UUID(d["parcel_id"].ToString());
mapitem.Extra = Convert.ToInt32(d["area"]);
mapitem.Extra2 = Convert.ToInt32(d["sale_price"]);
mapitem.name = d["name"].ToString();
mapitems.Add(mapitem);
}
remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
mapitems.Clear();
}
if (itemtype == (uint)OpenMetaverse.GridItemType.PgEvent ||
itemtype == (uint)OpenMetaverse.GridItemType.MatureEvent ||
itemtype == (uint)OpenMetaverse.GridItemType.AdultEvent)
{
//Find the maturity level
int maturity = (1 << 24);
//Find the maturity level
if (itemtype == (uint)OpenMetaverse.GridItemType.MatureEvent)
maturity = (1 << 25);
else
{
if (itemtype == (uint)OpenMetaverse.GridItemType.AdultEvent)
maturity = (1 << 26);
}
//The flags are: SortAsc (1 << 15), PerMeterSort (1 << 17)
maturity |= 163840;
//When character before | is a u get upcoming/in-progress events
//Character before | is number of days before/after current date
//Characters after | is the number for a category
Hashtable ReqHash = new()
{
["text"] = "u|0",
["flags"] = maturity.ToString(),
["query_start"] = "0"
};
Hashtable result = GenericXMLRPCRequest(ReqHash, "dir_events_query");
if (!Convert.ToBoolean(result["success"]))
{
remoteClient.SendAgentAlertMessage(result["errorMessage"].ToString(), false);
return;
}
ArrayList dataArray = (ArrayList)result["data"];
List<mapItemReply> mapitems = new();
int event_id;
string[] landingpoint;
foreach (Object o in dataArray)
{
Hashtable d = (Hashtable)o;
if (d["name"] is null)
continue;
mapItemReply mapitem = new();
//Events use a comma separator in the landing point
landingpoint = d["landing_point"].ToString().Split(',');
mapitem.x = Convert.ToUInt32(landingpoint[0]);
mapitem.y = Convert.ToUInt32(landingpoint[1]);
//This is a crazy way to pass the event ID back to the
//viewer but that is the way it wants the information.
event_id = Convert.ToInt32(d["event_id"]);
mapitem.id = new UUID("00000000-0000-0000-0000-0000" +
event_id.ToString("X8"));
mapitem.Extra = Convert.ToInt32(d["unix_time"]);
mapitem.Extra2 = 0; //FIXME: No idea what to do here
mapitem.name = d["name"].ToString();
mapitems.Add(mapitem);
}
remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
mapitems.Clear();
}
}
public void Refresh()
{
}
}
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" ?>
<Project name="OpenSimSearch.Modules" path="addon-modules/OpenSimSearch/Modules" type="Library" version="0.5.0-$Rev$" frameworkVersion="net8_0">
<Configuration name="Debug">
<Options>
<OutputPath>../../../bin/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../bin/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../bin/</ReferencePath>
<Reference name="OpenMetaverseTypes"/>
<Reference name="OpenMetaverse"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Services.Interfaces"/>
<Reference name="Nini"/>
<Reference name="log4net"/>
<Reference name="XMLRPC"/>
<Reference name="Mono.Addins"/>
<Files>
<Match pattern="*.cs" recurse="true">
<Exclude name="obj" pattern="obj"/>
</Match>
</Files>
</Project>

View File

@@ -1,4 +1,5 @@
<configuration>
<dllmap os="windows" cpu="x86-64" dll="sqlite3" target="lib64/sqlite3.dll" />
<dllmap os="!windows,osx" cpu="x86-64" dll="sqlite3" target="lib64/libsqlite3_64.so" />
<dllmap os="!windows,osx" cpu="arm64" dll="sqlite3" target="lib64/libsqlite3-arm64.so" />
</configuration>

View File

@@ -103,7 +103,7 @@
;# {ConsoleHistoryTimeStamp} {} {Time stamp commands in history file} {} false
;; Time stamp commands in history file (default false)
; ConsoleHistoryTimeStamp = false
;# {save_crashes} {} {Save crashes to disk?} {true false} false
;; Set this to true if you want to log crashes to disk
;; this can be useful when submitting bug reports.
@@ -268,7 +268,7 @@
;# {DefaultScriptEngine} {} {Default script engine} {YEngine}
;; Default script engine to use. Currently, we only have YEngine
; DefaultScriptEngine = "YEngine"
;# {HttpProxy} {} {Proxy URL for llHTTPRequest and dynamic texture loading} {} http://proxy.com:8080
;; Http proxy setting for llHTTPRequest and dynamic texture loading, if
;; required
@@ -283,8 +283,11 @@
; HttpProxyExceptions = ".mydomain.com;localhost"
;# {emailmodule} {} {Provide llEmail and llGetNextEmail functionality? (requires SMTP server)} {DefaultEmailModule} none
;; The email module requires some configuration. It needs an SMTP
;; server to send mail through.
;; By default email only works within the boundaries of a sim
;; For intersim mail, all sims involved need to use the same IMAP mailbox
;; and enableEmailToExternalObjects = true in [Email]
;; If you want to also allow mail to enter and leave the grid, SMTP will
;; also need to be setup
; emailmodule = DefaultEmailModule
;# {SpawnPointRouting} {} {Set routing method for Telehub Spawnpoints} {closest random sequence} closest
@@ -392,6 +395,16 @@
;;
; DeniedClients = ""
; It is strongly recommended to block at least these viewers by uncommenting ;DeniedClients below:
; The first 4 viewers are problematic/bugged official Firestorm releases,
; the last 7 viewers are copybots pretending to be (a very outdated) Firestorm and Singularity
; The + is needed for older OpenSim versions (<0.9.3.1), after the space before the version (it means 'one or more spaces')
; DeniedClients = "Firestorm-Release(x64)? +4.7.7.48706|Firestorm-Release(x64)? +6.6.8.68380|Firestorm-Release(x64)? +6.6.16.70339|Firestorm-Releasex64 +7.1.9.74745|Firestorm-Release(x64)? +6.2.0|Firestorm-Release(x64)? +4.6.8.42696|Firestorm-Release(x64)? +6.3.2.58086|Firestorm-Release(x64)? +6.3.8.58105|Firestorm-Release(x64)? +6.4.13.63251|Firestorm-Release(x64)? +6.4.23.64823|Singularity Alpha( 64)? +1.8.7.7610"
;# {ViewerDeniedMsg} {} {A message string} {"Access denied, your viewer is banned"}
; The message people see who attempt to teleport with a denied viewer
;ViewerDeniedMsg = "Access denied, your viewer is banned"
[Map]
;# {GenerateMaptiles} {} {Generate map tiles?} {true false} true
@@ -471,27 +484,20 @@
;; If set to true, then all permissions checks are carried out
; serverside_object_permissions = true
; if next 2 are false, several admin powers are only active if god powers requested on viewer
; this reduces mistakes
; set both to true to enable previous behaviour
; if next 2 are false, several admin powers are only active if god powers requested on viewer
; this reduces mistakes
; set both to true to enable previous behaviour
automatic_gods = false
implicit_gods = false
;# {allow_grid_gods} {} {Allow grid gods?} {true false} false
;# {allow_grid_gods} {} {Allow grid gods?} {true false} false
;; This allows users with a UserLevel of 200 or more to assume god
;; powers in the regions in this simulator.
;; if you don't trust grid admins, what are you doing there?
;; if you don't trust grid admins, what are you doing there?
allow_grid_gods = true
;; This allows some control over permissions
;; please note that this still doesn't duplicate SL, and is not intended to
;# {region_owner_is_god} {} {Allow region owner gods} {true false} true
;; Allow region owners to assume god powers in their regions
; region_owner_is_god = true
;# {region_manager_is_god} {} {Allow region manager gods} {true false} false
;; Allow region managers to assume god powers in regions they manage
; region_manager_is_god = false
;# {simple_build_permissions} {} {Allow building in parcel by access list (no groups)} {true false} false
;; More control over permissions
@@ -503,6 +509,9 @@
;; without having to use the Groups feature
; simple_build_permissions = false
;# {take_copy_restricted} {} {Disallow "take copy"} {true false} false
;; Disallow "take copy" of ANY object set as "Allow anyone to take a copy"
;take_copy_restricted = false
[Estates]
; If these values are commented out then the user will be asked for estate details when required (this is the normal case).
@@ -535,18 +544,10 @@
;; Password for the default estate owner
; DefaultEstateOwnerPassword = password
[SMTP]
;; The SMTP server enabled the email module to send email to external
;; destinations.
;# {enabled} {[Startup]emailmodule:DefaultEmailModule} {Enable module?} {true false} false
[Email]
;# {enabled} {[Startup]emailmodule:DefaultEmailModule} {Enable module?} {true false} true
;; Enable the email module
; enabled = false
;# {enabled} {[Startup]emailmodule:DefaultEmailModule} {Enable send to objects to regions not on instance?} {true false} true
;; Enable sending email to regions not on current opensimulator instance. Currently does not work
; enableEmailToExternalObjects = true
; enabled = true
;# {enabled} {[Startup]emailmodule:DefaultEmailModule} {maximum number of emails from a object owner per hour} {} 500
; MailsFromOwnerPerHour = 500
@@ -561,11 +562,11 @@
;# {enabled} {[Startup]emailmodule:DefaultEmailModule} {maximum number of emails to a SMTP address per hour} {} 10
; MailsToSMTPAddressPerHour = 10
;# {enabled} {[Startup]emailmodule:DefaultEmailModule} {Enable send to the world?} {true false} true
;; Enable sending email to the world.
; enableEmailToSMTP = true
;# {internal_object_host} {[Startup]emailmodule:DefaultEmailModule enabled:true} {Host name to treat as internal (object to object) email?} {} lsl.opensim.local
; Messages with this domain are considered grid-local
; Internal messages don't use SMTP.
; - If the destination exists on THIS sim, delivers directly
; - If the destination exists on ANOTHER sim, delivers through IMAP
; internal_object_host = lsl.opensim.local
;# {host_domain_header_from} {[Startup]emailmodule:DefaultEmailModule enabled:true} {From address to use in the sent email header?} {} 127.0.0.1
@@ -573,6 +574,14 @@
; if not set SMTP_SERVER_FROM below
; host_domain_header_from = "127.0.0.1"
; SMTP configuration: (off-grid mail)
;; The SMTP server enabled the email module to send email to external
;; destinations.
;# {enabled} {[Startup]emailmodule:DefaultEmailModule} {Enable send to the world?} {true false} false
;; Enable sending email to the world.
; enableEmailToSMTP = false
;# {SMTP_SERVER_FROM} {[Startup]emailmodule:DefaultEmailModule enabled:true} {SMTP server from name?} {}
; some smtp servers require a known From email address or will give Error 500 - Envelope from address is not authorised
; set to a valid email address that smtp will accept (in some cases must be like SMTP_SERVER_LOGIN)
@@ -605,6 +614,38 @@
;# {SMTP_VerifyCertNames} {[Startup]emailmodule:DefaultEmailModule enabled:true} {SMTP Verify cert chain option} {} true
; SMTP_VerifyCertNames = true
; Imap configuration: (grid-local mail)
;# {enabled} {[Startup]emailmodule:DefaultEmailModule} {Enable send to objects to regions not on instance?} {true false} false
;; Enable sending email to regions not on current opensimulator instance.
;; Requires a dedicated IMAP account, locally or remote
; enableEmailToExternalObjects = false
;# {IMAP_SERVER_TLS} {[Startup]emailmodule:DefaultEmailModule enabled:true} {IMAP use TLS?} {} false
; IMAP_SERVER_TLS = false
;# {IMAP_SERVER_HOSTNAME} {[Startup]emailmodule:DefaultEmailModule enabled:true} {IMAP server name?} {} 127.0.0.1
; IMAP_SERVER_HOSTNAME = 127.0.0.1
;# {IMAP_SERVER_PORT} {[Startup]emailmodule:DefaultEmailModule enabled:true} {IMAP server port?} {} 143
; If using IMAP with TLS, it is port 993
; IMAP_SERVER_PORT = 143
;# {IMAP_SERVER_LOGIN} {[Startup]emailmodule:DefaultEmailModule enabled:true} {IMAP server user name?} {}
; The user needs to have a Maildir folder in its homedirectory, with perms 700
; This can be made with: maildirmake.courier ~/Maildir
; IMAP_SERVER_LOGIN = foo
;# {IMAP_SERVER_PASSWORD} {[Startup]emailmodule:DefaultEmailModule enabled:true} {IMAP server password} {}
; IMAP_SERVER_PASSWORD = bar
; using TLS and an IMAP server with a self signed certificate you will need to set next two options false
;# {IMAP_VerifyCertChain} {[Startup]emailmodule:DefaultEmailModule enabled:true} {IMAP Verify cert chain option} {} true
; IMAP_VerifyCertChain = true
;# {IMAP_VerifyCertNames} {[Startup]emailmodule:DefaultEmailModule enabled:true} {IMAP Verify cert chain option} {} true
; IMAP_VerifyCertNames = true
[Network]
;# {ConsoleUser} {} {User name for console account} {}
;; Configure the remote console user here. This will not actually be used
@@ -628,15 +669,15 @@
; to use others like self signed certificates with those viewers,
; their debug option NoVerifySSLCert needs to be set true, You need to inform users about this
; the main unsecure port will still open for some services. this may change in future.
; set http_listener_ssl to enable main server ssl. it will replace unsecure port on most functions
;# {http_listener_ssl}{} {enable main server ssl port} {} false
;http_listener_ssl = false
; Set port for main SSL connections
;# {http_listener_sslport}{} {main server ssl port} {} 9001
;http_listener_sslport = 9001 ;
; currently if using ssl, regions ExternalHostName must the the same and equal to http_listener_cn
; this may be removed in future
;# {http_listener_cn}{} {main server ssl externalHostName} {} ""
@@ -690,8 +731,8 @@
;# {ExternalHostNameForLSL} {} {Hostname to use for HTTP-IN URLs. This should be reachable from the internet.} {}
;; Hostname to use in llRequestURL/llRequestSecureURL
;; if not defined - llRequestURL/llRequestSecureURL are disabled
;; this should be reachable from internet and point this machine
;; for standalones it can be
;; this should be reachable from internet and point this machine
;; for standalones it can be
ExternalHostNameForLSL = ${Const|BaseHostname}
;# {shard} {} {Name to use for X-Secondlife-Shard header? (press enter if unsure)} {} OpenSim
@@ -1144,7 +1185,7 @@
[InterestManagement]
;; This section controls how state updates are prioritized for each client
;# {UpdatePrioritizationScheme} {} {Update prioritization scheme?} {BestAvatarResponsiveness SimpleAngularDistance} BestAvatarResponsiveness
;; Valid values are BestAvatarResponsiveness and SimpleAngularDistance
;; SimpleAngularDistance does use more cpu

View File

@@ -24,7 +24,7 @@
; Time stamp commands in history file (default false)
; ConsoleHistoryTimeStamp = false
; Set this to true if you want to log crashes to disk
; this can be useful when submitting bug reports.
; However, this will only log crashes within OpenSimulator that cause the entire program to exit
@@ -112,12 +112,12 @@
;; Allow child agents to see into the region even if their root counterpart isn't allowed in here
see_into_region = true
;; use legacy math for sittarget offset "correction"
;; set this option to false to use improved math more compatibility with SL.
;; keep it true if you have many old objects with sits set by scripts.
;; the offset in question is added to the SitTarget to find the sitting avatar position.
;; acording to its size, etc.
; LegacySitOffsets = true
;; use legacy math for sittarget offset "correction"
;; set this option to false to use improved math more compatibility with SL.
;; keep it true if you have many old objects with sits set by scripts.
;; the offset in question is added to the SitTarget to find the sitting avatar position.
;; acording to its size, etc.
; LegacySitOffsets = true
; Maximum number of position, rotation and scale changes for each prim that the simulator will store for later undos
; Increasing this number will increase memory usage.
@@ -176,22 +176,22 @@
InworldRestartShutsDown = false
; Use of normalized 55FPS statistics
; Opensim does not have a frame rate control like other simulators.
; Most parameters that control timing can be configurable region by region.
; To achieve closer compatibility with values expected by viewers, scripts and users
; some parameters are converted to a equivalent per frame value.
; Additionally, they are scaled to values they would have on a system running at a nominal 55 frames per second rate.
; The scale factor it 55 * FrameTime, corresponding to 5 with default configuration
; You can choose to show the true physics FPS to viewers by setting Normalized55FPS to false.
; Normalized55FPS = true
; Opensim does not have a frame rate control like other simulators.
; Most parameters that control timing can be configurable region by region.
; To achieve closer compatibility with values expected by viewers, scripts and users
; some parameters are converted to a equivalent per frame value.
; Additionally, they are scaled to values they would have on a system running at a nominal 55 frames per second rate.
; The scale factor it 55 * FrameTime, corresponding to 5 with default configuration
; You can choose to show the true physics FPS to viewers by setting Normalized55FPS to false.
; Normalized55FPS = true
; Main Frame time
; This defines the rate of several simulation events.
; Default value should meet most needs.
; It can be reduced to improve the simulation of moving objects, with possible increase of cpu and network loads.
; It should not be less than the physics engine step time.
; Being a integer multiple of it may reduce some jitter in reported physics FPS.
; changing this value, you need to change some of the following *EveryNFrames so their actions timing remains the same
; This defines the rate of several simulation events.
; Default value should meet most needs.
; It can be reduced to improve the simulation of moving objects, with possible increase of cpu and network loads.
; It should not be less than the physics engine step time.
; Being a integer multiple of it may reduce some jitter in reported physics FPS.
; changing this value, you need to change some of the following *EveryNFrames so their actions timing remains the same
FrameTime = 0.0909
; The values below represent the percentage of the target frame time that,
@@ -314,9 +314,12 @@
; ##
; ## EMAIL MODULE
; ##
;; The email module requires some configuration. It needs an SMTP
;; server to send mail through.
;emailmodule = DefaultEmailModule
;; By default email only works within the boundaries of a sim
;; For intersim mail, all sims involved need to use the same IMAP mailbox
;; and enableEmailToExternalObjects = true in [Email]
;; If you want to also allow mail to enter and leave the grid, SMTP will
;; also need to be setup
emailmodule = DefaultEmailModule
; ##
; ## ANIMATIONS
@@ -443,7 +446,7 @@
; #
; # SSL certificates validation options
; #
; SSL certificate validation options
; you can allow selfsigned certificates or no official CA with next option set to true
; NoVerifyCertChain = true
@@ -491,18 +494,21 @@
; Attempt to render meshes and sculpties on the map
RenderMeshes = false
; warp3D rendering height limits for prims (relative to rez position not bounding box)
; prims above RenderMaxHeight are excluded
; valid values: 100 to 4086
;RenderMaxHeight = 4086
; prims below RenderMinHeight are excluded
; valid values: -100 to RenderMaxHeight - 10
;RenderMinHeight = -100
; warp3D rendering height limits for prims (relative to rez position not bounding box)
; prims above RenderMaxHeight are excluded
; valid values: 100 to 4086
;RenderMaxHeight = 4086
; prims below RenderMinHeight are excluded
; valid values: -100 to RenderMaxHeight - 10
;RenderMinHeight = -100
; Show NPCs as green world map dots
;ShowNPCs = true
; Where to store generated map tiles in the form of MAP-RegionUUID.png
;GenTilesDirectory = "."
[Permissions]
; ##
@@ -525,15 +531,9 @@
; This allows grid users with a UserLevel of 200 or more to assume god
; powers in the regions in this simulator.
; if you don't trust grid admins, what are you doing there?
; if you don't trust grid admins, what are you doing there?
allow_grid_gods = true
; Allow region owners to assume god powers in their regions
;region_owner_is_god = true
; Allow region managers to assume god powers in regions they manage
;region_manager_is_god = false
; God mode should be turned on in the viewer whenever
; the user has god rights somewhere. They may choose
; to turn it off again, though.
@@ -572,6 +572,8 @@
; Minimum user level required to upload assets
;LevelUpload = 0
; Disallow "take copy" of ANY object set as "Allow anyone to take a copy"
;take_copy_restricted = false
[RegionReady]
; Enable this module to get notified once all items and scripts in the region have been completely loaded and compiled
@@ -621,11 +623,13 @@
; AllowUserProfileWebURLs = true
[SMTP]
enabled = false
[Email]
enabled = true
;enabled = true
;internal_object_host = lsl.opensim.local
;enableEmailToSMTP = false
;host_domain_header_from = 127.0.0.1
;SMTP_SERVER_FROM = ""
;SMTP_SERVER_HOSTNAME = 127.0.0.1
@@ -636,6 +640,16 @@
;SMTP_VerifyCertChain = true
;SMTP_VerifyCertNames = true
;enableEmailToExternalObjects = false
;IMAP_SERVER_HOSTNAME = 127.0.0.1
;IMAP_SERVER_PORT = 143
;IMAP_SERVER_TLS = false
;IMAP_SERVER_LOGIN = foo
;IMAP_SERVER_PASSWORD = bar
;IMAP_VerifyCertChain = true
;IMAP_VerifyCertNames = true
[Network]
ConsoleUser = "Test"
ConsolePass = "secret"
@@ -645,12 +659,12 @@
; ssl config: Experimental!
http_listener_ssl = false ; if set to true main server is replaced by a ssl one
http_listener_sslport = 9001 ; Use this port for SSL connections
; currently if using ssl, regions ExternalHostName must the the same and equal to http_listener_cn
; this will change is future
; currently if using ssl, regions ExternalHostName must the the same and equal to http_listener_cn
; this will change is future
http_listener_cn = "myRegionsExternalHostName"
; if the cert doesnt have a oficial CA or is selfsigned viewers option NoVerifySSLCert need to be set true
; if the cert doesnt have a oficial CA or is selfsigned viewers option NoVerifySSLCert need to be set true
http_listener_cert_path = "mycert.p12" ; path for the cert file that is valid for the ExternalHostName
http_listener_cert_pass = "mycertpass" ; the cert passwork
http_listener_cert_pass = "mycertpass" ; the cert passwork
; addicional HTTPS for "Out of band" management applications such as the remote
; admin module or scripts
@@ -673,8 +687,8 @@
; HttpBodyMaxLenMAX=16384
; Hostname to use in llRequestURL/llRequestSecureURL
; must be a valid hostname for the ssl cert.
; if not defined - llRequestURL/llRequestSecureURL are disabled
; must be a valid hostname for the ssl cert.
; if not defined - llRequestURL/llRequestSecureURL are disabled
; ExternalHostNameForLSL=127.0.0.1
; Disallow the following address ranges for user scripting calls (e.g. llHttpRequest())
@@ -714,32 +728,54 @@
;MaxRequestConcurrency = 30
[ScriptsHttpRequestModule]
; options for llHttpRequest
; max number of concurrent connections per instance (all scenes), default 8
; MaxPoolThreads = 8
; options for llHttpRequest
; max number of concurrent connections per instance (all scenes), default 8
; MaxPoolThreads = 8
; max requests per second for all scripts on a prim, default 1
;PrimRequestsPerSec = 1.0
; initial unthrottled burst for all scripts on a prim, default 3
; initial unthrottled burst for all scripts on a prim, default 3
;PrimRequestsBurst = 3.0
; max requests per second for the objects owner (per instance), default 25
;PrimOwnerRequestsPerSec = 25.0
; initial unthrottled burst for the objects owner (per instance), default 5
; initial unthrottled burst for the objects owner (per instance), default 5
;PrimOwnerRequestsBurst = 5.0
; requests timeout in miliseconds, range 200 to 60000, default 30000
; requests timeout in miliseconds, range 200 to 60000, default 30000
;RequestsTimeOut = 30000
[AccessControl]
; Viewer-based access control. |-separated list of allowed viewers.
;# {AllowedClients} {} {Bar (|) separated list of allowed clients} {}
;; Bar (|) separated list of viewers which may gain access to the regions.
;; One can use a substring of the viewer name to enable only certain
;; versions
;; Example: Agent uses the viewer "Imprudence 1.3.2.0"
;; - "Imprudence" has access
;; - "Imprudence 1.3" has access
;; - "Imprudence 1.3.1" has no access
; AllowedClients = ""
; Viewer-based access control. |-separated list of denied viewers.
; No restrictions by default.
;# {DeniedClients} {} {Bar (|) separated list of denied clients} {}
;; Bar (|) separated list of viewers which may not gain access to the regions.
;; One can use a Substring of the viewer name to disable only certain
;; versions
;; Example: Agent uses the viewer "Imprudence 1.3.2.0"
;; - "Imprudence" has no access
;; - "Imprudence 1.3" has no access
;; - "Imprudence 1.3.1" has access
; DeniedClients = ""
; It is strongly recommended to block at least these viewers by uncommenting ;DeniedClients below:
; The first 4 viewers are problematic/bugged official Firestorm releases,
; the last 7 viewers are copybots pretending to be (a very outdated) Firestorm and Singularity
; The + is needed for older OpenSim versions (<0.9.3.1), after the space before the version (it means 'one or more spaces')
; DeniedClients = "Firestorm-Release(x64)? +4.7.7.48706|Firestorm-Release(x64)? +6.6.8.68380|Firestorm-Release(x64)? +6.6.16.70339|Firestorm-Releasex64 +7.1.9.74745|Firestorm-Release(x64)? +6.2.0|Firestorm-Release(x64)? +4.6.8.42696|Firestorm-Release(x64)? +6.3.2.58086|Firestorm-Release(x64)? +6.3.8.58105|Firestorm-Release(x64)? +6.4.13.63251|Firestorm-Release(x64)? +6.4.23.64823|Singularity Alpha( 64)? +1.8.7.7610"
;# {ViewerDeniedMsg} {} {A message string} {"Access denied, your viewer is banned"}
; The message people see who attempt to teleport with a denied viewer
;ViewerDeniedMsg = "Access denied, your viewer is banned"
[ClientStack.LindenUDP]
; Maximum outbound bytes per second for a single scene. This can be used to
@@ -799,11 +835,11 @@
;
;PausedAckTimeout = 300
; Support viewers object cache, default true
; users may need to reduce viewer bandwitdh if some prims or terrain parts fail to rez.
; change to false if you need to use old viewers that do not support this feature
;
; SupportViewerObjectsCache = true
; Support viewers object cache, default true
; users may need to reduce viewer bandwitdh if some prims or terrain parts fail to rez.
; change to false if you need to use old viewers that do not support this feature
;
; SupportViewerObjectsCache = true
[ClientStack.LindenCaps]
;; Long list of capabilities taken from
@@ -904,9 +940,9 @@
; Allow avatars to cross into and out of the region.
AllowAvatarCrossing = true
; This disables border transfers for objects. When true, objects can be placed outside
; the region's border without being transferred to another simulator.
DisableObjectTransfer = false
; This disables border transfers for objects. When true, objects can be placed outside
; the region's border without being transferred to another simulator.
DisableObjectTransfer = false
; Minimum user level required for HyperGrid teleports
LevelHGTeleport = 0
@@ -916,10 +952,10 @@
; Disabling cancellation can be okay in small closed grids where all teleports are highly likely to suceed.
DisableInterRegionTeleportCancellation = false
;; This option exists to control the behavior of teleporting gods into places that have landing points
;; and telehubs. Historically, there has been a difference: OpenSim (OS) has honored landing points and telehubs even for
;; avatars with god permissions; SL lets gods land wherever they want.
LandingPointBehavior = LandingPointBehavior_OS
;; This option exists to control the behavior of teleporting gods into places that have landing points
;; and telehubs. Historically, there has been a difference: OpenSim (OS) has honored landing points and telehubs even for
;; avatars with god permissions; SL lets gods land wherever they want.
LandingPointBehavior = LandingPointBehavior_OS
[Messaging]
@@ -1063,14 +1099,14 @@
avatar_terminal_velocity = 54
; World Step size.
; with legacy ODE this value needs to be close to 0.02s
; with ubOde this value can be reduced to improve simulation quality with the cost of higher cpu load
; you will need to test acording to you needs
; choosing a value that is a integer sub multiple of FrameRate reduces some jitter on reported physics FPS
; with legacy ODE this value needs to be close to 0.02s
; with ubOde this value can be reduced to improve simulation quality with the cost of higher cpu load
; you will need to test acording to you needs
; choosing a value that is a integer sub multiple of FrameRate reduces some jitter on reported physics FPS
world_stepsize = 0.01818
; number of iterations of constrains solver, higher should improve results
; up to a point where acumulated math errors eliminate the improvement
; more steps may increase CPU load. No real gain in changing
; number of iterations of constrains solver, higher should improve results
; up to a point where acumulated math errors eliminate the improvement
; more steps may increase CPU load. No real gain in changing
world_solver_iterations = 10
@@ -1707,13 +1743,13 @@
;PriceObjectRent = 0
;PriceObjectScaleFactor = 10
;PriceParcelRent = 0
; Mesh upload settings, independent of economymodule
; Create inventory entries for textures uploaded with a model
; default is false, ie, do not create
; MeshModelAllowTextureToInventory = true
; Mesh upload settings, independent of economymodule
; Create inventory entries for textures uploaded with a model
; default is false, ie, do not create
; MeshModelAllowTextureToInventory = true
[YEngine]
;; implements non preemptive microthreading, so fixing problems like llSleep or long events handlers
@@ -1721,10 +1757,10 @@
;; warning: scripts state is lost on TP or cross to Xengine regions (cars stop, etc)
;; ignore its extensions (subset of original XMRengine), those are still undefined.
Enabled = true
; maximum stack a script can use in KB
;ScriptStackSize = 2048
; maximum heap memory a script can use in KB
;ScriptHeapSize = 1024
@@ -1776,6 +1812,14 @@
; scripts states and cache parent folder location
;ScriptEnginesPath="ScriptEngines"
; Used in inventory offer messages to show the giving object origin
; To make /decline work for RLVa inventory offers, this has to
; start with "http://slurl", however a webpage does not need to
; exist at given location. Your grid may choose to host a slurl.com-like
; webmap if desired, for example at http://slurl.yourgrid.com
; The dialog will display it inworld as: SlurlPrefix/regionname/x/y/z/
; In SL the prefix is: http://slurl.com/secondlife
;SlurlPrefix="http://slurl.opensim.local"
[Concierge]
; Enable concierge module
@@ -2037,18 +2081,18 @@
LimitParcelLayerUpdateDistance = true
ParcelLayerViewDistance = 128
; set this to false to not display parcel ban lines
ShowParcelBansLines = true
; Parcel Bans max height above ground. Default 100m
; range 20m to 5000m
; BanLineSafeHeight = 100
; set this to false to not display parcel ban lines
ShowParcelBansLines = true
; Parcel Bans max height above ground. Default 100m
; range 20m to 5000m
; BanLineSafeHeight = 100
; setting the parcel to admin content, It works as setting the land to Linden content in SL.
; To use it, activate god mode in the viewer, select the parcel and go to: Admin -> Parcel -> Set to Linden Content ( CTRL+ALT+SHIFT+C)
; DefaultAdministratorParcelName = "Admin Parcel"
; DefaultAdministratorGroupUUID = "00000000-0000-0000-0000-000000000000"
; DefaultAdministratorOwnerUUID = "00000000-0000-0000-0000-000000000000"
; setting the parcel to admin content, It works as setting the land to Linden content in SL.
; To use it, activate god mode in the viewer, select the parcel and go to: Admin -> Parcel -> Set to Linden Content ( CTRL+ALT+SHIFT+C)
; DefaultAdministratorParcelName = "Admin Parcel"
; DefaultAdministratorGroupUUID = "00000000-0000-0000-0000-000000000000"
; DefaultAdministratorOwnerUUID = "00000000-0000-0000-0000-000000000000"
;;
@@ -2103,9 +2147,9 @@
DwellModule = DefaultDwellModule
[ServerReleaseNotes]
;; Comment or set to "" to disable
ServerReleaseNotesURL = "http://opensimulator.org/wiki/0.9.3.1_Release"
;; Comment or set to "" to disable
ServerReleaseNotesURL = "https://github.com/lickx/opensim-lickx/wiki"
[Modules]
Include-modules = "addon-modules/*/config/*.ini"

View File

@@ -490,6 +490,7 @@
[GridUserService]
; for the server connector
LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService"
;UseCache = true
[AgentPreferencesService]
@@ -500,6 +501,8 @@
[PresenceService]
; for the server connector
LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService"
;AllowDuplicatePresences = false
;UseCache = true
[AvatarService]
; for the server connector
@@ -637,6 +640,8 @@
[GridInfoService]
GridService = "OpenSim.Services.GridService.dll:GridService"
; These settings are used to return information on a get_grid_info call.
; Client launcher scripts and third-party clients make use of this to
; autoconfigure the client and to provide a nice user experience. If you
@@ -726,6 +731,9 @@
;; Allow banning via hashed MAC must be set in both [GatekeeperService] and [LoginService]
;DeniedMacs = "YOURLONGMACTRSING ANOTHERMAC"
;; What to show to a denied avatar wanting to visit:
;DeniedMessage = "Destination does not allow visitors from your world"
[UserAgentService]
LocalServiceModule = "OpenSim.Services.HypergridService.dll:UserAgentService"
;; for the service
@@ -838,6 +846,7 @@
UserAccountService = "OpenSim.Services.UserAccountService.dll:UserAccountService"
GridService = "OpenSim.Services.GridService.dll:GridService"
PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService"
GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService"
[HGInstantMessageService]

View File

@@ -431,6 +431,7 @@
[GridUserService]
; for the server connector
LocalServiceModule = "OpenSim.Services.UserAccountService.dll:GridUserService"
;UseCache = true
[AgentPreferencesService]
@@ -441,6 +442,8 @@
[PresenceService]
; for the server connector
LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService"
;AllowDuplicatePresences = false
;UseCache = true
[AvatarService]
; for the server connector
@@ -558,6 +561,8 @@
[GridInfoService]
GridService = "OpenSim.Services.GridService.dll:GridService"
; These settings are used to return information on a get_grid_info call.
; Client launcher scripts and third-party clients make use of this to
; autoconfigure the client and to provide a nice user experience. If you

View File

@@ -1858,6 +1858,14 @@
<key>value</key><string>0x2</string>
<key>tooltip</key><string>osTeleportObject flag: stop at jump point if tp fails</string>
</map>
<key>PAYMENT_INFO_ON_FILE</key><map>
<key>type</key><string>integer</string>
<key>value</key><string>1</string>
</map>
<key>PAYMENT_INFO_USED</key><map>
<key>type</key><string>integer</string>
<key>value</key><string>2</string>
</map>
<key>PARCEL_COUNT_GROUP</key><map>
<key>type</key><string>integer</string>
<key>value</key><string>2</string>
@@ -5108,6 +5116,13 @@
<map>
<key>return</key><string>float</string>
<key>arguments</key><undef/>
<key>tooltip</key><string>Returns parcel time in seconds since midnight.\n- Sleep: 0 seconds.</string>
</map>
<key>llGetRegionTimeOfDay</key>
<map>
<key>return</key><string>float</string>
<key>arguments</key><undef/>
<key>tooltip</key><string>Returns region time in seconds since midnight.\n- Sleep: 0 seconds.</string>
</map>
<key>llGetTimestamp</key>
<map>
@@ -9548,5 +9563,12 @@
<key>arguments</key><undef/>
<key>tooltip</key><string>Returns the name of the currently enabled wind plugin.</string>
</map>
<key>lxGetAgentViewer</key>
<map>
<key>return</key><string>string</string>
<key>arguments</key><array>
<map><key>avkey</key><map><key>type</key><string>key</string></map></map>
</array>
</map>
</map>
</map></llsd>

Binary file not shown.

View File

@@ -161,4 +161,10 @@
<Key Name="assetType" Value="1" />
<Key Name="fileName" Value="OSSndWindowOpen.ogg" />
</Section>
<Section Name="FSAlertSound">
<Key Name="assetID" Value="a3f48b85-c29f-1f97-ebb6-644b7c053512" />
<Key Name="name" Value="FSAlertSound" />
<Key Name="assetType" Value="1" />
<Key Name="fileName" Value="FSAlertSound.ogg" />
</Section>
</Nini>

View File

@@ -270,14 +270,14 @@
<Key Name="fileName" Value="water3.jp2" />
</Section>
<Section Name="Sea">
<Key Name="assetID" Value="482E671B-9244-4B86-A036-68953A898D11" />
<Key Name="assetID" Value="482e671b-9244-4b86-a036-68953a898d11" />
<Key Name="name" Value="Sea" />
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="water3.jp2" />
</Section>
<Section Name="SeaWaterTrasp">
<Section Name="SeaWaterTransp">
<Key Name="assetID" Value="2bfd3884-7e27-69b9-ba3a-3e673f680004" />
<Key Name="name" Value="SeaWaterTrasp" />
<Key Name="name" Value="SeaWaterTransp" />
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="seaWaterTransp.j2c" />
</Section>
@@ -375,26 +375,51 @@
</Section>
<Section Name="Terrain Dirt">
<Key Name="assetID" Value="b8d3965a-ad78-bf43-699b-bff8eca6c975"/>
<Key Name="assetID" Value="0bc58228-74a0-7e83-89bc-5c23464bcec5"/>
<Key Name="name" Value="Terrain Dirt"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="0bc58228-74a0-7e83-89bc-5c23464bcec5.j2c" />
</Section>
<Section Name="Terrain Grass">
<Key Name="assetID" Value="63338ede-0037-c4fd-855b-015d77112fc8"/>
<Key Name="name" Value="Terrain Grass"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="63338ede-0037-c4fd-855b-015d77112fc8.j2c" />
</Section>
<Section Name="Terrain Mountain">
<Key Name="assetID" Value="303cd381-8560-7579-23f1-f0a880799740"/>
<Key Name="name" Value="Terrain Mountain"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="303cd381-8560-7579-23f1-f0a880799740.j2c" />
</Section>
<Section Name="Terrain Rock">
<Key Name="assetID" Value="53a2f406-4895-1d13-d541-d2e3b86bc19c"/>
<Key Name="name" Value="Terrain Rock"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="53a2f406-4895-1d13-d541-d2e3b86bc19c.j2c" />
</Section>
<Section Name="Terrain Dirt (legacy)">
<Key Name="assetID" Value="b8d3965a-ad78-bf43-699b-bff8eca6c975"/>
<Key Name="name" Value="Terrain Dirt (legacy)"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="Terrain Dirt-b8d3965a-ad78-bf43-699b-bff8eca6c975.texture" />
</Section>
<Section Name="Terrain Grass">
<Section Name="Terrain Grass (legacy)">
<Key Name="assetID" Value="abb783e6-3e93-26c0-248a-247666855da3"/>
<Key Name="name" Value="Terrain Grass"/>
<Key Name="name" Value="Terrain Grass (legacy)"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="Terrain Grass-abb783e6-3e93-26c0-248a-247666855da3.texture" />
</Section>
<Section Name="Terrain Mountain">
<Section Name="Terrain Mountain (legacy)">
<Key Name="assetID" Value="179cdabd-398a-9b6b-1391-4dc333ba321f"/>
<Key Name="name" Value="Terrain Mountain"/>
<Key Name="name" Value="Terrain Mountain (legacy)"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="Terrain Mountain-179cdabd-398a-9b6b-1391-4dc333ba321f.texture" />
</Section>
<Section Name="Terrain Rock">
<Section Name="Terrain Rock (legacy)">
<Key Name="assetID" Value="beb169c7-11ea-fff2-efe5-0f24dc881df2"/>
<Key Name="name" Value="Terrain Rock"/>
<Key Name="name" Value="Terrain Rock (legacy)"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="Terrain Rock-beb169c7-11ea-fff2-efe5-0f24dc881df2.texture" />
</Section>
@@ -755,13 +780,13 @@
Texture expected by viewers for properly displaying stars in the night sky
Name derives from label in viewer code
-->
<Section Name="IMG_BLOOM1 Texture">
<Section Name="IMG_BLOOM1">
<Key Name="assetID" Value="3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"/>
<Key Name="name" Value="IMG_BLOOM1 Texture"/>
<Key Name="name" Value="IMG_BLOOM1"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="IMG_BLOOM1.jp2" />
<Key Name="fileName" Value="3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef.j2c" />
</Section>
<Section Name="Smoke">
<Key Name="assetID" Value="b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"/>
<Key Name="name" Value="Smoke"/>
@@ -769,8 +794,39 @@
<Key Name="fileName" Value="b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d.j2c"/>
</Section>
<!-- Sprite used to generate collision visual effect -->
<Section Name="IMG_SHOT">
<Key Name="assetID" Value="35f217a3-f618-49cf-bbca-c86d486551a9"/>
<Key Name="name" Value="IMG_SHOT"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="35f217a3-f618-49cf-bbca-c86d486551a9.j2c" />
</Section>
<!-- Not sure what this is used for but it looks like a smokey cloud in Photoshop -->
<Section Name="IMG_DEFAULT">
<Key Name="assetID" Value="d2114404-dd59-4a4d-8e6c-49359e91bbf0"/>
<Key Name="name" Value="IMG_DEFAULT"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="d2114404-dd59-4a4d-8e6c-49359e91bbf0.j2c" />
</Section>
<!-- Pre-EEP sun -->
<Section Name="IMG_SUN">
<Key Name="assetID" Value="cce0f112-878f-4586-a2e2-a8f104bba271"/>
<Key Name="name" Value="IMG_SUN"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="sun.j2c" />
</Section>
<Section Name="IMG_SMOKE_POOF">
<Key Name="assetID" Value="1e63e323-5fe0-452e-92f8-b98bd0f764e3"/>
<Key Name="name" Value="IMG_SMOKE_POOF"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="1e63e323-5fe0-452e-92f8-b98bd0f764e3.j2c" />
</Section>
<Section Name="Water">
<Key Name="assetID" Value="DB814CAF-26AC-4D75-977B-A68578FE643D"/>
<Key Name="assetID" Value="db814caf-26ac-4d75-977b-a68578fe643d"/>
<Key Name="name" Value="Water"/>
<Key Name="assetType" Value="0" />
<Key Name="fileName" Value="water.jp2" />

Binary file not shown.

View File

@@ -223,7 +223,7 @@
Allow_osTeleportObject = ${OSSL|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER
; ThreatLevel Severe with additional internal restrictions
Allow_osGetAgentIP = true ; always restricted to Administrators (true or false to disable)
Allow_osGetAgentIP = false ; always restricted to Administrators (true or false to disable)
Allow_osSetContentType = false

View File

@@ -516,7 +516,7 @@
<Section Name="Terrain Dirt">
<Key Name="inventoryID" Value="00000000-0000-2222-9999-000000000006"/>
<Key Name="assetID" Value="b8d3965a-ad78-bf43-699b-bff8eca6c975"/>
<Key Name="assetID" Value="0bc58228-74a0-7e83-89bc-5c23464bcec5"/>
<Key Name="folderID" Value="00000112-000f-0000-0000-000100bba001"/>
<Key Name="description" Value="" />
<Key Name="name" Value="Terrain Dirt" />
@@ -526,7 +526,7 @@
<Section Name="Terrain Grass">
<Key Name="inventoryID" Value="00000000-0000-2222-9999-000000000007"/>
<Key Name="assetID" Value="abb783e6-3e93-26c0-248a-247666855da3"/>
<Key Name="assetID" Value="63338ede-0037-c4fd-855b-015d77112fc8"/>
<Key Name="folderID" Value="00000112-000f-0000-0000-000100bba001"/>
<Key Name="description" Value="" />
<Key Name="name" Value="Terrain Grass" />
@@ -536,7 +536,7 @@
<Section Name="Terrain Mountain">
<Key Name="inventoryID" Value="00000000-0000-2222-9999-000000000008"/>
<Key Name="assetID" Value="179cdabd-398a-9b6b-1391-4dc333ba321f"/>
<Key Name="assetID" Value="303cd381-8560-7579-23f1-f0a880799740"/>
<Key Name="folderID" Value="00000112-000f-0000-0000-000100bba001"/>
<Key Name="description" Value="" />
<Key Name="name" Value="Terrain Mountain" />
@@ -546,7 +546,7 @@
<Section Name="Terrain Rock">
<Key Name="inventoryID" Value="00000000-0000-2222-9999-000000000009"/>
<Key Name="assetID" Value="beb169c7-11ea-fff2-efe5-0f24dc881df2"/>
<Key Name="assetID" Value="53a2f406-4895-1d13-d541-d2e3b86bc19c"/>
<Key Name="folderID" Value="00000112-000f-0000-0000-000100bba001"/>
<Key Name="description" Value="" />
<Key Name="name" Value="Terrain Rock" />

Binary file not shown.

View File

@@ -1,3 +1,6 @@
; Copy this file to shutdown_commands.txt to execute region console commands when the simulator is asked to shut down
; e.g. show stats
; Lines that start with ; are comments
; Persist currently unsaved object changes immediately:
backup

View File

@@ -1,3 +1,6 @@
; Copy this file to startup_commands.txt to run region console commands once the simulator has finished starting up
; e.g. show stats
; Lines that start with ; are comments.
;Attempt a deep scan and cache of all assets in all scenes:
fcache assets

View File

@@ -0,0 +1,47 @@
/*M!999999\- enable the sandbox mode */
-- MariaDB dump 10.19 Distrib 10.11.11-MariaDB, for debian-linux-gnu (aarch64)
--
-- Host: localhost Database: grid
-- ------------------------------------------------------
-- Server version 10.11.11-MariaDB-0+deb12u1
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
--
-- Table structure for table `mutelist`
--
DROP TABLE IF EXISTS `mutelist`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `mutelist` (
`AgentID` char(36) NOT NULL,
`MuteID` char(36) NOT NULL,
`MuteName` varchar(255) NOT NULL,
`type` int(11) unsigned NOT NULL,
`flags` int(11) unsigned NOT NULL,
`Stamp` timestamp NOT NULL DEFAULT current_timestamp(),
UNIQUE KEY `AgentID_2` (`AgentID`,`MuteID`) USING BTREE,
KEY `AgentID` (`AgentID`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2025-04-14 10:18:07

View File

@@ -0,0 +1,13 @@
OpenSimMutelist
https://github.com/lickx/OpenSimMutelist
The advantage of this 3rd party module over the standard
mutelist module, is that mutes are stored on the grid
instead of the user's viewer cache; thus surviving
a viewer cache clear.
Only MySQL/MariaDB supported for now
To be sourced into your robust database
Needs the mute web helper to also be setup

View File

@@ -0,0 +1 @@
0 * * * * wget -q --spider https://example.com/helper/search/parser.php

View File

@@ -0,0 +1,115 @@
DROP TABLE IF EXISTS `search_allparcels`;
CREATE TABLE `search_allparcels` (
`regionUUID` char(36) NOT NULL,
`parcelname` varchar(255) NOT NULL,
`ownerUUID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
`groupUUID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
`landingpoint` varchar(255) NOT NULL,
`parcelUUID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
`infoUUID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
`parcelarea` int(11) NOT NULL,
PRIMARY KEY (`parcelUUID`),
KEY `regionUUID` (`regionUUID`)
);
DROP TABLE IF EXISTS `search_events`;
CREATE TABLE `search_events` (
`owneruuid` char(36) NOT NULL,
`name` varchar(255) NOT NULL,
`eventid` int(11) unsigned NOT NULL AUTO_INCREMENT,
`creatoruuid` char(36) NOT NULL,
`category` int(2) NOT NULL,
`description` text NOT NULL,
`dateUTC` int(10) NOT NULL,
`duration` int(10) NOT NULL,
`covercharge` tinyint(1) NOT NULL,
`coveramount` int(10) NOT NULL,
`simname` varchar(255) NOT NULL,
`parcelUUID` char(36) NOT NULL,
`globalPos` varchar(255) NOT NULL,
`eventflags` int(1) NOT NULL,
PRIMARY KEY (`eventid`)
);
DROP TABLE IF EXISTS `search_hostsregister`;
CREATE TABLE `search_hostsregister` (
`host` varchar(255) NOT NULL,
`port` int(5) NOT NULL,
`register` int(10) NOT NULL,
`nextcheck` int(10) NOT NULL,
`checked` tinyint(1) NOT NULL,
`failcounter` int(10) NOT NULL,
PRIMARY KEY (`host`,`port`)
);
DROP TABLE IF EXISTS `search_objects`;
CREATE TABLE `search_objects` (
`objectuuid` char(36) NOT NULL,
`parceluuid` char(36) NOT NULL,
`location` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`description` varchar(255) NOT NULL,
`regionuuid` char(36) NOT NULL DEFAULT '',
PRIMARY KEY (`objectuuid`,`parceluuid`)
);
DROP TABLE IF EXISTS `search_parcels`;
CREATE TABLE `search_parcels` (
`regionUUID` char(36) NOT NULL,
`parcelname` varchar(255) NOT NULL,
`parcelUUID` char(36) NOT NULL,
`landingpoint` varchar(255) NOT NULL,
`description` varchar(255) NOT NULL,
`searchcategory` varchar(50) NOT NULL,
`build` enum('true','false') NOT NULL,
`script` enum('true','false') NOT NULL,
`public` enum('true','false') NOT NULL,
`dwell` float NOT NULL DEFAULT 0,
`infouuid` varchar(36) NOT NULL DEFAULT '',
`mature` varchar(10) NOT NULL DEFAULT 'PG',
`pictureUUID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
PRIMARY KEY (`regionUUID`,`parcelUUID`),
KEY `name` (`parcelname`),
KEY `description` (`description`),
KEY `searchcategory` (`searchcategory`),
KEY `dwell` (`dwell`)
);
DROP TABLE IF EXISTS `search_parcelsales`;
CREATE TABLE `search_parcelsales` (
`regionUUID` char(36) NOT NULL,
`parcelname` varchar(255) NOT NULL,
`parcelUUID` char(36) NOT NULL,
`area` int(6) NOT NULL,
`saleprice` int(11) NOT NULL,
`landingpoint` varchar(255) NOT NULL,
`infoUUID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
`dwell` int(11) NOT NULL,
`parentestate` int(11) NOT NULL DEFAULT 1,
`mature` varchar(10) NOT NULL DEFAULT 'PG',
PRIMARY KEY (`regionUUID`,`parcelUUID`)
);
DROP TABLE IF EXISTS `search_popularplaces`;
CREATE TABLE `search_popularplaces` (
`parcelUUID` char(36) NOT NULL,
`name` varchar(255) NOT NULL,
`dwell` float NOT NULL,
`infoUUID` char(36) NOT NULL,
`has_picture` tinyint(1) NOT NULL,
`mature` varchar(10) NOT NULL,
PRIMARY KEY (`parcelUUID`)
);
DROP TABLE IF EXISTS `search_regions`;
CREATE TABLE `search_regions` (
`regionname` varchar(255) NOT NULL,
`regionUUID` char(36) NOT NULL,
`regionhandle` varchar(255) NOT NULL,
`url` varchar(255) NOT NULL,
`owner` varchar(255) NOT NULL,
`owneruuid` char(36) NOT NULL,
PRIMARY KEY (`regionUUID`)
);

View File

@@ -0,0 +1,12 @@
OpenSimSearch
https://github.com/lickx/OpenSimSearch
For having search functionality on a grid
Only MySQL/MariaDB supported for now
To be sourced in your robust database
Note the classifieds table will already be made by robust itself
Needs the search web helper to also be setup

View File

@@ -0,0 +1,37 @@
-- Purge all search entries related to a permanently deleted region
-- Prerequisites: OpenSimSearch, lickx branch
-- https://github.com/lickx/OpenSimSearch/tree/lickx
-- To be sourced into your robust database.
-- Usage example: CALL sp_searchpurge('2ef309ab-dc66-4123-85e8-873d00b8acc9');
DELIMITER //
CREATE OR REPLACE PROCEDURE sp_searchpurge (IN pRegionID CHAR(36))
BEGIN
-- classifieds (note, classifieds is the only table that isn't prefixed with search_ because Robust expects and queries it under this name)
DELETE classifieds FROM classifieds INNER JOIN search_parcels ON classifieds.parceluuid = search_parcels.parcelUUID WHERE search_parcels.regionUUID=pRegionID;
-- events
DELETE search_events FROM search_events INNER JOIN search_parcels ON search_events.parcelUUID = search_parcels.parcelUUID WHERE search_parcels.regionUUID=pRegionID;
-- objects
DELETE FROM search_objects WHERE regionuuid=pRegionID;
-- regionsales
DELETE FROM search_parcelsales WHERE regionUUID=pRegionID;
-- popularplaces
DELETE search_popularplaces FROM search_popularplaces INNER JOIN search_parcels ON search_popularplaces.parcelUUID = search_parcels.parcelUUID WHERE search_parcels.regionUUID=pRegionID;
-- allparcels
DELETE FROM search_allparcels WHERE regionUUID=pRegionID;
-- parcels
DELETE FROM search_parcels WHERE regionUUID=pRegionID;
-- regions
DELETE FROM search_regions WHERE regionUUID=pRegionID;
END //
DELIMITER ;

View File

@@ -0,0 +1,64 @@
<?php
/**
* Gloebit default configuration
*
* DO NOT EDIT THIS FILE. It will be replaced on next update.
* Instead copy the 'define(...)' lines to config.php, before the addons include
* command, and customize from there.
*
* @package magicoli/opensim-helpers
* @author Gudule Lapointe <gudule@speculoos.world>
* @link https://github.com/magicoli/opensim-helpers
* @license AGPLv3
*/
if ( CURRENCY_PROVIDER != 'gloebit' ) {
die();
}
/**
* Set to true to activate sandbox mode, during initial installation and tests.
* Set to false once ready to go live.
*
* @var boolean
*/
if ( ! defined( 'GLOEBIT_SANDBOX' ) ) {
define( 'GLOEBIT_SANDBOX', false );
}
/**
* Gloebit currency conversion table
*
* Used to display a cost estimation when using the viewer Buy Currency feature.
* Conversion rate between Gloebit amount and US$ cents. Must match the packages
* and prices idsplayed on Gloebit website.
* // TODO: fetch conversion values from Gloebit website.
*
* @var array
*/
if ( ! defined( 'GLOEBIT_CONVERSION_TABLE' ) ) {
define(
'GLOEBIT_CONVERSION_TABLE',
array(
400 => 199,
1050 => 499,
2150 => 999,
4500 => 1999,
11500 => 4999,
)
);
}
/**
* Affects the suggested purchase amount. Gloebit only allow predifined amounts
* to be purchased.
* - Set threshold of 1.0 to switch to the next pack even for 1$G more
* (e.g. if user request 401, suggest 1050)
* - Set theshold to 1.1 or 1.2 to keep the low pack for small differences.
* (e.g. if user request 401, still suggest 400)
* The user can still choose another pack on the web purchase page.
*
* @GLOEBIT_CONVERSION_THRESHOLD float must be >= 1.0
*/
if ( ! defined( 'GLOEBIT_CONVERSION_THRESHOLD' ) ) {
define( 'GLOEBIT_CONVERSION_THRESHOLD', 1.2 );
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* Podex default configuration file.
*
* DO NOT EDIT THIS FILE. It will be replaced on next update.
* Instead copy the 'define(...)' lines to config.php, before the addons include
* command, and customize from there.
*
* @package magicoli/opensim-helpers
* @author Gudule Lapointe <gudule@speculoos.world>
* @link https://github.com/magicoli/opensim-helpers
* @license AGPLv3
*/
if ( CURRENCY_PROVIDER != 'podex' ) {
die();
}
/**
* This is the message displayed to users when they use the viewer "Buy
* currency" feature. Podex Buy and sell transactions are actually provided by
* in-world terminals. Adjust the message and the url to instruct user to
* teleport to the region providing Podex terminals.
*
* @var [type]
*/
if ( ! defined( 'PODEX_ERROR_MESSAGE' ) ) {
define( 'PODEX_ERROR_MESSAGE', 'Please use our terminals in-world to proceed. Click OK to teleport to terminals region.' );
}
if ( ! defined( 'PODEX_REDIRECT_URL' ) ) {
define( 'PODEX_REDIRECT_URL', 'secondlife://Podex Exchange/128/128/21' );
}

382
helper/economy/currency.php Normal file
View File

@@ -0,0 +1,382 @@
<?php
/**
* currency.php
*
* Provides web tools for OpenSim currencies
*
* Requires an OpenSimulator Money Server
* [DTL/NSL Money Server for OpenSim](http://www.nsl.tuis.ac.jp/xoops/modules/xpwiki/?OpenSim%2FMoneyServer)
* or [Gloebit module](http://dev.gloebit.com/opensim/configuration-instructions/)
*
* @package magicoli/opensim-helpers
* @author Gudule Lapointe <gudule@speculoos.world>
* @link https://github.com/magicoli/opensim-helpers
* @license AGPLv3
*
* Includes portions of code from
* Melanie Thielker and Teravus Ovares (http://opensimulator.org/)
* Fumi.Iseki for CMS/LMS '09 5/31
*/
// error_reporting(E_ERROR | E_WARNING | E_PARSE);
require_once 'includes/config.php';
require_once 'includes/economy.php';
//
// The XMLRPC server object
//
$xmlrpc_server = xmlrpc_server_create();
//
// Viewer retrieves currency buy quote
//
xmlrpc_server_register_method( $xmlrpc_server, 'getCurrencyQuote', 'currency_xmlrpc_quote' );
function currency_xmlrpc_quote( $method_name, $params, $app_data ) {
$req = $params[0];
$agentid = $req['agentId'];
$sessionid = $req['secureSessionId'];
$amount = $req['currencyBuy'];
$ipAddress = $_SERVER['REMOTE_ADDR'];
$ret = opensim_check_secure_session( $agentid, null, $sessionid );
if ( $ret ) {
$confirmvalue = currency_get_confirm_value( $ipAddress );
switch ( CURRENCY_PROVIDER ) {
case 'gloebit':
$cost = 1; // default cost if no table;
$conversion_table = GLOEBIT_CONVERSION_TABLE;
foreach ( $conversion_table as $key => $value ) {
$cost = $value;
if ( GLOEBIT_CONVERSION_THRESHOLD > 0 ) {
$threshold = GLOEBIT_CONVERSION_THRESHOLD;
} else {
$threshold = 1;
}
if ( $key >= $amount / $threshold ) {
break;
}
}
break;
default:
$cost = currency_virtual_to_real( $amount );
$realamount = $amount;
}
$currency = array(
'estimatedCost' => $cost,
'currencyBuy' => $realamount,
);
$response_xml = xmlrpc_encode(
array(
'success' => true,
'currency' => $currency,
'confirm' => $confirmvalue,
)
);
} else {
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => "Unable to Authenticate\n\nClick URL for more info.",
'errorURI' => '' . CURRENCY_HELPER_URL . '',
)
);
}
header( 'Content-type: text/xml' );
echo $response_xml;
return '';
}
//
// Viewer buys currency
//
xmlrpc_server_register_method( $xmlrpc_server, 'buyCurrency', 'currency_xmlrpc_buy' );
function currency_xmlrpc_buy( $method_name, $params, $app_data ) {
$req = $params[0];
$agentid = $req['agentId'];
$sessionid = $req['secureSessionId'];
$amount = $req['currencyBuy'];
$confim = $req['confirm'];
$ipAddress = $_SERVER['REMOTE_ADDR'];
if ( $confim != currency_get_confirm_value( $ipAddress ) ) {
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => "\n\nMissmatch Confirm Value!!",
'errorURI' => '' . CURRENCY_HELPER_URL . '',
)
);
header( 'Content-type: text/xml' );
echo $response_xml;
return '';
}
$checkSecure = opensim_check_secure_session( $agentid, null, $sessionid );
if ( ! $checkSecure ) {
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => "\n\nMissmatch Secure Session ID!!",
'errorURI' => '' . CURRENCY_HELPER_URL . '',
)
);
header( 'Content-type: text/xml' );
echo $response_xml;
return '';
}
$ret = false;
$cost = currency_virtual_to_real( $amount );
$transactionPermit = currency_process_transaction( $agentid, $cost, $ipAddress );
if ( $transactionPermit ) {
$res = currency_add_money( $agentid, $amount, $sessionid );
if ( $res['success'] ) {
$ret = true;
}
}
if ( $ret ) {
$response_xml = xmlrpc_encode( array( 'success' => true ) );
} else {
switch ( CURRENCY_PROVIDER ) {
case 'podex':
$errorURI = null; // opensim_format_tp(PODEX_REDIRECT_URL, TPLINK_HOP);
$errorMessage = PODEX_ERROR_MESSAGE . ' ' . PODEX_REDIRECT_URL;
break;
case 'gloebit':
if ( defined( GLOEBIT_SANDBOX ) && GLOEBIT_SANDBOX ) {
$baseurl = 'https://sandbox.gloebit.com/purchase';
} else {
$baseurl = 'https://www.gloebit.com/purchase';
}
$server_info = opensim_get_server_info( $agentid );
$serverip = $server_info['serverIP'];
$httpport = $server_info['serverHttpPort'];
$informurl = "http://${serverip}:${httpport}/gloebit/buy_complete?agentId=${agentid}";
$errorURI = "${baseurl}?reset&r=&inform=$informurl";
$errorMessage = 'Click OK to finish the transaction on Gloebit website.';
break;
default:
$errorMessage = 'Unable to process the transaction. The gateway denied your charge. Open help page?';
$errorURI = empty( W4OS_GRID_INFO['help'] ) ? CURRENCY_HELPER_URL : W4OS_GRID_INFO['help'];
}
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => $errorMessage,
'errorURI' => $errorURI,
)
);
}
header( 'Content-type: text/xml' );
echo $response_xml;
return '';
}
//
// Region requests account balance
//
xmlrpc_server_register_method( $xmlrpc_server, 'simulatorUserBalanceRequest', 'currency_xmlrpc_balance' );
function currency_xmlrpc_balance( $method_name, $params, $app_data ) {
$req = $params[0];
$agentid = $req['agentId'];
$sessionid = $req['secureSessionId'];
$balance = currency_get_balance( $agentid, $sessionid );
if ( $balance >= 0 ) {
$response_xml = xmlrpc_encode(
array(
'success' => true,
'agentId' => $agentid,
'funds' => $balance,
)
);
} else {
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => 'Could not authenticate your avatar. Money operations may be unavailable',
'errorURI' => ' ',
)
);
}
header( 'Content-type: text/xml' );
echo $response_xml;
return '';
}
//
// Region initiates money transfer (Direct DB Operation for security)
//
xmlrpc_server_register_method( $xmlrpc_server, 'regionMoveMoney', 'currency_xmlrpc_regionMoveMoney' );
function currency_xmlrpc_regionMoveMoney( $method_name, $params, $app_data ) {
$req = $params[0];
$agentid = $req['agentId'];
$destid = $req['destId'];
$sessionid = $req['secureSessionId'];
$regionid = $req['regionId'];
$secret = $req['secret'];
$currencySecret = $req['currencySecret'];
$cash = $req['cash'];
$aggregatePermInventory = $req['aggregatePermInventory'];
$aggregatePermNextOwner = $req['aggregatePermNextOwner'];
$flags = $req['flags'];
$transactiontype = $req['transactionType'];
$description = $req['description'];
$ipAddress = $_SERVER['REMOTE_ADDR'];
$ret = opensim_check_region_secret( $regionid, $secret );
if ( $ret ) {
$ret = opensim_check_secure_session( $agentid, $regionid, $sessionid );
if ( $ret ) {
$balance = currency_get_balance( $agentid, $sessionid );
if ( $balance >= $cash ) {
currency_move_money(
$agentid,
$destid,
$cash,
$transactiontype,
$flags,
$description,
$aggregatePermInventory,
$aggregatePermNextOwner,
$ipAddress
);
$sbalance = currency_get_balance( $agentid, $sessionid );
$dbalance = currency_get_balance( $destid );
$response_xml = xmlrpc_encode(
array(
'success' => true,
'agentId' => $agentid,
'funds' => $balance,
'funds2' => $balance,
'currencySecret' => ' ',
)
);
currency_update_simulator_balance( $agentid, $sbalance, $sessionid );
currency_update_simulator_balance( $destid, $dbalance );
} else {
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => 'You do not have sufficient funds for this purchase',
'errorURI' => ' ',
)
);
}
} else {
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => 'Unable to authenticate avatar. Money operations may be unavailable',
'errorURI' => ' ',
)
);
}
} else {
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => 'This region is not authorized to manage your money.',
'errorURI' => ' ',
)
);
}
header( 'Content-type: text/xml' );
echo $response_xml;
return '';
}
//
// Region claims user
//
xmlrpc_server_register_method( $xmlrpc_server, 'simulatorClaimUserRequest', 'currency_xmlrpc_claimUserRequest' );
function currency_xmlrpc_claimUserRequest( $method_name, $params, $app_data ) {
$req = $params[0];
$agentid = $req['agentId'];
$sessionid = $req['secureSessionId'];
$regionid = $req['regionId'];
$secret = $req['secret'];
$ret = opensim_check_region_secret( $regionid, $secret );
if ( $ret ) {
$ret = opensim_check_secure_session( $agentid, null, $sessionid );
if ( $ret ) {
$ret = opensim_set_current_region( $agentid, $regionid );
if ( $ret ) {
$balance = currency_get_balance( $agentid, $sessionid );
$response_xml = xmlrpc_encode(
array(
'success' => true,
'agentId' => $agentid,
'funds' => $balance,
'currencySecret' => ' ',
)
);
} else {
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => 'Error occurred, when DB was updated.',
'errorURI' => ' ',
)
);
}
} else {
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => 'Unable to authenticate avatar. Money operations may be unavailable.',
'errorURI' => ' ',
)
);
}
} else {
$response_xml = xmlrpc_encode(
array(
'success' => false,
'errorMessage' => 'This region is not authorized to manage your money.',
'errorURI' => ' ',
)
);
}
header( 'Content-type: text/xml' );
echo $response_xml;
return '';
}
//
// Process the request
//
$request_xml = file_get_contents( 'php://input' );
// error_log(__FILE__ . ' '. $request_xml);
xmlrpc_server_call_method( $xmlrpc_server, $request_xml, '' );
xmlrpc_server_destroy( $xmlrpc_server );
die();

View File

@@ -0,0 +1,82 @@
<?php
/**
* config.example.php
*
* Helpers configuration
* Rename this file as "config.php" before editing.
*
* @package magicoli/opensim-helpers
* @author Gudule Lapointe <gudule@speculoos.world>
* @link https://github.com/magicoli/opensim-helpers
* @license AGPLv3
*/
/**
* Main database.
* For grids, use Robust database credentials.
* For standalone simulators, use OpenSim database credentials.
*
* Access to OpenSim database is required
* - for search including classifieds
* - for offline messages processing
* - for economy
* It is not required if only search is needed, without classifieds (e.g. to for
* a multi-grid search engine). In this case search will only provide results
* for places, land for sale and events.
*/
define( 'OPENSIM_DB', true ); // Set to false for search only, see above
define( 'OPENSIM_DB_HOST', 'localhost' );
define( 'OPENSIM_DB_NAME', 'opensim' );
define( 'OPENSIM_DB_USER', 'opensim' );
define( 'OPENSIM_DB_PASS', 'password' );
define( 'SEARCH_TABLE_EVENTS', 'events' );
/**
* Search database credentials and settings.
* Needed if you enable search in OpenSim server.
*
* A dedicated database is:
* - strongly recommended if the search engine is shared by several grids
* - recommended and more efficient for large and/or hypergrid-enabled grids
* - optional for closed grids and standalone simulators
* These are recommendations, the Robust database can safely be used instead.
*/
define( 'SEARCH_DB_HOST', OPENSIM_DB_HOST );
define( 'SEARCH_DB_NAME', OPENSIM_DB_NAME );
define( 'SEARCH_DB_USER', OPENSIM_DB_USER );
define( 'SEARCH_DB_PASS', OPENSIM_DB_PASS );
/**
* Currency database credentials and settings.
* Needed if currency is enabled on OpenSim server.
* A dedicated database is recommended, but not mandatory.
*/
define( 'CURRENCY_DB_HOST', OPENSIM_DB_HOST );
define( 'CURRENCY_DB_NAME', OPENSIM_DB_NAME );
define( 'CURRENCY_DB_USER', OPENSIM_DB_USER );
define( 'CURRENCY_DB_PASS', OPENSIM_DB_PASS );
define( 'CURRENCY_MONEY_TBL', 'balances' );
define( 'CURRENCY_TRANSACTION_TBL', 'transactions' );
/**
* Money Server settings.
*/
define( 'CURRENCY_USE_MONEYSERVER', false );
define( 'CURRENCY_SCRIPT_KEY', '123456789' );
define( 'CURRENCY_RATE', 10 ); // amount in dollar...
define( 'CURRENCY_RATE_PER', 1000 ); // ... for this amount in virtual currency
define( 'CURRENCY_PROVIDER', null ); // NULL, 'podex' or 'gloebit'
define( 'CURRENCY_HELPER_URL', 'http://yourgrid.org/helpers/' );
// if (!defined('CURRENCY_HELPER_PATH')) define('CURRENCY_HELPER_PATH', dirname(__DIR__));
/**
* DO NOT MAKE CHANGES BELOW THIS
* Add your custom values above.
*/
require_once 'databases.php';
require_once 'functions.php';
$currency_addon = dirname( __DIR__ ) . '/addons/' . CURRENCY_PROVIDER . '.php';
if ( file_exists( $currency_addon ) ) {
require_once $currency_addon;
}

View File

@@ -0,0 +1,98 @@
<?php
/**
* New database class using PDO, replaces DB class using mysqli
*
* @package magicoli/opensim-helpers
* @author Gudule Lapointe <gudule@speculoos.world>
* @link https://github.com/magicoli/opensim-helpers
* @license AGPLv3
*/
class OSPDO extends PDO {
public function __construct( $dsn, $username = null, $password = null, $driver_options = null ) {
try {
@parent::__construct( $dsn, $username, $password, $driver_options );
$this->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$this->connected = true;
} catch ( PDOException $e ) {
error_log( "Could not connect to database $dsn as $username" );
// error_log($e);
$this->connected = false;
}
}
/**
* Prepare SQL query, execute with params and log error if any
*
* @param string $query
* @param array $options options passed to prepare()
* @param array $params substitute markers passed to execute()
* @return PDOstatement if success, false on error
*/
public function prepareAndExecute( $query, $params = null, $options = array() ) {
$trace = debug_backtrace()[0];
$trace = $trace['file'] . ':' . $trace['line'];
try {
$statement = $this->prepare( $query, $options );
$result = $statement->execute( $params );
} catch ( PDOException $e ) {
error_log( 'Error ' . $e->getCode() . ' ' . $e->getMessage() . ' query ' . print_r( $query, true ) . ' params ' . print_r( $params, true ) . ' ' . $trace );
return false;
}
// $statement = $this->prepare( $query, $options );
// $result = $statement->execute( $params );
if ( $result ) {
return $statement;
}
error_log( 'Error ' . $statement->errorCode() . ' ' . $statement->errorInfo()[2] . ' ' . $trace );
return false;
}
public function insert( $table, $values ) {
foreach ( $values as $field => $value ) {
$markers[] = ':' . $field;
}
$markers = implode( ',', $markers );
$fields = implode( ',', array_keys( $values ) );
$sql = "INSERT INTO $table ($fields) VALUES ($markers)";
$statement = $this->prepare( $sql );
return $statement->execute( $values );
}
}
function tableExists( $pdo, $tables ) {
if ( ! is_object( $pdo ) ) {
return false;
}
if ( ! $pdo->connected ) {
return false;
}
// error_log("pdo " . print_r($pdo, true));
if ( is_string( $tables ) ) {
$tables = array( $tables );
}
foreach ( $tables as $table ) {
// Try a select statement against the table
// Run it in try/catch in case PDO is in ERRMODE_EXCEPTION.
try {
$result = $pdo->query( "SELECT 1 FROM $table LIMIT 1" );
} catch ( Exception $e ) {
error_log( __FILE__ . ': ' . SEARCH_DB_NAME . " is missing table $table" );
// We got an exception == table not found
return false;
}
if ( $result == false ) {
error_log( __FILE__ . ': ' . SEARCH_DB_NAME . " is missing table $table" );
return false;
}
}
return true;
}
if ( defined( 'OPENSIM_DB' ) && OPENSIM_DB === true ) {
$OpenSimDB = new OSPDO( 'mysql:host=' . OPENSIM_DB_HOST . ';dbname=' . OPENSIM_DB_NAME, OPENSIM_DB_USER, OPENSIM_DB_PASS );
}

View File

@@ -0,0 +1,581 @@
<?php
/**
* economy.php
*
* Provides functions required only by currency.php and landtool.php
*
* Requires an OpenSimulator Money Server
* [DTL/NSL Money Server for OpenSim](http://www.nsl.tuis.ac.jp/xoops/modules/xpwiki/?OpenSim%2FMoneyServer)
* or [Gloebit module](http://dev.gloebit.com/opensim/configuration-instructions/)
*
* @package magicoli/opensim-helpers
* @author Gudule Lapointe <gudule@speculoos.world>
* @link https://github.com/magicoli/opensim-helpers
* @license AGPLv3
*
* Includes portions of code from original DTLS/NLS Money Server, by:
* Melanie Thielker and Teravus Ovares (http://opensimulator.org/)
* Fumi.Iseki for CMS/LMS '09 5/31
**/
require_once 'functions.php';
if ( defined( 'CURRENCY_DB_HOST' ) ) {
$CurrencyDB = new OSPDO( 'mysql:host=' . CURRENCY_DB_HOST . ';dbname=' . CURRENCY_DB_NAME, CURRENCY_DB_USER, CURRENCY_DB_PASS );
} else {
$CurrencyDB = &$OpenSimDB;
}
function noserver_save_transaction( $sourceId, $destId, $amount, $type, $flags, $desc, $prminvent, $nxtowner, $ip ) {
global $CurrencyDB;
if ( ! is_numeric( $amount ) ) {
return;
}
if ( ! opensim_isuuid( $sourceId ) ) {
$sourceId = NULL_KEY;
}
if ( ! opensim_isuuid( $destId ) ) {
$destId = NULL_KEY;
}
$region = NULL_KEY;
$client = $sourceId;
if ( $client == NULL_KEY ) {
$client = $destId;
}
$avt = opensim_get_avatar_session( $client );
if ( $avt != null ) {
$region = $avt['regionID'];
}
$CurrencyDB->insert(
CURRENCY_TRANSACTION_TBL,
array(
'sourceId' => $sourceId,
'destId' => $destId,
'amount' => $amount,
'flags' => $flags,
'aggregatePermInventory' => $prminvent,
'aggregatePermNextOwner' => $nxtowner,
'description' => $desc,
'transactionType' => $type,
'timeOccurred' => time(),
'RegionGenerated' => $region,
'ipGenerated' => $ip,
)
);
}
function noserver_get_balance( $agentID ) {
global $CurrencyDB;
if ( ! opensim_isuuid( $agentID ) ) {
return -1;
}
$sent_sum = 0;
$received_sum = 0;
$credits = $CurrencyDB->prepareAndExecute(
'SELECT SUM(amount) FROM ' . CURRENCY_TRANSACTION_TBL . ' WHERE destId = :destId',
array( 'destId' => $agentID )
);
if ( $credits ) {
list($received_sum) = $credits->fetch();
}
$debits = $CurrencyDB->prepareAndExecute(
'SELECT SUM(amount) FROM ' . CURRENCY_TRANSACTION_TBL . ' WHERE sourceId = :sourceId',
array( 'sourceId' => $agentID )
);
if ( $debits ) {
list($sent_sum) = $debits->fetch();
}
$cash = (int) $received_sum - (int) $sent_sum;
return $cash;
}
function currency_save_transaction( $sourceId, $destId, $amount, $type, $flags, $description, &$deprecated = null ) {
global $CurrencyDB;
if ( ! is_numeric( $amount ) ) {
return;
}
if ( ! opensim_isuuid( $sourceId ) ) {
$sourceId = NULL_KEY;
}
if ( ! opensim_isuuid( $destId ) ) {
$destId = NULL_KEY;
}
$handle = 0;
$secure = NULL_KEY;
$client = $sourceId;
$UUID = make_random_guid();
$sourceID = $sourceId;
$destID = $destId;
if ( $client == NULL_KEY ) {
$client = $destId;
}
$avt = opensim_get_avatar_session( $client );
if ( $avt != null ) {
$region = $avt['regionID'];
$secure = $avt['secureID'];
$rgn = opensim_get_region_info( $region );
if ( $rgn != null ) {
$handle = $rgn['regionHandle'];
}
}
$CurrencyDB->insert(
CURRENCY_TRANSACTION_TBL,
array(
'UUID' => $UUID,
'sender' => $sourceID,
'receiver' => $destID,
'amount' => $amount,
'objectUUID' => NULL_KEY,
'regionHandle' => $handle,
'type' => $type,
'time' => time(),
'secure' => $secure,
'status' => $flags,
'description' => $description,
)
);
}
function currency_set_currency_balance( $agentID, $amount, &$deprecated = null ) {
if ( ! opensim_isuuid( $agentID ) or ! is_numeric( $amount ) ) {
return false;
}
global $CurrencyDB;
$balances_table = CURRENCY_MONEY_TBL;
$CurrencyDB->query( "LOCK TABLES $balances_table" );
$currentbalance = $CurrencyDB->prepareAndExecute(
"SELECT balance FROM $balances_table WHERE user = :user",
array(
'user' => $agentID,
)
);
if ( $currentbalance ) {
list($cash) = $currentbalance->fetch();
$balance = (int) $cash + (int) $amount;
$result = $CurrencyDB->prepareAndExecute(
"UPDATE $balances_table SET balance = :balance WHERE user = :user",
array(
'balance' => $balance,
'user' => $agentID,
)
);
} else {
$result = false;
}
$CurrencyDB->query( "UNLOCK TABLES $balances_table" );
return $result;
}
function currency_update_simulator_balance( $agentID, $amount = -1, $secureID = null ) {
if ( ! opensim_isuuid( $agentID ) ) {
return false;
}
if ( $amount < 0 ) {
$amount = currency_get_balance( $agentID, $secureID );
if ( $amount < 0 ) {
return false;
}
}
// XML RPC to Region Server
if ( ! opensim_isuuid( $secureID, true ) ) {
return false;
}
$agentServer = opensim_get_server_info( $agentID );
if ( ! $agentServer ) {
return false;
}
$serverip = $agentServer['serverIP'];
$httpport = $agentServer['serverHttpPort'];
$serveruri = $agentServer['serverURI'];
$avatarSession = opensim_get_avatar_session( $agentID );
if ( ! $avatarSession ) {
return false;
}
$sessionID = $avatarSession['sessionID'];
if ( $secureID == null ) {
$secureID = $avatarSession['secureID'];
}
$request = xmlrpc_encode_request(
'UpdateBalance',
array(
array(
'clientUUID' => $agentID,
'clientSessionID' => $sessionID,
'clientSecureSessionID' => $secureID,
'Balance' => $amount,
),
)
);
$response = currency_xmlrpc_call( $serverip, $httpport, $serveruri, $request );
return $response;
}
function currency_move_money( $agentID, $destID, $amount, $type, $flags, $desc, $prminvent = 0, $nxtowner = 0, $ip = '' ) {
if ( ! CURRENCY_USE_MONEYSERVER ) {
noserver_save_transaction( $agentID, $destID, $amount, $type, $flags, $desc, $prminvent, $nxtowner, $ip );
return true;
}
// Direct DB access for security
// $url = preg_split("/[:\/]/", USER_SERVER_URI);
// $userip = $url[3];
currency_save_transaction( $agentID, $destID, $amount, $type, $flags, $desc );
// TODO: Shouldn't we execute both balance updates only if all of the four
// conditions are met and none of them if any of the checks fails?
if ( opensim_isuuid( $agentID ) and $agentID != NULL_KEY ) {
currency_set_currency_balance( $agentID, -$amount );
}
if ( opensim_isuuid( $destID ) and $destID != NULL_KEY ) {
currency_set_currency_balance( $destID, $amount );
}
return true;
}
function currency_add_money( $agentID, $amount, $secureID = null ) {
if ( ! opensim_isuuid( $agentID ) ) {
return false;
}
if ( ! CURRENCY_USE_MONEYSERVER ) {
noserver_save_transaction( null, $agentID, $amount, 5010, 0, 'Add Money', 0, 0, '' );
$response = array( 'success' => true );
return $response;
}
//
// XML RPC to Region Server
//
if ( ! opensim_isuuid( $secureID, true ) ) {
return false;
}
$agentServer = opensim_get_server_info( $agentID );
$serverip = $agentServer['serverIP'];
$httpport = $agentServer['serverHttpPort'];
$serveruri = $agentServer['serverURI'];
if ( $serverip == '' ) {
return false;
}
$avatarSession = opensim_get_avatar_session( $agentID );
$sessionID = $avatarSession['sessionID'];
// if ($sessionID=="") return false;
if ( $secureID == null ) {
$secureID = $avatarSession['secureID'];
}
$request = xmlrpc_encode_request(
'AddBankerMoney',
array(
array(
'clientUUID' => $agentID,
'clientSessionID' => $sessionID,
'clientSecureSessionID' => $secureID,
'amount' => $amount,
),
)
);
$response = currency_xmlrpc_call( $serverip, $httpport, $serveruri, $request );
return $response;
}
//
// Send the money to avatar for bonus
// by Milo
//
function currency_send_money( $agentID, $amount, $secretCode = null ) {
if ( ! opensim_isuuid( $agentID ) ) {
return false;
}
if ( ! CURRENCY_USE_MONEYSERVER ) {
noserver_save_transaction( null, $agentID, $amount, 5003, 0, 'Send Money', 0, 0, '' );
$response = array( 'success' => true );
return $response;
}
//
// XML RPC to Region Server
//
$agentServer = opensim_get_server_info( $agentID );
$serverip = $agentServer['serverIP'];
$httpport = $agentServer['serverHttpPort'];
$serveruri = $agentServer['serverURI'];
if ( $serverip == '' ) {
return false;
}
$serverip = gethostbyname( $serverip );
if ( $secretCode != null ) {
$secretCode = md5( $secretCode . '_' . $serverip );
} else {
$secretCode = currency_get_confirm_value( $serverip );
}
$request = xmlrpc_encode_request(
'SendMoneyBalance',
array(
array(
'clientUUID' => $agentID,
'secretAccessCode' => $secretCode,
'amount' => $amount,
),
)
);
$response = currency_xmlrpc_call( $serverip, $httpport, $serveruri, $request );
return $response;
}
function currency_get_balance( $agentID, $secureID = null ) {
$cash = -1;
if ( ! opensim_isuuid( $agentID ) ) {
return (int) $cash;
}
if ( ! CURRENCY_USE_MONEYSERVER ) {
$cash = noserver_get_balance( $agentID );
return (int) $cash;
}
if ( ! opensim_isuuid( $secureID, true ) ) {
return (int) $cash;
}
$agentServer = opensim_get_server_info( $agentID );
$serverip = $agentServer['serverIP'];
$httpport = $agentServer['serverHttpPort'];
$serveruri = $agentServer['serverURI'];
if ( $serverip == '' ) {
return (int) $cash;
}
$avatarSession = opensim_get_avatar_session( $agentID );
$sessionID = $avatarSession['sessionID'];
if ( $sessionID == '' ) {
return (int) $cash;
}
if ( $secureID == null ) {
$secureID = $avatarSession['secureID'];
}
$request = xmlrpc_encode_request(
'GetBalance',
array(
array(
'clientUUID' => $agentID,
'clientSessionID' => $sessionID,
'clientSecureSessionID' => $secureID,
),
)
);
$response = currency_xmlrpc_call( $serverip, $httpport, $serveruri, $request );
if ( $response ) {
$cash = $response['balance'];
}
return (int) $cash;
}
function currency_get_confirm_value( $ipAddress ) {
// TODO:
// Option to force key to be something else than default
$key = empty( CURRENCY_SCRIPT_KEY ) ? '1234567883789' : CURRENCY_SCRIPT_KEY;
$confirmvalue = md5( $key . '_' . $ipAddress );
return $confirmvalue;
}
function currency_process_transaction( $avatarID, $cost, $ipAddress ) {
// Do external processing here! (credit card, paypal, any money system)
// Return False if it fails!
// Remember, $amount is stored without decimal places, however it's assumed
// that the transaction amount is in Cents and has two decimal places
// 5 dollars will be 500
// 15 dollars will be 1500
// if ($avatarID==CURRENCY_BANKER) return true;
// return false;
return true;
}
function currency_virtual_to_real( $amount ) {
$cost = (int) ( CURRENCY_RATE / CURRENCY_RATE_PER * 100 * $amount );
return $cost;
}
// XML RPC
function currency_xmlrpc_call( $host, $port, $uri, $request ) {
$url = '';
if ( $uri != '' ) {
$dec = explode( ':', $uri );
if ( ! strncasecmp( $dec[0], 'http', 4 ) ) {
$url = "$dec[0]:$dec[1]";
}
}
if ( $url == '' ) {
$url = "http://$host";
}
$url = "$url:$port/";
// TODO: use file_get_contents() instead of over complicate curl procedure
$header[] = 'Content-type: text/xml';
$header[] = 'Content-length: ' . strlen( $request );
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt( $ch, CURLOPT_TIMEOUT, 3 );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $header );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $request );
$data = curl_exec( $ch );
if ( ! curl_errno( $ch ) ) {
curl_close( $ch );
}
$ret = false;
if ( $data ) {
$ret = xmlrpc_decode( $data );
}
return $ret;
}
/**
* Following functions are not specific to money and could be useful in other
* helpers. However, they are not: they are currently only used in currency
* scripts, so I leave them here, hence the opensim_ prefix.
*/
function opensim_get_avatar_session( $agentID, &$deprecated = null ) {
global $OpenSimDB;
if ( ! opensim_isuuid( $agentID ) ) {
return null;
}
$result = $OpenSimDB->query( "SELECT RegionID,SessionID,SecureSessionID FROM Presence WHERE UserID='$agentID'" );
if ( $result ) {
list($RegionID, $SessionID, $SecureSessionID) = $result->fetch();
} else {
return array();
}
$av_session['regionID'] = $RegionID;
$av_session['sessionID'] = $SessionID;
$av_session['secureID'] = $SecureSessionID;
return $av_session;
}
function opensim_set_current_region( $agentID, $regionid, &$deprecated = null ) {
global $OpenSimDB;
if ( ! opensim_isuuid( $agentID ) or ! opensim_isuuid( $regionid ) ) {
return false;
}
$sql = "UPDATE Presence SET RegionID='$regionid' WHERE UserID='$agentID'";
$result = $OpenSimDB->query( $sql );
if ( ! $result ) {
return false;
}
return true;
}
function opensim_get_server_info( $userid, &$deprecated = null ) {
global $OpenSimDB;
if ( ! opensim_isuuid( $userid ) ) {
return array();
}
$result = $OpenSimDB->query(
"SELECT serverIP,serverHttpPort,serverURI,regionSecret
FROM GridUser INNER JOIN regions ON regions.uuid=GridUser.LastRegionID
WHERE GridUser.UserID='$userid'"
);
if ( $result ) {
list($serverip, $httpport, $serveruri, $secret) = $result->fetch();
} else {
return array();
}
$serverinfo['serverIP'] = $serverip;
$serverinfo['serverHttpPort'] = $httpport;
$serverinfo['serverURI'] = $serveruri;
$serverinfo['regionSecret'] = $secret;
return $serverinfo;
}
function opensim_check_secure_session( $agentID, $regionid, $secure, &$deprecated = null ) {
global $OpenSimDB;
if ( ! opensim_isuuid( $agentID ) or ! opensim_isuuid( $secure ) ) {
return false;
}
$sql = "SELECT UserID FROM Presence WHERE UserID='$agentID' AND SecureSessionID='$secure'";
if ( opensim_isuuid( $regionid ) ) {
$sql = $sql . " AND RegionID='$regionid'";
}
$result = $OpenSimDB->query( $sql );
if ( ! $result ) {
return false;
}
list($UUID) = $result->fetch();
if ( $UUID != $agentID ) {
return false;
}
return true;
}
function opensim_check_region_secret( $regionID, $secret, &$deprecated = null ) {
global $OpenSimDB;
if ( ! opensim_isuuid( $regionID ) ) {
return false;
}
$result = $OpenSimDB->prepareAndExecute(
'SELECT UUID FROM regions WHERE UUID=:uuid AND regionSecret=:regionSecret',
array(
'uuid' => $regionID,
'regionSecret' => $secret,
)
);
if ( $result ) {
list($UUID) = $result->fetch();
if ( $UUID == $regionID ) {
return true;
}
}
return false;
}

Some files were not shown because too many files have changed in this diff Show More