aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llinventory/llparcel.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llinventory/llparcel.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llinventory/llparcel.cpp')
-rw-r--r--linden/indra/llinventory/llparcel.cpp1832
1 files changed, 1832 insertions, 0 deletions
diff --git a/linden/indra/llinventory/llparcel.cpp b/linden/indra/llinventory/llparcel.cpp
new file mode 100644
index 0000000..9839e43
--- /dev/null
+++ b/linden/indra/llinventory/llparcel.cpp
@@ -0,0 +1,1832 @@
1/**
2 * @file llparcel.cpp
3 * @brief A land parcel.
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "linden_common.h"
29
30#include "indra_constants.h"
31#include <iostream>
32
33#include "llparcel.h"
34#include "llstreamtools.h"
35
36#include "llmath.h"
37#include "lltransactiontypes.h"
38#include "lltransactionflags.h"
39#include "message.h"
40#include "u64.h"
41
42static const F32 SOME_BIG_NUMBER = 1000.0f;
43static const F32 SOME_BIG_NEG_NUMBER = -1000.0f;
44static const char* PARCEL_OWNERSHIP_STATUS_STRING[LLParcel::OS_COUNT] =
45{
46 "leased",
47 "lease_pending",
48 "abandoned"
49};
50
51// NOTE: Adding parcel categories also requires updating:
52// * newview/app_settings/floater_directory.xml category combobox
53// * Web site "create event" tools
54static const char* PARCEL_CATEGORY_STRING[LLParcel::C_COUNT] =
55{
56 "none",
57 "linden",
58 "adult",
59 "arts",
60 "store", // "business" legacy name
61 "educational",
62 "game", // "gaming" legacy name
63 "gather", // "hangout" legacy name
64 "newcomer",
65 "park",
66 "home", // "residential" legacy name
67 "shopping",
68 "stage",
69 "other",
70};
71static const char* PARCEL_CATEGORY_UI_STRING[LLParcel::C_COUNT + 1] =
72{
73 "None",
74 "Linden Location",
75 "Adult",
76 "Arts & Culture",
77 "Business",
78 "Educational",
79 "Gaming",
80 "Hangout",
81 "Newcomer Friendly",
82 "Parks & Nature",
83 "Residential",
84 "Shopping",
85 "Stage",
86 "Other",
87 "Any", // valid string for parcel searches
88};
89
90static const char* PARCEL_ACTION_STRING[LLParcel::A_COUNT + 1] =
91{
92 "create",
93 "release",
94 "absorb",
95 "absorbed",
96 "divide",
97 "division",
98 "acquire",
99 "relinquish",
100 "confirm",
101 "unknown"
102};
103
104// Timeouts for parcels
105// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
106const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
107// ***** TESTING is 10 minutes
108//const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000);
109
110// group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000
111const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
112// ***** TESTING is 10 minutes
113//const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000);
114
115// default sale timeout is 2 days -> 172800000000
116const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
117// ***** TESTING is 10 minutes
118//const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000);
119
120// more grace period extensions.
121const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
122
123// if more than 100,000s before sale revert, and no extra extension
124// has been given, go ahead and extend it more. That's about 1.2 days.
125const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
126
127
128const char* ownership_status_to_string(LLParcel::EOwnershipStatus status);
129LLParcel::EOwnershipStatus ownership_string_to_status(const char* s);
130//const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action);
131//LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s);
132const char* category_to_string(LLParcel::ECategory category);
133const char* category_to_ui_string(LLParcel::ECategory category);
134LLParcel::ECategory category_string_to_category(const char* s);
135LLParcel::ECategory category_ui_string_to_category(const char* s);
136
137LLParcel::LLParcel()
138{
139 init(LLUUID::null, TRUE, FALSE, FALSE, 0, 0, 0, 0, 0, 1.f, 0);
140}
141
142
143LLParcel::LLParcel(const LLUUID &owner_id,
144 BOOL modify, BOOL terraform, BOOL damage,
145 time_t claim_date, S32 claim_price_per_meter,
146 S32 rent_price_per_meter, S32 area, S32 sim_object_limit, F32 parcel_object_bonus,
147 BOOL is_group_owned)
148{
149 init( owner_id, modify, terraform, damage, claim_date,
150 claim_price_per_meter, rent_price_per_meter, area, sim_object_limit, parcel_object_bonus,
151 is_group_owned);
152}
153
154
155// virtual
156LLParcel::~LLParcel()
157{
158 // user list cleaned up by LLDynamicArray destructor.
159}
160
161void LLParcel::init(const LLUUID &owner_id,
162 BOOL modify, BOOL terraform, BOOL damage,
163 time_t claim_date, S32 claim_price_per_meter,
164 S32 rent_price_per_meter, S32 area, S32 sim_object_limit, F32 parcel_object_bonus,
165 BOOL is_group_owned)
166{
167 mID.setNull();
168 mOwnerID = owner_id;
169 mGroupOwned = is_group_owned;
170 mClaimDate = claim_date;
171 mClaimPricePerMeter = claim_price_per_meter;
172 mRentPricePerMeter = rent_price_per_meter;
173 mArea = area;
174 mDiscountRate = 1.0f;
175 mDrawDistance = 512.f;
176
177 mUserLookAt.setVec(0.0f, 0.f, 0.f);
178 // Default to using the parcel's landing point, if any.
179 mLandingType = L_LANDING_POINT;
180
181 // *FIX: if owner_id != null, should be owned or sale pending,
182 // investigate init callers.
183 mStatus = OS_NONE;
184 mCategory = C_NONE;
185 mAuthBuyerID.setNull();
186 //mBuyerID.setNull();
187 //mJoinNeighbors = 0x0;
188 mSaleTimerExpires.setTimerExpirySec(0);
189 mSaleTimerExpires.stop();
190 mGraceExtension = 0;
191 //mExpireAction = STEA_REVERT;
192 mRecordTransaction = FALSE;
193
194 mAuctionID = 0;
195 mIsReservedForNewbie = FALSE;
196 mInEscrow = false;
197
198 mParcelFlags = PF_DEFAULT;
199 setParcelFlag(PF_CREATE_OBJECTS, modify);
200 setParcelFlag(PF_ALLOW_TERRAFORM, terraform);
201 setParcelFlag(PF_ALLOW_DAMAGE, damage);
202
203 mSalePrice = 10000;
204 setName(NULL);
205 setDesc(NULL);
206 setMusicURL(NULL);
207 setMediaURL(NULL);
208 mMediaID.setNull();
209 mMediaAutoScale = 0;
210
211 mGroupID.setNull();
212
213 mPassPrice = PARCEL_PASS_PRICE_DEFAULT;
214 mPassHours = PARCEL_PASS_HOURS_DEFAULT;
215
216 mAABBMin.setVec(SOME_BIG_NUMBER, SOME_BIG_NUMBER, SOME_BIG_NUMBER);
217 mAABBMax.setVec(SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER);
218
219 mLocalID = 0;
220
221 //mSimWidePrimCorrection = 0;
222 setMaxPrimCapacity((S32)(sim_object_limit * area / (F32)(REGION_WIDTH_METERS * REGION_WIDTH_METERS)));
223 setSimWideMaxPrimCapacity(0);
224 setSimWidePrimCount(0);
225 setOwnerPrimCount(0);
226 setGroupPrimCount(0);
227 setOtherPrimCount(0);
228 setSelectedPrimCount(0);
229 setTempPrimCount(0);
230 setCleanOtherTime(0);
231 setParcelPrimBonus(parcel_object_bonus);
232
233 setPreviousOwnerID(LLUUID::null);
234 setPreviouslyGroupOwned(FALSE);
235}
236
237void LLParcel::overrideOwner(const LLUUID& owner_id, BOOL is_group_owned)
238{
239 // Override with system permission (LLUUID::null)
240 // Overridden parcels have no group
241 mOwnerID = owner_id;
242 mGroupOwned = is_group_owned;
243 if(mGroupOwned)
244 {
245 mGroupID = mOwnerID;
246 }
247 else
248 {
249 mGroupID.setNull();
250 }
251 mInEscrow = false;
252}
253
254void LLParcel::overrideParcelFlags(U32 flags)
255{
256 mParcelFlags = flags;
257}
258
259void set_std_string(const char* src, std::string& dest)
260{
261 if(src)
262 {
263 dest.assign(src);
264 }
265 else
266 {
267#if (LL_LINUX && __GNUC__ < 3)
268 dest.assign(std::string(""));
269#else
270 dest.clear();
271#endif
272 }
273}
274
275void LLParcel::setName(const char* name)
276{
277 // The escaping here must match the escaping in the database
278 // abstraction layer.
279 set_std_string(name, mName);
280 LLStringFn::replace_nonprintable(mName, LL_UNKNOWN_CHAR);
281}
282
283void LLParcel::setDesc(const char* desc)
284{
285 // The escaping here must match the escaping in the database
286 // abstraction layer.
287 set_std_string(desc, mDesc);
288 mDesc = rawstr_to_utf8(mDesc);
289}
290
291void LLParcel::setMusicURL(const char* url)
292{
293 set_std_string(url, mMusicURL);
294
295 // The escaping here must match the escaping in the database
296 // abstraction layer.
297 // This should really filter the url in some way. Other than
298 // simply requiring non-printable.
299 LLStringFn::replace_nonprintable(mMusicURL, LL_UNKNOWN_CHAR);
300}
301
302void LLParcel::setMediaURL(const char* url)
303{
304 set_std_string(url, mMediaURL);
305
306 // The escaping here must match the escaping in the database
307 // abstraction layer if it's ever added.
308 // This should really filter the url in some way. Other than
309 // simply requiring non-printable.
310 LLStringFn::replace_nonprintable(mMediaURL, LL_UNKNOWN_CHAR);
311}
312
313// virtual
314void LLParcel::setLocalID(S32 local_id)
315{
316 mLocalID = local_id;
317}
318
319void LLParcel::setParcelFlag(U32 flag, BOOL b)
320{
321 if (b)
322 {
323 mParcelFlags |= flag;
324 }
325 else
326 {
327 mParcelFlags &= ~flag;
328 }
329}
330
331
332BOOL LLParcel::allowModifyBy(const LLUUID &agent_id, const LLUUID &group_id) const
333{
334 if (agent_id == LLUUID::null)
335 {
336 // system always can enter
337 return TRUE;
338 }
339 else if (isPublic())
340 {
341 return TRUE;
342 }
343 else if (agent_id == mOwnerID)
344 {
345 // owner can always perform operations
346 return TRUE;
347 }
348 else if (mParcelFlags & PF_CREATE_OBJECTS)
349 {
350 return TRUE;
351 }
352 else if ((mParcelFlags & PF_CREATE_GROUP_OBJECTS)
353 && group_id.notNull() )
354 {
355 return (getGroupID() == group_id);
356 }
357
358 return FALSE;
359}
360
361BOOL LLParcel::allowTerraformBy(const LLUUID &agent_id) const
362{
363 if (agent_id == LLUUID::null)
364 {
365 // system always can enter
366 return TRUE;
367 }
368 else if(OS_LEASED == mStatus)
369 {
370 if(agent_id == mOwnerID)
371 {
372 // owner can modify leased land
373 return TRUE;
374 }
375 else
376 {
377 // otherwise check other people
378 return mParcelFlags & PF_ALLOW_TERRAFORM;
379 }
380 }
381 else
382 {
383 return FALSE;
384 }
385}
386
387
388bool LLParcel::isAgentBlockedFromParcel(LLParcel* parcelp,
389 const LLUUID& agent_id,
390 const std::vector<LLUUID>& group_ids,
391 const BOOL is_agent_identified,
392 const BOOL is_agent_transacted)
393{
394 S32 current_group_access = parcelp->blockAccess(agent_id, LLUUID::null, is_agent_identified, is_agent_transacted);
395 S32 count;
396 bool is_allowed = (current_group_access == BA_ALLOWED) ? true: false;
397 LLUUID group_id;
398
399 count = group_ids.size();
400 for (int i = 0; i < count && !is_allowed; i++)
401 {
402 group_id = group_ids[i];
403 current_group_access = parcelp->blockAccess(agent_id, group_id, is_agent_identified, is_agent_transacted);
404
405 if (current_group_access == BA_ALLOWED) is_allowed = true;
406 }
407
408 return !is_allowed;
409}
410
411BOOL LLParcel::isAgentBanned(const LLUUID& agent_id) const
412{
413 // Test ban list
414 if (getParcelFlag(PF_USE_BAN_LIST)
415 && (mBanList.find(agent_id) != mBanList.end()))
416 {
417 return TRUE;
418 }
419
420 return FALSE;
421}
422S32 LLParcel::blockAccess(const LLUUID& agent_id, const LLUUID& group_id,
423 const BOOL is_agent_identified,
424 const BOOL is_agent_transacted) const
425{
426 // Test ban list
427 if (isAgentBanned(agent_id))
428 {
429 return BA_BANNED;
430 }
431
432 // Always allow owner on (unless he banned himself, useful for
433 // testing). We will also allow estate owners/managers in if they
434 // are not explicitly banned.
435 if (agent_id == mOwnerID)
436 {
437 return BA_ALLOWED;
438 }
439
440 // Special case when using pass list where group access is being restricted but not
441 // using access list. In this case group members are allowed only if they buy a pass.
442 // We return BA_NOT_IN_LIST if not in list
443 BOOL passWithGroup = getParcelFlag(PF_USE_PASS_LIST) && !getParcelFlag(PF_USE_ACCESS_LIST)
444 && getParcelFlag(PF_USE_ACCESS_GROUP) && !mGroupID.isNull() && group_id == mGroupID;
445
446
447 // Test group list
448 if (getParcelFlag(PF_USE_ACCESS_GROUP)
449 && !mGroupID.isNull()
450 && group_id == mGroupID
451 && !passWithGroup)
452 {
453 return BA_ALLOWED;
454 }
455
456 // Test access list
457 if (getParcelFlag(PF_USE_ACCESS_LIST) || passWithGroup )
458 {
459 if (mAccessList.find(agent_id) != mAccessList.end())
460 {
461 return BA_ALLOWED;
462 }
463
464 return BA_NOT_ON_LIST;
465 }
466
467 // If we're not doing any other limitations, all users
468 // can enter, unless
469 if ( !getParcelFlag(PF_USE_ACCESS_GROUP)
470 && !getParcelFlag(PF_USE_ACCESS_LIST))
471 {
472 //If the land is group owned, and you are in the group, bypass these checks
473 if(getIsGroupOwned() && group_id == mGroupID)
474 {
475 return BA_ALLOWED;
476 }
477
478 // Test for "payment" access levels
479 // Anonymous - No Payment Info on File
480 if(getParcelFlag(PF_DENY_ANONYMOUS) && !is_agent_identified && !is_agent_transacted)
481 {
482 return BA_NO_ACCESS_LEVEL;
483 }
484 // Identified - Payment Info on File
485 // Must check to make sure we're only banning Identified, since Transacted accounts
486 // also have their identified flag set
487 if(getParcelFlag(PF_DENY_IDENTIFIED) && is_agent_identified && !is_agent_transacted)
488 {
489 return BA_NO_ACCESS_LEVEL;
490 }
491 // Transacted - Payment Info Used
492 if(getParcelFlag(PF_DENY_TRANSACTED) && is_agent_transacted)
493 {
494 return BA_NO_ACCESS_LEVEL;
495 }
496 return BA_ALLOWED;
497 }
498
499 return BA_NOT_IN_GROUP;
500
501}
502
503
504void LLParcel::setArea(S32 area, S32 sim_object_limit)
505{
506 mArea = area;
507 setMaxPrimCapacity((S32)(sim_object_limit * area / (F32)(REGION_WIDTH_METERS * REGION_WIDTH_METERS)));
508}
509
510void LLParcel::setDiscountRate(F32 rate)
511{
512 // this is to make sure that the rate is at least sane - this is
513 // not intended to enforce economy rules. It only enfoces that the
514 // rate is a scaler between 0 and 1.
515 mDiscountRate = llclampf(rate);
516}
517
518
519//-----------------------------------------------------------
520// File input and output
521//-----------------------------------------------------------
522
523
524// WARNING: Area will be wrong until you calculate it.
525BOOL LLParcel::importStream(std::istream& input_stream)
526{
527 U32 setting;
528 S32 secs_until_revert = 0;
529
530 skip_to_end_of_next_keyword("{", input_stream);
531 if (!input_stream.good())
532 {
533 llwarns << "LLParcel::importStream() - bad input_stream" << llendl;
534 return FALSE;
535 }
536
537 while (input_stream.good())
538 {
539 skip_comments_and_emptyspace(input_stream);
540 LLString line, keyword, value;
541 get_line(line, input_stream, MAX_STRING);
542 get_keyword_and_value(keyword, value, line);
543
544 if ("}" == keyword)
545 {
546 break;
547 }
548 else if ("parcel_id" == keyword)
549 {
550 mID.set(value.c_str());
551 }
552 else if ("status" == keyword)
553 {
554 mStatus = ownership_string_to_status(value.c_str());
555 }
556 else if ("category" == keyword)
557 {
558 mCategory = category_string_to_category(value.c_str());
559 }
560 else if ("local_id" == keyword)
561 {
562 LLString::convertToS32(value, mLocalID);
563 }
564 else if ("name" == keyword)
565 {
566 setName( value.c_str() );
567 }
568 else if ("desc" == keyword)
569 {
570 setDesc( value.c_str() );
571 }
572 else if ("music_url" == keyword)
573 {
574 setMusicURL( value.c_str() );
575 }
576 else if ("media_url" == keyword)
577 {
578 setMediaURL( value.c_str() );
579 }
580 else if ("media_id" == keyword)
581 {
582 mMediaID.set( value.c_str() );
583 }
584 else if ("media_auto_scale" == keyword)
585 {
586 LLString::convertToU8(value, mMediaAutoScale);
587 }
588 else if ("owner_id" == keyword)
589 {
590 mOwnerID.set( value.c_str() );
591 }
592 else if ("group_owned" == keyword)
593 {
594 LLString::convertToBOOL(value, mGroupOwned);
595 }
596 else if ("clean_other_time" == keyword)
597 {
598 S32 time;
599 LLString::convertToS32(value, time);
600 setCleanOtherTime(time);
601 }
602 else if ("auth_buyer_id" == keyword)
603 {
604 mAuthBuyerID.set(value.c_str());
605 }
606 else if ("snapshot_id" == keyword)
607 {
608 mSnapshotID.set(value.c_str());
609 }
610 else if ("user_location" == keyword)
611 {
612 sscanf(value.c_str(), "%f %f %f",
613 &mUserLocation.mV[VX],
614 &mUserLocation.mV[VY],
615 &mUserLocation.mV[VZ]);
616 }
617 else if ("user_look_at" == keyword)
618 {
619 sscanf(value.c_str(), "%f %f %f",
620 &mUserLookAt.mV[VX],
621 &mUserLookAt.mV[VY],
622 &mUserLookAt.mV[VZ]);
623 }
624 else if ("landing_type" == keyword)
625 {
626 S32 landing_type = 0;
627 LLString::convertToS32(value, landing_type);
628 mLandingType = (ELandingType) landing_type;
629 }
630 else if ("join_neighbors" == keyword)
631 {
632 llinfos << "found deprecated keyword join_neighbors" << llendl;
633 }
634 else if ("revert_sale" == keyword)
635 {
636 LLString::convertToS32(value, secs_until_revert);
637 if (secs_until_revert > 0)
638 {
639 mSaleTimerExpires.start();
640 mSaleTimerExpires.setTimerExpirySec((F32)secs_until_revert);
641 }
642 }
643 else if("extended_grace" == keyword)
644 {
645 LLString::convertToS32(value, mGraceExtension);
646 }
647 else if ("user_list_type" == keyword)
648 {
649 // deprecated
650 }
651 else if("auction_id" == keyword)
652 {
653 LLString::convertToU32(value, mAuctionID);
654 }
655 else if("reserved_newbie" == keyword)
656 {
657 LLString::convertToBOOL(value, mIsReservedForNewbie);
658 }
659 else if ("allow_modify" == keyword)
660 {
661 LLString::convertToU32(value, setting);
662 setParcelFlag(PF_CREATE_OBJECTS, setting);
663 }
664 else if ("allow_group_modify" == keyword)
665 {
666 LLString::convertToU32(value, setting);
667 setParcelFlag(PF_CREATE_GROUP_OBJECTS, setting);
668 }
669 else if ("allow_all_object_entry" == keyword)
670 {
671 LLString::convertToU32(value, setting);
672 setParcelFlag(PF_ALLOW_ALL_OBJECT_ENTRY, setting);
673 }
674 else if ("allow_group_object_entry" == keyword)
675 {
676 LLString::convertToU32(value, setting);
677 setParcelFlag(PF_ALLOW_GROUP_OBJECT_ENTRY, setting);
678 }
679 else if ("allow_deed_to_group" == keyword)
680 {
681 LLString::convertToU32(value, setting);
682 setParcelFlag(PF_ALLOW_DEED_TO_GROUP, setting);
683 }
684 else if("contribute_with_deed" == keyword)
685 {
686 LLString::convertToU32(value, setting);
687 setParcelFlag(PF_CONTRIBUTE_WITH_DEED, setting);
688 }
689 else if ("allow_terraform" == keyword)
690 {
691 LLString::convertToU32(value, setting);
692 setParcelFlag(PF_ALLOW_TERRAFORM, setting);
693 }
694 else if ("allow_damage" == keyword)
695 {
696 LLString::convertToU32(value, setting);
697 setParcelFlag(PF_ALLOW_DAMAGE, setting);
698 }
699 else if ("allow_fly" == keyword)
700 {
701 LLString::convertToU32(value, setting);
702 setParcelFlag(PF_ALLOW_FLY, setting);
703 }
704 else if ("allow_landmark" == keyword)
705 {
706 LLString::convertToU32(value, setting);
707 setParcelFlag(PF_ALLOW_LANDMARK, setting);
708 }
709 else if ("sound_local" == keyword)
710 {
711 LLString::convertToU32(value, setting);
712 setParcelFlag(PF_SOUND_LOCAL, setting);
713 }
714 else if ("allow_group_scripts" == keyword)
715 {
716 LLString::convertToU32(value, setting);
717 setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, setting);
718 }
719 else if ("allow_scripts" == keyword)
720 {
721 LLString::convertToU32(value, setting);
722 setParcelFlag(PF_ALLOW_OTHER_SCRIPTS, setting);
723 }
724 else if ("for_sale" == keyword)
725 {
726 LLString::convertToU32(value, setting);
727 setParcelFlag(PF_FOR_SALE, setting);
728 }
729 else if ("sell_w_objects" == keyword)
730 {
731 LLString::convertToU32(value, setting);
732 setParcelFlag(PF_SELL_PARCEL_OBJECTS, setting);
733 }
734 else if ("use_pass_list" == keyword)
735 {
736 LLString::convertToU32(value, setting);
737 setParcelFlag(PF_USE_PASS_LIST, setting);
738 }
739 else if ("show_directory" == keyword)
740 {
741 LLString::convertToU32(value, setting);
742 setParcelFlag(PF_SHOW_DIRECTORY, setting);
743 }
744 else if ("allow_publish" == keyword)
745 {
746 LLString::convertToU32(value, setting);
747 setParcelFlag(PF_ALLOW_PUBLISH, setting);
748 }
749 else if ("mature_publish" == keyword)
750 {
751 LLString::convertToU32(value, setting);
752 setParcelFlag(PF_MATURE_PUBLISH, setting);
753 }
754 else if ("claim_date" == keyword)
755 {
756 // BUG: This will fail when time rolls over in 2038.
757 S32 time;
758 LLString::convertToS32(value, time);
759 mClaimDate = time;
760 }
761 else if ("claim_price" == keyword)
762 {
763 LLString::convertToS32(value, mClaimPricePerMeter);
764 }
765 else if ("rent_price" == keyword)
766 {
767 LLString::convertToS32(value, mRentPricePerMeter);
768 }
769 else if ("discount_rate" == keyword)
770 {
771 LLString::convertToF32(value, mDiscountRate);
772 }
773 else if ("draw_distance" == keyword)
774 {
775 LLString::convertToF32(value, mDrawDistance);
776 }
777 else if ("sale_price" == keyword)
778 {
779 LLString::convertToS32(value, mSalePrice);
780 }
781 else if ("pass_price" == keyword)
782 {
783 LLString::convertToS32(value, mPassPrice);
784 }
785 else if ("pass_hours" == keyword)
786 {
787 LLString::convertToF32(value, mPassHours);
788 }
789 else if ("box" == keyword)
790 {
791 // deprecated
792 }
793 else if ("aabb_min" == keyword)
794 {
795 sscanf(value.c_str(), "%f %f %f",
796 &mAABBMin.mV[VX], &mAABBMin.mV[VY], &mAABBMin.mV[VZ]);
797 }
798 else if ("use_access_group" == keyword)
799 {
800 LLString::convertToU32(value, setting);
801 setParcelFlag(PF_USE_ACCESS_GROUP, setting);
802 }
803 else if ("use_access_list" == keyword)
804 {
805 LLString::convertToU32(value, setting);
806 setParcelFlag(PF_USE_ACCESS_LIST, setting);
807 }
808 else if ("use_ban_list" == keyword)
809 {
810 LLString::convertToU32(value, setting);
811 setParcelFlag(PF_USE_BAN_LIST, setting);
812 }
813 else if ("group_name" == keyword)
814 {
815 llinfos << "found deprecated keyword group_name" << llendl;
816 }
817 else if ("group_id" == keyword)
818 {
819 mGroupID.set( value.c_str() );
820 }
821 // TODO: DEPRECATED FLAG
822 // Flag removed from simstate files in 1.11.1
823 // Remove at some point where we have guarenteed this flag
824 // no longer exists anywhere in simstate files.
825 else if ("require_identified" == keyword)
826 {
827 LLString::convertToU32(value, setting);
828 setParcelFlag(PF_DENY_ANONYMOUS, setting);
829 }
830 // TODO: DEPRECATED FLAG
831 // Flag removed from simstate files in 1.11.1
832 // Remove at some point where we have guarenteed this flag
833 // no longer exists anywhere in simstate files.
834 else if ("require_transacted" == keyword)
835 {
836 LLString::convertToU32(value, setting);
837 setParcelFlag(PF_DENY_ANONYMOUS, setting);
838 setParcelFlag(PF_DENY_IDENTIFIED, setting);
839 }
840 else if ("restrict_pushobject" == keyword)
841 {
842 LLString::convertToU32(value, setting);
843 setParcelFlag(PF_RESTRICT_PUSHOBJECT, setting);
844 }
845 else if ("deny_anonymous" == keyword)
846 {
847 LLString::convertToU32(value, setting);
848 setParcelFlag(PF_DENY_ANONYMOUS, setting);
849 }
850 else if ("deny_identified" == keyword)
851 {
852 LLString::convertToU32(value, setting);
853 setParcelFlag(PF_DENY_IDENTIFIED, setting);
854 }
855 else if ("deny_transacted" == keyword)
856 {
857 LLString::convertToU32(value, setting);
858 setParcelFlag(PF_DENY_TRANSACTED, setting);
859 }
860 else if ("access_list" == keyword)
861 {
862 S32 entry_count = 0;
863 LLString::convertToS32(value, entry_count);
864 for (S32 i = 0; i < entry_count; i++)
865 {
866 LLAccessEntry entry;
867 if (importAccessEntry(input_stream, &entry))
868 {
869 mAccessList[entry.mID] = entry;
870 }
871 }
872 }
873 else if ("ban_list" == keyword)
874 {
875 S32 entry_count = 0;
876 LLString::convertToS32(value, entry_count);
877 for (S32 i = 0; i < entry_count; i++)
878 {
879 LLAccessEntry entry;
880 if (importAccessEntry(input_stream, &entry))
881 {
882 mBanList[entry.mID] = entry;
883 }
884 }
885 }
886 else if ("renter_list" == keyword)
887 {
888 /*
889 S32 entry_count = 0;
890 LLString::convertToS32(value, entry_count);
891 for (S32 i = 0; i < entry_count; i++)
892 {
893 LLAccessEntry entry;
894 if (importAccessEntry(input_stream, &entry))
895 {
896 mRenterList.put(entry);
897 }
898 }*/
899 }
900 else if ("pass_list" == keyword)
901 {
902 // legacy - put into access list
903 S32 entry_count = 0;
904 LLString::convertToS32(value, entry_count);
905 for (S32 i = 0; i < entry_count; i++)
906 {
907 LLAccessEntry entry;
908 if (importAccessEntry(input_stream, &entry))
909 {
910 mAccessList[entry.mID] = entry;
911 }
912 }
913 }
914
915 else
916 {
917 llwarns << "Unknown keyword in parcel section: <"
918 << keyword << ">" << llendl;
919 }
920 }
921
922 // this code block detects if we have loaded a 1.1 simstate file,
923 // and follows the conversion rules specified in
924 // design_docs/land/pay_for_parcel.txt.
925 F32 time_to_expire = 0.0f;
926 if(mID.isNull())
927 {
928 mID.generate();
929 mStatus = OS_LEASE_PENDING;
930 //mBuyerID = mOwnerID;
931 if(getIsGroupOwned())
932 {
933 time_to_expire += GROUP_USEC_CONVERSION_TIMEOUT / SEC_TO_MICROSEC;
934 }
935 else
936 {
937 time_to_expire += DEFAULT_USEC_CONVERSION_TIMEOUT / SEC_TO_MICROSEC;
938 }
939 //mExpireAction = STEA_PUBLIC;
940 mRecordTransaction = TRUE;
941 }
942
943 // this code block deals with giving an extension to pending
944 // parcels to the midday of 2004-01-19 if they were originally set
945 // for some time on 2004-01-12.
946 if((0 == mGraceExtension)
947 && (EXTEND_GRACE_IF_MORE_THAN_SEC < secs_until_revert))
948 {
949 const S32 NEW_CONVERSION_DATE = 1074538800; // 2004-01-19T11:00:00
950 time_t now = time(NULL); // now in epoch
951 secs_until_revert = (S32)(NEW_CONVERSION_DATE - now);
952 time_to_expire = (F32)secs_until_revert;
953 mGraceExtension = 1;
954 }
955
956 // This code block adds yet another week to the deadline. :(
957 if(1 == mGraceExtension)
958 {
959 time_to_expire += SEVEN_DAYS_IN_USEC / SEC_TO_MICROSEC;
960 mGraceExtension = 2;
961 }
962
963 if (time_to_expire > 0)
964 {
965 mSaleTimerExpires.setTimerExpirySec(time_to_expire);
966 mSaleTimerExpires.start();
967 }
968
969 // successful import
970 return TRUE;
971}
972
973
974BOOL LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entry)
975{
976 skip_to_end_of_next_keyword("{", input_stream);
977 while (input_stream.good())
978 {
979 skip_comments_and_emptyspace(input_stream);
980 LLString line, keyword, value;
981 get_line(line, input_stream, MAX_STRING);
982 get_keyword_and_value(keyword, value, line);
983
984 if ("}" == keyword)
985 {
986 break;
987 }
988 else if ("id" == keyword)
989 {
990 entry->mID.set( value.c_str() );
991 }
992 else if ("name" == keyword)
993 {
994 // deprecated
995 }
996 else if ("time" == keyword)
997 {
998 S32 when;
999 LLString::convertToS32(value, when);
1000 entry->mTime = when;
1001 }
1002 else if ("flags" == keyword)
1003 {
1004 U32 setting;
1005 LLString::convertToU32(value, setting);
1006 entry->mFlags = setting;
1007 }
1008 else
1009 {
1010 llwarns << "Unknown keyword in parcel access entry section: <"
1011 << keyword << ">" << llendl;
1012 }
1013 }
1014 return input_stream.good();
1015}
1016
1017BOOL LLParcel::exportStream(std::ostream& output_stream)
1018{
1019 S32 setting;
1020 char id_string[MAX_STRING];
1021
1022 std::ios::fmtflags old_flags = output_stream.flags();
1023 output_stream.setf(std::ios::showpoint);
1024 output_stream << "\t{\n";
1025
1026 mID.toString(id_string);
1027 output_stream << "\t\t parcel_id " << id_string << "\n";
1028 output_stream << "\t\t status " << ownership_status_to_string(mStatus) << "\n";
1029 output_stream << "\t\t category " << category_to_string(mCategory) << "\n";
1030
1031 output_stream << "\t\t local_id " << mLocalID << "\n";
1032
1033 const char* name = (mName.empty() ? "" : mName.c_str() );
1034 output_stream << "\t\t name " << name << "\n";
1035
1036 const char* desc = (mDesc.empty() ? "" : mDesc.c_str() );
1037 output_stream << "\t\t desc " << desc << "\n";
1038
1039 const char* music_url = (mMusicURL.empty() ? "" : mMusicURL.c_str() );
1040 output_stream << "\t\t music_url " << music_url << "\n";
1041
1042 const char* media_url = (mMediaURL.empty() ? "" : mMediaURL.c_str() );
1043 output_stream << "\t\t media_url " << media_url << "\n";
1044
1045 output_stream << "\t\t media_auto_scale " << (mMediaAutoScale ? 1 : 0) << "\n";
1046
1047 mMediaID.toString(id_string);
1048 output_stream << "\t\t media_id " << id_string << "\n";
1049
1050 mOwnerID.toString(id_string);
1051 output_stream << "\t\t owner_id " << id_string << "\n";
1052 output_stream << "\t\t group_owned " << (mGroupOwned ? 1 : 0) << "\n";
1053 output_stream << "\t\t clean_other_time " << getCleanOtherTime() << "\n";
1054
1055 if(!mAuthBuyerID.isNull())
1056 {
1057 mAuthBuyerID.toString(id_string);
1058 output_stream << "\t\t auth_buyer_id " << id_string << "\n";
1059 }
1060 if (!mSnapshotID.isNull())
1061 {
1062 mSnapshotID.toString(id_string);
1063 output_stream << "\t\t snapshot_id " << id_string << "\n";
1064 }
1065 if (!mUserLocation.isExactlyZero())
1066 {
1067 output_stream << "\t\t user_location "
1068 << (F64)mUserLocation.mV[VX]
1069 << " " << (F64)mUserLocation.mV[VY]
1070 << " " << (F64)mUserLocation.mV[VZ] << "\n";
1071 output_stream << "\t\t user_look_at "
1072 << (F64)mUserLookAt.mV[VX]
1073 << " " << (F64)mUserLookAt.mV[VY]
1074 << " " << (F64)mUserLookAt.mV[VZ] << "\n";
1075 }
1076 output_stream << "\t\t landing_type " << mLandingType << "\n";
1077 //if(mJoinNeighbors)
1078 //{
1079 // output_stream << "\t\t join_neighbors " << mJoinNeighbors << "\n";
1080 //}
1081 if(mSaleTimerExpires.getStarted())
1082 {
1083 S32 dt_sec = (S32) mSaleTimerExpires.getRemainingTimeF32()+60; // Add a minute to prevent race conditions
1084 output_stream << "\t\t revert_sale " << dt_sec << "\n";
1085 //output_stream << "\t\t revert_action " << revert_action_to_string(mExpireAction) << "\n";
1086 output_stream << "\t\t extended_grace " << mGraceExtension << "\n";
1087 }
1088
1089 if(0 != mAuctionID)
1090 {
1091 output_stream << "\t\t auction_id " << mAuctionID << "\n";
1092 }
1093 if(mIsReservedForNewbie)
1094 {
1095 output_stream << "\t\t reserved_newbie " << mIsReservedForNewbie << "\n";
1096 }
1097
1098 output_stream << "\t\t allow_modify " << getAllowModify() << "\n";
1099 output_stream << "\t\t allow_group_modify " << getAllowGroupModify() << "\n";
1100 output_stream << "\t\t allow_all_object_entry " << getAllowAllObjectEntry() << "\n";
1101 output_stream << "\t\t allow_group_object_entry " << getAllowGroupObjectEntry() << "\n";
1102 output_stream << "\t\t allow_terraform " << getAllowTerraform() << "\n";
1103 output_stream << "\t\t allow_deed_to_group " << getAllowDeedToGroup() << "\n";
1104 output_stream << "\t\t contribute_with_deed " << getContributeWithDeed() << "\n";
1105 output_stream << "\t\t allow_damage " << getAllowDamage() << "\n";
1106 output_stream << "\t\t claim_date " << (S32)mClaimDate << "\n";
1107 output_stream << "\t\t claim_price " << mClaimPricePerMeter << "\n";
1108 output_stream << "\t\t rent_price " << mRentPricePerMeter << "\n";
1109 output_stream << "\t\t discount_rate " << mDiscountRate << "\n";
1110 output_stream << "\t\t allow_fly " << (getAllowFly() ? 1 : 0) << "\n";
1111 output_stream << "\t\t allow_landmark " << (getAllowLandmark() ? 1 : 0) << "\n";
1112 output_stream << "\t\t sound_local " << (getSoundLocal() ? 1 : 0) << "\n";
1113 output_stream << "\t\t allow_scripts " << (getAllowOtherScripts() ? 1 : 0) << "\n";
1114 output_stream << "\t\t allow_group_scripts " << (getAllowGroupScripts() ? 1 : 0) << "\n";
1115 output_stream << "\t\t for_sale " << (getForSale() ? 1 : 0) << "\n";
1116 output_stream << "\t\t sell_w_objects " << (getSellWithObjects() ? 1 : 0) << "\n";
1117 output_stream << "\t\t draw_distance " << mDrawDistance << "\n";
1118 output_stream << "\t\t sale_price " << mSalePrice << "\n";
1119
1120 setting = (getParcelFlag(PF_USE_ACCESS_GROUP) ? 1 : 0);
1121 output_stream << "\t\t use_access_group " << setting << "\n";
1122
1123 setting = (getParcelFlag(PF_USE_ACCESS_LIST) ? 1 : 0);
1124 output_stream << "\t\t use_access_list " << setting << "\n";
1125
1126 setting = (getParcelFlag(PF_USE_BAN_LIST) ? 1 : 0);
1127 output_stream << "\t\t use_ban_list " << setting << "\n";
1128
1129 mGroupID.toString(id_string);
1130 output_stream << "\t\t group_id " << id_string << "\n";
1131
1132 //const char* group_name
1133 // = (mGroupName.isEmpty() ? "" : mGroupName.c_str() );
1134 //output_stream << "\t\t group_name " << group_name << "\n";
1135
1136 setting = (getParcelFlag(PF_USE_PASS_LIST) ? 1 : 0);
1137 output_stream << "\t\t use_pass_list " << setting << "\n";
1138
1139 output_stream << "\t\t pass_price " << mPassPrice << "\n";
1140 output_stream << "\t\t pass_hours " << mPassHours << "\n";
1141
1142 setting = (getParcelFlag(PF_SHOW_DIRECTORY) ? 1 : 0);
1143 output_stream << "\t\t show_directory " << setting << "\n";
1144
1145 setting = (getParcelFlag(PF_ALLOW_PUBLISH) ? 1 : 0);
1146 output_stream << "\t\t allow_publish " << setting << "\n";
1147
1148 setting = (getParcelFlag(PF_MATURE_PUBLISH) ? 1 : 0);
1149 output_stream << "\t\t mature_publish " << setting << "\n";
1150
1151 setting = (getParcelFlag(PF_DENY_ANONYMOUS) ? 1 : 0);
1152 output_stream << "\t\t deny_anonymous " << setting << "\n";
1153
1154 setting = (getParcelFlag(PF_DENY_IDENTIFIED) ? 1 : 0);
1155 output_stream << "\t\t deny_identified " << setting << "\n";
1156
1157 setting = (getParcelFlag(PF_DENY_TRANSACTED) ? 1 : 0);
1158 output_stream << "\t\t deny_transacted " << setting << "\n";
1159
1160 setting = (getParcelFlag(PF_RESTRICT_PUSHOBJECT) ? 1 : 0);
1161 output_stream << "\t\t restrict_pushobject " << setting << "\n";
1162
1163 output_stream << "\t\t aabb_min "
1164 << mAABBMin.mV[VX]
1165 << " " << mAABBMin.mV[VY]
1166 << " " << mAABBMin.mV[VZ] << "\n";
1167
1168 if (!mAccessList.empty())
1169 {
1170 output_stream << "\t\t access_list " << mAccessList.size() << "\n";
1171 access_map_const_iterator cit = mAccessList.begin();
1172 access_map_const_iterator end = mAccessList.end();
1173
1174 for ( ; cit != end; ++cit)
1175 {
1176 output_stream << "\t\t{\n";
1177 const LLAccessEntry& entry = (*cit).second;
1178 entry.mID.toString(id_string);
1179 output_stream << "\t\t\tid " << id_string << "\n";
1180 output_stream << "\t\t\ttime " << entry.mTime << "\n";
1181 output_stream << "\t\t\tflags " << entry.mFlags << "\n";
1182 output_stream << "\t\t}\n";
1183 }
1184 }
1185
1186 if (!mBanList.empty())
1187 {
1188 output_stream << "\t\t ban_list " << mBanList.size() << "\n";
1189 access_map_const_iterator cit = mBanList.begin();
1190 access_map_const_iterator end = mBanList.end();
1191
1192 for ( ; cit != end; ++cit)
1193 {
1194 output_stream << "\t\t{\n";
1195 const LLAccessEntry& entry = (*cit).second;
1196 entry.mID.toString(id_string);
1197 output_stream << "\t\t\tid " << id_string << "\n";
1198 output_stream << "\t\t\ttime " << entry.mTime << "\n";
1199 output_stream << "\t\t\tflags " << entry.mFlags << "\n";
1200 output_stream << "\t\t}\n";
1201 }
1202 }
1203
1204 /*if (mRenterList.count() > 0)
1205 {
1206 output_stream << "\t\t renter_list " << mRenterList.count() << "\n";
1207 for (i = 0; i < mRenterList.count(); i++)
1208 {
1209 output_stream << "\t\t{\n";
1210 const LLAccessEntry& entry = mRenterList.get(i);
1211 entry.mID.toString(id_string);
1212 output_stream << "\t\t\tid " << id_string << "\n";
1213 output_stream << "\t\t\ttime " << entry.mTime << "\n";
1214 output_stream << "\t\t\tflags " << entry.mFlags << "\n";
1215 output_stream << "\t\t}\n";
1216 }
1217 }*/
1218
1219 output_stream << "\t}\n";
1220 output_stream.flags(old_flags);
1221
1222 return TRUE;
1223}
1224
1225
1226// Assumes we are in a block "ParcelData"
1227void LLParcel::packMessage(LLMessageSystem* msg)
1228{
1229 msg->addU32Fast( _PREHASH_ParcelFlags, getParcelFlags() );
1230 msg->addS32Fast( _PREHASH_SalePrice, getSalePrice() );
1231 msg->addStringFast( _PREHASH_Name, getName() );
1232 msg->addStringFast( _PREHASH_Desc, getDesc() );
1233 msg->addStringFast( _PREHASH_MusicURL, getMusicURL() );
1234 msg->addStringFast( _PREHASH_MediaURL, getMediaURL() );
1235 msg->addU8 ( "MediaAutoScale", getMediaAutoScale () );
1236 msg->addUUIDFast( _PREHASH_MediaID, getMediaID() );
1237 msg->addUUIDFast( _PREHASH_GroupID, getGroupID() );
1238 msg->addS32Fast( _PREHASH_PassPrice, mPassPrice );
1239 msg->addF32Fast( _PREHASH_PassHours, mPassHours );
1240 msg->addU8Fast( _PREHASH_Category, (U8)mCategory);
1241 msg->addUUIDFast( _PREHASH_AuthBuyerID, mAuthBuyerID);
1242 msg->addUUIDFast( _PREHASH_SnapshotID, mSnapshotID);
1243 msg->addVector3Fast(_PREHASH_UserLocation, mUserLocation);
1244 msg->addVector3Fast(_PREHASH_UserLookAt, mUserLookAt);
1245 msg->addU8Fast( _PREHASH_LandingType, (U8)mLandingType);
1246}
1247
1248
1249void LLParcel::unpackMessage(LLMessageSystem* msg)
1250{
1251 char buffer[256];
1252
1253 msg->getU32Fast( _PREHASH_ParcelData,_PREHASH_ParcelFlags, mParcelFlags );
1254 msg->getS32Fast( _PREHASH_ParcelData,_PREHASH_SalePrice, mSalePrice );
1255 msg->getStringFast( _PREHASH_ParcelData,_PREHASH_Name, 256, buffer );
1256 setName(buffer);
1257 msg->getStringFast( _PREHASH_ParcelData,_PREHASH_Desc, 256, buffer );
1258 setDesc(buffer);
1259 msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MusicURL, 256, buffer );
1260 setMusicURL(buffer);
1261 msg->getStringFast( _PREHASH_ParcelData,_PREHASH_MediaURL, 256, buffer );
1262 setMediaURL(buffer);
1263
1264 // non-optimized version
1265 msg->getU8 ( "ParcelData", "MediaAutoScale", mMediaAutoScale );
1266
1267 msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_MediaID, mMediaID );
1268 msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_GroupID, mGroupID );
1269 msg->getS32Fast( _PREHASH_ParcelData,_PREHASH_PassPrice, mPassPrice );
1270 msg->getF32Fast( _PREHASH_ParcelData,_PREHASH_PassHours, mPassHours );
1271 U8 category;
1272 msg->getU8Fast( _PREHASH_ParcelData,_PREHASH_Category, category);
1273 mCategory = (ECategory)category;
1274 msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_AuthBuyerID, mAuthBuyerID);
1275 msg->getUUIDFast( _PREHASH_ParcelData,_PREHASH_SnapshotID, mSnapshotID);
1276 msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLocation, mUserLocation);
1277 msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLookAt, mUserLookAt);
1278 U8 landing_type;
1279 msg->getU8Fast( _PREHASH_ParcelData,_PREHASH_LandingType, landing_type);
1280 mLandingType = (ELandingType)landing_type;
1281}
1282
1283
1284void LLParcel::packAccessEntries(LLMessageSystem* msg,
1285 const std::map<LLUUID,LLAccessEntry>& list)
1286{
1287 access_map_const_iterator cit = list.begin();
1288 access_map_const_iterator end = list.end();
1289
1290 if (cit == end)
1291 {
1292 msg->nextBlockFast(_PREHASH_List);
1293 msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
1294 msg->addS32Fast(_PREHASH_Time, 0 );
1295 msg->addU32Fast(_PREHASH_Flags, 0 );
1296 return;
1297 }
1298
1299 for ( ; cit != end; ++cit)
1300 {
1301 const LLAccessEntry& entry = (*cit).second;
1302
1303 msg->nextBlockFast(_PREHASH_List);
1304 msg->addUUIDFast(_PREHASH_ID, entry.mID );
1305 msg->addS32Fast(_PREHASH_Time, entry.mTime );
1306 msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
1307 }
1308}
1309
1310
1311void LLParcel::unpackAccessEntries(LLMessageSystem* msg,
1312 std::map<LLUUID,LLAccessEntry>* list)
1313{
1314 LLUUID id;
1315 S32 time;
1316 U32 flags;
1317
1318 S32 i;
1319 S32 count = msg->getNumberOfBlocksFast(_PREHASH_List);
1320 for (i = 0; i < count; i++)
1321 {
1322 msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i);
1323 msg->getS32Fast( _PREHASH_List, _PREHASH_Time, time, i);
1324 msg->getU32Fast( _PREHASH_List, _PREHASH_Flags, flags, i);
1325
1326 if (id.notNull())
1327 {
1328 LLAccessEntry entry;
1329 entry.mID = id;
1330 entry.mTime = time;
1331 entry.mFlags = flags;
1332
1333 (*list)[entry.mID] = entry;
1334 }
1335 }
1336}
1337
1338
1339void LLParcel::expirePasses(S32 now)
1340{
1341 access_map_iterator itor = mAccessList.begin();
1342 while (itor != mAccessList.end())
1343 {
1344 const LLAccessEntry& entry = (*itor).second;
1345
1346 if (entry.mTime != 0 && entry.mTime < now)
1347 {
1348 mAccessList.erase(itor++);
1349 }
1350 else
1351 {
1352 ++itor;
1353 }
1354 }
1355}
1356
1357
1358bool LLParcel::operator==(const LLParcel &rhs) const
1359{
1360 if (mOwnerID != rhs.mOwnerID)
1361 return FALSE;
1362
1363 if (mParcelFlags != rhs.mParcelFlags)
1364 return FALSE;
1365
1366 if (mClaimDate != rhs.mClaimDate)
1367 return FALSE;
1368
1369 if (mClaimPricePerMeter != rhs.mClaimPricePerMeter)
1370 return FALSE;
1371
1372 if (mRentPricePerMeter != rhs.mRentPricePerMeter)
1373 return FALSE;
1374
1375 return TRUE;
1376}
1377
1378// Calculate rent
1379S32 LLParcel::getTotalRent() const
1380{
1381 return (S32)floor(0.5f + (F32)mArea * (F32)mRentPricePerMeter * (1.0f - mDiscountRate));
1382}
1383
1384F32 LLParcel::getAdjustedRentPerMeter() const
1385{
1386 return ((F32)mRentPricePerMeter * (1.0f - mDiscountRate));
1387}
1388
1389LLVector3 LLParcel::getCenterpoint() const
1390{
1391 LLVector3 rv;
1392 rv.mV[VX] = (getAABBMin().mV[VX] + getAABBMax().mV[VX]) * 0.5f;
1393 rv.mV[VY] = (getAABBMin().mV[VY] + getAABBMax().mV[VY]) * 0.5f;
1394 rv.mV[VZ] = 0.0f;
1395 return rv;
1396}
1397
1398void LLParcel::extendAABB(const LLVector3& box_min, const LLVector3& box_max)
1399{
1400 // Patch up min corner of AABB
1401 S32 i;
1402 for (i=0; i<3; i++)
1403 {
1404 if (box_min.mV[i] < mAABBMin.mV[i])
1405 {
1406 mAABBMin.mV[i] = box_min.mV[i];
1407 }
1408 }
1409
1410 // Patch up max corner of AABB
1411 for (i=0; i<3; i++)
1412 {
1413 if (box_max.mV[i] > mAABBMax.mV[i])
1414 {
1415 mAABBMax.mV[i] = box_max.mV[i];
1416 }
1417 }
1418}
1419
1420BOOL LLParcel::addToAccessList(const LLUUID& agent_id, S32 time)
1421{
1422 if (!((mParcelFlags & PF_USE_ACCESS_LIST) || (mParcelFlags & PF_USE_PASS_LIST))
1423 || mAccessList.size() >= (U32) PARCEL_MAX_ACCESS_LIST)
1424 {
1425 // Not using access list, so not a rational thing to do
1426 return FALSE;
1427 }
1428 if (agent_id == getOwnerID())
1429 {
1430 // Can't add owner to these lists
1431 return FALSE;
1432 }
1433 access_map_iterator itor = mAccessList.begin();
1434 while (itor != mAccessList.end())
1435 {
1436 const LLAccessEntry& entry = (*itor).second;
1437 if (entry.mID == agent_id)
1438 {
1439 if (time == 0 || (entry.mTime != 0 && entry.mTime < time))
1440 {
1441 mAccessList.erase(itor++);
1442 }
1443 else
1444 {
1445 // existing one expires later
1446 return FALSE;
1447 }
1448 }
1449 else
1450 {
1451 ++itor;
1452 }
1453 }
1454
1455 removeFromBanList(agent_id);
1456
1457 LLAccessEntry new_entry;
1458 new_entry.mID = agent_id;
1459 new_entry.mTime = time;
1460 new_entry.mFlags = 0x0;
1461 mAccessList[new_entry.mID] = new_entry;
1462 return TRUE;
1463}
1464
1465BOOL LLParcel::addToBanList(const LLUUID& agent_id, S32 time)
1466{
1467 if (!(mParcelFlags & PF_USE_BAN_LIST)
1468 || mBanList.size() >= (U32) PARCEL_MAX_ACCESS_LIST)
1469 {
1470 // Not using ban list, so not a rational thing to do
1471 return FALSE;
1472 }
1473 if (agent_id == getOwnerID())
1474 {
1475 // Can't add owner to these lists
1476 return FALSE;
1477 }
1478
1479 access_map_iterator itor = mBanList.begin();
1480 while (itor != mBanList.end())
1481 {
1482 const LLAccessEntry& entry = (*itor).second;
1483 if (entry.mID == agent_id)
1484 {
1485 if (time == 0 || (entry.mTime != 0 && entry.mTime < time))
1486 {
1487 mBanList.erase(itor++);
1488 }
1489 else
1490 {
1491 // existing one expires later
1492 return FALSE;
1493 }
1494 }
1495 else
1496 {
1497 ++itor;
1498 }
1499 }
1500
1501 removeFromAccessList(agent_id);
1502
1503 LLAccessEntry new_entry;
1504 new_entry.mID = agent_id;
1505 new_entry.mTime = time;
1506 new_entry.mFlags = 0x0;
1507 mBanList[new_entry.mID] = new_entry;
1508 return TRUE;
1509}
1510
1511BOOL remove_from_access_array(std::map<LLUUID,LLAccessEntry>* list,
1512 const LLUUID& agent_id)
1513{
1514 BOOL removed = FALSE;
1515 access_map_iterator itor = list->begin();
1516 while (itor != list->end())
1517 {
1518 const LLAccessEntry& entry = (*itor).second;
1519 if (entry.mID == agent_id)
1520 {
1521 list->erase(itor++);
1522 removed = TRUE;
1523 }
1524 else
1525 {
1526 ++itor;
1527 }
1528 }
1529 return removed;
1530}
1531
1532BOOL LLParcel::removeFromAccessList(const LLUUID& agent_id)
1533{
1534 return remove_from_access_array(&mAccessList, agent_id);
1535}
1536
1537BOOL LLParcel::removeFromBanList(const LLUUID& agent_id)
1538{
1539 return remove_from_access_array(&mBanList, agent_id);
1540}
1541
1542// static
1543const char* LLParcel::getOwnershipStatusString(EOwnershipStatus status)
1544{
1545 return ownership_status_to_string(status);
1546}
1547
1548// static
1549const char* LLParcel::getCategoryString(ECategory category)
1550{
1551 return category_to_string(category);
1552}
1553
1554// static
1555const char* LLParcel::getCategoryUIString(ECategory category)
1556{
1557 return category_to_ui_string(category);
1558}
1559
1560// static
1561LLParcel::ECategory LLParcel::getCategoryFromString(const char* string)
1562{
1563 return category_string_to_category(string);
1564}
1565
1566// static
1567LLParcel::ECategory LLParcel::getCategoryFromUIString(const char* string)
1568{
1569 return category_ui_string_to_category(string);
1570}
1571
1572// static
1573const char* LLParcel::getActionString(LLParcel::EAction action)
1574{
1575 S32 index = 0;
1576 if((action >= 0) && (action < LLParcel::A_COUNT))
1577 {
1578 index = action;
1579 }
1580 else
1581 {
1582 index = A_COUNT;
1583 }
1584 return PARCEL_ACTION_STRING[index];
1585}
1586
1587BOOL LLParcel::isSaleTimerExpired(const U64& time)
1588{
1589 if (mSaleTimerExpires.getStarted() == FALSE)
1590 {
1591 return FALSE;
1592 }
1593 BOOL expired = mSaleTimerExpires.checkExpirationAndReset(0.0);
1594 if (expired)
1595 {
1596 mSaleTimerExpires.stop();
1597 }
1598 return expired;
1599}
1600
1601
1602void LLParcel::startSale(const LLUUID& buyer_id, BOOL is_buyer_group)
1603{
1604 // TODO -- this and all Sale related methods need to move out of the LLParcel
1605 // base class and into server-side-only LLSimParcel class
1606 setPreviousOwnerID(mOwnerID);
1607 setPreviouslyGroupOwned(mGroupOwned);
1608
1609 mOwnerID = buyer_id;
1610 mGroupOwned = is_buyer_group;
1611 if(mGroupOwned)
1612 {
1613 mGroupID = mOwnerID;
1614 }
1615 else
1616 {
1617 mGroupID.setNull();
1618 }
1619 mSaleTimerExpires.start();
1620 mSaleTimerExpires.setTimerExpirySec(DEFAULT_USEC_SALE_TIMEOUT / SEC_TO_MICROSEC);
1621 mStatus = OS_LEASE_PENDING;
1622 mClaimDate = time(NULL);
1623 mAuctionID = 0;
1624 // clear the autoreturn whenever land changes hands
1625 setCleanOtherTime(0);
1626}
1627
1628void LLParcel::expireSale(U32& type, U8& flags, LLUUID& from_id, LLUUID& to_id)
1629{
1630 mSaleTimerExpires.setTimerExpirySec(0.0);
1631 mSaleTimerExpires.stop();
1632 setPreviousOwnerID(LLUUID::null);
1633 setPreviouslyGroupOwned(FALSE);
1634 setSellWithObjects(FALSE);
1635 type = TRANS_LAND_RELEASE;
1636 mStatus = OS_NONE;
1637 mIsReservedForNewbie = FALSE;
1638 flags = pack_transaction_flags(mGroupOwned, FALSE);
1639 mAuthBuyerID.setNull();
1640 from_id = mOwnerID;
1641 mOwnerID.setNull();
1642 to_id.setNull();
1643}
1644
1645void LLParcel::completeSale(U32& type, U8& flags,
1646 LLUUID& to_id)
1647{
1648 mSaleTimerExpires.setTimerExpirySec(0.0);
1649 mSaleTimerExpires.stop();
1650 mStatus = OS_LEASED;
1651 type = TRANS_LAND_SALE;
1652 flags = pack_transaction_flags(mGroupOwned, mGroupOwned);
1653 to_id = mOwnerID;
1654 mAuthBuyerID.setNull();
1655 mIsReservedForNewbie = FALSE;
1656
1657 // Purchased parcels are assumed to no longer be for sale.
1658 // Otherwise someone can snipe the sale.
1659 setForSale(FALSE);
1660
1661 // Turn off show directory, since it's a recurring fee that
1662 // the buyer may not want.
1663 setParcelFlag(PF_SHOW_DIRECTORY, FALSE);
1664
1665 //should be cleared on sale.
1666 mAccessList.clear();
1667 mBanList.clear();
1668
1669}
1670
1671void LLParcel::clearSale()
1672{
1673 mSaleTimerExpires.setTimerExpirySec(0.0);
1674 mSaleTimerExpires.stop();
1675 if(isPublic())
1676 {
1677 mStatus = OS_NONE;
1678 }
1679 else
1680 {
1681 mStatus = OS_LEASED;
1682 }
1683 mAuthBuyerID.setNull();
1684 setForSale(FALSE);
1685 setPreviousOwnerID(LLUUID::null);
1686 setPreviouslyGroupOwned(FALSE);
1687 setSellWithObjects(FALSE);
1688 mIsReservedForNewbie = FALSE;
1689}
1690
1691BOOL LLParcel::isPublic() const
1692{
1693 return (mOwnerID.isNull());
1694}
1695
1696BOOL LLParcel::isBuyerAuthorized(const LLUUID& buyer_id) const
1697{
1698 if(mAuthBuyerID.isNull())
1699 {
1700 return TRUE;
1701 }
1702 return (mAuthBuyerID == buyer_id);
1703}
1704
1705void LLParcel::clearParcel()
1706{
1707 overrideParcelFlags(PF_DEFAULT);
1708 setName(NULL);
1709 setDesc(NULL);
1710 setMusicURL(NULL);
1711 setMediaURL(NULL);
1712 setMediaID(LLUUID::null);
1713 setMediaAutoScale(0);
1714 setInEscrow(FALSE);
1715 setAuthorizedBuyerID(LLUUID::null);
1716 setCategory(C_NONE);
1717 setSnapshotID(LLUUID::null);
1718 setUserLocation(LLVector3::zero);
1719 setUserLookAt(LLVector3::x_axis);
1720 setLandingType(L_LANDING_POINT);
1721 setAuctionID(0);
1722 setReservedForNewbie(FALSE);
1723 setGroupID(LLUUID::null);
1724 setPassPrice(0);
1725 setPassHours(0.f);
1726 mAccessList.clear();
1727 mBanList.clear();
1728 //mRenterList.reset();
1729}
1730
1731void LLParcel::dump()
1732{
1733 llinfos << "parcel " << mLocalID << " area " << mArea << llendl;
1734 llinfos << " name <" << mName << ">" << llendl;
1735 llinfos << " desc <" << mDesc << ">" << llendl;
1736}
1737
1738const char* ownership_status_to_string(LLParcel::EOwnershipStatus status)
1739{
1740 if(status >= 0 && status < LLParcel::OS_COUNT)
1741 {
1742 return PARCEL_OWNERSHIP_STATUS_STRING[status];
1743 }
1744 return "none";
1745}
1746
1747LLParcel::EOwnershipStatus ownership_string_to_status(const char* s)
1748{
1749 for(S32 i = 0; i < LLParcel::OS_COUNT; ++i)
1750 {
1751 if(0 == strcmp(s, PARCEL_OWNERSHIP_STATUS_STRING[i]))
1752 {
1753 return (LLParcel::EOwnershipStatus)i;
1754 }
1755 }
1756 return LLParcel::OS_NONE;
1757}
1758
1759//const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action)
1760//{
1761// S32 index = 0;
1762// if(action >= 0 && action < LLParcel::STEA_COUNT)
1763// {
1764// index = action;
1765// }
1766// return PARCEL_SALE_TIMER_ACTION[index];
1767//}
1768
1769//LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s)
1770//{
1771// for(S32 i = 0; i < LLParcel::STEA_COUNT; ++i)
1772// {
1773// if(0 == strcmp(s, PARCEL_SALE_TIMER_ACTION[i]))
1774// {
1775// return (LLParcel::ESaleTimerExpireAction)i;
1776// }
1777// }
1778// return LLParcel::STEA_REVERT;
1779//}
1780
1781const char* category_to_string(LLParcel::ECategory category)
1782{
1783 S32 index = 0;
1784 if((category >= 0) && (category < LLParcel::C_COUNT))
1785 {
1786 index = category;
1787 }
1788 return PARCEL_CATEGORY_STRING[index];
1789}
1790
1791const char* category_to_ui_string(LLParcel::ECategory category)
1792{
1793 S32 index = 0;
1794 if((category >= 0) && (category < LLParcel::C_COUNT))
1795 {
1796 index = category;
1797 }
1798 else
1799 {
1800 // C_ANY = -1 , but the "Any" string is at the end of the list
1801 index = ((S32) LLParcel::C_COUNT) + 1;
1802 }
1803 return PARCEL_CATEGORY_UI_STRING[index];
1804}
1805
1806LLParcel::ECategory category_string_to_category(const char* s)
1807{
1808 for(S32 i = 0; i < LLParcel::C_COUNT; ++i)
1809 {
1810 if(0 == strcmp(s, PARCEL_CATEGORY_STRING[i]))
1811 {
1812 return (LLParcel::ECategory)i;
1813 }
1814 }
1815 llwarns << "Parcel category outside of possibilities " << s << llendl;
1816 return LLParcel::C_NONE;
1817}
1818
1819LLParcel::ECategory category_ui_string_to_category(const char* s)
1820{
1821 for(S32 i = 0; i < LLParcel::C_COUNT; ++i)
1822 {
1823 if(0 == strcmp(s, PARCEL_CATEGORY_UI_STRING[i]))
1824 {
1825 return (LLParcel::ECategory)i;
1826 }
1827 }
1828 // "Any" is a valid category for searches, and
1829 // is a distinct option from "None" and "Other"
1830 return LLParcel::C_ANY;
1831}
1832