llparcel.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "indra_constants.h"
00035 #include <iostream>
00036 
00037 #include "llparcel.h"
00038 #include "llstreamtools.h"
00039 
00040 #include "llmath.h"
00041 #include "llsd.h"
00042 #include "llsdutil.h"
00043 #include "lltransactiontypes.h"
00044 #include "lltransactionflags.h"
00045 #include "message.h"
00046 #include "u64.h"
00047 
00048 static const F32 SOME_BIG_NUMBER = 1000.0f;
00049 static const F32 SOME_BIG_NEG_NUMBER = -1000.0f;
00050 static const char* PARCEL_OWNERSHIP_STATUS_STRING[LLParcel::OS_COUNT] =
00051 {
00052         "leased",
00053         "lease_pending",
00054         "abandoned"
00055 };
00056 
00057 // NOTE: Adding parcel categories also requires updating:
00058 // * newview/app_settings/floater_directory.xml category combobox
00059 // * Web site "create event" tools
00060 static const char* PARCEL_CATEGORY_STRING[LLParcel::C_COUNT] =
00061 {
00062         "none",
00063         "linden",
00064         "adult",
00065         "arts",
00066         "store",        // "business" legacy name
00067         "educational",
00068         "game",         // "gaming" legacy name
00069         "gather",       // "hangout" legacy name
00070         "newcomer",
00071         "park",
00072         "home",         // "residential" legacy name
00073         "shopping",
00074         "stage",
00075         "other",
00076 };
00077 static const char* PARCEL_CATEGORY_UI_STRING[LLParcel::C_COUNT + 1] =
00078 {
00079         "None",
00080         "Linden Location",
00081         "Adult",
00082         "Arts & Culture",
00083         "Business",
00084         "Educational",
00085         "Gaming",
00086         "Hangout",
00087         "Newcomer Friendly",
00088         "Parks & Nature",
00089         "Residential",
00090         "Shopping",
00091         "Stage",
00092         "Other",
00093         "Any",          // valid string for parcel searches
00094 };
00095 
00096 static const char* PARCEL_ACTION_STRING[LLParcel::A_COUNT + 1] =
00097 {
00098         "create",
00099         "release",
00100         "absorb",
00101         "absorbed",
00102         "divide",
00103         "division",
00104         "acquire",
00105         "relinquish",
00106         "confirm",
00107         "unknown"
00108 };
00109 
00110 // Timeouts for parcels
00111 // default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
00112 const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
00113 // ***** TESTING is 10 minutes
00114 //const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000);
00115 
00116 // group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000
00117 const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
00118 // ***** TESTING is 10 minutes
00119 //const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000);
00120 
00121 // default sale timeout is 2 days -> 172800000000
00122 const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
00123 // ***** TESTING is 10 minutes
00124 //const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000);
00125 
00126 // more grace period extensions.
00127 const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
00128 
00129 // if more than 100,000s before sale revert, and no extra extension
00130 // has been given, go ahead and extend it more. That's about 1.2 days.
00131 const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
00132 
00133 
00134 const char* ownership_status_to_string(LLParcel::EOwnershipStatus status);
00135 LLParcel::EOwnershipStatus ownership_string_to_status(const char* s);
00136 //const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action);
00137 //LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s);
00138 const char* category_to_string(LLParcel::ECategory category);
00139 const char* category_to_ui_string(LLParcel::ECategory category);
00140 LLParcel::ECategory category_string_to_category(const char* s);
00141 LLParcel::ECategory category_ui_string_to_category(const char* s);
00142 
00143 LLParcel::LLParcel()
00144 {
00145         init(LLUUID::null, TRUE, FALSE, FALSE, 0, 0, 0, 0, 0, 1.f, 0);
00146 }
00147 
00148 
00149 LLParcel::LLParcel(const LLUUID &owner_id,
00150                                    BOOL modify, BOOL terraform, BOOL damage,
00151                                    time_t claim_date, S32 claim_price_per_meter,
00152                                    S32 rent_price_per_meter, S32 area, S32 sim_object_limit, F32 parcel_object_bonus,
00153                                    BOOL is_group_owned)
00154 {
00155         init(   owner_id, modify, terraform, damage, claim_date,
00156                         claim_price_per_meter, rent_price_per_meter, area, sim_object_limit, parcel_object_bonus,
00157                         is_group_owned);
00158 }
00159 
00160 
00161 // virtual
00162 LLParcel::~LLParcel()
00163 {
00164         // user list cleaned up by LLDynamicArray destructor.
00165 }
00166 
00167 void LLParcel::init(const LLUUID &owner_id,
00168                                         BOOL modify, BOOL terraform, BOOL damage,
00169                                         time_t claim_date, S32 claim_price_per_meter,
00170                                         S32 rent_price_per_meter, S32 area, S32 sim_object_limit, F32 parcel_object_bonus,
00171                                         BOOL is_group_owned)
00172 {
00173         mID.setNull();
00174         mOwnerID                        = owner_id;
00175         mGroupOwned                     = is_group_owned;
00176         mClaimDate                      = claim_date;
00177         mClaimPricePerMeter     = claim_price_per_meter;
00178         mRentPricePerMeter      = rent_price_per_meter;
00179         mArea                           = area;
00180         mDiscountRate           = 1.0f;
00181         mDrawDistance           = 512.f;
00182 
00183         mUserLookAt.setVec(0.0f, 0.f, 0.f);
00184         // Default to using the parcel's landing point, if any.
00185         mLandingType = L_LANDING_POINT;
00186 
00187         // *FIX: if owner_id != null, should be owned or sale pending,
00188         // investigate init callers.
00189         mStatus = OS_NONE;
00190         mCategory = C_NONE;
00191         mAuthBuyerID.setNull();
00192         //mBuyerID.setNull();
00193         //mJoinNeighbors = 0x0;
00194         mSaleTimerExpires.setTimerExpirySec(0);
00195         mSaleTimerExpires.stop();
00196         mGraceExtension = 0;
00197         //mExpireAction = STEA_REVERT;
00198         mRecordTransaction = FALSE;
00199 
00200         mAuctionID = 0;
00201         mInEscrow = false;
00202 
00203         mParcelFlags = PF_DEFAULT;
00204         setParcelFlag(PF_CREATE_OBJECTS,  modify);
00205         setParcelFlag(PF_ALLOW_TERRAFORM, terraform);
00206         setParcelFlag(PF_ALLOW_DAMAGE,    damage);
00207 
00208         mSalePrice                      = 10000;
00209         setName(NULL);
00210         setDesc(NULL);
00211         setMusicURL(NULL);
00212         setMediaURL(NULL);
00213         mMediaID.setNull();
00214         mMediaAutoScale = 0;
00215 
00216         mGroupID.setNull();
00217 
00218         mPassPrice = PARCEL_PASS_PRICE_DEFAULT;
00219         mPassHours = PARCEL_PASS_HOURS_DEFAULT;
00220 
00221         mAABBMin.setVec(SOME_BIG_NUMBER, SOME_BIG_NUMBER, SOME_BIG_NUMBER);
00222         mAABBMax.setVec(SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER, SOME_BIG_NEG_NUMBER);
00223 
00224         mLocalID = 0;
00225 
00226         //mSimWidePrimCorrection = 0;
00227         setMaxPrimCapacity((S32)(sim_object_limit * area / (F32)(REGION_WIDTH_METERS * REGION_WIDTH_METERS)));
00228         setSimWideMaxPrimCapacity(0);
00229         setSimWidePrimCount(0);
00230         setOwnerPrimCount(0);
00231         setGroupPrimCount(0);
00232         setOtherPrimCount(0);
00233         setSelectedPrimCount(0);
00234         setTempPrimCount(0);
00235         setCleanOtherTime(0);
00236         setParcelPrimBonus(parcel_object_bonus);
00237 
00238         setPreviousOwnerID(LLUUID::null);
00239         setPreviouslyGroupOwned(FALSE);
00240 }
00241 
00242 void LLParcel::overrideOwner(const LLUUID& owner_id, BOOL is_group_owned)
00243 {
00244         // Override with system permission (LLUUID::null)
00245         // Overridden parcels have no group
00246         mOwnerID = owner_id;
00247         mGroupOwned = is_group_owned;
00248         if(mGroupOwned)
00249         {
00250                 mGroupID = mOwnerID;
00251         }
00252         else
00253         {
00254                 mGroupID.setNull();
00255         }
00256         mInEscrow = false;
00257 }
00258 
00259 void LLParcel::overrideParcelFlags(U32 flags)
00260 {
00261         mParcelFlags = flags;
00262 }
00263 
00264 void LLParcel::setName(const LLString& name)
00265 {
00266         // The escaping here must match the escaping in the database
00267         // abstraction layer.
00268         mName = name;
00269         LLStringFn::replace_nonprintable(mName, LL_UNKNOWN_CHAR);
00270 }
00271 
00272 void LLParcel::setDesc(const LLString& desc)
00273 {
00274         // The escaping here must match the escaping in the database
00275         // abstraction layer.
00276         mDesc = desc;
00277         mDesc = rawstr_to_utf8(mDesc);
00278 }
00279 
00280 void LLParcel::setMusicURL(const LLString& url)
00281 {
00282         mMusicURL = url;
00283         // The escaping here must match the escaping in the database
00284         // abstraction layer.
00285         // This should really filter the url in some way. Other than
00286         // simply requiring non-printable.
00287         LLStringFn::replace_nonprintable(mMusicURL, LL_UNKNOWN_CHAR);
00288 }
00289 
00290 void LLParcel::setMediaURL(const LLString& url)
00291 {
00292         mMediaURL = url;
00293         // The escaping here must match the escaping in the database
00294         // abstraction layer if it's ever added.
00295         // This should really filter the url in some way. Other than
00296         // simply requiring non-printable.
00297         LLStringFn::replace_nonprintable(mMediaURL, LL_UNKNOWN_CHAR);
00298 }
00299 
00300 // virtual
00301 void LLParcel::setLocalID(S32 local_id)
00302 {
00303         mLocalID = local_id;
00304 }
00305 
00306 void LLParcel::setAllParcelFlags(U32 flags)
00307 {
00308         mParcelFlags = flags;
00309 }
00310 
00311 void LLParcel::setParcelFlag(U32 flag, BOOL b)
00312 {
00313         if (b)
00314         {
00315                 mParcelFlags |= flag;
00316         }
00317         else
00318         {
00319                 mParcelFlags &= ~flag;
00320         }
00321 }
00322 
00323 
00324 BOOL LLParcel::allowModifyBy(const LLUUID &agent_id, const LLUUID &group_id) const
00325 {
00326         if (agent_id == LLUUID::null)
00327         {
00328                 // system always can enter
00329                 return TRUE;
00330         }
00331         else if (isPublic())
00332         {
00333                 return TRUE;
00334         }
00335         else if (agent_id == mOwnerID)
00336         {
00337                 // owner can always perform operations
00338                 return TRUE;
00339         }
00340         else if (mParcelFlags & PF_CREATE_OBJECTS)
00341         {
00342                 return TRUE;
00343         }
00344         else if ((mParcelFlags & PF_CREATE_GROUP_OBJECTS)
00345                         && group_id.notNull() )
00346         {
00347                 return (getGroupID() == group_id);
00348         }
00349         
00350         return FALSE;
00351 }
00352 
00353 BOOL LLParcel::allowTerraformBy(const LLUUID &agent_id) const
00354 {
00355         if (agent_id == LLUUID::null)
00356         {
00357                 // system always can enter
00358                 return TRUE;
00359         }
00360         else if(OS_LEASED == mStatus)
00361         {
00362                 if(agent_id == mOwnerID)
00363                 {
00364                         // owner can modify leased land
00365                         return TRUE;
00366                 }
00367                 else
00368                 {
00369                         // otherwise check other people
00370                         return mParcelFlags & PF_ALLOW_TERRAFORM;
00371                 }
00372         }
00373         else
00374         {
00375                 return FALSE;
00376         }
00377 }
00378 
00379 
00380 bool LLParcel::isAgentBlockedFromParcel(LLParcel* parcelp,
00381                                                                                 const LLUUID& agent_id,
00382                                                                                 const std::vector<LLUUID>& group_ids,
00383                                                                                 const BOOL is_agent_identified,
00384                                                                                 const BOOL is_agent_transacted)
00385 {
00386         S32 current_group_access = parcelp->blockAccess(agent_id, LLUUID::null, is_agent_identified, is_agent_transacted);
00387         S32 count;
00388         bool is_allowed = (current_group_access == BA_ALLOWED) ? true: false;
00389         LLUUID group_id;
00390 
00391         count = group_ids.size();
00392         for (int i = 0; i < count && !is_allowed; i++)
00393         {
00394                 group_id = group_ids[i];
00395                 current_group_access = parcelp->blockAccess(agent_id, group_id, is_agent_identified, is_agent_transacted);
00396 
00397                 if (current_group_access == BA_ALLOWED) is_allowed = true;
00398         }
00399 
00400         return !is_allowed;
00401 }
00402 
00403 BOOL LLParcel::isAgentBanned(const LLUUID& agent_id) const
00404 {
00405         // Test ban list
00406         if (getParcelFlag(PF_USE_BAN_LIST)
00407                 && (mBanList.find(agent_id) != mBanList.end()))
00408         {
00409                 return TRUE;
00410         }
00411 
00412         return FALSE;
00413 }
00414 S32 LLParcel::blockAccess(const LLUUID& agent_id, const LLUUID& group_id,
00415                                                                                 const BOOL is_agent_identified,
00416                                                                                 const BOOL is_agent_transacted) const
00417 {
00418         // Test ban list
00419         if (isAgentBanned(agent_id))
00420         {
00421                 return BA_BANNED;
00422         }
00423 
00424         // Always allow owner on (unless he banned himself, useful for
00425         // testing). We will also allow estate owners/managers in if they 
00426         // are not explicitly banned.
00427         if (agent_id == mOwnerID)
00428         {
00429                 return BA_ALLOWED;
00430         }
00431 
00432         // Special case when using pass list where group access is being restricted but not 
00433         // using access list.  In this case group members are allowed only if they buy a pass.
00434         // We return BA_NOT_IN_LIST if not in list
00435         BOOL passWithGroup = getParcelFlag(PF_USE_PASS_LIST) && !getParcelFlag(PF_USE_ACCESS_LIST) 
00436                                                  && getParcelFlag(PF_USE_ACCESS_GROUP) && !mGroupID.isNull() && group_id == mGroupID;
00437 
00438 
00439         // Test group list
00440         if (getParcelFlag(PF_USE_ACCESS_GROUP)
00441                 && !mGroupID.isNull()
00442                 && group_id == mGroupID
00443                 && !passWithGroup)
00444         {
00445                 return BA_ALLOWED;
00446         }
00447         
00448         // Test access list
00449         if (getParcelFlag(PF_USE_ACCESS_LIST) || passWithGroup )
00450         {
00451                 if (mAccessList.find(agent_id) != mAccessList.end())
00452                 {
00453                         return BA_ALLOWED;
00454                 }
00455                 
00456                 return BA_NOT_ON_LIST;  
00457         }
00458 
00459         // If we're not doing any other limitations, all users
00460         // can enter, unless
00461         if (   !getParcelFlag(PF_USE_ACCESS_GROUP)
00462                 && !getParcelFlag(PF_USE_ACCESS_LIST))
00463         {       
00464                 //If the land is group owned, and you are in the group, bypass these checks
00465                 if(getIsGroupOwned() && group_id == mGroupID)
00466                 {
00467                         return BA_ALLOWED;
00468                 }
00469                 
00470                 // Test for "payment" access levels
00471                 // Anonymous - No Payment Info on File
00472                 if(getParcelFlag(PF_DENY_ANONYMOUS) && !is_agent_identified && !is_agent_transacted)
00473                 {
00474                         return BA_NO_ACCESS_LEVEL;
00475                 }
00476                 // Identified - Payment Info on File
00477                 // Must check to make sure we're only banning Identified, since Transacted accounts
00478                 // also have their identified flag set
00479                 if(getParcelFlag(PF_DENY_IDENTIFIED) && is_agent_identified && !is_agent_transacted)
00480                 {
00481                         return BA_NO_ACCESS_LEVEL;
00482                 }
00483                 // Transacted - Payment Info Used
00484                 if(getParcelFlag(PF_DENY_TRANSACTED) && is_agent_transacted)
00485                 {
00486                         return BA_NO_ACCESS_LEVEL;
00487                 }
00488                 return BA_ALLOWED;
00489         }
00490 
00491         return BA_NOT_IN_GROUP;
00492 
00493 }
00494 
00495 
00496 void LLParcel::setArea(S32 area, S32 sim_object_limit)
00497 {
00498         mArea = area;
00499         setMaxPrimCapacity((S32)(sim_object_limit * area / (F32)(REGION_WIDTH_METERS * REGION_WIDTH_METERS)));
00500 }
00501 
00502 void LLParcel::setDiscountRate(F32 rate)
00503 {
00504         // this is to make sure that the rate is at least sane - this is
00505         // not intended to enforce economy rules. It only enfoces that the
00506         // rate is a scaler between 0 and 1.
00507         mDiscountRate = llclampf(rate);
00508 }
00509 
00510 
00511 //-----------------------------------------------------------
00512 // File input and output
00513 //-----------------------------------------------------------
00514 
00515 
00516 // WARNING: Area will be wrong until you calculate it.
00517 BOOL LLParcel::importStream(std::istream& input_stream)
00518 {
00519         U32 setting;
00520         S32 secs_until_revert = 0;
00521 
00522         skip_to_end_of_next_keyword("{", input_stream);
00523         if (!input_stream.good()) 
00524         {
00525                 llwarns << "LLParcel::importStream() - bad input_stream" << llendl;
00526                 return FALSE;
00527         }
00528 
00529         while (input_stream.good())
00530         {
00531                 skip_comments_and_emptyspace(input_stream);
00532                 LLString line, keyword, value;
00533                 get_line(line, input_stream, MAX_STRING);
00534                 get_keyword_and_value(keyword, value, line);
00535 
00536                 if ("}" == keyword)
00537                 {
00538                         break;
00539                 }
00540                 else if ("parcel_id" == keyword)
00541                 {
00542                         mID.set(value.c_str());
00543                 }
00544                 else if ("status" == keyword)
00545                 {
00546                         mStatus = ownership_string_to_status(value.c_str());
00547                 }
00548                 else if ("category" == keyword)
00549                 {
00550                         mCategory = category_string_to_category(value.c_str());
00551                 }
00552                 else if ("local_id" == keyword)
00553                 {
00554                         LLString::convertToS32(value, mLocalID);
00555                 }
00556                 else if ("name" == keyword)
00557                 {
00558                         setName( value );
00559                 }
00560                 else if ("desc" == keyword)
00561                 {
00562                         setDesc( value );
00563                 }
00564                 else if ("music_url" == keyword)
00565                 {
00566                         setMusicURL( value );
00567                 }
00568                 else if ("media_url" == keyword)
00569                 {
00570                         setMediaURL( value );
00571                 }
00572                 else if ("media_id" == keyword)
00573                 {
00574                         mMediaID.set( value.c_str() );
00575                 }
00576                 else if ("media_auto_scale" == keyword)
00577                 {
00578                         LLString::convertToU8(value, mMediaAutoScale);
00579                 }
00580                 else if ("owner_id" == keyword)
00581                 {
00582                         mOwnerID.set( value.c_str() );
00583                 }
00584                 else if ("group_owned" == keyword)
00585                 {
00586                         LLString::convertToBOOL(value, mGroupOwned);
00587                 }
00588                 else if ("clean_other_time" == keyword)
00589                 {
00590                         S32 time;
00591                         LLString::convertToS32(value, time);
00592                         setCleanOtherTime(time);
00593                 }
00594                 else if ("auth_buyer_id" == keyword)
00595                 {
00596                         mAuthBuyerID.set(value.c_str());
00597                 }
00598                 else if ("snapshot_id" == keyword)
00599                 {
00600                         mSnapshotID.set(value.c_str());
00601                 }
00602                 else if ("user_location" == keyword)
00603                 {
00604                         sscanf(value.c_str(), "%f %f %f",
00605                                 &mUserLocation.mV[VX],
00606                                 &mUserLocation.mV[VY],
00607                                 &mUserLocation.mV[VZ]);
00608                 }
00609                 else if ("user_look_at" == keyword)
00610                 {
00611                         sscanf(value.c_str(), "%f %f %f",
00612                                 &mUserLookAt.mV[VX],
00613                                 &mUserLookAt.mV[VY],
00614                                 &mUserLookAt.mV[VZ]);
00615                 }
00616                 else if ("landing_type" == keyword)
00617                 {
00618                         S32 landing_type = 0;
00619                         LLString::convertToS32(value, landing_type);
00620                         mLandingType = (ELandingType) landing_type;
00621                 }
00622                 else if ("join_neighbors" == keyword)
00623                 {
00624                         llinfos << "found deprecated keyword join_neighbors" << llendl;
00625                 }
00626                 else if ("revert_sale" == keyword)
00627                 {
00628                         LLString::convertToS32(value, secs_until_revert);
00629                         if (secs_until_revert > 0)
00630                         {
00631                                 mSaleTimerExpires.start();
00632                                 mSaleTimerExpires.setTimerExpirySec((F32)secs_until_revert);
00633                         }
00634                 }
00635                 else if("extended_grace" == keyword)
00636                 {
00637                         LLString::convertToS32(value, mGraceExtension);
00638                 }
00639                 else if ("user_list_type" == keyword)
00640                 {
00641                         // deprecated
00642                 }
00643                 else if("auction_id" == keyword)
00644                 {
00645                         LLString::convertToU32(value, mAuctionID);
00646                 }
00647                 else if ("allow_modify" == keyword)
00648                 {
00649                         LLString::convertToU32(value, setting);
00650                         setParcelFlag(PF_CREATE_OBJECTS, setting);
00651                 }
00652                 else if ("allow_group_modify" == keyword)
00653                 {
00654                         LLString::convertToU32(value, setting);
00655                         setParcelFlag(PF_CREATE_GROUP_OBJECTS, setting);
00656                 }
00657                 else if ("allow_all_object_entry" == keyword)
00658                 {
00659                         LLString::convertToU32(value, setting);
00660                         setParcelFlag(PF_ALLOW_ALL_OBJECT_ENTRY, setting);
00661                 }
00662                 else if ("allow_group_object_entry" == keyword)
00663                 {
00664                         LLString::convertToU32(value, setting);
00665                         setParcelFlag(PF_ALLOW_GROUP_OBJECT_ENTRY, setting);
00666                 }
00667                 else if ("allow_deed_to_group" == keyword)
00668                 {
00669                         LLString::convertToU32(value, setting);
00670                         setParcelFlag(PF_ALLOW_DEED_TO_GROUP, setting);
00671                 }
00672                 else if("contribute_with_deed" == keyword)
00673                 {
00674                         LLString::convertToU32(value, setting);
00675                         setParcelFlag(PF_CONTRIBUTE_WITH_DEED, setting);
00676                 }
00677                 else if ("allow_terraform" == keyword)
00678                 {
00679                         LLString::convertToU32(value, setting);
00680                         setParcelFlag(PF_ALLOW_TERRAFORM, setting);
00681                 }
00682                 else if ("allow_damage" == keyword)
00683                 {
00684                         LLString::convertToU32(value, setting);
00685                         setParcelFlag(PF_ALLOW_DAMAGE, setting);
00686                 }
00687                 else if ("allow_fly" == keyword)
00688                 {
00689                         LLString::convertToU32(value, setting);
00690                         setParcelFlag(PF_ALLOW_FLY, setting);
00691                 }
00692                 else if ("allow_landmark" == keyword)
00693                 {
00694                         LLString::convertToU32(value, setting);
00695                         setParcelFlag(PF_ALLOW_LANDMARK, setting);
00696                 }
00697                 else if ("sound_local" == keyword)
00698                 {
00699                         LLString::convertToU32(value, setting);
00700                         setParcelFlag(PF_SOUND_LOCAL, setting);
00701                 }
00702                 else if ("allow_group_scripts" == keyword)
00703                 {
00704                         LLString::convertToU32(value, setting);
00705                         setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, setting);
00706                 }
00707                 else if ("allow_voice_chat" == keyword)
00708                 {
00709                         LLString::convertToU32(value, setting);
00710                         setParcelFlag(PF_ALLOW_VOICE_CHAT, setting);
00711                 }
00712                 else if ("use_estate_voice_chan" == keyword)
00713                 {
00714                         LLString::convertToU32(value, setting);
00715                         setParcelFlag(PF_USE_ESTATE_VOICE_CHAN, setting);
00716                 }
00717                 else if ("allow_scripts" == keyword)
00718                 {
00719                         LLString::convertToU32(value, setting);
00720                         setParcelFlag(PF_ALLOW_OTHER_SCRIPTS, setting);
00721                 }
00722                 else if ("for_sale" == keyword)
00723                 {
00724                         LLString::convertToU32(value, setting);
00725                         setParcelFlag(PF_FOR_SALE, setting);
00726                 }
00727                 else if ("sell_w_objects" == keyword)
00728                 {
00729                         LLString::convertToU32(value, setting);
00730                         setParcelFlag(PF_SELL_PARCEL_OBJECTS, setting);
00731                 }
00732                 else if ("use_pass_list" == keyword)
00733                 {
00734                         LLString::convertToU32(value, setting);
00735                         setParcelFlag(PF_USE_PASS_LIST, setting);
00736                 }
00737                 else if ("show_directory" == keyword)
00738                 {
00739                         LLString::convertToU32(value, setting);
00740                         setParcelFlag(PF_SHOW_DIRECTORY, setting);
00741                 }
00742                 else if ("allow_publish" == keyword)
00743                 {
00744                         LLString::convertToU32(value, setting);
00745                         setParcelFlag(PF_ALLOW_PUBLISH, setting);
00746                 }
00747                 else if ("mature_publish" == keyword)
00748                 {
00749                         LLString::convertToU32(value, setting);
00750                         setParcelFlag(PF_MATURE_PUBLISH, setting);
00751                 }
00752                 else if ("claim_date" == keyword)
00753                 {
00754                         // BUG: This will fail when time rolls over in 2038.
00755                         S32 time;
00756                         LLString::convertToS32(value, time);
00757                         mClaimDate = time;
00758                 }
00759                 else if ("claim_price" == keyword)
00760                 {
00761                         LLString::convertToS32(value, mClaimPricePerMeter);
00762                 }
00763                 else if ("rent_price" == keyword)
00764                 {
00765                         LLString::convertToS32(value, mRentPricePerMeter);
00766                 }
00767                 else if ("discount_rate" == keyword)
00768                 {
00769                         LLString::convertToF32(value, mDiscountRate);
00770                 }
00771                 else if ("draw_distance" == keyword)
00772                 {
00773                         LLString::convertToF32(value, mDrawDistance);
00774                 }
00775                 else if ("sale_price" == keyword)
00776                 {
00777                         LLString::convertToS32(value, mSalePrice);
00778                 }
00779                 else if ("pass_price" == keyword)
00780                 {
00781                         LLString::convertToS32(value, mPassPrice);
00782                 }
00783                 else if ("pass_hours" == keyword)
00784                 {
00785                         LLString::convertToF32(value, mPassHours);
00786                 }
00787                 else if ("box" == keyword)
00788                 {
00789                         // deprecated
00790                 }
00791                 else if ("aabb_min" == keyword)
00792                 {
00793                         sscanf(value.c_str(), "%f %f %f", 
00794                                 &mAABBMin.mV[VX], &mAABBMin.mV[VY], &mAABBMin.mV[VZ]);
00795                 }
00796                 else if ("use_access_group" == keyword)
00797                 {
00798                         LLString::convertToU32(value, setting);
00799                         setParcelFlag(PF_USE_ACCESS_GROUP, setting);
00800                 }
00801                 else if ("use_access_list" == keyword)
00802                 {
00803                         LLString::convertToU32(value, setting);
00804                         setParcelFlag(PF_USE_ACCESS_LIST, setting);
00805                 }
00806                 else if ("use_ban_list" == keyword)
00807                 {
00808                         LLString::convertToU32(value, setting);
00809                         setParcelFlag(PF_USE_BAN_LIST, setting);
00810                 }
00811                 else if ("group_name" == keyword)
00812                 {
00813                         llinfos << "found deprecated keyword group_name" << llendl;
00814                 }
00815                 else if ("group_id" == keyword)
00816                 {
00817                         mGroupID.set( value.c_str() );
00818                 }
00819                 // TODO: DEPRECATED FLAG
00820                 // Flag removed from simstate files in 1.11.1
00821                 // Remove at some point where we have guarenteed this flag
00822                 // no longer exists anywhere in simstate files.
00823                 else if ("require_identified" == keyword)
00824                 {
00825                         LLString::convertToU32(value, setting);
00826                         setParcelFlag(PF_DENY_ANONYMOUS, setting);
00827                 }
00828                 // TODO: DEPRECATED FLAG
00829                 // Flag removed from simstate files in 1.11.1
00830                 // Remove at some point where we have guarenteed this flag
00831                 // no longer exists anywhere in simstate files.
00832                 else if ("require_transacted" == keyword)
00833                 {
00834                         LLString::convertToU32(value, setting);
00835                         setParcelFlag(PF_DENY_ANONYMOUS, setting);
00836                         setParcelFlag(PF_DENY_IDENTIFIED, setting);
00837                 }
00838                 else if ("restrict_pushobject" == keyword)
00839                 {
00840                         LLString::convertToU32(value, setting);
00841                         setParcelFlag(PF_RESTRICT_PUSHOBJECT, setting);
00842                 }
00843                 else if ("deny_anonymous" == keyword)
00844                 {
00845                         LLString::convertToU32(value, setting);
00846                         setParcelFlag(PF_DENY_ANONYMOUS, setting);
00847                 }
00848                 else if ("deny_identified" == keyword)
00849                 {
00850                         LLString::convertToU32(value, setting);
00851                         setParcelFlag(PF_DENY_IDENTIFIED, setting);
00852                 }
00853                 else if ("deny_transacted" == keyword)
00854                 {
00855                         LLString::convertToU32(value, setting);
00856                         setParcelFlag(PF_DENY_TRANSACTED, setting);
00857                 }
00858                 else if ("access_list" == keyword)
00859                 {
00860                         S32 entry_count = 0;
00861                         LLString::convertToS32(value, entry_count);
00862                         for (S32 i = 0; i < entry_count; i++)
00863                         {
00864                                 LLAccessEntry entry;
00865                                 if (importAccessEntry(input_stream, &entry))
00866                                 {
00867                                         mAccessList[entry.mID] = entry;
00868                                 }
00869                         }
00870                 }
00871                 else if ("ban_list" == keyword)
00872                 {
00873                         S32 entry_count = 0;
00874                         LLString::convertToS32(value, entry_count);
00875                         for (S32 i = 0; i < entry_count; i++)
00876                         {
00877                                 LLAccessEntry entry;
00878                                 if (importAccessEntry(input_stream, &entry))
00879                                 {
00880                                         mBanList[entry.mID] = entry;
00881                                 }
00882                         }
00883                 }
00884                 else if ("renter_list" == keyword)
00885                 {
00886                         /*
00887                         S32 entry_count = 0;
00888                         LLString::convertToS32(value, entry_count);
00889                         for (S32 i = 0; i < entry_count; i++)
00890                         {
00891                                 LLAccessEntry entry;
00892                                 if (importAccessEntry(input_stream, &entry))
00893                                 {
00894                                         mRenterList.put(entry);
00895                                 }
00896                         }*/
00897                 }
00898                 else if ("pass_list" == keyword)
00899                 {
00900                         // legacy - put into access list
00901                         S32 entry_count = 0;
00902                         LLString::convertToS32(value, entry_count);
00903                         for (S32 i = 0; i < entry_count; i++)
00904                         {
00905                                 LLAccessEntry entry;
00906                                 if (importAccessEntry(input_stream, &entry))
00907                                 {
00908                                         mAccessList[entry.mID] = entry;
00909                                 }
00910                         }
00911                 }
00912 
00913                 else
00914                 {
00915                         llwarns << "Unknown keyword in parcel section: <" 
00916                                 << keyword << ">" << llendl;
00917                 }
00918         }
00919 
00920         // this code block detects if we have loaded a 1.1 simstate file,
00921         // and follows the conversion rules specified in
00922         // design_docs/land/pay_for_parcel.txt.
00923         F32 time_to_expire = 0.0f;
00924         if(mID.isNull())
00925         {
00926                 mID.generate();
00927                 mStatus = OS_LEASE_PENDING;
00928                 //mBuyerID = mOwnerID;
00929                 if(getIsGroupOwned())
00930                 {
00931                         time_to_expire += GROUP_USEC_CONVERSION_TIMEOUT / SEC_TO_MICROSEC;
00932                 }
00933                 else
00934                 {
00935                         time_to_expire += DEFAULT_USEC_CONVERSION_TIMEOUT / SEC_TO_MICROSEC;
00936                 }
00937                 //mExpireAction = STEA_PUBLIC;
00938                 mRecordTransaction = TRUE;
00939         }
00940 
00941         // this code block deals with giving an extension to pending
00942         // parcels to the midday of 2004-01-19 if they were originally set
00943         // for some time on 2004-01-12.
00944         if((0 == mGraceExtension)
00945            && (EXTEND_GRACE_IF_MORE_THAN_SEC < secs_until_revert))
00946         {
00947                 const S32 NEW_CONVERSION_DATE = 1074538800; // 2004-01-19T11:00:00
00948                 time_t now = time(NULL); // now in epoch
00949                 secs_until_revert = (S32)(NEW_CONVERSION_DATE - now);
00950                 time_to_expire = (F32)secs_until_revert;
00951                 mGraceExtension = 1;
00952         }
00953 
00954         // This code block adds yet another week to the deadline. :(
00955         if(1 == mGraceExtension)
00956         {
00957                 time_to_expire += SEVEN_DAYS_IN_USEC / SEC_TO_MICROSEC;
00958                 mGraceExtension = 2;
00959         }
00960 
00961         if (time_to_expire > 0)
00962         {
00963                 mSaleTimerExpires.setTimerExpirySec(time_to_expire);
00964                 mSaleTimerExpires.start();
00965         }
00966 
00967         // successful import
00968         return TRUE;
00969 }
00970 
00971 
00972 BOOL LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entry)
00973 {
00974         skip_to_end_of_next_keyword("{", input_stream);
00975         while (input_stream.good())
00976         {
00977                 skip_comments_and_emptyspace(input_stream);
00978                 LLString line, keyword, value;
00979                 get_line(line, input_stream, MAX_STRING);
00980                 get_keyword_and_value(keyword, value, line);
00981 
00982                 if ("}" == keyword)
00983                 {
00984                         break;
00985                 }
00986                 else if ("id" == keyword)
00987                 {
00988                         entry->mID.set( value.c_str() );
00989                 }
00990                 else if ("name" == keyword)
00991                 {
00992                         // deprecated
00993                 }
00994                 else if ("time" == keyword)
00995                 {
00996                         S32 when;
00997                         LLString::convertToS32(value, when);
00998                         entry->mTime = when;
00999                 }
01000                 else if ("flags" == keyword)
01001                 {
01002                         U32 setting;
01003                         LLString::convertToU32(value, setting);
01004                         entry->mFlags = setting;
01005                 }
01006                 else
01007                 {
01008                         llwarns << "Unknown keyword in parcel access entry section: <" 
01009                                 << keyword << ">" << llendl;
01010                 }
01011         }
01012         return input_stream.good();
01013 }
01014 
01015 BOOL LLParcel::exportStream(std::ostream& output_stream)
01016 {
01017         S32 setting;
01018         char id_string[MAX_STRING];     /* Flawfinder: ignore */
01019 
01020         std::ios::fmtflags old_flags = output_stream.flags();
01021         output_stream.setf(std::ios::showpoint);
01022         output_stream << "\t{\n";
01023 
01024         mID.toString(id_string);
01025         output_stream << "\t\t parcel_id        " << id_string << "\n";
01026         output_stream << "\t\t status           " << ownership_status_to_string(mStatus) << "\n";
01027         output_stream << "\t\t category         " << category_to_string(mCategory) << "\n";
01028 
01029         output_stream << "\t\t local_id         " << mLocalID  << "\n";
01030 
01031         const char* name = (mName.empty() ? "" : mName.c_str() );
01032         output_stream << "\t\t name             " << name << "\n";
01033 
01034         const char* desc = (mDesc.empty() ? "" : mDesc.c_str() );
01035         output_stream << "\t\t desc             " << desc << "\n";
01036 
01037         const char* music_url = (mMusicURL.empty() ? "" : mMusicURL.c_str() );
01038         output_stream << "\t\t music_url        " << music_url << "\n";
01039 
01040         const char* media_url = (mMediaURL.empty() ? "" : mMediaURL.c_str() );
01041         output_stream << "\t\t media_url        " << media_url << "\n";
01042 
01043         output_stream << "\t\t media_auto_scale " << (mMediaAutoScale ? 1 : 0)  << "\n";
01044 
01045         mMediaID.toString(id_string);
01046         output_stream << "\t\t media_id         " << id_string  << "\n";
01047 
01048         mOwnerID.toString(id_string);
01049         output_stream << "\t\t owner_id         " << id_string  << "\n";
01050         output_stream << "\t\t group_owned         " << (mGroupOwned ? 1 : 0)  << "\n";
01051         output_stream << "\t\t clean_other_time " << getCleanOtherTime() << "\n";
01052 
01053         if(!mAuthBuyerID.isNull())
01054         {
01055                 mAuthBuyerID.toString(id_string);
01056                 output_stream << "\t\t auth_buyer_id    " << id_string << "\n";
01057         }
01058         if (!mSnapshotID.isNull())
01059         {
01060                 mSnapshotID.toString(id_string);
01061                 output_stream << "\t\t snapshot_id      " << id_string << "\n";
01062         }
01063         if (!mUserLocation.isExactlyZero())
01064         {
01065                 output_stream << "\t\t user_location " 
01066                         << (F64)mUserLocation.mV[VX]
01067                         << " " << (F64)mUserLocation.mV[VY]
01068                         << " " << (F64)mUserLocation.mV[VZ] << "\n";
01069                 output_stream << "\t\t user_look_at " 
01070                         << (F64)mUserLookAt.mV[VX]
01071                         << " " << (F64)mUserLookAt.mV[VY]
01072                         << " " << (F64)mUserLookAt.mV[VZ] << "\n";
01073         }
01074         output_stream << "\t\t landing_type " << mLandingType << "\n";
01075         //if(mJoinNeighbors)
01076         //{
01077         //      output_stream << "\t\t join_neighbors " << mJoinNeighbors << "\n";
01078         //}
01079         if(mSaleTimerExpires.getStarted())
01080         {
01081                 S32 dt_sec = (S32) mSaleTimerExpires.getRemainingTimeF32()+60; // Add a minute to prevent race conditions
01082                 output_stream << "\t\t revert_sale      " << dt_sec << "\n";
01083                 //output_stream << "\t\t revert_action    " << revert_action_to_string(mExpireAction) << "\n";
01084                 output_stream << "\t\t extended_grace   " << mGraceExtension << "\n";
01085         }
01086 
01087         if(0 != mAuctionID)
01088         {
01089                 output_stream << "\t\t auction_id       " << mAuctionID << "\n";
01090         }
01091 
01092         output_stream << "\t\t allow_modify     " << getAllowModify()  << "\n";
01093         output_stream << "\t\t allow_group_modify     " << getAllowGroupModify()  << "\n";
01094         output_stream << "\t\t allow_all_object_entry     " << getAllowAllObjectEntry()  << "\n";
01095         output_stream << "\t\t allow_group_object_entry     " << getAllowGroupObjectEntry()  << "\n";
01096         output_stream << "\t\t allow_terraform  " << getAllowTerraform()  << "\n";
01097         output_stream << "\t\t allow_deed_to_group " << getAllowDeedToGroup()  << "\n";
01098         output_stream << "\t\t contribute_with_deed " << getContributeWithDeed() << "\n";
01099         output_stream << "\t\t allow_damage     " << getAllowDamage()  << "\n";
01100         output_stream << "\t\t claim_date       " << (S32)mClaimDate  << "\n";
01101         output_stream << "\t\t claim_price      " << mClaimPricePerMeter  << "\n";
01102         output_stream << "\t\t rent_price       " << mRentPricePerMeter  << "\n";
01103         output_stream << "\t\t discount_rate    " << mDiscountRate  << "\n";
01104         output_stream << "\t\t allow_fly        " << (getAllowFly()      ? 1 : 0)  << "\n";
01105         output_stream << "\t\t allow_landmark   " << (getAllowLandmark() ? 1 : 0)  << "\n";
01106         output_stream << "\t\t sound_local         " << (getSoundLocal() ? 1 : 0)  << "\n";
01107         output_stream << "\t\t allow_scripts    " << (getAllowOtherScripts()  ? 1 : 0)  << "\n";
01108         output_stream << "\t\t allow_group_scripts    " << (getAllowGroupScripts()  ? 1 : 0)  << "\n";
01109         output_stream << "\t\t allow_voice_chat    " << (getVoiceEnabled() ? 1 : 0) << "\n";
01110         output_stream << "\t\t use_estate_voice_chan   " << (getVoiceUseEstateChannel() ? 1 : 0) << "\n";
01111         output_stream << "\t\t for_sale         " << (getForSale()       ? 1 : 0)  << "\n";
01112         output_stream << "\t\t sell_w_objects   " << (getSellWithObjects()      ? 1 : 0)  << "\n";
01113         output_stream << "\t\t draw_distance    " << mDrawDistance  << "\n";
01114         output_stream << "\t\t sale_price       " << mSalePrice  << "\n";
01115 
01116         setting = (getParcelFlag(PF_USE_ACCESS_GROUP) ? 1 : 0);
01117         output_stream << "\t\t use_access_group " << setting  << "\n";
01118 
01119         setting = (getParcelFlag(PF_USE_ACCESS_LIST) ? 1 : 0);
01120         output_stream << "\t\t use_access_list  " << setting  << "\n";
01121 
01122         setting = (getParcelFlag(PF_USE_BAN_LIST) ? 1 : 0);
01123         output_stream << "\t\t use_ban_list     " << setting  << "\n";
01124 
01125         mGroupID.toString(id_string);
01126         output_stream << "\t\t group_id  " << id_string  << "\n";
01127 
01128         //const char* group_name
01129         //      = (mGroupName.isEmpty() ? "" : mGroupName.c_str() );
01130         //output_stream << "\t\t group_name " << group_name << "\n";
01131 
01132         setting = (getParcelFlag(PF_USE_PASS_LIST) ? 1 : 0);
01133         output_stream << "\t\t use_pass_list    " << setting  << "\n";
01134 
01135         output_stream << "\t\t pass_price       " << mPassPrice  << "\n";
01136         output_stream << "\t\t pass_hours       " << mPassHours  << "\n";
01137 
01138         setting = (getParcelFlag(PF_SHOW_DIRECTORY) ? 1 : 0);
01139         output_stream << "\t\t show_directory   " << setting  << "\n";
01140 
01141         setting = (getParcelFlag(PF_ALLOW_PUBLISH) ? 1 : 0);
01142         output_stream << "\t\t allow_publish     " << setting  << "\n";
01143 
01144         setting = (getParcelFlag(PF_MATURE_PUBLISH) ? 1 : 0);
01145         output_stream << "\t\t mature_publish     " << setting  << "\n";
01146 
01147         setting = (getParcelFlag(PF_DENY_ANONYMOUS) ? 1 : 0);
01148         output_stream << "\t\t deny_anonymous     " << setting  << "\n";
01149 
01150         setting = (getParcelFlag(PF_DENY_IDENTIFIED) ? 1 : 0);
01151         output_stream << "\t\t deny_identified     " << setting  << "\n";
01152 
01153         setting = (getParcelFlag(PF_DENY_TRANSACTED) ? 1 : 0);
01154         output_stream << "\t\t deny_transacted     " << setting  << "\n";
01155 
01156         setting = (getParcelFlag(PF_RESTRICT_PUSHOBJECT) ? 1 : 0);
01157         output_stream << "\t\t restrict_pushobject " << setting  << "\n";
01158 
01159         output_stream << "\t\t aabb_min         " 
01160                 << mAABBMin.mV[VX]
01161                 << " " << mAABBMin.mV[VY]
01162                 << " " << mAABBMin.mV[VZ] << "\n";
01163 
01164         if (!mAccessList.empty())
01165         {
01166                 output_stream << "\t\t access_list " << mAccessList.size()  << "\n";
01167                 access_map_const_iterator cit = mAccessList.begin();
01168                 access_map_const_iterator end = mAccessList.end();
01169 
01170                 for ( ; cit != end; ++cit)
01171                 {
01172                         output_stream << "\t\t{\n";
01173                         const LLAccessEntry& entry = (*cit).second;
01174                         entry.mID.toString(id_string);
01175                         output_stream << "\t\t\tid " << id_string << "\n";
01176                         output_stream << "\t\t\ttime " << entry.mTime  << "\n";
01177                         output_stream << "\t\t\tflags " << entry.mFlags  << "\n";
01178                         output_stream << "\t\t}\n";
01179                 }
01180         }
01181 
01182         if (!mBanList.empty())
01183         {
01184                 output_stream << "\t\t ban_list " << mBanList.size()  << "\n";
01185                 access_map_const_iterator cit = mBanList.begin();
01186                 access_map_const_iterator end = mBanList.end();
01187 
01188                 for ( ; cit != end; ++cit)
01189                 {
01190                         output_stream << "\t\t{\n";
01191                         const LLAccessEntry& entry = (*cit).second;
01192                         entry.mID.toString(id_string);
01193                         output_stream << "\t\t\tid " << id_string << "\n";
01194                         output_stream << "\t\t\ttime " << entry.mTime  << "\n";
01195                         output_stream << "\t\t\tflags " << entry.mFlags  << "\n";
01196                         output_stream << "\t\t}\n";
01197                 }
01198         }
01199 
01200         /*if (mRenterList.count() > 0)
01201         {
01202                 output_stream << "\t\t renter_list " << mRenterList.count()  << "\n";
01203                 for (i = 0; i < mRenterList.count(); i++)
01204                 {
01205                         output_stream << "\t\t{\n";
01206                         const LLAccessEntry& entry = mRenterList.get(i);
01207                         entry.mID.toString(id_string);
01208                         output_stream << "\t\t\tid " << id_string << "\n";
01209                         output_stream << "\t\t\ttime " << entry.mTime  << "\n";
01210                         output_stream << "\t\t\tflags " << entry.mFlags  << "\n";
01211                         output_stream << "\t\t}\n";
01212                 }
01213         }*/
01214 
01215         output_stream << "\t}\n";
01216         output_stream.flags(old_flags);
01217 
01218         return TRUE;
01219 }
01220 
01221 
01222 // Assumes we are in a block "ParcelData"
01223 void LLParcel::packMessage(LLMessageSystem* msg)
01224 {
01225         msg->addU32Fast(        _PREHASH_ParcelFlags,   getParcelFlags() );
01226         msg->addS32Fast(        _PREHASH_SalePrice,     getSalePrice() );
01227         msg->addStringFast(     _PREHASH_Name,                  getName() );
01228         msg->addStringFast(     _PREHASH_Desc,                  getDesc() );
01229         msg->addStringFast(     _PREHASH_MusicURL,              getMusicURL() );
01230         msg->addStringFast(     _PREHASH_MediaURL,              getMediaURL() );
01231         msg->addU8 ( "MediaAutoScale", getMediaAutoScale () );
01232         msg->addUUIDFast(       _PREHASH_MediaID,               getMediaID() );
01233         msg->addUUIDFast(       _PREHASH_GroupID,               getGroupID() );
01234         msg->addS32Fast(        _PREHASH_PassPrice,     mPassPrice );
01235         msg->addF32Fast(        _PREHASH_PassHours,     mPassHours );
01236         msg->addU8Fast(         _PREHASH_Category,              (U8)mCategory);
01237         msg->addUUIDFast(       _PREHASH_AuthBuyerID,   mAuthBuyerID);
01238         msg->addUUIDFast(       _PREHASH_SnapshotID,    mSnapshotID);
01239         msg->addVector3Fast(_PREHASH_UserLocation,      mUserLocation);
01240         msg->addVector3Fast(_PREHASH_UserLookAt,        mUserLookAt);
01241         msg->addU8Fast(         _PREHASH_LandingType,   (U8)mLandingType);
01242 }
01243 
01244 
01245 void LLParcel::unpackMessage(LLMessageSystem* msg)
01246 {
01247         char buffer[256];       /* Flawfinder: ignore */
01248 
01249         msg->getU32Fast(        _PREHASH_ParcelData,_PREHASH_ParcelFlags, mParcelFlags );
01250         msg->getS32Fast(        _PREHASH_ParcelData,_PREHASH_SalePrice, mSalePrice );
01251         msg->getStringFast(     _PREHASH_ParcelData,_PREHASH_Name, 256, buffer );
01252         setName(buffer);
01253         msg->getStringFast(     _PREHASH_ParcelData,_PREHASH_Desc, 256, buffer );
01254         setDesc(buffer);
01255         msg->getStringFast(     _PREHASH_ParcelData,_PREHASH_MusicURL, 256, buffer );
01256         setMusicURL(buffer);
01257         msg->getStringFast(     _PREHASH_ParcelData,_PREHASH_MediaURL, 256, buffer );
01258         setMediaURL(buffer);
01259 
01260         // non-optimized version
01261         msg->getU8 ( "ParcelData", "MediaAutoScale", mMediaAutoScale );
01262 
01263         msg->getUUIDFast(       _PREHASH_ParcelData,_PREHASH_MediaID, mMediaID );
01264         msg->getUUIDFast(       _PREHASH_ParcelData,_PREHASH_GroupID, mGroupID );
01265         msg->getS32Fast(        _PREHASH_ParcelData,_PREHASH_PassPrice, mPassPrice );
01266         msg->getF32Fast(        _PREHASH_ParcelData,_PREHASH_PassHours, mPassHours );
01267         U8 category;
01268         msg->getU8Fast(         _PREHASH_ParcelData,_PREHASH_Category, category);
01269         mCategory = (ECategory)category;
01270         msg->getUUIDFast(       _PREHASH_ParcelData,_PREHASH_AuthBuyerID, mAuthBuyerID);
01271         msg->getUUIDFast(       _PREHASH_ParcelData,_PREHASH_SnapshotID, mSnapshotID);
01272         msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLocation, mUserLocation);
01273         msg->getVector3Fast(_PREHASH_ParcelData,_PREHASH_UserLookAt, mUserLookAt);
01274         U8 landing_type;
01275         msg->getU8Fast(         _PREHASH_ParcelData,_PREHASH_LandingType, landing_type);
01276         mLandingType = (ELandingType)landing_type;
01277 }
01278 
01279 
01280 void LLParcel::packAccessEntries(LLMessageSystem* msg,
01281                                                                  const std::map<LLUUID,LLAccessEntry>& list)
01282 {
01283         access_map_const_iterator cit = list.begin();
01284         access_map_const_iterator end = list.end();
01285 
01286         if (cit == end)
01287         {
01288                 msg->nextBlockFast(_PREHASH_List);
01289                 msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
01290                 msg->addS32Fast(_PREHASH_Time, 0 );
01291                 msg->addU32Fast(_PREHASH_Flags, 0 );
01292                 return;
01293         }
01294 
01295         for ( ; cit != end; ++cit)
01296         {
01297                 const LLAccessEntry& entry = (*cit).second;
01298 
01299                 msg->nextBlockFast(_PREHASH_List);
01300                 msg->addUUIDFast(_PREHASH_ID,           entry.mID );
01301                 msg->addS32Fast(_PREHASH_Time,          entry.mTime );
01302                 msg->addU32Fast(_PREHASH_Flags, entry.mFlags );
01303         }
01304 }
01305 
01306 
01307 void LLParcel::unpackAccessEntries(LLMessageSystem* msg,
01308                                                                    std::map<LLUUID,LLAccessEntry>* list)
01309 {
01310         LLUUID id;
01311         S32 time;
01312         U32 flags;
01313 
01314         S32 i;
01315         S32 count = msg->getNumberOfBlocksFast(_PREHASH_List);
01316         for (i = 0; i < count; i++)
01317         {
01318                 msg->getUUIDFast(_PREHASH_List, _PREHASH_ID, id, i);
01319                 msg->getS32Fast(   _PREHASH_List, _PREHASH_Time, time, i);
01320                 msg->getU32Fast(   _PREHASH_List, _PREHASH_Flags, flags, i);
01321 
01322                 if (id.notNull())
01323                 {
01324                         LLAccessEntry entry;
01325                         entry.mID = id;
01326                         entry.mTime = time;
01327                         entry.mFlags = flags;
01328 
01329                         (*list)[entry.mID] = entry;
01330                 }
01331         }
01332 }
01333 
01334 
01335 void LLParcel::expirePasses(S32 now)
01336 {
01337         access_map_iterator itor = mAccessList.begin();
01338         while (itor != mAccessList.end())
01339         {
01340                 const LLAccessEntry& entry = (*itor).second;
01341 
01342                 if (entry.mTime != 0 && entry.mTime < now)
01343                 {
01344                         mAccessList.erase(itor++);
01345                 }
01346                 else
01347                 {
01348                         ++itor;
01349                 }
01350         }
01351 }
01352 
01353 
01354 bool LLParcel::operator==(const LLParcel &rhs) const
01355 {
01356         if (mOwnerID != rhs.mOwnerID)
01357                 return FALSE;
01358 
01359         if (mParcelFlags != rhs.mParcelFlags)
01360                 return FALSE;
01361 
01362         if (mClaimDate != rhs.mClaimDate)
01363                 return FALSE;
01364 
01365         if (mClaimPricePerMeter != rhs.mClaimPricePerMeter)
01366                 return FALSE;
01367 
01368         if (mRentPricePerMeter != rhs.mRentPricePerMeter)
01369                 return FALSE;
01370 
01371         return TRUE;
01372 }
01373 
01374 // Calculate rent
01375 S32 LLParcel::getTotalRent() const
01376 {
01377         return (S32)floor(0.5f + (F32)mArea * (F32)mRentPricePerMeter * (1.0f - mDiscountRate));
01378 }
01379 
01380 F32 LLParcel::getAdjustedRentPerMeter() const
01381 {
01382         return ((F32)mRentPricePerMeter * (1.0f - mDiscountRate));
01383 }
01384 
01385 LLVector3 LLParcel::getCenterpoint() const
01386 {
01387         LLVector3 rv;
01388         rv.mV[VX] = (getAABBMin().mV[VX] + getAABBMax().mV[VX]) * 0.5f;
01389         rv.mV[VY] = (getAABBMin().mV[VY] + getAABBMax().mV[VY]) * 0.5f;
01390         rv.mV[VZ] = 0.0f;
01391         return rv;
01392 }
01393 
01394 void LLParcel::extendAABB(const LLVector3& box_min, const LLVector3& box_max)
01395 {
01396         // Patch up min corner of AABB
01397         S32 i;
01398         for (i=0; i<3; i++)
01399         {
01400                 if (box_min.mV[i] < mAABBMin.mV[i])
01401                 {
01402                         mAABBMin.mV[i] = box_min.mV[i];
01403                 }
01404         }
01405 
01406         // Patch up max corner of AABB
01407         for (i=0; i<3; i++)
01408         {
01409                 if (box_max.mV[i] > mAABBMax.mV[i])
01410                 {
01411                         mAABBMax.mV[i] = box_max.mV[i];
01412                 }
01413         }
01414 }
01415 
01416 BOOL LLParcel::addToAccessList(const LLUUID& agent_id, S32 time)
01417 {
01418         if (!((mParcelFlags & PF_USE_ACCESS_LIST) || (mParcelFlags & PF_USE_PASS_LIST)) 
01419                 || mAccessList.size() >= (U32) PARCEL_MAX_ACCESS_LIST)
01420         {
01421                 // Not using access list, so not a rational thing to do
01422                 return FALSE;
01423         }
01424         if (agent_id == getOwnerID())
01425         {
01426                 // Can't add owner to these lists
01427                 return FALSE;
01428         }
01429         access_map_iterator itor = mAccessList.begin();
01430         while (itor != mAccessList.end())
01431         {
01432                 const LLAccessEntry& entry = (*itor).second;
01433                 if (entry.mID == agent_id)
01434                 {
01435                         if (time == 0 || (entry.mTime != 0 && entry.mTime < time))
01436                         {
01437                                 mAccessList.erase(itor++);
01438                         }
01439                         else
01440                         {
01441                                 // existing one expires later
01442                                 return FALSE;
01443                         }
01444                 }
01445                 else
01446                 {
01447                         ++itor;
01448                 }
01449         }
01450 
01451         removeFromBanList(agent_id);
01452 
01453         LLAccessEntry new_entry;
01454         new_entry.mID    = agent_id;
01455         new_entry.mTime  = time;
01456         new_entry.mFlags = 0x0;
01457         mAccessList[new_entry.mID] = new_entry;
01458         return TRUE;
01459 }
01460 
01461 BOOL LLParcel::addToBanList(const LLUUID& agent_id, S32 time)
01462 {
01463         if (!(mParcelFlags & PF_USE_BAN_LIST) 
01464                 || mBanList.size() >= (U32) PARCEL_MAX_ACCESS_LIST)
01465         {
01466                 // Not using ban list, so not a rational thing to do
01467                 return FALSE;
01468         }
01469         if (agent_id == getOwnerID())
01470         {
01471                 // Can't add owner to these lists
01472                 return FALSE;
01473         }
01474 
01475         access_map_iterator itor = mBanList.begin();
01476         while (itor != mBanList.end())
01477         {
01478                 const LLAccessEntry& entry = (*itor).second;
01479                 if (entry.mID == agent_id)
01480                 {
01481                         if (time == 0 || (entry.mTime != 0 && entry.mTime < time))
01482                         {
01483                                 mBanList.erase(itor++);
01484                         }
01485                         else
01486                         {
01487                                 // existing one expires later
01488                                 return FALSE;
01489                         }
01490                 }
01491                 else
01492                 {
01493                         ++itor;
01494                 }
01495         }
01496 
01497         removeFromAccessList(agent_id);
01498 
01499         LLAccessEntry new_entry;
01500         new_entry.mID    = agent_id;
01501         new_entry.mTime  = time;
01502         new_entry.mFlags = 0x0;
01503         mBanList[new_entry.mID] = new_entry;
01504         return TRUE;
01505 }
01506 
01507 BOOL remove_from_access_array(std::map<LLUUID,LLAccessEntry>* list,
01508                                                          const LLUUID& agent_id)
01509 {
01510         BOOL removed = FALSE;
01511         access_map_iterator itor = list->begin();
01512         while (itor != list->end())
01513         {
01514                 const LLAccessEntry& entry = (*itor).second;
01515                 if (entry.mID == agent_id)
01516                 {
01517                         list->erase(itor++);
01518                         removed = TRUE;
01519                 }
01520                 else
01521                 {
01522                         ++itor;
01523                 }
01524         }
01525         return removed;
01526 }
01527 
01528 BOOL LLParcel::removeFromAccessList(const LLUUID& agent_id)
01529 {
01530         return remove_from_access_array(&mAccessList, agent_id);
01531 }
01532 
01533 BOOL LLParcel::removeFromBanList(const LLUUID& agent_id)
01534 {
01535         return remove_from_access_array(&mBanList, agent_id);
01536 }
01537 
01538 // static
01539 const char* LLParcel::getOwnershipStatusString(EOwnershipStatus status)
01540 {
01541         return ownership_status_to_string(status);
01542 }
01543 
01544 // static
01545 const char* LLParcel::getCategoryString(ECategory category)
01546 {
01547         return category_to_string(category);
01548 }
01549 
01550 // static
01551 const char* LLParcel::getCategoryUIString(ECategory category)
01552 {
01553         return category_to_ui_string(category);
01554 }
01555 
01556 // static
01557 LLParcel::ECategory LLParcel::getCategoryFromString(const char* string)
01558 {
01559         return category_string_to_category(string);
01560 }
01561 
01562 // static
01563 LLParcel::ECategory LLParcel::getCategoryFromUIString(const char* string)
01564 {
01565         return category_ui_string_to_category(string);
01566 }
01567 
01568 // static
01569 const char* LLParcel::getActionString(LLParcel::EAction action)
01570 {
01571         S32 index = 0;
01572         if((action >= 0) && (action < LLParcel::A_COUNT))
01573         {
01574                 index = action;
01575         }
01576         else
01577         {
01578                 index = A_COUNT;
01579         }
01580         return PARCEL_ACTION_STRING[index];
01581 }
01582 
01583 BOOL LLParcel::isSaleTimerExpired(const U64& time)
01584 {
01585         if (mSaleTimerExpires.getStarted() == FALSE)
01586         {
01587                 return FALSE;
01588         }
01589         BOOL expired = mSaleTimerExpires.checkExpirationAndReset(0.0);
01590         if (expired)
01591         {
01592                 mSaleTimerExpires.stop();
01593         }
01594         return expired;
01595 }
01596 
01597 
01598 void LLParcel::startSale(const LLUUID& buyer_id, BOOL is_buyer_group)
01599 {
01600         // TODO -- this and all Sale related methods need to move out of the LLParcel 
01601         // base class and into server-side-only LLSimParcel class
01602         setPreviousOwnerID(mOwnerID);
01603         setPreviouslyGroupOwned(mGroupOwned);
01604 
01605         mOwnerID = buyer_id;
01606         mGroupOwned = is_buyer_group;
01607         if(mGroupOwned)
01608         {
01609                 mGroupID = mOwnerID;
01610         }
01611         else
01612         {
01613                 mGroupID.setNull();
01614         }
01615         mSaleTimerExpires.start();
01616         mSaleTimerExpires.setTimerExpirySec(DEFAULT_USEC_SALE_TIMEOUT / SEC_TO_MICROSEC);
01617         mStatus = OS_LEASE_PENDING;
01618         mClaimDate = time(NULL);
01619         setAuctionID(0);
01620         // clear the autoreturn whenever land changes hands
01621         setCleanOtherTime(0);
01622 }
01623 
01624 void LLParcel::expireSale(U32& type, U8& flags, LLUUID& from_id, LLUUID& to_id)
01625 {
01626         mSaleTimerExpires.setTimerExpirySec(0.0);
01627         mSaleTimerExpires.stop();
01628         setPreviousOwnerID(LLUUID::null);
01629         setPreviouslyGroupOwned(FALSE);
01630         setSellWithObjects(FALSE);
01631         type = TRANS_LAND_RELEASE;
01632         mStatus = OS_NONE;
01633         flags = pack_transaction_flags(mGroupOwned, FALSE);
01634         mAuthBuyerID.setNull();
01635         from_id = mOwnerID;
01636         mOwnerID.setNull();
01637         to_id.setNull();
01638 }
01639 
01640 void LLParcel::completeSale(U32& type, U8& flags,
01641                                                     LLUUID& to_id)
01642 {
01643         mSaleTimerExpires.setTimerExpirySec(0.0);
01644         mSaleTimerExpires.stop();
01645         mStatus = OS_LEASED;
01646         type = TRANS_LAND_SALE;
01647         flags = pack_transaction_flags(mGroupOwned, mGroupOwned);
01648         to_id = mOwnerID;
01649         mAuthBuyerID.setNull();
01650 
01651         // Purchased parcels are assumed to no longer be for sale.
01652         // Otherwise someone can snipe the sale.
01653         setForSale(FALSE);
01654         setAuctionID(0);
01655 
01656         // Turn off show directory, since it's a recurring fee that
01657         // the buyer may not want.
01658         setParcelFlag(PF_SHOW_DIRECTORY, FALSE);
01659 
01660         //should be cleared on sale.
01661         mAccessList.clear();
01662         mBanList.clear();
01663         
01664 }
01665 
01666 void LLParcel::clearSale()
01667 {
01668         mSaleTimerExpires.setTimerExpirySec(0.0);
01669         mSaleTimerExpires.stop();
01670         if(isPublic())
01671         {
01672                 mStatus = OS_NONE;
01673         }
01674         else
01675         {
01676                 mStatus = OS_LEASED;
01677         }
01678         mAuthBuyerID.setNull();
01679         setForSale(FALSE);
01680         setAuctionID(0);
01681         setPreviousOwnerID(LLUUID::null);
01682         setPreviouslyGroupOwned(FALSE);
01683         setSellWithObjects(FALSE);
01684 }
01685 
01686 BOOL LLParcel::isPublic() const
01687 {
01688         return (mOwnerID.isNull());
01689 }
01690 
01691 BOOL LLParcel::isBuyerAuthorized(const LLUUID& buyer_id) const
01692 {
01693         if(mAuthBuyerID.isNull())
01694         {
01695                 return TRUE;
01696         }
01697         return (mAuthBuyerID == buyer_id);
01698 }
01699 
01700 void LLParcel::clearParcel()
01701 {
01702         overrideParcelFlags(PF_DEFAULT);
01703         setName(NULL);
01704         setDesc(NULL);
01705         setMusicURL(NULL);
01706         setMediaURL(NULL);
01707         setMediaID(LLUUID::null);
01708         setMediaAutoScale(0);
01709         setInEscrow(FALSE);
01710         setAuthorizedBuyerID(LLUUID::null);
01711         setCategory(C_NONE);
01712         setSnapshotID(LLUUID::null);
01713         setUserLocation(LLVector3::zero);
01714         setUserLookAt(LLVector3::x_axis);
01715         setLandingType(L_LANDING_POINT);
01716         setAuctionID(0);
01717         setGroupID(LLUUID::null);
01718         setPassPrice(0);
01719         setPassHours(0.f);
01720         mAccessList.clear();
01721         mBanList.clear();
01722         //mRenterList.reset();
01723 }
01724 
01725 void LLParcel::dump()
01726 {
01727         llinfos << "parcel " << mLocalID << " area " << mArea << llendl;
01728         llinfos << "  name <" << mName << ">" << llendl;
01729         llinfos << "  desc <" << mDesc << ">" << llendl;
01730 }
01731 
01732 const char* ownership_status_to_string(LLParcel::EOwnershipStatus status)
01733 {
01734         if(status >= 0 && status < LLParcel::OS_COUNT)
01735         {
01736                 return PARCEL_OWNERSHIP_STATUS_STRING[status];
01737         }
01738         return "none";
01739 }
01740 
01741 LLParcel::EOwnershipStatus ownership_string_to_status(const char* s)
01742 {
01743         for(S32 i = 0; i < LLParcel::OS_COUNT; ++i)
01744         {
01745                 if(0 == strcmp(s, PARCEL_OWNERSHIP_STATUS_STRING[i]))
01746                 {
01747                         return (LLParcel::EOwnershipStatus)i;
01748                 }
01749         }
01750         return LLParcel::OS_NONE;
01751 }
01752 
01753 //const char* revert_action_to_string(LLParcel::ESaleTimerExpireAction action)
01754 //{
01755 //      S32 index = 0;
01756 //      if(action >= 0 && action < LLParcel::STEA_COUNT)
01757 //      {
01758 //              index = action;
01759 //      }
01760 //      return PARCEL_SALE_TIMER_ACTION[index];
01761 //}
01762 
01763 //LLParcel::ESaleTimerExpireAction revert_string_to_action(const char* s)
01764 //{
01765 //      for(S32 i = 0; i < LLParcel::STEA_COUNT; ++i)
01766 //      {
01767 //              if(0 == strcmp(s, PARCEL_SALE_TIMER_ACTION[i]))
01768 //              {
01769 //                      return (LLParcel::ESaleTimerExpireAction)i;
01770 //              }
01771 //      }
01772 //      return LLParcel::STEA_REVERT;
01773 //}
01774 
01775 const char* category_to_string(LLParcel::ECategory category)
01776 {
01777         S32 index = 0;
01778         if((category >= 0) && (category < LLParcel::C_COUNT))
01779         {
01780                 index = category;
01781         }
01782         return PARCEL_CATEGORY_STRING[index];
01783 }
01784 
01785 const char* category_to_ui_string(LLParcel::ECategory category)
01786 {
01787         S32 index = 0;
01788         if((category >= 0) && (category < LLParcel::C_COUNT))
01789         {
01790                 index = category;
01791         }
01792         else
01793         {
01794                 // C_ANY = -1 , but the "Any" string is at the end of the list
01795                 index = ((S32) LLParcel::C_COUNT);
01796         }
01797         return PARCEL_CATEGORY_UI_STRING[index];
01798 }
01799 
01800 LLParcel::ECategory category_string_to_category(const char* s)
01801 {
01802         for(S32 i = 0; i < LLParcel::C_COUNT; ++i)
01803         {
01804                 if(0 == strcmp(s, PARCEL_CATEGORY_STRING[i]))
01805                 {
01806                         return (LLParcel::ECategory)i;
01807                 }
01808         }
01809         llwarns << "Parcel category outside of possibilities " << s << llendl;
01810         return LLParcel::C_NONE;
01811 }
01812 
01813 LLParcel::ECategory category_ui_string_to_category(const char* s)
01814 {
01815         for(S32 i = 0; i < LLParcel::C_COUNT; ++i)
01816         {
01817                 if(0 == strcmp(s, PARCEL_CATEGORY_UI_STRING[i]))
01818                 {
01819                         return (LLParcel::ECategory)i;
01820                 }
01821         }
01822         // "Any" is a valid category for searches, and
01823         // is a distinct option from "None" and "Other"
01824         return LLParcel::C_ANY;
01825 }
01826 
01827 

Generated on Thu Jul 1 06:08:59 2010 for Second Life Viewer by  doxygen 1.4.7