diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llinventory | |
parent | README.txt (diff) | |
download | meta-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')
25 files changed, 9176 insertions, 0 deletions
diff --git a/linden/indra/llinventory/files.lst b/linden/indra/llinventory/files.lst new file mode 100644 index 0000000..c96cd03 --- /dev/null +++ b/linden/indra/llinventory/files.lst | |||
@@ -0,0 +1,10 @@ | |||
1 | llinventory/llcategory.cpp | ||
2 | llinventory/lleconomy.cpp | ||
3 | llinventory/llinventory.cpp | ||
4 | llinventory/lllandmark.cpp | ||
5 | llinventory/llnotecard.cpp | ||
6 | llinventory/llparcel.cpp | ||
7 | llinventory/llpermissions.cpp | ||
8 | llinventory/llsaleinfo.cpp | ||
9 | llinventory/lltransactionflags.cpp | ||
10 | llinventory/lluserrelations.cpp | ||
diff --git a/linden/indra/llinventory/llcategory.cpp b/linden/indra/llinventory/llcategory.cpp new file mode 100644 index 0000000..e27733c --- /dev/null +++ b/linden/indra/llinventory/llcategory.cpp | |||
@@ -0,0 +1,180 @@ | |||
1 | /** | ||
2 | * @file llcategory.cpp | ||
3 | * | ||
4 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
5 | * | ||
6 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
7 | * to you under the terms of the GNU General Public License, version 2.0 | ||
8 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
9 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
10 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
11 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
12 | * | ||
13 | * There are special exceptions to the terms and conditions of the GPL as | ||
14 | * it is applied to this Source Code. View the full text of the exception | ||
15 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/flossexception | ||
17 | * | ||
18 | * By copying, modifying or distributing this software, you acknowledge | ||
19 | * that you have read and understood your obligations described above, | ||
20 | * and agree to abide by those obligations. | ||
21 | * | ||
22 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
23 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
24 | * COMPLETENESS OR PERFORMANCE. | ||
25 | */ | ||
26 | |||
27 | #include "linden_common.h" | ||
28 | |||
29 | #include "llcategory.h" | ||
30 | |||
31 | #include "message.h" | ||
32 | |||
33 | const LLCategory LLCategory::none; | ||
34 | |||
35 | ///---------------------------------------------------------------------------- | ||
36 | /// Local function declarations, constants, enums, and typedefs | ||
37 | ///---------------------------------------------------------------------------- | ||
38 | |||
39 | // This is the storage of the category names. It's loosely based on a | ||
40 | // heap-like structure with indices into it for faster searching and | ||
41 | // so that we don't have to maintain a balanced heap. It's *VITALLY* | ||
42 | // important that the CATEGORY_INDEX and CATEGORY_NAME tables are kept | ||
43 | // in synch. | ||
44 | |||
45 | // CATEGORY_INDEX indexes into CATEGORY_NAME at the first occurance of | ||
46 | // a child. Thus, the first child of root is "Object" which is located | ||
47 | // in CATEGORY_NAME[1]. | ||
48 | const S32 CATEGORY_INDEX[] = | ||
49 | { | ||
50 | 1, // ROOT | ||
51 | 6, // object | ||
52 | 7, // clothing | ||
53 | 7, // texture | ||
54 | 7, // sound | ||
55 | 7, // landmark | ||
56 | 7, // object|component | ||
57 | 7, // off the end (required for child count calculations) | ||
58 | }; | ||
59 | |||
60 | // The heap of names | ||
61 | const char* CATEGORY_NAME[] = | ||
62 | { | ||
63 | "(none)", | ||
64 | "Object", // (none) | ||
65 | "Clothing", | ||
66 | "Texture", | ||
67 | "Sound", | ||
68 | "Landmark", | ||
69 | "Component", // object | ||
70 | NULL | ||
71 | }; | ||
72 | |||
73 | ///---------------------------------------------------------------------------- | ||
74 | /// Class llcategory | ||
75 | ///---------------------------------------------------------------------------- | ||
76 | |||
77 | LLCategory::LLCategory() | ||
78 | { | ||
79 | // this is used as a simple compile time assertion. If this code | ||
80 | // fails to compile, the depth has been changed, and we need to | ||
81 | // clean up some of the code that relies on the depth, such as the | ||
82 | // default constructor. If CATEGORY_DEPTH != 4, this code will | ||
83 | // attempt to construct a zero length array - which the compiler | ||
84 | // should balk at. | ||
85 | // static const char CATEGORY_DEPTH_CHECK[(CATEGORY_DEPTH == 4)?1:0] = {' '}; // unused | ||
86 | |||
87 | // actually initialize the object. | ||
88 | mData[0] = 0; | ||
89 | mData[1] = 0; | ||
90 | mData[2] = 0; | ||
91 | mData[3] = 0; | ||
92 | } | ||
93 | |||
94 | void LLCategory::init(U32 value) | ||
95 | { | ||
96 | U8 v; | ||
97 | for(S32 i = 0; i < CATEGORY_DEPTH; i++) | ||
98 | { | ||
99 | v = (U8)((0x000000ff) & value); | ||
100 | mData[CATEGORY_DEPTH - 1 - i] = v; | ||
101 | value >>= 8; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | U32 LLCategory::getU32() const | ||
106 | { | ||
107 | U32 rv = 0; | ||
108 | rv |= mData[0]; | ||
109 | rv <<= 8; | ||
110 | rv |= mData[1]; | ||
111 | rv <<= 8; | ||
112 | rv |= mData[2]; | ||
113 | rv <<= 8; | ||
114 | rv |= mData[3]; | ||
115 | return rv; | ||
116 | } | ||
117 | |||
118 | S32 LLCategory::getSubCategoryCount() const | ||
119 | { | ||
120 | S32 rv = CATEGORY_INDEX[mData[0] + 1] - CATEGORY_INDEX[mData[0]]; | ||
121 | return rv; | ||
122 | } | ||
123 | |||
124 | // This method will return a category that is the nth subcategory. If | ||
125 | // you're already at the bottom of the hierarchy, then the method will | ||
126 | // return a copy of this. | ||
127 | LLCategory LLCategory::getSubCategory(U8 n) const | ||
128 | { | ||
129 | LLCategory rv(*this); | ||
130 | for(S32 i = 0; i < (CATEGORY_DEPTH - 1); i++) | ||
131 | { | ||
132 | if(rv.mData[i] == 0) | ||
133 | { | ||
134 | rv.mData[i] = n + 1; | ||
135 | break; | ||
136 | } | ||
137 | } | ||
138 | return rv; | ||
139 | } | ||
140 | |||
141 | // This method will return the name of the leaf category type | ||
142 | const char* LLCategory::lookupName() const | ||
143 | { | ||
144 | S32 i = 0; | ||
145 | S32 index = mData[i++]; | ||
146 | while((i < CATEGORY_DEPTH) && (mData[i] != 0)) | ||
147 | { | ||
148 | index = CATEGORY_INDEX[index]; | ||
149 | ++i; | ||
150 | } | ||
151 | return CATEGORY_NAME[index]; | ||
152 | } | ||
153 | |||
154 | // message serialization | ||
155 | void LLCategory::packMessage(LLMessageSystem* msg) const | ||
156 | { | ||
157 | U32 data = getU32(); | ||
158 | msg->addU32Fast(_PREHASH_Category, data); | ||
159 | } | ||
160 | |||
161 | // message serialization | ||
162 | void LLCategory::unpackMessage(LLMessageSystem* msg, const char* block) | ||
163 | { | ||
164 | U32 data; | ||
165 | msg->getU32Fast(block, _PREHASH_Category, data); | ||
166 | init(data); | ||
167 | } | ||
168 | |||
169 | // message serialization | ||
170 | void LLCategory::unpackMultiMessage(LLMessageSystem* msg, const char* block, | ||
171 | S32 block_num) | ||
172 | { | ||
173 | U32 data; | ||
174 | msg->getU32Fast(block, _PREHASH_Category, data, block_num); | ||
175 | init(data); | ||
176 | } | ||
177 | |||
178 | ///---------------------------------------------------------------------------- | ||
179 | /// Local function definitions | ||
180 | ///---------------------------------------------------------------------------- | ||
diff --git a/linden/indra/llinventory/llcategory.h b/linden/indra/llinventory/llcategory.h new file mode 100644 index 0000000..f566987 --- /dev/null +++ b/linden/indra/llinventory/llcategory.h | |||
@@ -0,0 +1,99 @@ | |||
1 | /** | ||
2 | * @file llcategory.h | ||
3 | * @brief LLCategory class header file. | ||
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 | #ifndef LL_LLCATEGORY_H | ||
29 | #define LL_LLCATEGORY_H | ||
30 | |||
31 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
32 | // Class LLCategory | ||
33 | // | ||
34 | // An instance of the LLCategory class represents a particular | ||
35 | // category in a hierarchical classification system. For now, it is 4 | ||
36 | // levels deep with 255 (minus 1) possible values at each level. If a | ||
37 | // non zero value is found at level 4, that is the leaf category, | ||
38 | // otherwise, it is the first level that has a 0 in the next depth | ||
39 | // level. | ||
40 | // | ||
41 | // To output the names of all top level categories, you could do the | ||
42 | // following: | ||
43 | // | ||
44 | // S32 count = LLCategory::none.getSubCategoryCount(); | ||
45 | // for(S32 i = 0; i < count; i++) | ||
46 | // { | ||
47 | // llinfos << none.getSubCategory(i).lookupNmae() << llendl; | ||
48 | // } | ||
49 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
50 | |||
51 | class LLMessageSystem; | ||
52 | |||
53 | class LLCategory | ||
54 | { | ||
55 | public: | ||
56 | // Nice default static const. | ||
57 | static const LLCategory none; | ||
58 | |||
59 | // construction. Since this is really a POD type, destruction, | ||
60 | // copy, and assignment are handled by the compiler. | ||
61 | LLCategory(); | ||
62 | explicit LLCategory(U32 value) { init(value); } | ||
63 | |||
64 | // methods | ||
65 | void init(U32 value); | ||
66 | U32 getU32() const; | ||
67 | S32 getSubCategoryCount() const; | ||
68 | |||
69 | // This method will return a category that is the nth | ||
70 | // subcategory. If you're already at the bottom of the hierarchy, | ||
71 | // then the method will return a copy of this. | ||
72 | LLCategory getSubCategory(U8 n) const; | ||
73 | |||
74 | // This method will return the name of the leaf category type | ||
75 | const char* lookupName() const; | ||
76 | |||
77 | // This method will return the full hierarchy name in an easily | ||
78 | // interpreted (TOP)|(SUB1)|(SUB2) format. *NOTE: not implemented | ||
79 | // because we don't have anything but top level categories at the | ||
80 | // moment. | ||
81 | //const char* lookupFullName() const; | ||
82 | |||
83 | // message serialization | ||
84 | void packMessage(LLMessageSystem* msg) const; | ||
85 | void unpackMessage(LLMessageSystem* msg, const char* block); | ||
86 | void unpackMultiMessage(LLMessageSystem* msg, const char* block, | ||
87 | S32 block_num); | ||
88 | protected: | ||
89 | enum | ||
90 | { | ||
91 | CATEGORY_TOP = 0, | ||
92 | CATEGORY_DEPTH = 4, | ||
93 | }; | ||
94 | |||
95 | U8 mData[CATEGORY_DEPTH]; | ||
96 | }; | ||
97 | |||
98 | |||
99 | #endif // LL_LLCATEGORY_H | ||
diff --git a/linden/indra/llinventory/lleconomy.cpp b/linden/indra/llinventory/lleconomy.cpp new file mode 100644 index 0000000..2337a3e --- /dev/null +++ b/linden/indra/llinventory/lleconomy.cpp | |||
@@ -0,0 +1,246 @@ | |||
1 | /** | ||
2 | * @file lleconomy.cpp | ||
3 | * | ||
4 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
5 | * | ||
6 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
7 | * to you under the terms of the GNU General Public License, version 2.0 | ||
8 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
9 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
10 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
11 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
12 | * | ||
13 | * There are special exceptions to the terms and conditions of the GPL as | ||
14 | * it is applied to this Source Code. View the full text of the exception | ||
15 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/flossexception | ||
17 | * | ||
18 | * By copying, modifying or distributing this software, you acknowledge | ||
19 | * that you have read and understood your obligations described above, | ||
20 | * and agree to abide by those obligations. | ||
21 | * | ||
22 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
23 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
24 | * COMPLETENESS OR PERFORMANCE. | ||
25 | */ | ||
26 | |||
27 | #include "linden_common.h" | ||
28 | |||
29 | #include "lleconomy.h" | ||
30 | #include "llerror.h" | ||
31 | #include "message.h" | ||
32 | #include "v3math.h" | ||
33 | |||
34 | LLGlobalEconomy::LLGlobalEconomy() | ||
35 | : mObjectCount( -1 ), | ||
36 | mObjectCapacity( -1 ), | ||
37 | mPriceObjectClaim( -1 ), | ||
38 | mPricePublicObjectDecay( -1 ), | ||
39 | mPricePublicObjectDelete( -1 ), | ||
40 | mPriceEnergyUnit( -1 ), | ||
41 | mPriceUpload( -1 ), | ||
42 | mPriceRentLight( -1 ), | ||
43 | mTeleportMinPrice( -1 ), | ||
44 | mTeleportPriceExponent( -1 ), | ||
45 | mPriceGroupCreate( -1 ) | ||
46 | { } | ||
47 | |||
48 | LLGlobalEconomy::~LLGlobalEconomy() | ||
49 | { } | ||
50 | |||
51 | // static | ||
52 | void LLGlobalEconomy::processEconomyData(LLMessageSystem *msg, void** user_data) | ||
53 | { | ||
54 | S32 i; | ||
55 | F32 f; | ||
56 | |||
57 | LLGlobalEconomy *this_ptr = (LLGlobalEconomy*)user_data; | ||
58 | |||
59 | msg->getS32Fast(_PREHASH_Info, _PREHASH_ObjectCapacity, i); | ||
60 | this_ptr->setObjectCapacity(i); | ||
61 | msg->getS32Fast(_PREHASH_Info, _PREHASH_ObjectCount, i); | ||
62 | this_ptr->setObjectCount(i); | ||
63 | msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceEnergyUnit, i); | ||
64 | this_ptr->setPriceEnergyUnit(i); | ||
65 | msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceObjectClaim, i); | ||
66 | this_ptr->setPriceObjectClaim(i); | ||
67 | msg->getS32Fast(_PREHASH_Info, _PREHASH_PricePublicObjectDecay, i); | ||
68 | this_ptr->setPricePublicObjectDecay(i); | ||
69 | msg->getS32Fast(_PREHASH_Info, _PREHASH_PricePublicObjectDelete, i); | ||
70 | this_ptr->setPricePublicObjectDelete(i); | ||
71 | msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceUpload, i); | ||
72 | this_ptr->setPriceUpload(i); | ||
73 | msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceRentLight, i); | ||
74 | this_ptr->setPriceRentLight(i); | ||
75 | msg->getS32Fast(_PREHASH_Info, _PREHASH_TeleportMinPrice, i); | ||
76 | this_ptr->setTeleportMinPrice(i); | ||
77 | msg->getF32Fast(_PREHASH_Info, _PREHASH_TeleportPriceExponent, f); | ||
78 | this_ptr->setTeleportPriceExponent(f); | ||
79 | msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceGroupCreate, i); | ||
80 | this_ptr->setPriceGroupCreate(i); | ||
81 | } | ||
82 | |||
83 | S32 LLGlobalEconomy::calculateTeleportCost(F32 distance) const | ||
84 | { | ||
85 | S32 min_cost = getTeleportMinPrice(); | ||
86 | F32 exponent = getTeleportPriceExponent(); | ||
87 | F32 divisor = 100.f * pow(3.f, exponent); | ||
88 | S32 cost = (U32)(distance * pow(log10(distance), exponent) / divisor); | ||
89 | if (cost < 0) | ||
90 | { | ||
91 | cost = 0; | ||
92 | } | ||
93 | else if (cost < min_cost) | ||
94 | { | ||
95 | cost = min_cost; | ||
96 | } | ||
97 | |||
98 | return cost; | ||
99 | } | ||
100 | |||
101 | S32 LLGlobalEconomy::calculateLightRent(const LLVector3& object_size) const | ||
102 | { | ||
103 | F32 intensity_mod = llmax(object_size.magVec(), 1.f); | ||
104 | return (S32)(intensity_mod * getPriceRentLight()); | ||
105 | } | ||
106 | |||
107 | void LLGlobalEconomy::print() | ||
108 | { | ||
109 | llinfos << "Global Economy Settings: " << llendl; | ||
110 | llinfos << "Object Capacity: " << mObjectCapacity << llendl; | ||
111 | llinfos << "Object Count: " << mObjectCount << llendl; | ||
112 | llinfos << "Claim Price Per Object: " << mPriceObjectClaim << llendl; | ||
113 | llinfos << "Claim Price Per Public Object: " << mPricePublicObjectDecay << llendl; | ||
114 | llinfos << "Delete Price Per Public Object: " << mPricePublicObjectDelete << llendl; | ||
115 | llinfos << "Release Price Per Public Object: " << getPricePublicObjectRelease() << llendl; | ||
116 | llinfos << "Price Per Energy Unit: " << mPriceEnergyUnit << llendl; | ||
117 | llinfos << "Price Per Upload: " << mPriceUpload << llendl; | ||
118 | llinfos << "Light Base Price: " << mPriceRentLight << llendl; | ||
119 | llinfos << "Teleport Min Price: " << mTeleportMinPrice << llendl; | ||
120 | llinfos << "Teleport Price Exponent: " << mTeleportPriceExponent << llendl; | ||
121 | llinfos << "Price for group creation: " << mPriceGroupCreate << llendl; | ||
122 | } | ||
123 | |||
124 | LLRegionEconomy::LLRegionEconomy() | ||
125 | : LLGlobalEconomy(), | ||
126 | mPriceObjectRent( -1.f ), | ||
127 | mPriceObjectScaleFactor( -1.f ), | ||
128 | mEnergyEfficiency( -1.f ), | ||
129 | mBasePriceParcelClaimDefault(-1), | ||
130 | mBasePriceParcelClaimActual(-1), | ||
131 | mPriceParcelClaimFactor(-1.f), | ||
132 | mBasePriceParcelRent(-1), | ||
133 | mAreaOwned(-1.f), | ||
134 | mAreaTotal(-1.f) | ||
135 | { } | ||
136 | |||
137 | LLRegionEconomy::~LLRegionEconomy() | ||
138 | { } | ||
139 | |||
140 | BOOL LLRegionEconomy::hasData() const | ||
141 | { | ||
142 | return (mBasePriceParcelRent != -1); | ||
143 | } | ||
144 | |||
145 | // static | ||
146 | void LLRegionEconomy::processEconomyData(LLMessageSystem *msg, void** user_data) | ||
147 | { | ||
148 | S32 i; | ||
149 | F32 f; | ||
150 | |||
151 | LLGlobalEconomy::processEconomyData(msg, user_data); | ||
152 | |||
153 | LLRegionEconomy *this_ptr = (LLRegionEconomy*)user_data; | ||
154 | |||
155 | msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceParcelClaim, i); | ||
156 | this_ptr->setBasePriceParcelClaimDefault(i); | ||
157 | msg->getF32(_PREHASH_Info, _PREHASH_PriceParcelClaimFactor, f); | ||
158 | this_ptr->setPriceParcelClaimFactor(f); | ||
159 | msg->getF32Fast(_PREHASH_Info, _PREHASH_EnergyEfficiency, f); | ||
160 | this_ptr->setEnergyEfficiency(f); | ||
161 | msg->getF32Fast(_PREHASH_Info, _PREHASH_PriceObjectRent, f); | ||
162 | this_ptr->setPriceObjectRent(f); | ||
163 | msg->getF32Fast(_PREHASH_Info, _PREHASH_PriceObjectScaleFactor, f); | ||
164 | this_ptr->setPriceObjectScaleFactor(f); | ||
165 | msg->getS32Fast(_PREHASH_Info, _PREHASH_PriceParcelRent, i); | ||
166 | this_ptr->setBasePriceParcelRent(i); | ||
167 | } | ||
168 | |||
169 | // static | ||
170 | void LLRegionEconomy::processEconomyDataRequest(LLMessageSystem *msg, void **user_data) | ||
171 | { | ||
172 | LLRegionEconomy *this_ptr = (LLRegionEconomy*)user_data; | ||
173 | |||
174 | msg->newMessageFast(_PREHASH_EconomyData); | ||
175 | msg->nextBlockFast(_PREHASH_Info); | ||
176 | msg->addS32Fast(_PREHASH_ObjectCapacity, this_ptr->getObjectCapacity()); | ||
177 | msg->addS32Fast(_PREHASH_ObjectCount, this_ptr->getObjectCount()); | ||
178 | msg->addS32Fast(_PREHASH_PriceEnergyUnit, this_ptr->getPriceEnergyUnit()); | ||
179 | msg->addS32Fast(_PREHASH_PriceObjectClaim, this_ptr->getPriceObjectClaim()); | ||
180 | msg->addS32Fast(_PREHASH_PricePublicObjectDecay, this_ptr->getPricePublicObjectDecay()); | ||
181 | msg->addS32Fast(_PREHASH_PricePublicObjectDelete, this_ptr->getPricePublicObjectDelete()); | ||
182 | msg->addS32Fast(_PREHASH_PriceParcelClaim, this_ptr->mBasePriceParcelClaimActual); | ||
183 | msg->addF32Fast(_PREHASH_PriceParcelClaimFactor, this_ptr->mPriceParcelClaimFactor); | ||
184 | msg->addS32Fast(_PREHASH_PriceUpload, this_ptr->getPriceUpload()); | ||
185 | msg->addS32Fast(_PREHASH_PriceRentLight, this_ptr->getPriceRentLight()); | ||
186 | msg->addS32Fast(_PREHASH_TeleportMinPrice, this_ptr->getTeleportMinPrice()); | ||
187 | msg->addF32Fast(_PREHASH_TeleportPriceExponent, this_ptr->getTeleportPriceExponent()); | ||
188 | |||
189 | msg->addF32Fast(_PREHASH_EnergyEfficiency, this_ptr->getEnergyEfficiency()); | ||
190 | msg->addF32Fast(_PREHASH_PriceObjectRent, this_ptr->getPriceObjectRent()); | ||
191 | msg->addF32Fast(_PREHASH_PriceObjectScaleFactor, this_ptr->getPriceObjectScaleFactor()); | ||
192 | msg->addS32Fast(_PREHASH_PriceParcelRent, this_ptr->getPriceParcelRent()); | ||
193 | msg->addS32Fast(_PREHASH_PriceGroupCreate, this_ptr->getPriceGroupCreate()); | ||
194 | |||
195 | msg->sendReliable(msg->getSender()); | ||
196 | } | ||
197 | |||
198 | |||
199 | S32 LLRegionEconomy::getPriceParcelClaim() const | ||
200 | { | ||
201 | //return (S32)((F32)mBasePriceParcelClaim * (mAreaTotal / (mAreaTotal - mAreaOwned))); | ||
202 | return (S32)((F32)mBasePriceParcelClaimActual * mPriceParcelClaimFactor); | ||
203 | } | ||
204 | |||
205 | S32 LLRegionEconomy::getPriceParcelRent() const | ||
206 | { | ||
207 | return mBasePriceParcelRent; | ||
208 | } | ||
209 | |||
210 | |||
211 | void LLRegionEconomy::print() | ||
212 | { | ||
213 | this->LLGlobalEconomy::print(); | ||
214 | |||
215 | llinfos << "Region Economy Settings: " << llendl; | ||
216 | llinfos << "Land (square meters): " << mAreaTotal << llendl; | ||
217 | llinfos << "Owned Land (square meters): " << mAreaOwned << llendl; | ||
218 | llinfos << "Daily Object Rent: " << mPriceObjectRent << llendl; | ||
219 | llinfos << "Daily Land Rent (per meter): " << getPriceParcelRent() << llendl; | ||
220 | llinfos << "Energey Efficiency: " << mEnergyEfficiency << llendl; | ||
221 | } | ||
222 | |||
223 | |||
224 | void LLRegionEconomy::setBasePriceParcelClaimDefault(S32 val) | ||
225 | { | ||
226 | mBasePriceParcelClaimDefault = val; | ||
227 | if(mBasePriceParcelClaimActual == -1) | ||
228 | { | ||
229 | mBasePriceParcelClaimActual = val; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | void LLRegionEconomy::setBasePriceParcelClaimActual(S32 val) | ||
234 | { | ||
235 | mBasePriceParcelClaimActual = val; | ||
236 | } | ||
237 | |||
238 | void LLRegionEconomy::setPriceParcelClaimFactor(F32 val) | ||
239 | { | ||
240 | mPriceParcelClaimFactor = val; | ||
241 | } | ||
242 | |||
243 | void LLRegionEconomy::setBasePriceParcelRent(S32 val) | ||
244 | { | ||
245 | mBasePriceParcelRent = val; | ||
246 | } | ||
diff --git a/linden/indra/llinventory/lleconomy.h b/linden/indra/llinventory/lleconomy.h new file mode 100644 index 0000000..7690142 --- /dev/null +++ b/linden/indra/llinventory/lleconomy.h | |||
@@ -0,0 +1,135 @@ | |||
1 | /** | ||
2 | * @file lleconomy.h | ||
3 | * | ||
4 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
5 | * | ||
6 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
7 | * to you under the terms of the GNU General Public License, version 2.0 | ||
8 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
9 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
10 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
11 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
12 | * | ||
13 | * There are special exceptions to the terms and conditions of the GPL as | ||
14 | * it is applied to this Source Code. View the full text of the exception | ||
15 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/flossexception | ||
17 | * | ||
18 | * By copying, modifying or distributing this software, you acknowledge | ||
19 | * that you have read and understood your obligations described above, | ||
20 | * and agree to abide by those obligations. | ||
21 | * | ||
22 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
23 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
24 | * COMPLETENESS OR PERFORMANCE. | ||
25 | */ | ||
26 | |||
27 | #ifndef LL_LLECONOMY_H | ||
28 | #define LL_LLECONOMY_H | ||
29 | |||
30 | class LLMessageSystem; | ||
31 | class LLVector3; | ||
32 | |||
33 | class LLGlobalEconomy | ||
34 | { | ||
35 | public: | ||
36 | LLGlobalEconomy(); | ||
37 | virtual ~LLGlobalEconomy(); | ||
38 | |||
39 | virtual void print(); | ||
40 | |||
41 | static void processEconomyData(LLMessageSystem *msg, void **user_data); | ||
42 | |||
43 | S32 calculateTeleportCost(F32 distance) const; | ||
44 | S32 calculateLightRent(const LLVector3& object_size) const; | ||
45 | |||
46 | S32 getObjectCount() const { return mObjectCount; } | ||
47 | S32 getObjectCapacity() const { return mObjectCapacity; } | ||
48 | S32 getPriceObjectClaim() const { return mPriceObjectClaim; } | ||
49 | S32 getPricePublicObjectDecay() const { return mPricePublicObjectDecay; } | ||
50 | S32 getPricePublicObjectDelete() const { return mPricePublicObjectDelete; } | ||
51 | S32 getPricePublicObjectRelease() const { return mPriceObjectClaim - mPricePublicObjectDelete; } | ||
52 | S32 getPriceEnergyUnit() const { return mPriceEnergyUnit; } | ||
53 | S32 getPriceUpload() const { return mPriceUpload; } | ||
54 | S32 getPriceRentLight() const { return mPriceRentLight; } | ||
55 | S32 getTeleportMinPrice() const { return mTeleportMinPrice; } | ||
56 | F32 getTeleportPriceExponent() const { return mTeleportPriceExponent; } | ||
57 | S32 getPriceGroupCreate() const { return mPriceGroupCreate; } | ||
58 | |||
59 | |||
60 | void setObjectCount(S32 val) { mObjectCount = val; } | ||
61 | void setObjectCapacity(S32 val) { mObjectCapacity = val; } | ||
62 | void setPriceObjectClaim(S32 val) { mPriceObjectClaim = val; } | ||
63 | void setPricePublicObjectDecay(S32 val) { mPricePublicObjectDecay = val; } | ||
64 | void setPricePublicObjectDelete(S32 val) { mPricePublicObjectDelete = val; } | ||
65 | void setPriceEnergyUnit(S32 val) { mPriceEnergyUnit = val; } | ||
66 | void setPriceUpload(S32 val) { mPriceUpload = val; } | ||
67 | void setPriceRentLight(S32 val) { mPriceRentLight = val; } | ||
68 | void setTeleportMinPrice(S32 val) { mTeleportMinPrice = val; } | ||
69 | void setTeleportPriceExponent(F32 val) { mTeleportPriceExponent = val; } | ||
70 | void setPriceGroupCreate(S32 val) { mPriceGroupCreate = val; } | ||
71 | |||
72 | private: | ||
73 | S32 mObjectCount; | ||
74 | S32 mObjectCapacity; | ||
75 | S32 mPriceObjectClaim; // per primitive | ||
76 | S32 mPricePublicObjectDecay; // per primitive | ||
77 | S32 mPricePublicObjectDelete; // per primitive | ||
78 | S32 mPriceEnergyUnit; | ||
79 | S32 mPriceUpload; | ||
80 | S32 mPriceRentLight; | ||
81 | S32 mTeleportMinPrice; | ||
82 | F32 mTeleportPriceExponent; | ||
83 | S32 mPriceGroupCreate; | ||
84 | }; | ||
85 | |||
86 | |||
87 | class LLRegionEconomy : public LLGlobalEconomy | ||
88 | { | ||
89 | public: | ||
90 | LLRegionEconomy(); | ||
91 | ~LLRegionEconomy(); | ||
92 | |||
93 | static void processEconomyData(LLMessageSystem *msg, void **user_data); | ||
94 | static void processEconomyDataRequest(LLMessageSystem *msg, void **user_data); | ||
95 | |||
96 | void print(); | ||
97 | |||
98 | BOOL hasData() const; | ||
99 | F32 getPriceObjectRent() const { return mPriceObjectRent; } | ||
100 | F32 getPriceObjectScaleFactor() const {return mPriceObjectScaleFactor;} | ||
101 | F32 getEnergyEfficiency() const { return mEnergyEfficiency; } | ||
102 | S32 getPriceParcelClaim() const; | ||
103 | S32 getPriceParcelRent() const; | ||
104 | F32 getAreaOwned() const { return mAreaOwned; } | ||
105 | F32 getAreaTotal() const { return mAreaTotal; } | ||
106 | S32 getBasePriceParcelClaimActual() const { return mBasePriceParcelClaimActual; } | ||
107 | |||
108 | void setPriceObjectRent(F32 val) { mPriceObjectRent = val; } | ||
109 | void setPriceObjectScaleFactor(F32 val) { mPriceObjectScaleFactor = val; } | ||
110 | void setEnergyEfficiency(F32 val) { mEnergyEfficiency = val; } | ||
111 | |||
112 | void setBasePriceParcelClaimDefault(S32 val); | ||
113 | void setBasePriceParcelClaimActual(S32 val); | ||
114 | void setPriceParcelClaimFactor(F32 val); | ||
115 | void setBasePriceParcelRent(S32 val); | ||
116 | |||
117 | void setAreaOwned(F32 val) { mAreaOwned = val; } | ||
118 | void setAreaTotal(F32 val) { mAreaTotal = val; } | ||
119 | |||
120 | private: | ||
121 | F32 mPriceObjectRent; | ||
122 | F32 mPriceObjectScaleFactor; | ||
123 | F32 mEnergyEfficiency; | ||
124 | |||
125 | S32 mBasePriceParcelClaimDefault; | ||
126 | S32 mBasePriceParcelClaimActual; | ||
127 | F32 mPriceParcelClaimFactor; | ||
128 | S32 mBasePriceParcelRent; | ||
129 | |||
130 | F32 mAreaOwned; | ||
131 | F32 mAreaTotal; | ||
132 | |||
133 | }; | ||
134 | |||
135 | #endif | ||
diff --git a/linden/indra/llinventory/llinventory.cpp b/linden/indra/llinventory/llinventory.cpp new file mode 100644 index 0000000..1f7efb3 --- /dev/null +++ b/linden/indra/llinventory/llinventory.cpp | |||
@@ -0,0 +1,1792 @@ | |||
1 | /** | ||
2 | * @file llinventory.cpp | ||
3 | * @brief Implementation of the inventory system. | ||
4 | * | ||
5 | * Copyright (c) 2001-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 <time.h> | ||
31 | |||
32 | #include "llinventory.h" | ||
33 | |||
34 | #include "lldbstrings.h" | ||
35 | #include "llcrypto.h" | ||
36 | #include "llsd.h" | ||
37 | #include "message.h" | ||
38 | #include <boost/tokenizer.hpp> | ||
39 | |||
40 | #include "llsdutil.h" | ||
41 | |||
42 | #include "llsdutil.h" | ||
43 | |||
44 | ///---------------------------------------------------------------------------- | ||
45 | /// Local function declarations, constants, enums, and typedefs | ||
46 | ///---------------------------------------------------------------------------- | ||
47 | |||
48 | const U8 TASK_INVENTORY_ITEM_KEY = 0; | ||
49 | const U8 TASK_INVENTORY_ASSET_KEY = 1; | ||
50 | |||
51 | const LLUUID MAGIC_ID("3c115e51-04f4-523c-9fa6-98aff1034730"); | ||
52 | |||
53 | // helper function which returns true if inventory type and asset type | ||
54 | // are potentially compatible. For example, an attachment must be an | ||
55 | // object, but a wearable can be a bodypart or clothing asset. | ||
56 | bool inventory_and_asset_types_match( | ||
57 | LLInventoryType::EType inventory_type, | ||
58 | LLAssetType::EType asset_type); | ||
59 | |||
60 | |||
61 | ///---------------------------------------------------------------------------- | ||
62 | /// Class LLInventoryType | ||
63 | ///---------------------------------------------------------------------------- | ||
64 | |||
65 | // Unlike asset type names, not limited to 8 characters. | ||
66 | // Need not match asset type names. | ||
67 | static const char* INVENTORY_TYPE_NAMES[LLInventoryType::IT_COUNT] = | ||
68 | { | ||
69 | "texture", // 0 | ||
70 | "sound", | ||
71 | "callcard", | ||
72 | "landmark", | ||
73 | NULL, | ||
74 | NULL, // 5 | ||
75 | "object", | ||
76 | "notecard", | ||
77 | "category", | ||
78 | "root", | ||
79 | "script", // 10 | ||
80 | NULL, | ||
81 | NULL, | ||
82 | NULL, | ||
83 | NULL, | ||
84 | "snapshot", // 15 | ||
85 | NULL, | ||
86 | "attach", | ||
87 | "wearable", | ||
88 | "animation", | ||
89 | "gesture", // 20 | ||
90 | }; | ||
91 | |||
92 | // This table is meant for decoding to human readable form. Put any | ||
93 | // and as many printable characters you want in each one. | ||
94 | // See also LLAssetType::mAssetTypeHumanNames | ||
95 | static const char* INVENTORY_TYPE_HUMAN_NAMES[LLInventoryType::IT_COUNT] = | ||
96 | { | ||
97 | "texture", // 0 | ||
98 | "sound", | ||
99 | "calling card", | ||
100 | "landmark", | ||
101 | NULL, | ||
102 | NULL, // 5 | ||
103 | "object", | ||
104 | "note card", | ||
105 | "folder", | ||
106 | "root", | ||
107 | "script", // 10 | ||
108 | NULL, | ||
109 | NULL, | ||
110 | NULL, | ||
111 | NULL, | ||
112 | "snapshot", // 15 | ||
113 | NULL, | ||
114 | "attachment", | ||
115 | "wearable", | ||
116 | "animation", | ||
117 | "gesture", // 20 | ||
118 | }; | ||
119 | |||
120 | // Maps asset types to the default inventory type for that kind of asset. | ||
121 | // Thus, "Lost and Found" is a "Category" | ||
122 | static const LLInventoryType::EType | ||
123 | DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = | ||
124 | { | ||
125 | LLInventoryType::IT_TEXTURE, // AT_TEXTURE | ||
126 | LLInventoryType::IT_SOUND, // AT_SOUND | ||
127 | LLInventoryType::IT_CALLINGCARD, // AT_CALLINGCARD | ||
128 | LLInventoryType::IT_LANDMARK, // AT_LANDMARK | ||
129 | LLInventoryType::IT_LSL, // AT_SCRIPT | ||
130 | LLInventoryType::IT_WEARABLE, // AT_CLOTHING | ||
131 | LLInventoryType::IT_OBJECT, // AT_OBJECT | ||
132 | LLInventoryType::IT_NOTECARD, // AT_NOTECARD | ||
133 | LLInventoryType::IT_CATEGORY, // AT_CATEGORY | ||
134 | LLInventoryType::IT_ROOT_CATEGORY, // AT_ROOT_CATEGORY | ||
135 | LLInventoryType::IT_LSL, // AT_LSL_TEXT | ||
136 | LLInventoryType::IT_LSL, // AT_LSL_BYTECODE | ||
137 | LLInventoryType::IT_TEXTURE, // AT_TEXTURE_TGA | ||
138 | LLInventoryType::IT_WEARABLE, // AT_BODYPART | ||
139 | LLInventoryType::IT_CATEGORY, // AT_TRASH | ||
140 | LLInventoryType::IT_CATEGORY, // AT_SNAPSHOT_CATEGORY | ||
141 | LLInventoryType::IT_CATEGORY, // AT_LOST_AND_FOUND | ||
142 | LLInventoryType::IT_SOUND, // AT_SOUND_WAV | ||
143 | LLInventoryType::IT_NONE, // AT_IMAGE_TGA | ||
144 | LLInventoryType::IT_NONE, // AT_IMAGE_JPEG | ||
145 | LLInventoryType::IT_ANIMATION, // AT_ANIMATION | ||
146 | LLInventoryType::IT_GESTURE, // AT_GESTURE | ||
147 | }; | ||
148 | |||
149 | static const int MAX_POSSIBLE_ASSET_TYPES = 2; | ||
150 | static const LLAssetType::EType | ||
151 | INVENTORY_TO_ASSET_TYPE[LLInventoryType::IT_COUNT][MAX_POSSIBLE_ASSET_TYPES] = | ||
152 | { | ||
153 | { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_TEXTURE | ||
154 | { LLAssetType::AT_SOUND, LLAssetType::AT_NONE }, // IT_SOUND | ||
155 | { LLAssetType::AT_CALLINGCARD, LLAssetType::AT_NONE }, // IT_CALLINGCARD | ||
156 | { LLAssetType::AT_LANDMARK, LLAssetType::AT_NONE }, // IT_LANDMARK | ||
157 | { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, | ||
158 | { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, | ||
159 | { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_OBJECT | ||
160 | { LLAssetType::AT_NOTECARD, LLAssetType::AT_NONE }, // IT_NOTECARD | ||
161 | { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_CATEGORY | ||
162 | { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_ROOT_CATEGORY | ||
163 | { LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE }, // IT_LSL | ||
164 | { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, | ||
165 | { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, | ||
166 | { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, | ||
167 | { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, | ||
168 | { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_SNAPSHOT | ||
169 | { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, | ||
170 | { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_ATTACHMENT | ||
171 | { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART }, // IT_WEARABLE | ||
172 | { LLAssetType::AT_ANIMATION, LLAssetType::AT_NONE }, // IT_ANIMATION | ||
173 | { LLAssetType::AT_GESTURE, LLAssetType::AT_NONE }, // IT_GESTURE | ||
174 | }; | ||
175 | |||
176 | // static | ||
177 | const char* LLInventoryType::lookup(EType type) | ||
178 | { | ||
179 | if((type >= 0) && (type < IT_COUNT)) | ||
180 | { | ||
181 | return INVENTORY_TYPE_NAMES[S32(type)]; | ||
182 | } | ||
183 | else | ||
184 | { | ||
185 | return NULL; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | // static | ||
190 | LLInventoryType::EType LLInventoryType::lookup(const char* name) | ||
191 | { | ||
192 | for(S32 i = 0; i < IT_COUNT; ++i) | ||
193 | { | ||
194 | if((INVENTORY_TYPE_NAMES[i]) | ||
195 | && (0 == strcmp(name, INVENTORY_TYPE_NAMES[i]))) | ||
196 | { | ||
197 | // match | ||
198 | return (EType)i; | ||
199 | } | ||
200 | } | ||
201 | return IT_NONE; | ||
202 | } | ||
203 | |||
204 | // XUI:translate | ||
205 | // translation from a type to a human readable form. | ||
206 | // static | ||
207 | const char* LLInventoryType::lookupHumanReadable(EType type) | ||
208 | { | ||
209 | if((type >= 0) && (type < IT_COUNT)) | ||
210 | { | ||
211 | return INVENTORY_TYPE_HUMAN_NAMES[S32(type)]; | ||
212 | } | ||
213 | else | ||
214 | { | ||
215 | return NULL; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | // return the default inventory for the given asset type. | ||
220 | // static | ||
221 | LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType asset_type) | ||
222 | { | ||
223 | if((asset_type >= 0) && (asset_type < LLAssetType::AT_COUNT)) | ||
224 | { | ||
225 | return DEFAULT_ASSET_FOR_INV_TYPE[S32(asset_type)]; | ||
226 | } | ||
227 | else | ||
228 | { | ||
229 | return IT_NONE; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | ///---------------------------------------------------------------------------- | ||
234 | /// Class LLInventoryObject | ||
235 | ///---------------------------------------------------------------------------- | ||
236 | |||
237 | LLInventoryObject::LLInventoryObject( | ||
238 | const LLUUID& uuid, | ||
239 | const LLUUID& parent_uuid, | ||
240 | LLAssetType::EType type, | ||
241 | const LLString& name) : | ||
242 | mUUID(uuid), | ||
243 | mParentUUID(parent_uuid), | ||
244 | mType(type), | ||
245 | mName(name) | ||
246 | { | ||
247 | LLString::replaceNonstandardASCII(mName, ' '); | ||
248 | LLString::replaceChar(mName, '|', ' '); | ||
249 | LLString::trim(mName); | ||
250 | LLString::truncate(mName, DB_INV_ITEM_NAME_STR_LEN); | ||
251 | } | ||
252 | |||
253 | LLInventoryObject::LLInventoryObject() : | ||
254 | mType(LLAssetType::AT_NONE) | ||
255 | { | ||
256 | } | ||
257 | |||
258 | LLInventoryObject::~LLInventoryObject( void ) | ||
259 | { | ||
260 | } | ||
261 | |||
262 | void LLInventoryObject::copy(const LLInventoryObject* other) | ||
263 | { | ||
264 | mUUID = other->mUUID; | ||
265 | mParentUUID = other->mParentUUID; | ||
266 | mType = other->mType; | ||
267 | mName = other->mName; | ||
268 | } | ||
269 | |||
270 | const LLUUID& LLInventoryObject::getUUID() const | ||
271 | { | ||
272 | return mUUID; | ||
273 | } | ||
274 | |||
275 | const LLUUID& LLInventoryObject::getParentUUID() const | ||
276 | { | ||
277 | return mParentUUID; | ||
278 | } | ||
279 | |||
280 | const LLString& LLInventoryObject::getName() const | ||
281 | { | ||
282 | return mName; | ||
283 | } | ||
284 | |||
285 | LLAssetType::EType LLInventoryObject::getType() const | ||
286 | { | ||
287 | return mType; | ||
288 | } | ||
289 | |||
290 | void LLInventoryObject::setUUID(const LLUUID& new_uuid) | ||
291 | { | ||
292 | mUUID = new_uuid; | ||
293 | } | ||
294 | |||
295 | void LLInventoryObject::rename(const LLString& n) | ||
296 | { | ||
297 | LLString new_name(n); | ||
298 | LLString::replaceNonstandardASCII(new_name, ' '); | ||
299 | LLString::replaceChar(new_name, '|', ' '); | ||
300 | LLString::trim(new_name); | ||
301 | LLString::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN); | ||
302 | |||
303 | if( new_name != mName ) | ||
304 | { | ||
305 | mName = new_name; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | void LLInventoryObject::setParent(const LLUUID& new_parent) | ||
310 | { | ||
311 | mParentUUID = new_parent; | ||
312 | } | ||
313 | |||
314 | void LLInventoryObject::setType(LLAssetType::EType type) | ||
315 | { | ||
316 | mType = type; | ||
317 | } | ||
318 | |||
319 | |||
320 | // virtual | ||
321 | BOOL LLInventoryObject::importLegacyStream(std::istream& input_stream) | ||
322 | { | ||
323 | char buffer[MAX_STRING]; | ||
324 | char keyword[MAX_STRING]; | ||
325 | char valuestr[MAX_STRING]; | ||
326 | |||
327 | keyword[0] = '\0'; | ||
328 | valuestr[0] = '\0'; | ||
329 | while(input_stream.good()) | ||
330 | { | ||
331 | input_stream.getline(buffer, MAX_STRING); | ||
332 | sscanf(buffer, " %254s %254s", keyword, valuestr); | ||
333 | if(!keyword) | ||
334 | { | ||
335 | continue; | ||
336 | } | ||
337 | if(0 == strcmp("{",keyword)) | ||
338 | { | ||
339 | continue; | ||
340 | } | ||
341 | if(0 == strcmp("}", keyword)) | ||
342 | { | ||
343 | break; | ||
344 | } | ||
345 | else if(0 == strcmp("obj_id", keyword)) | ||
346 | { | ||
347 | mUUID.set(valuestr); | ||
348 | } | ||
349 | else if(0 == strcmp("parent_id", keyword)) | ||
350 | { | ||
351 | mParentUUID.set(valuestr); | ||
352 | } | ||
353 | else if(0 == strcmp("type", keyword)) | ||
354 | { | ||
355 | mType = LLAssetType::lookup(valuestr); | ||
356 | } | ||
357 | else if(0 == strcmp("name", keyword)) | ||
358 | { | ||
359 | //strcpy(valuestr, buffer + strlen(keyword) + 3); | ||
360 | // *NOTE: Not ANSI C, but widely supported. | ||
361 | sscanf(buffer, " %254s %[^|]", keyword, valuestr); | ||
362 | mName.assign(valuestr); | ||
363 | LLString::replaceNonstandardASCII(mName, ' '); | ||
364 | LLString::replaceChar(mName, '|', ' '); | ||
365 | LLString::trim(mName); | ||
366 | LLString::truncate(mName, DB_INV_ITEM_NAME_STR_LEN); | ||
367 | } | ||
368 | else | ||
369 | { | ||
370 | llwarns << "unknown keyword '" << keyword | ||
371 | << "' in LLInventoryObject::importLegacyStream() for object " << mUUID << llendl; | ||
372 | } | ||
373 | } | ||
374 | return TRUE; | ||
375 | } | ||
376 | |||
377 | // exportFile should be replaced with exportLegacyStream | ||
378 | // not sure whether exportLegacyStream(llofstream(fp)) would work, fp may need to get icramented... | ||
379 | BOOL LLInventoryObject::exportFile(FILE* fp, BOOL) const | ||
380 | { | ||
381 | char uuid_str[UUID_STR_LENGTH]; | ||
382 | fprintf(fp, "\tinv_object\t0\n\t{\n"); | ||
383 | mUUID.toString(uuid_str); | ||
384 | fprintf(fp, "\t\tobj_id\t%s\n", uuid_str); | ||
385 | mParentUUID.toString(uuid_str); | ||
386 | fprintf(fp, "\t\tparent_id\t%s\n", uuid_str); | ||
387 | fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); | ||
388 | fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); | ||
389 | fprintf(fp,"\t}\n"); | ||
390 | return TRUE; | ||
391 | } | ||
392 | |||
393 | BOOL LLInventoryObject::exportLegacyStream(std::ostream& output_stream, BOOL) const | ||
394 | { | ||
395 | char uuid_str[UUID_STR_LENGTH]; | ||
396 | output_stream << "\tinv_object\t0\n\t{\n"; | ||
397 | mUUID.toString(uuid_str); | ||
398 | output_stream << "\t\tobj_id\t" << uuid_str << "\n"; | ||
399 | mParentUUID.toString(uuid_str); | ||
400 | output_stream << "\t\tparent_id\t" << uuid_str << "\n"; | ||
401 | output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n"; | ||
402 | output_stream << "\t\tname\t" << mName.c_str() << "|\n"; | ||
403 | output_stream << "\t}\n"; | ||
404 | return TRUE; | ||
405 | } | ||
406 | |||
407 | |||
408 | void LLInventoryObject::removeFromServer() | ||
409 | { | ||
410 | // don't do nothin' | ||
411 | llwarns << "LLInventoryObject::removeFromServer() called. Doesn't do anything." << llendl; | ||
412 | } | ||
413 | |||
414 | void LLInventoryObject::updateParentOnServer(BOOL) const | ||
415 | { | ||
416 | // don't do nothin' | ||
417 | llwarns << "LLInventoryObject::updateParentOnServer() called. Doesn't do anything." << llendl; | ||
418 | } | ||
419 | |||
420 | void LLInventoryObject::updateServer(BOOL) const | ||
421 | { | ||
422 | // don't do nothin' | ||
423 | llwarns << "LLInventoryObject::updateServer() called. Doesn't do anything." << llendl; | ||
424 | } | ||
425 | |||
426 | |||
427 | ///---------------------------------------------------------------------------- | ||
428 | /// Class LLInventoryItem | ||
429 | ///---------------------------------------------------------------------------- | ||
430 | |||
431 | LLInventoryItem::LLInventoryItem( | ||
432 | const LLUUID& uuid, | ||
433 | const LLUUID& parent_uuid, | ||
434 | const LLPermissions& permissions, | ||
435 | const LLUUID& asset_uuid, | ||
436 | LLAssetType::EType type, | ||
437 | LLInventoryType::EType inv_type, | ||
438 | const LLString& name, | ||
439 | const LLString& desc, | ||
440 | const LLSaleInfo& sale_info, | ||
441 | U32 flags, | ||
442 | S32 creation_date_utc) : | ||
443 | LLInventoryObject(uuid, parent_uuid, type, name), | ||
444 | mPermissions(permissions), | ||
445 | mAssetUUID(asset_uuid), | ||
446 | mDescription(desc), | ||
447 | mSaleInfo(sale_info), | ||
448 | mInventoryType(inv_type), | ||
449 | mFlags(flags), | ||
450 | mCreationDate(creation_date_utc) | ||
451 | { | ||
452 | LLString::replaceNonstandardASCII(mDescription, ' '); | ||
453 | LLString::replaceChar(mDescription, '|', ' '); | ||
454 | } | ||
455 | |||
456 | LLInventoryItem::LLInventoryItem() : | ||
457 | LLInventoryObject(), | ||
458 | mPermissions(), | ||
459 | mAssetUUID(), | ||
460 | mDescription(), | ||
461 | mSaleInfo(), | ||
462 | mInventoryType(LLInventoryType::IT_NONE), | ||
463 | mFlags(0), | ||
464 | mCreationDate(0) | ||
465 | { | ||
466 | } | ||
467 | |||
468 | LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) : | ||
469 | LLInventoryObject() | ||
470 | { | ||
471 | copy(other); | ||
472 | } | ||
473 | |||
474 | LLInventoryItem::~LLInventoryItem() | ||
475 | { | ||
476 | } | ||
477 | |||
478 | // virtual | ||
479 | void LLInventoryItem::copy(const LLInventoryItem* other) | ||
480 | { | ||
481 | LLInventoryObject::copy(other); | ||
482 | mPermissions = other->mPermissions; | ||
483 | mAssetUUID = other->mAssetUUID; | ||
484 | mDescription = other->mDescription; | ||
485 | mSaleInfo = other->mSaleInfo; | ||
486 | mInventoryType = other->mInventoryType; | ||
487 | mFlags = other->mFlags; | ||
488 | mCreationDate = other->mCreationDate; | ||
489 | } | ||
490 | |||
491 | // As a constructor alternative, the clone() method works like a | ||
492 | // copy constructor, but gens a new UUID. | ||
493 | void LLInventoryItem::clone(LLPointer<LLInventoryItem>& newitem) const | ||
494 | { | ||
495 | newitem = new LLInventoryItem; | ||
496 | newitem->copy(this); | ||
497 | newitem->mUUID.generate(); | ||
498 | } | ||
499 | |||
500 | const LLPermissions& LLInventoryItem::getPermissions() const | ||
501 | { | ||
502 | return mPermissions; | ||
503 | } | ||
504 | |||
505 | const LLUUID& LLInventoryItem::getCreatorUUID() const | ||
506 | { | ||
507 | return mPermissions.getCreator(); | ||
508 | } | ||
509 | |||
510 | const LLUUID& LLInventoryItem::getAssetUUID() const | ||
511 | { | ||
512 | return mAssetUUID; | ||
513 | } | ||
514 | |||
515 | void LLInventoryItem::setAssetUUID(const LLUUID& asset_id) | ||
516 | { | ||
517 | mAssetUUID = asset_id; | ||
518 | } | ||
519 | |||
520 | |||
521 | const LLString& LLInventoryItem::getDescription() const | ||
522 | { | ||
523 | return mDescription; | ||
524 | } | ||
525 | |||
526 | S32 LLInventoryItem::getCreationDate() const | ||
527 | { | ||
528 | return mCreationDate; | ||
529 | } | ||
530 | |||
531 | U32 LLInventoryItem::getCRC32() const | ||
532 | { | ||
533 | // *FIX: Not a real crc - more of a checksum. | ||
534 | // *NOTE: We currently do not validate the name or description, | ||
535 | // but if they change in transit, it's no big deal. | ||
536 | U32 crc = mUUID.getCRC32(); | ||
537 | //lldebugs << "1 crc: " << std::hex << crc << std::dec << llendl; | ||
538 | crc += mParentUUID.getCRC32(); | ||
539 | //lldebugs << "2 crc: " << std::hex << crc << std::dec << llendl; | ||
540 | crc += mPermissions.getCRC32(); | ||
541 | //lldebugs << "3 crc: " << std::hex << crc << std::dec << llendl; | ||
542 | crc += mAssetUUID.getCRC32(); | ||
543 | //lldebugs << "4 crc: " << std::hex << crc << std::dec << llendl; | ||
544 | crc += mType; | ||
545 | //lldebugs << "5 crc: " << std::hex << crc << std::dec << llendl; | ||
546 | crc += mInventoryType; | ||
547 | //lldebugs << "6 crc: " << std::hex << crc << std::dec << llendl; | ||
548 | crc += mFlags; | ||
549 | //lldebugs << "7 crc: " << std::hex << crc << std::dec << llendl; | ||
550 | crc += mSaleInfo.getCRC32(); | ||
551 | //lldebugs << "8 crc: " << std::hex << crc << std::dec << llendl; | ||
552 | crc += mCreationDate; | ||
553 | //lldebugs << "9 crc: " << std::hex << crc << std::dec << llendl; | ||
554 | return crc; | ||
555 | } | ||
556 | |||
557 | |||
558 | void LLInventoryItem::setDescription(const LLString& d) | ||
559 | { | ||
560 | LLString new_desc(d); | ||
561 | LLString::replaceNonstandardASCII(new_desc, ' '); | ||
562 | LLString::replaceChar(new_desc, '|', ' '); | ||
563 | if( new_desc != mDescription ) | ||
564 | { | ||
565 | mDescription = new_desc; | ||
566 | } | ||
567 | } | ||
568 | |||
569 | void LLInventoryItem::setPermissions(const LLPermissions& perm) | ||
570 | { | ||
571 | mPermissions = perm; | ||
572 | } | ||
573 | |||
574 | void LLInventoryItem::setInventoryType(LLInventoryType::EType inv_type) | ||
575 | { | ||
576 | mInventoryType = inv_type; | ||
577 | } | ||
578 | |||
579 | void LLInventoryItem::setFlags(U32 flags) | ||
580 | { | ||
581 | mFlags = flags; | ||
582 | } | ||
583 | |||
584 | void LLInventoryItem::setCreationDate(S32 creation_date_utc) | ||
585 | { | ||
586 | mCreationDate = creation_date_utc; | ||
587 | } | ||
588 | |||
589 | |||
590 | const LLSaleInfo& LLInventoryItem::getSaleInfo() const | ||
591 | { | ||
592 | return mSaleInfo; | ||
593 | } | ||
594 | |||
595 | void LLInventoryItem::setSaleInfo(const LLSaleInfo& sale_info) | ||
596 | { | ||
597 | mSaleInfo = sale_info; | ||
598 | } | ||
599 | |||
600 | LLInventoryType::EType LLInventoryItem::getInventoryType() const | ||
601 | { | ||
602 | return mInventoryType; | ||
603 | } | ||
604 | |||
605 | U32 LLInventoryItem::getFlags() const | ||
606 | { | ||
607 | return mFlags; | ||
608 | } | ||
609 | |||
610 | // virtual | ||
611 | void LLInventoryItem::packMessage(LLMessageSystem* msg) const | ||
612 | { | ||
613 | msg->addUUIDFast(_PREHASH_ItemID, mUUID); | ||
614 | msg->addUUIDFast(_PREHASH_FolderID, mParentUUID); | ||
615 | mPermissions.packMessage(msg); | ||
616 | msg->addUUIDFast(_PREHASH_AssetID, mAssetUUID); | ||
617 | S8 type = static_cast<S8>(mType); | ||
618 | msg->addS8Fast(_PREHASH_Type, type); | ||
619 | type = static_cast<S8>(mInventoryType); | ||
620 | msg->addS8Fast(_PREHASH_InvType, type); | ||
621 | msg->addU32Fast(_PREHASH_Flags, mFlags); | ||
622 | mSaleInfo.packMessage(msg); | ||
623 | msg->addStringFast(_PREHASH_Name, mName); | ||
624 | msg->addStringFast(_PREHASH_Description, mDescription); | ||
625 | msg->addS32Fast(_PREHASH_CreationDate, mCreationDate); | ||
626 | U32 crc = getCRC32(); | ||
627 | msg->addU32Fast(_PREHASH_CRC, crc); | ||
628 | } | ||
629 | |||
630 | // virtual | ||
631 | BOOL LLInventoryItem::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) | ||
632 | { | ||
633 | msg->getUUIDFast(block, _PREHASH_ItemID, mUUID, block_num); | ||
634 | msg->getUUIDFast(block, _PREHASH_FolderID, mParentUUID, block_num); | ||
635 | mPermissions.unpackMessage(msg, block, block_num); | ||
636 | msg->getUUIDFast(block, _PREHASH_AssetID, mAssetUUID, block_num); | ||
637 | |||
638 | S8 type; | ||
639 | msg->getS8Fast(block, _PREHASH_Type, type, block_num); | ||
640 | mType = static_cast<LLAssetType::EType>(type); | ||
641 | msg->getS8(block, "InvType", type, block_num); | ||
642 | mInventoryType = static_cast<LLInventoryType::EType>(type); | ||
643 | |||
644 | msg->getU32Fast(block, _PREHASH_Flags, mFlags, block_num); | ||
645 | |||
646 | mSaleInfo.unpackMultiMessage(msg, block, block_num); | ||
647 | |||
648 | char name[DB_INV_ITEM_NAME_BUF_SIZE]; | ||
649 | msg->getStringFast(block, _PREHASH_Name, DB_INV_ITEM_NAME_BUF_SIZE, name, block_num); | ||
650 | mName.assign(name); | ||
651 | LLString::replaceNonstandardASCII(mName, ' '); | ||
652 | |||
653 | char desc[DB_INV_ITEM_DESC_BUF_SIZE]; | ||
654 | msg->getStringFast(block, _PREHASH_Description, DB_INV_ITEM_DESC_BUF_SIZE, desc, block_num); | ||
655 | mDescription.assign(desc); | ||
656 | LLString::replaceNonstandardASCII(mDescription, ' '); | ||
657 | |||
658 | msg->getS32(block, "CreationDate", mCreationDate, block_num); | ||
659 | |||
660 | U32 local_crc = getCRC32(); | ||
661 | U32 remote_crc = 0; | ||
662 | msg->getU32(block, "CRC", remote_crc, block_num); | ||
663 | //#define CRC_CHECK | ||
664 | #ifdef CRC_CHECK | ||
665 | if(local_crc == remote_crc) | ||
666 | { | ||
667 | lldebugs << "crc matches" << llendl; | ||
668 | return TRUE; | ||
669 | } | ||
670 | else | ||
671 | { | ||
672 | llwarns << "inventory crc mismatch: local=" << std::hex << local_crc | ||
673 | << " remote=" << remote_crc << std::dec << llendl; | ||
674 | return FALSE; | ||
675 | } | ||
676 | #else | ||
677 | return (local_crc == remote_crc); | ||
678 | #endif | ||
679 | } | ||
680 | |||
681 | // virtual | ||
682 | BOOL LLInventoryItem::importFile(FILE* fp) | ||
683 | { | ||
684 | char buffer[MAX_STRING]; | ||
685 | char keyword[MAX_STRING]; | ||
686 | char valuestr[MAX_STRING]; | ||
687 | char junk[MAX_STRING]; | ||
688 | BOOL success = TRUE; | ||
689 | |||
690 | keyword[0] = '\0'; | ||
691 | valuestr[0] = '\0'; | ||
692 | |||
693 | mInventoryType = LLInventoryType::IT_NONE; | ||
694 | mAssetUUID.setNull(); | ||
695 | while(success && (!feof(fp))) | ||
696 | { | ||
697 | fgets(buffer, MAX_STRING, fp); | ||
698 | sscanf(buffer, " %254s %254s", keyword, valuestr); | ||
699 | if(!keyword) | ||
700 | { | ||
701 | continue; | ||
702 | } | ||
703 | if(0 == strcmp("{",keyword)) | ||
704 | { | ||
705 | continue; | ||
706 | } | ||
707 | if(0 == strcmp("}", keyword)) | ||
708 | { | ||
709 | break; | ||
710 | } | ||
711 | else if(0 == strcmp("item_id", keyword)) | ||
712 | { | ||
713 | mUUID.set(valuestr); | ||
714 | } | ||
715 | else if(0 == strcmp("parent_id", keyword)) | ||
716 | { | ||
717 | mParentUUID.set(valuestr); | ||
718 | } | ||
719 | else if(0 == strcmp("permissions", keyword)) | ||
720 | { | ||
721 | success = mPermissions.importFile(fp); | ||
722 | } | ||
723 | else if(0 == strcmp("sale_info", keyword)) | ||
724 | { | ||
725 | // Sale info used to contain next owner perm. It is now in | ||
726 | // the permissions. Thus, we read that out, and fix legacy | ||
727 | // objects. It's possible this op would fail, but it | ||
728 | // should pick up the vast majority of the tasks. | ||
729 | BOOL has_perm_mask = FALSE; | ||
730 | U32 perm_mask = 0; | ||
731 | success = mSaleInfo.importFile(fp, has_perm_mask, perm_mask); | ||
732 | if(has_perm_mask) | ||
733 | { | ||
734 | if(perm_mask == PERM_NONE) | ||
735 | { | ||
736 | perm_mask = mPermissions.getMaskOwner(); | ||
737 | } | ||
738 | // fair use fix. | ||
739 | if(!(perm_mask & PERM_COPY)) | ||
740 | { | ||
741 | perm_mask |= PERM_TRANSFER; | ||
742 | } | ||
743 | mPermissions.setMaskNext(perm_mask); | ||
744 | } | ||
745 | } | ||
746 | else if(0 == strcmp("shadow_id", keyword)) | ||
747 | { | ||
748 | mAssetUUID.set(valuestr); | ||
749 | LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); | ||
750 | cipher.decrypt(mAssetUUID.mData, UUID_BYTES); | ||
751 | } | ||
752 | else if(0 == strcmp("asset_id", keyword)) | ||
753 | { | ||
754 | mAssetUUID.set(valuestr); | ||
755 | } | ||
756 | else if(0 == strcmp("type", keyword)) | ||
757 | { | ||
758 | mType = LLAssetType::lookup(valuestr); | ||
759 | } | ||
760 | else if(0 == strcmp("inv_type", keyword)) | ||
761 | { | ||
762 | mInventoryType = LLInventoryType::lookup(valuestr); | ||
763 | } | ||
764 | else if(0 == strcmp("flags", keyword)) | ||
765 | { | ||
766 | sscanf(valuestr, "%x", &mFlags); | ||
767 | } | ||
768 | else if(0 == strcmp("name", keyword)) | ||
769 | { | ||
770 | //strcpy(valuestr, buffer + strlen(keyword) + 3); | ||
771 | // *NOTE: Not ANSI C, but widely supported. | ||
772 | sscanf(buffer, " %254s%[\t]%[^|]", keyword, junk, valuestr); | ||
773 | |||
774 | // IW: sscanf chokes and puts | in valuestr if there's no name | ||
775 | if (valuestr[0] == '|') | ||
776 | { | ||
777 | valuestr[0] = '\000'; | ||
778 | } | ||
779 | |||
780 | mName.assign(valuestr); | ||
781 | LLString::replaceNonstandardASCII(mName, ' '); | ||
782 | LLString::replaceChar(mName, '|', ' '); | ||
783 | } | ||
784 | else if(0 == strcmp("desc", keyword)) | ||
785 | { | ||
786 | //strcpy(valuestr, buffer + strlen(keyword) + 3); | ||
787 | // *NOTE: Not ANSI C, but widely supported. | ||
788 | sscanf(buffer, " %s%[\t]%[^|]", keyword, junk, valuestr); | ||
789 | |||
790 | if (valuestr[0] == '|') | ||
791 | { | ||
792 | valuestr[0] = '\000'; | ||
793 | } | ||
794 | |||
795 | mDescription.assign(valuestr); | ||
796 | LLString::replaceNonstandardASCII(mDescription, ' '); | ||
797 | /* TODO -- ask Ian about this code | ||
798 | const char *donkey = mDescription.c_str(); | ||
799 | if (donkey[0] == '|') | ||
800 | { | ||
801 | llerrs << "Donkey" << llendl; | ||
802 | } | ||
803 | */ | ||
804 | } | ||
805 | else if(0 == strcmp("creation_date", keyword)) | ||
806 | { | ||
807 | sscanf(valuestr, "%d", &mCreationDate); | ||
808 | } | ||
809 | else | ||
810 | { | ||
811 | llwarns << "unknown keyword '" << keyword | ||
812 | << "' in inventory import of item " << mUUID << llendl; | ||
813 | } | ||
814 | } | ||
815 | |||
816 | // Need to convert 1.0 simstate files to a useful inventory type | ||
817 | // and potentially deal with bad inventory tyes eg, a landmark | ||
818 | // marked as a texture. | ||
819 | if((LLInventoryType::IT_NONE == mInventoryType) | ||
820 | || !inventory_and_asset_types_match(mInventoryType, mType)) | ||
821 | { | ||
822 | lldebugs << "Resetting inventory type for " << mUUID << llendl; | ||
823 | mInventoryType = LLInventoryType::defaultForAssetType(mType); | ||
824 | } | ||
825 | return success; | ||
826 | } | ||
827 | |||
828 | BOOL LLInventoryItem::exportFile(FILE* fp, BOOL include_asset_key) const | ||
829 | { | ||
830 | char uuid_str[UUID_STR_LENGTH]; | ||
831 | fprintf(fp, "\tinv_item\t0\n\t{\n"); | ||
832 | mUUID.toString(uuid_str); | ||
833 | fprintf(fp, "\t\titem_id\t%s\n", uuid_str); | ||
834 | mParentUUID.toString(uuid_str); | ||
835 | fprintf(fp, "\t\tparent_id\t%s\n", uuid_str); | ||
836 | mPermissions.exportFile(fp); | ||
837 | |||
838 | // Check for permissions to see the asset id, and if so write it | ||
839 | // out as an asset id. Otherwise, apply our cheesy encryption. | ||
840 | if(include_asset_key) | ||
841 | { | ||
842 | U32 mask = mPermissions.getMaskBase(); | ||
843 | if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) | ||
844 | || (mAssetUUID.isNull())) | ||
845 | { | ||
846 | mAssetUUID.toString(uuid_str); | ||
847 | fprintf(fp, "\t\tasset_id\t%s\n", uuid_str); | ||
848 | } | ||
849 | else | ||
850 | { | ||
851 | LLUUID shadow_id(mAssetUUID); | ||
852 | LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); | ||
853 | cipher.encrypt(shadow_id.mData, UUID_BYTES); | ||
854 | shadow_id.toString(uuid_str); | ||
855 | fprintf(fp, "\t\tshadow_id\t%s\n", uuid_str); | ||
856 | } | ||
857 | } | ||
858 | else | ||
859 | { | ||
860 | LLUUID::null.toString(uuid_str); | ||
861 | fprintf(fp, "\t\tasset_id\t%s\n", uuid_str); | ||
862 | } | ||
863 | fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); | ||
864 | const char* inv_type_str = LLInventoryType::lookup(mInventoryType); | ||
865 | if(inv_type_str) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str); | ||
866 | fprintf(fp, "\t\tflags\t%08x\n", mFlags); | ||
867 | mSaleInfo.exportFile(fp); | ||
868 | fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); | ||
869 | fprintf(fp, "\t\tdesc\t%s|\n", mDescription.c_str()); | ||
870 | fprintf(fp, "\t\tcreation_date\t%d\n", mCreationDate); | ||
871 | fprintf(fp,"\t}\n"); | ||
872 | return TRUE; | ||
873 | } | ||
874 | |||
875 | // virtual | ||
876 | BOOL LLInventoryItem::importLegacyStream(std::istream& input_stream) | ||
877 | { | ||
878 | char buffer[MAX_STRING]; | ||
879 | char keyword[MAX_STRING]; | ||
880 | char valuestr[MAX_STRING]; | ||
881 | char junk[MAX_STRING]; | ||
882 | BOOL success = TRUE; | ||
883 | |||
884 | keyword[0] = '\0'; | ||
885 | valuestr[0] = '\0'; | ||
886 | |||
887 | mInventoryType = LLInventoryType::IT_NONE; | ||
888 | mAssetUUID.setNull(); | ||
889 | while(success && input_stream.good()) | ||
890 | { | ||
891 | input_stream.getline(buffer, MAX_STRING); | ||
892 | sscanf(buffer, " %s %s", keyword, valuestr); | ||
893 | if(!keyword) | ||
894 | { | ||
895 | continue; | ||
896 | } | ||
897 | if(0 == strcmp("{",keyword)) | ||
898 | { | ||
899 | continue; | ||
900 | } | ||
901 | if(0 == strcmp("}", keyword)) | ||
902 | { | ||
903 | break; | ||
904 | } | ||
905 | else if(0 == strcmp("item_id", keyword)) | ||
906 | { | ||
907 | mUUID.set(valuestr); | ||
908 | } | ||
909 | else if(0 == strcmp("parent_id", keyword)) | ||
910 | { | ||
911 | mParentUUID.set(valuestr); | ||
912 | } | ||
913 | else if(0 == strcmp("permissions", keyword)) | ||
914 | { | ||
915 | success = mPermissions.importLegacyStream(input_stream); | ||
916 | } | ||
917 | else if(0 == strcmp("sale_info", keyword)) | ||
918 | { | ||
919 | // Sale info used to contain next owner perm. It is now in | ||
920 | // the permissions. Thus, we read that out, and fix legacy | ||
921 | // objects. It's possible this op would fail, but it | ||
922 | // should pick up the vast majority of the tasks. | ||
923 | BOOL has_perm_mask = FALSE; | ||
924 | U32 perm_mask = 0; | ||
925 | success = mSaleInfo.importLegacyStream(input_stream, has_perm_mask, perm_mask); | ||
926 | if(has_perm_mask) | ||
927 | { | ||
928 | if(perm_mask == PERM_NONE) | ||
929 | { | ||
930 | perm_mask = mPermissions.getMaskOwner(); | ||
931 | } | ||
932 | // fair use fix. | ||
933 | if(!(perm_mask & PERM_COPY)) | ||
934 | { | ||
935 | perm_mask |= PERM_TRANSFER; | ||
936 | } | ||
937 | mPermissions.setMaskNext(perm_mask); | ||
938 | } | ||
939 | } | ||
940 | else if(0 == strcmp("shadow_id", keyword)) | ||
941 | { | ||
942 | mAssetUUID.set(valuestr); | ||
943 | LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); | ||
944 | cipher.decrypt(mAssetUUID.mData, UUID_BYTES); | ||
945 | } | ||
946 | else if(0 == strcmp("asset_id", keyword)) | ||
947 | { | ||
948 | mAssetUUID.set(valuestr); | ||
949 | } | ||
950 | else if(0 == strcmp("type", keyword)) | ||
951 | { | ||
952 | mType = LLAssetType::lookup(valuestr); | ||
953 | } | ||
954 | else if(0 == strcmp("inv_type", keyword)) | ||
955 | { | ||
956 | mInventoryType = LLInventoryType::lookup(valuestr); | ||
957 | } | ||
958 | else if(0 == strcmp("flags", keyword)) | ||
959 | { | ||
960 | sscanf(valuestr, "%x", &mFlags); | ||
961 | } | ||
962 | else if(0 == strcmp("name", keyword)) | ||
963 | { | ||
964 | //strcpy(valuestr, buffer + strlen(keyword) + 3); | ||
965 | // *NOTE: Not ANSI C, but widely supported. | ||
966 | sscanf(buffer, " %s%[\t]%[^|]", keyword, junk, valuestr); | ||
967 | |||
968 | // IW: sscanf chokes and puts | in valuestr if there's no name | ||
969 | if (valuestr[0] == '|') | ||
970 | { | ||
971 | valuestr[0] = '\000'; | ||
972 | } | ||
973 | |||
974 | mName.assign(valuestr); | ||
975 | LLString::replaceNonstandardASCII(mName, ' '); | ||
976 | LLString::replaceChar(mName, '|', ' '); | ||
977 | } | ||
978 | else if(0 == strcmp("desc", keyword)) | ||
979 | { | ||
980 | //strcpy(valuestr, buffer + strlen(keyword) + 3); | ||
981 | // *NOTE: Not ANSI C, but widely supported. | ||
982 | sscanf(buffer, " %s%[\t]%[^|]", keyword, junk, valuestr); | ||
983 | |||
984 | if (valuestr[0] == '|') | ||
985 | { | ||
986 | valuestr[0] = '\000'; | ||
987 | } | ||
988 | |||
989 | mDescription.assign(valuestr); | ||
990 | LLString::replaceNonstandardASCII(mDescription, ' '); | ||
991 | /* TODO -- ask Ian about this code | ||
992 | const char *donkey = mDescription.c_str(); | ||
993 | if (donkey[0] == '|') | ||
994 | { | ||
995 | llerrs << "Donkey" << llendl; | ||
996 | } | ||
997 | */ | ||
998 | } | ||
999 | else if(0 == strcmp("creation_date", keyword)) | ||
1000 | { | ||
1001 | sscanf(valuestr, "%d", &mCreationDate); | ||
1002 | } | ||
1003 | else | ||
1004 | { | ||
1005 | llwarns << "unknown keyword '" << keyword | ||
1006 | << "' in inventory import of item " << mUUID << llendl; | ||
1007 | } | ||
1008 | } | ||
1009 | |||
1010 | // Need to convert 1.0 simstate files to a useful inventory type | ||
1011 | // and potentially deal with bad inventory tyes eg, a landmark | ||
1012 | // marked as a texture. | ||
1013 | if((LLInventoryType::IT_NONE == mInventoryType) | ||
1014 | || !inventory_and_asset_types_match(mInventoryType, mType)) | ||
1015 | { | ||
1016 | lldebugs << "Resetting inventory type for " << mUUID << llendl; | ||
1017 | mInventoryType = LLInventoryType::defaultForAssetType(mType); | ||
1018 | } | ||
1019 | return success; | ||
1020 | } | ||
1021 | |||
1022 | BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key) const | ||
1023 | { | ||
1024 | char uuid_str[UUID_STR_LENGTH]; | ||
1025 | output_stream << "\tinv_item\t0\n\t{\n"; | ||
1026 | mUUID.toString(uuid_str); | ||
1027 | output_stream << "\t\titem_id\t" << uuid_str << "\n"; | ||
1028 | mParentUUID.toString(uuid_str); | ||
1029 | output_stream << "\t\tparent_id\t" << uuid_str << "\n"; | ||
1030 | mPermissions.exportLegacyStream(output_stream); | ||
1031 | |||
1032 | // Check for permissions to see the asset id, and if so write it | ||
1033 | // out as an asset id. Otherwise, apply our cheesy encryption. | ||
1034 | if(include_asset_key) | ||
1035 | { | ||
1036 | U32 mask = mPermissions.getMaskBase(); | ||
1037 | if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) | ||
1038 | || (mAssetUUID.isNull())) | ||
1039 | { | ||
1040 | mAssetUUID.toString(uuid_str); | ||
1041 | output_stream << "\t\tasset_id\t" << uuid_str << "\n"; | ||
1042 | } | ||
1043 | else | ||
1044 | { | ||
1045 | LLUUID shadow_id(mAssetUUID); | ||
1046 | LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); | ||
1047 | cipher.encrypt(shadow_id.mData, UUID_BYTES); | ||
1048 | shadow_id.toString(uuid_str); | ||
1049 | output_stream << "\t\tshadow_id\t" << uuid_str << "\n"; | ||
1050 | } | ||
1051 | } | ||
1052 | else | ||
1053 | { | ||
1054 | LLUUID::null.toString(uuid_str); | ||
1055 | output_stream << "\t\tasset_id\t" << uuid_str << "\n"; | ||
1056 | } | ||
1057 | output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n"; | ||
1058 | const char* inv_type_str = LLInventoryType::lookup(mInventoryType); | ||
1059 | if(inv_type_str) | ||
1060 | output_stream << "\t\tinv_type\t" << inv_type_str << "\n"; | ||
1061 | char buffer[32]; | ||
1062 | sprintf(buffer, "\t\tflags\t%08x\n", mFlags); | ||
1063 | output_stream << buffer; | ||
1064 | mSaleInfo.exportLegacyStream(output_stream); | ||
1065 | output_stream << "\t\tname\t" << mName.c_str() << "|\n"; | ||
1066 | output_stream << "\t\tdesc\t" << mDescription.c_str() << "|\n"; | ||
1067 | output_stream << "\t\tcreation_date\t" << mCreationDate << "\n"; | ||
1068 | output_stream << "\t}\n"; | ||
1069 | return TRUE; | ||
1070 | } | ||
1071 | |||
1072 | LLSD LLInventoryItem::asLLSD() const | ||
1073 | { | ||
1074 | LLSD sd = LLSD(); | ||
1075 | sd["item_id"] = mUUID; | ||
1076 | sd["parent_id"] = mParentUUID; | ||
1077 | sd["permissions"] = ll_create_sd_from_permissions(mPermissions); | ||
1078 | |||
1079 | U32 mask = mPermissions.getMaskBase(); | ||
1080 | if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) | ||
1081 | || (mAssetUUID.isNull())) | ||
1082 | { | ||
1083 | sd["asset_id"] = mAssetUUID; | ||
1084 | } | ||
1085 | else | ||
1086 | { | ||
1087 | LLUUID shadow_id(mAssetUUID); | ||
1088 | LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); | ||
1089 | cipher.encrypt(shadow_id.mData, UUID_BYTES); | ||
1090 | sd["shadow_id"] = shadow_id; | ||
1091 | } | ||
1092 | sd["type"] = LLAssetType::lookup(mType); | ||
1093 | const char* inv_type_str = LLInventoryType::lookup(mInventoryType); | ||
1094 | if(inv_type_str) | ||
1095 | { | ||
1096 | sd["inv_type"] = inv_type_str; | ||
1097 | } | ||
1098 | sd["flags"] = ll_sd_from_U32(mFlags); | ||
1099 | sd["sale_info"] = mSaleInfo; | ||
1100 | sd["name"] = mName; | ||
1101 | sd["desc"] = mDescription; | ||
1102 | sd["creation_date"] = mCreationDate; | ||
1103 | |||
1104 | return sd; | ||
1105 | } | ||
1106 | |||
1107 | bool LLInventoryItem::fromLLSD(LLSD& sd) | ||
1108 | { | ||
1109 | mInventoryType = LLInventoryType::IT_NONE; | ||
1110 | mAssetUUID.setNull(); | ||
1111 | const char *w; | ||
1112 | |||
1113 | w = "item_id"; | ||
1114 | if (sd.has(w)) | ||
1115 | { | ||
1116 | mUUID = sd[w]; | ||
1117 | } | ||
1118 | w = "parent_id"; | ||
1119 | if (sd.has(w)) | ||
1120 | { | ||
1121 | mParentUUID = sd[w]; | ||
1122 | } | ||
1123 | w = "permissions"; | ||
1124 | if (sd.has(w)) | ||
1125 | { | ||
1126 | mPermissions = ll_permissions_from_sd(sd[w]); | ||
1127 | } | ||
1128 | w = "sale_info"; | ||
1129 | if (sd.has(w)) | ||
1130 | { | ||
1131 | // Sale info used to contain next owner perm. It is now in | ||
1132 | // the permissions. Thus, we read that out, and fix legacy | ||
1133 | // objects. It's possible this op would fail, but it | ||
1134 | // should pick up the vast majority of the tasks. | ||
1135 | BOOL has_perm_mask = FALSE; | ||
1136 | U32 perm_mask = 0; | ||
1137 | if (!mSaleInfo.fromLLSD(sd[w], has_perm_mask, perm_mask)) | ||
1138 | { | ||
1139 | goto fail; | ||
1140 | } | ||
1141 | if (has_perm_mask) | ||
1142 | { | ||
1143 | if(perm_mask == PERM_NONE) | ||
1144 | { | ||
1145 | perm_mask = mPermissions.getMaskOwner(); | ||
1146 | } | ||
1147 | // fair use fix. | ||
1148 | if(!(perm_mask & PERM_COPY)) | ||
1149 | { | ||
1150 | perm_mask |= PERM_TRANSFER; | ||
1151 | } | ||
1152 | mPermissions.setMaskNext(perm_mask); | ||
1153 | } | ||
1154 | } | ||
1155 | w = "shadow_id"; | ||
1156 | if (sd.has(w)) | ||
1157 | { | ||
1158 | mAssetUUID = sd[w]; | ||
1159 | LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); | ||
1160 | cipher.decrypt(mAssetUUID.mData, UUID_BYTES); | ||
1161 | } | ||
1162 | w = "asset_id"; | ||
1163 | if (sd.has(w)) | ||
1164 | { | ||
1165 | mAssetUUID = sd[w]; | ||
1166 | } | ||
1167 | w = "type"; | ||
1168 | if (sd.has(w)) | ||
1169 | { | ||
1170 | mType = LLAssetType::lookup(sd[w].asString().c_str()); | ||
1171 | } | ||
1172 | w = "inv_type"; | ||
1173 | if (sd.has(w)) | ||
1174 | { | ||
1175 | mInventoryType = LLInventoryType::lookup(sd[w].asString().c_str()); | ||
1176 | } | ||
1177 | w = "flags"; | ||
1178 | if (sd.has(w)) | ||
1179 | { | ||
1180 | mFlags = ll_U32_from_sd(sd[w]); | ||
1181 | } | ||
1182 | w = "name"; | ||
1183 | if (sd.has(w)) | ||
1184 | { | ||
1185 | mName = sd[w].asString(); | ||
1186 | LLString::replaceNonstandardASCII(mName, ' '); | ||
1187 | LLString::replaceChar(mName, '|', ' '); | ||
1188 | } | ||
1189 | w = "desc"; | ||
1190 | if (sd.has(w)) | ||
1191 | { | ||
1192 | mDescription = sd[w].asString(); | ||
1193 | LLString::replaceNonstandardASCII(mDescription, ' '); | ||
1194 | } | ||
1195 | w = "creation_date"; | ||
1196 | if (sd.has(w)) | ||
1197 | { | ||
1198 | mCreationDate = sd[w]; | ||
1199 | } | ||
1200 | |||
1201 | // Need to convert 1.0 simstate files to a useful inventory type | ||
1202 | // and potentially deal with bad inventory tyes eg, a landmark | ||
1203 | // marked as a texture. | ||
1204 | if((LLInventoryType::IT_NONE == mInventoryType) | ||
1205 | || !inventory_and_asset_types_match(mInventoryType, mType)) | ||
1206 | { | ||
1207 | lldebugs << "Resetting inventory type for " << mUUID << llendl; | ||
1208 | mInventoryType = LLInventoryType::defaultForAssetType(mType); | ||
1209 | } | ||
1210 | |||
1211 | return true; | ||
1212 | fail: | ||
1213 | return false; | ||
1214 | |||
1215 | } | ||
1216 | |||
1217 | LLXMLNode *LLInventoryItem::exportFileXML(BOOL include_asset_key) const | ||
1218 | { | ||
1219 | LLMemType m1(LLMemType::MTYPE_INVENTORY); | ||
1220 | LLXMLNode *ret = new LLXMLNode("item", FALSE); | ||
1221 | |||
1222 | ret->createChild("uuid", TRUE)->setUUIDValue(1, &mUUID); | ||
1223 | ret->createChild("parent_uuid", TRUE)->setUUIDValue(1, &mParentUUID); | ||
1224 | |||
1225 | mPermissions.exportFileXML()->setParent(ret); | ||
1226 | |||
1227 | // Check for permissions to see the asset id, and if so write it | ||
1228 | // out as an asset id. Otherwise, apply our cheesy encryption. | ||
1229 | if(include_asset_key) | ||
1230 | { | ||
1231 | U32 mask = mPermissions.getMaskBase(); | ||
1232 | if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) | ||
1233 | || (mAssetUUID.isNull())) | ||
1234 | { | ||
1235 | ret->createChild("asset_id", FALSE)->setUUIDValue(1, &mAssetUUID); | ||
1236 | } | ||
1237 | else | ||
1238 | { | ||
1239 | LLUUID shadow_id(mAssetUUID); | ||
1240 | LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); | ||
1241 | cipher.encrypt(shadow_id.mData, UUID_BYTES); | ||
1242 | |||
1243 | ret->createChild("shadow_id", FALSE)->setUUIDValue(1, &shadow_id); | ||
1244 | } | ||
1245 | } | ||
1246 | |||
1247 | LLString type_str = LLAssetType::lookup(mType); | ||
1248 | LLString inv_type_str = LLInventoryType::lookup(mInventoryType); | ||
1249 | |||
1250 | ret->createChild("asset_type", FALSE)->setStringValue(1, &type_str); | ||
1251 | ret->createChild("inventory_type", FALSE)->setStringValue(1, &inv_type_str); | ||
1252 | S32 tmp_flags = (S32) mFlags; | ||
1253 | ret->createChild("flags", FALSE)->setByteValue(4, (U8*)(&tmp_flags), LLXMLNode::ENCODING_HEX); | ||
1254 | |||
1255 | mSaleInfo.exportFileXML()->setParent(ret); | ||
1256 | |||
1257 | LLString temp; | ||
1258 | temp.assign(mName); | ||
1259 | ret->createChild("name", FALSE)->setStringValue(1, &temp); | ||
1260 | temp.assign(mDescription); | ||
1261 | ret->createChild("description", FALSE)->setStringValue(1, &temp); | ||
1262 | ret->createChild("creation_date", FALSE)->setIntValue(1, &mCreationDate); | ||
1263 | |||
1264 | return ret; | ||
1265 | } | ||
1266 | |||
1267 | BOOL LLInventoryItem::importXML(LLXMLNode* node) | ||
1268 | { | ||
1269 | BOOL success = FALSE; | ||
1270 | if (node) | ||
1271 | { | ||
1272 | success = TRUE; | ||
1273 | LLXMLNodePtr sub_node; | ||
1274 | if (node->getChild("uuid", sub_node)) | ||
1275 | success = (1 == sub_node->getUUIDValue(1, &mUUID)); | ||
1276 | if (node->getChild("parent_uuid", sub_node)) | ||
1277 | success = success && (1 == sub_node->getUUIDValue(1, &mParentUUID)); | ||
1278 | if (node->getChild("permissions", sub_node)) | ||
1279 | success = success && mPermissions.importXML(sub_node); | ||
1280 | if (node->getChild("asset_id", sub_node)) | ||
1281 | success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID)); | ||
1282 | if (node->getChild("shadow_id", sub_node)) | ||
1283 | { | ||
1284 | success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID)); | ||
1285 | LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); | ||
1286 | cipher.decrypt(mAssetUUID.mData, UUID_BYTES); | ||
1287 | } | ||
1288 | if (node->getChild("asset_type", sub_node)) | ||
1289 | mType = LLAssetType::lookup(sub_node->getValue().c_str()); | ||
1290 | if (node->getChild("inventory_type", sub_node)) | ||
1291 | mInventoryType = LLInventoryType::lookup(sub_node->getValue().c_str()); | ||
1292 | if (node->getChild("flags", sub_node)) | ||
1293 | { | ||
1294 | S32 tmp_flags = 0; | ||
1295 | success = success && (1 == sub_node->getIntValue(1, &tmp_flags)); | ||
1296 | mFlags = (U32) tmp_flags; | ||
1297 | } | ||
1298 | if (node->getChild("sale_info", sub_node)) | ||
1299 | success = success && mSaleInfo.importXML(sub_node); | ||
1300 | if (node->getChild("name", sub_node)) | ||
1301 | mName = sub_node->getValue(); | ||
1302 | if (node->getChild("description", sub_node)) | ||
1303 | mDescription = sub_node->getValue(); | ||
1304 | if (node->getChild("creation_date", sub_node)) | ||
1305 | success = success && (1 == sub_node->getIntValue(1, &mCreationDate)); | ||
1306 | if (!success) | ||
1307 | { | ||
1308 | lldebugs << "LLInventory::importXML() failed for node named '" | ||
1309 | << node->getName() << "'" << llendl; | ||
1310 | } | ||
1311 | } | ||
1312 | return success; | ||
1313 | } | ||
1314 | |||
1315 | S32 LLInventoryItem::packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override) const | ||
1316 | { | ||
1317 | // Figure out which permissions to use. | ||
1318 | LLPermissions perm; | ||
1319 | if (perm_override) | ||
1320 | { | ||
1321 | // Use the permissions override. | ||
1322 | perm = *perm_override; | ||
1323 | } | ||
1324 | else | ||
1325 | { | ||
1326 | // Use the current permissions. | ||
1327 | perm = getPermissions(); | ||
1328 | } | ||
1329 | |||
1330 | // describe the inventory item | ||
1331 | char* buffer = (char*) bin_bucket; | ||
1332 | char creator_id_str[UUID_STR_LENGTH]; | ||
1333 | |||
1334 | perm.getCreator().toString(creator_id_str); | ||
1335 | char owner_id_str[UUID_STR_LENGTH]; | ||
1336 | perm.getOwner().toString(owner_id_str); | ||
1337 | char last_owner_id_str[UUID_STR_LENGTH]; | ||
1338 | perm.getLastOwner().toString(last_owner_id_str); | ||
1339 | char group_id_str[UUID_STR_LENGTH]; | ||
1340 | perm.getGroup().toString(group_id_str); | ||
1341 | char asset_id_str[UUID_STR_LENGTH]; | ||
1342 | getAssetUUID().toString(asset_id_str); | ||
1343 | S32 size = sprintf(buffer, | ||
1344 | "%d|%d|%s|%s|%s|%s|%s|%x|%x|%x|%x|%x|%s|%s|%d|%d|%x", | ||
1345 | getType(), | ||
1346 | getInventoryType(), | ||
1347 | getName().c_str(), | ||
1348 | creator_id_str, | ||
1349 | owner_id_str, | ||
1350 | last_owner_id_str, | ||
1351 | group_id_str, | ||
1352 | perm.getMaskBase(), | ||
1353 | perm.getMaskOwner(), | ||
1354 | perm.getMaskGroup(), | ||
1355 | perm.getMaskEveryone(), | ||
1356 | perm.getMaskNextOwner(), | ||
1357 | asset_id_str, | ||
1358 | getDescription().c_str(), | ||
1359 | getSaleInfo().getSaleType(), | ||
1360 | getSaleInfo().getSalePrice(), | ||
1361 | getFlags()) + 1; | ||
1362 | |||
1363 | return size; | ||
1364 | } | ||
1365 | |||
1366 | void LLInventoryItem::unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size) | ||
1367 | { | ||
1368 | // Early exit on an empty binary bucket. | ||
1369 | if (bin_bucket_size <= 1) return; | ||
1370 | |||
1371 | // Convert the bin_bucket into a string. | ||
1372 | char* item_buffer = new char[bin_bucket_size+1]; | ||
1373 | memcpy(item_buffer, bin_bucket, bin_bucket_size); | ||
1374 | item_buffer[bin_bucket_size] = '\0'; | ||
1375 | std::string str(item_buffer); | ||
1376 | |||
1377 | lldebugs << "item buffer: " << item_buffer << llendl; | ||
1378 | delete[] item_buffer; | ||
1379 | |||
1380 | // Tokenize the string. | ||
1381 | typedef boost::tokenizer<boost::char_separator<char> > tokenizer; | ||
1382 | boost::char_separator<char> sep("|", "", boost::keep_empty_tokens); | ||
1383 | tokenizer tokens(str, sep); | ||
1384 | tokenizer::iterator iter = tokens.begin(); | ||
1385 | |||
1386 | // Extract all values. | ||
1387 | LLUUID item_id; | ||
1388 | item_id.generate(); | ||
1389 | setUUID(item_id); | ||
1390 | |||
1391 | LLAssetType::EType type; | ||
1392 | type = (LLAssetType::EType)(atoi((*(iter++)).c_str())); | ||
1393 | setType( type ); | ||
1394 | |||
1395 | LLInventoryType::EType inv_type; | ||
1396 | inv_type = (LLInventoryType::EType)(atoi((*(iter++)).c_str())); | ||
1397 | setInventoryType( inv_type ); | ||
1398 | |||
1399 | LLString name((*(iter++)).c_str()); | ||
1400 | rename( name ); | ||
1401 | |||
1402 | LLUUID creator_id((*(iter++)).c_str()); | ||
1403 | LLUUID owner_id((*(iter++)).c_str()); | ||
1404 | LLUUID last_owner_id((*(iter++)).c_str()); | ||
1405 | LLUUID group_id((*(iter++)).c_str()); | ||
1406 | PermissionMask mask_base = strtoul((*(iter++)).c_str(), NULL, 16); | ||
1407 | PermissionMask mask_owner = strtoul((*(iter++)).c_str(), NULL, 16); | ||
1408 | PermissionMask mask_group = strtoul((*(iter++)).c_str(), NULL, 16); | ||
1409 | PermissionMask mask_every = strtoul((*(iter++)).c_str(), NULL, 16); | ||
1410 | PermissionMask mask_next = strtoul((*(iter++)).c_str(), NULL, 16); | ||
1411 | LLPermissions perm; | ||
1412 | perm.init(creator_id, owner_id, last_owner_id, group_id); | ||
1413 | perm.initMasks(mask_base, mask_owner, mask_group, mask_every, mask_next); | ||
1414 | setPermissions(perm); | ||
1415 | //lldebugs << "perm: " << perm << llendl; | ||
1416 | |||
1417 | LLUUID asset_id((*(iter++)).c_str()); | ||
1418 | setAssetUUID(asset_id); | ||
1419 | |||
1420 | LLString desc((*(iter++)).c_str()); | ||
1421 | setDescription(desc); | ||
1422 | |||
1423 | LLSaleInfo::EForSale sale_type; | ||
1424 | sale_type = (LLSaleInfo::EForSale)(atoi((*(iter++)).c_str())); | ||
1425 | S32 price = atoi((*(iter++)).c_str()); | ||
1426 | LLSaleInfo sale_info(sale_type, price); | ||
1427 | setSaleInfo(sale_info); | ||
1428 | |||
1429 | U32 flags = strtoul((*(iter++)).c_str(), NULL, 16); | ||
1430 | setFlags(flags); | ||
1431 | |||
1432 | time_t now = time(NULL); | ||
1433 | setCreationDate(now); | ||
1434 | } | ||
1435 | |||
1436 | // returns TRUE if a should appear before b | ||
1437 | BOOL item_dictionary_sort( LLInventoryItem* a, LLInventoryItem* b ) | ||
1438 | { | ||
1439 | return (LLString::compareDict( a->getName().c_str(), b->getName().c_str() ) < 0); | ||
1440 | } | ||
1441 | |||
1442 | // returns TRUE if a should appear before b | ||
1443 | BOOL item_date_sort( LLInventoryItem* a, LLInventoryItem* b ) | ||
1444 | { | ||
1445 | return a->getCreationDate() < b->getCreationDate(); | ||
1446 | } | ||
1447 | |||
1448 | |||
1449 | ///---------------------------------------------------------------------------- | ||
1450 | /// Class LLInventoryCategory | ||
1451 | ///---------------------------------------------------------------------------- | ||
1452 | |||
1453 | LLInventoryCategory::LLInventoryCategory( | ||
1454 | const LLUUID& uuid, | ||
1455 | const LLUUID& parent_uuid, | ||
1456 | LLAssetType::EType preferred_type, | ||
1457 | const LLString& name) : | ||
1458 | LLInventoryObject(uuid, parent_uuid, LLAssetType::AT_CATEGORY, name), | ||
1459 | mPreferredType(preferred_type) | ||
1460 | { | ||
1461 | } | ||
1462 | |||
1463 | LLInventoryCategory::LLInventoryCategory() : | ||
1464 | mPreferredType(LLAssetType::AT_NONE) | ||
1465 | { | ||
1466 | mType = LLAssetType::AT_CATEGORY; | ||
1467 | } | ||
1468 | |||
1469 | LLInventoryCategory::LLInventoryCategory(const LLInventoryCategory* other) : | ||
1470 | LLInventoryObject() | ||
1471 | { | ||
1472 | copy(other); | ||
1473 | } | ||
1474 | |||
1475 | LLInventoryCategory::~LLInventoryCategory() | ||
1476 | { | ||
1477 | } | ||
1478 | |||
1479 | // virtual | ||
1480 | void LLInventoryCategory::copy(const LLInventoryCategory* other) | ||
1481 | { | ||
1482 | LLInventoryObject::copy(other); | ||
1483 | mPreferredType = other->mPreferredType; | ||
1484 | } | ||
1485 | |||
1486 | LLAssetType::EType LLInventoryCategory::getPreferredType() const | ||
1487 | { | ||
1488 | return mPreferredType; | ||
1489 | } | ||
1490 | |||
1491 | void LLInventoryCategory::setPreferredType(LLAssetType::EType type) | ||
1492 | { | ||
1493 | mPreferredType = type; | ||
1494 | } | ||
1495 | |||
1496 | // virtual | ||
1497 | void LLInventoryCategory::packMessage(LLMessageSystem* msg) const | ||
1498 | { | ||
1499 | msg->addUUIDFast(_PREHASH_FolderID, mUUID); | ||
1500 | msg->addUUIDFast(_PREHASH_ParentID, mParentUUID); | ||
1501 | S8 type = static_cast<S8>(mPreferredType); | ||
1502 | msg->addS8Fast(_PREHASH_Type, type); | ||
1503 | msg->addStringFast(_PREHASH_Name, mName); | ||
1504 | } | ||
1505 | |||
1506 | // virtual | ||
1507 | void LLInventoryCategory::unpackMessage(LLMessageSystem* msg, | ||
1508 | const char* block, | ||
1509 | S32 block_num) | ||
1510 | { | ||
1511 | msg->getUUIDFast(block, _PREHASH_FolderID, mUUID, block_num); | ||
1512 | msg->getUUIDFast(block, _PREHASH_ParentID, mParentUUID, block_num); | ||
1513 | S8 type; | ||
1514 | msg->getS8Fast(block, _PREHASH_Type, type, block_num); | ||
1515 | mPreferredType = static_cast<LLAssetType::EType>(type); | ||
1516 | char name[DB_INV_ITEM_NAME_BUF_SIZE]; | ||
1517 | msg->getStringFast(block, _PREHASH_Name, DB_INV_ITEM_NAME_BUF_SIZE, name, block_num); | ||
1518 | mName.assign(name); | ||
1519 | LLString::replaceNonstandardASCII(mName, ' '); | ||
1520 | } | ||
1521 | |||
1522 | // virtual | ||
1523 | BOOL LLInventoryCategory::importFile(FILE* fp) | ||
1524 | { | ||
1525 | char buffer[MAX_STRING]; | ||
1526 | char keyword[MAX_STRING]; | ||
1527 | char valuestr[MAX_STRING]; | ||
1528 | |||
1529 | keyword[0] = '\0'; | ||
1530 | valuestr[0] = '\0'; | ||
1531 | while(!feof(fp)) | ||
1532 | { | ||
1533 | fgets(buffer, MAX_STRING, fp); | ||
1534 | sscanf(buffer, " %s %s", keyword, valuestr); | ||
1535 | if(!keyword) | ||
1536 | { | ||
1537 | continue; | ||
1538 | } | ||
1539 | if(0 == strcmp("{",keyword)) | ||
1540 | { | ||
1541 | continue; | ||
1542 | } | ||
1543 | if(0 == strcmp("}", keyword)) | ||
1544 | { | ||
1545 | break; | ||
1546 | } | ||
1547 | else if(0 == strcmp("cat_id", keyword)) | ||
1548 | { | ||
1549 | mUUID.set(valuestr); | ||
1550 | } | ||
1551 | else if(0 == strcmp("parent_id", keyword)) | ||
1552 | { | ||
1553 | mParentUUID.set(valuestr); | ||
1554 | } | ||
1555 | else if(0 == strcmp("type", keyword)) | ||
1556 | { | ||
1557 | mType = LLAssetType::lookup(valuestr); | ||
1558 | } | ||
1559 | else if(0 == strcmp("pref_type", keyword)) | ||
1560 | { | ||
1561 | mPreferredType = LLAssetType::lookup(valuestr); | ||
1562 | } | ||
1563 | else if(0 == strcmp("name", keyword)) | ||
1564 | { | ||
1565 | //strcpy(valuestr, buffer + strlen(keyword) + 3); | ||
1566 | // *NOTE: Not ANSI C, but widely supported. | ||
1567 | sscanf(buffer, " %s %[^|]", keyword, valuestr); | ||
1568 | mName.assign(valuestr); | ||
1569 | LLString::replaceNonstandardASCII(mName, ' '); | ||
1570 | LLString::replaceChar(mName, '|', ' '); | ||
1571 | } | ||
1572 | else | ||
1573 | { | ||
1574 | llwarns << "unknown keyword '" << keyword | ||
1575 | << "' in inventory import category " << mUUID << llendl; | ||
1576 | } | ||
1577 | } | ||
1578 | return TRUE; | ||
1579 | } | ||
1580 | |||
1581 | BOOL LLInventoryCategory::exportFile(FILE* fp, BOOL) const | ||
1582 | { | ||
1583 | char uuid_str[UUID_STR_LENGTH]; | ||
1584 | fprintf(fp, "\tinv_category\t0\n\t{\n"); | ||
1585 | mUUID.toString(uuid_str); | ||
1586 | fprintf(fp, "\t\tcat_id\t%s\n", uuid_str); | ||
1587 | mParentUUID.toString(uuid_str); | ||
1588 | fprintf(fp, "\t\tparent_id\t%s\n", uuid_str); | ||
1589 | fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); | ||
1590 | fprintf(fp, "\t\tpref_type\t%s\n", LLAssetType::lookup(mPreferredType)); | ||
1591 | fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); | ||
1592 | fprintf(fp,"\t}\n"); | ||
1593 | return TRUE; | ||
1594 | } | ||
1595 | |||
1596 | |||
1597 | // virtual | ||
1598 | BOOL LLInventoryCategory::importLegacyStream(std::istream& input_stream) | ||
1599 | { | ||
1600 | char buffer[MAX_STRING]; | ||
1601 | char keyword[MAX_STRING]; | ||
1602 | char valuestr[MAX_STRING]; | ||
1603 | |||
1604 | keyword[0] = '\0'; | ||
1605 | valuestr[0] = '\0'; | ||
1606 | while(input_stream.good()) | ||
1607 | { | ||
1608 | input_stream.getline(buffer, MAX_STRING); | ||
1609 | sscanf(buffer, " %s %s", keyword, valuestr); | ||
1610 | if(!keyword) | ||
1611 | { | ||
1612 | continue; | ||
1613 | } | ||
1614 | if(0 == strcmp("{",keyword)) | ||
1615 | { | ||
1616 | continue; | ||
1617 | } | ||
1618 | if(0 == strcmp("}", keyword)) | ||
1619 | { | ||
1620 | break; | ||
1621 | } | ||
1622 | else if(0 == strcmp("cat_id", keyword)) | ||
1623 | { | ||
1624 | mUUID.set(valuestr); | ||
1625 | } | ||
1626 | else if(0 == strcmp("parent_id", keyword)) | ||
1627 | { | ||
1628 | mParentUUID.set(valuestr); | ||
1629 | } | ||
1630 | else if(0 == strcmp("type", keyword)) | ||
1631 | { | ||
1632 | mType = LLAssetType::lookup(valuestr); | ||
1633 | } | ||
1634 | else if(0 == strcmp("pref_type", keyword)) | ||
1635 | { | ||
1636 | mPreferredType = LLAssetType::lookup(valuestr); | ||
1637 | } | ||
1638 | else if(0 == strcmp("name", keyword)) | ||
1639 | { | ||
1640 | //strcpy(valuestr, buffer + strlen(keyword) + 3); | ||
1641 | // *NOTE: Not ANSI C, but widely supported. | ||
1642 | sscanf(buffer, " %s %[^|]", keyword, valuestr); | ||
1643 | mName.assign(valuestr); | ||
1644 | LLString::replaceNonstandardASCII(mName, ' '); | ||
1645 | LLString::replaceChar(mName, '|', ' '); | ||
1646 | } | ||
1647 | else | ||
1648 | { | ||
1649 | llwarns << "unknown keyword '" << keyword | ||
1650 | << "' in inventory import category " << mUUID << llendl; | ||
1651 | } | ||
1652 | } | ||
1653 | return TRUE; | ||
1654 | } | ||
1655 | |||
1656 | BOOL LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, BOOL) const | ||
1657 | { | ||
1658 | char uuid_str[UUID_STR_LENGTH]; | ||
1659 | output_stream << "\tinv_category\t0\n\t{\n"; | ||
1660 | mUUID.toString(uuid_str); | ||
1661 | output_stream << "\t\tcat_id\t" << uuid_str << "\n"; | ||
1662 | mParentUUID.toString(uuid_str); | ||
1663 | output_stream << "\t\tparent_id\t" << uuid_str << "\n"; | ||
1664 | output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n"; | ||
1665 | output_stream << "\t\tpref_type\t" << LLAssetType::lookup(mPreferredType) << "\n"; | ||
1666 | output_stream << "\t\tname\t" << mName.c_str() << "|\n"; | ||
1667 | output_stream << "\t}\n"; | ||
1668 | return TRUE; | ||
1669 | } | ||
1670 | |||
1671 | ///---------------------------------------------------------------------------- | ||
1672 | /// Local function definitions | ||
1673 | ///---------------------------------------------------------------------------- | ||
1674 | |||
1675 | bool inventory_and_asset_types_match( | ||
1676 | LLInventoryType::EType inventory_type, | ||
1677 | LLAssetType::EType asset_type) | ||
1678 | { | ||
1679 | bool rv = false; | ||
1680 | if((inventory_type >= 0) && (inventory_type < LLInventoryType::IT_COUNT)) | ||
1681 | { | ||
1682 | for(S32 i = 0; i < MAX_POSSIBLE_ASSET_TYPES; ++i) | ||
1683 | { | ||
1684 | if(INVENTORY_TO_ASSET_TYPE[inventory_type][i] == asset_type) | ||
1685 | { | ||
1686 | rv = true; | ||
1687 | break; | ||
1688 | } | ||
1689 | } | ||
1690 | } | ||
1691 | return rv; | ||
1692 | } | ||
1693 | |||
1694 | ///---------------------------------------------------------------------------- | ||
1695 | /// exported functions | ||
1696 | ///---------------------------------------------------------------------------- | ||
1697 | |||
1698 | static const std::string INV_ITEM_ID_LABEL("item_id"); | ||
1699 | static const std::string INV_FOLDER_ID_LABEL("folder_id"); | ||
1700 | static const std::string INV_PARENT_ID_LABEL("parent_id"); | ||
1701 | static const std::string INV_ASSET_TYPE_LABEL("asset_type"); | ||
1702 | static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type"); | ||
1703 | static const std::string INV_INVENTORY_TYPE_LABEL("inv_type"); | ||
1704 | static const std::string INV_NAME_LABEL("name"); | ||
1705 | static const std::string INV_DESC_LABEL("description"); | ||
1706 | static const std::string INV_PERMISSIONS_LABEL("permissions"); | ||
1707 | static const std::string INV_ASSET_ID_LABEL("asset_id"); | ||
1708 | static const std::string INV_SALE_INFO_LABEL("sale_info"); | ||
1709 | static const std::string INV_FLAGS_LABEL("flags"); | ||
1710 | static const std::string INV_CREATION_DATE_LABEL("created_at"); | ||
1711 | |||
1712 | LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item) | ||
1713 | { | ||
1714 | LLSD rv; | ||
1715 | if(item.isNull()) return rv; | ||
1716 | if (item->getType() == LLAssetType::AT_NONE) | ||
1717 | { | ||
1718 | llwarns << "ll_create_sd_from_inventory_item() for item with AT_NONE" | ||
1719 | << llendl; | ||
1720 | return rv; | ||
1721 | } | ||
1722 | rv[INV_ITEM_ID_LABEL] = item->getUUID(); | ||
1723 | rv[INV_PARENT_ID_LABEL] = item->getParentUUID(); | ||
1724 | rv[INV_NAME_LABEL] = item->getName(); | ||
1725 | rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(item->getType()); | ||
1726 | rv[INV_ASSET_ID_LABEL] = item->getAssetUUID(); | ||
1727 | rv[INV_DESC_LABEL] = item->getDescription(); | ||
1728 | rv[INV_SALE_INFO_LABEL] = ll_create_sd_from_sale_info(item->getSaleInfo()); | ||
1729 | rv[INV_PERMISSIONS_LABEL] = | ||
1730 | ll_create_sd_from_permissions(item->getPermissions()); | ||
1731 | rv[INV_INVENTORY_TYPE_LABEL] = | ||
1732 | LLInventoryType::lookup(item->getInventoryType()); | ||
1733 | rv[INV_FLAGS_LABEL] = (S32)item->getFlags(); | ||
1734 | rv[INV_CREATION_DATE_LABEL] = item->getCreationDate(); | ||
1735 | return rv; | ||
1736 | } | ||
1737 | |||
1738 | LLPointer<LLInventoryItem> ll_create_item_from_sd(const LLSD& sd_item) | ||
1739 | { | ||
1740 | LLPointer<LLInventoryItem> rv = new LLInventoryItem; | ||
1741 | rv->setUUID(sd_item[INV_ITEM_ID_LABEL].asUUID()); | ||
1742 | rv->setParent(sd_item[INV_PARENT_ID_LABEL].asUUID()); | ||
1743 | rv->rename(sd_item[INV_NAME_LABEL].asString()); | ||
1744 | rv->setType( | ||
1745 | LLAssetType::lookup(sd_item[INV_ASSET_TYPE_LABEL].asString().c_str())); | ||
1746 | rv->setAssetUUID(sd_item[INV_ASSET_ID_LABEL].asUUID()); | ||
1747 | rv->setDescription(sd_item[INV_DESC_LABEL].asString()); | ||
1748 | rv->setSaleInfo(ll_sale_info_from_sd(sd_item[INV_SALE_INFO_LABEL])); | ||
1749 | rv->setPermissions(ll_permissions_from_sd(sd_item[INV_PERMISSIONS_LABEL])); | ||
1750 | rv->setInventoryType( | ||
1751 | LLInventoryType::lookup( | ||
1752 | sd_item[INV_INVENTORY_TYPE_LABEL].asString().c_str())); | ||
1753 | rv->setFlags((U32)(sd_item[INV_FLAGS_LABEL].asInteger())); | ||
1754 | rv->setCreationDate(sd_item[INV_CREATION_DATE_LABEL].asInteger()); | ||
1755 | return rv; | ||
1756 | } | ||
1757 | |||
1758 | LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat) | ||
1759 | { | ||
1760 | LLSD rv; | ||
1761 | if(cat.isNull()) return rv; | ||
1762 | if (cat->getType() == LLAssetType::AT_NONE) | ||
1763 | { | ||
1764 | llwarns << "ll_create_sd_from_inventory_category() for cat with AT_NONE" | ||
1765 | << llendl; | ||
1766 | return rv; | ||
1767 | } | ||
1768 | rv[INV_FOLDER_ID_LABEL] = cat->getUUID(); | ||
1769 | rv[INV_PARENT_ID_LABEL] = cat->getParentUUID(); | ||
1770 | rv[INV_NAME_LABEL] = cat->getName(); | ||
1771 | rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(cat->getType()); | ||
1772 | if(LLAssetType::AT_NONE != cat->getPreferredType()) | ||
1773 | { | ||
1774 | rv[INV_PREFERRED_TYPE_LABEL] = | ||
1775 | LLAssetType::lookup(cat->getPreferredType()); | ||
1776 | } | ||
1777 | return rv; | ||
1778 | } | ||
1779 | |||
1780 | LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat) | ||
1781 | { | ||
1782 | LLPointer<LLInventoryCategory> rv = new LLInventoryCategory; | ||
1783 | rv->setUUID(sd_cat[INV_FOLDER_ID_LABEL].asUUID()); | ||
1784 | rv->setParent(sd_cat[INV_PARENT_ID_LABEL].asUUID()); | ||
1785 | rv->rename(sd_cat[INV_NAME_LABEL].asString()); | ||
1786 | rv->setType( | ||
1787 | LLAssetType::lookup(sd_cat[INV_ASSET_TYPE_LABEL].asString().c_str())); | ||
1788 | rv->setPreferredType( | ||
1789 | LLAssetType::lookup( | ||
1790 | sd_cat[INV_PREFERRED_TYPE_LABEL].asString().c_str())); | ||
1791 | return rv; | ||
1792 | } | ||
diff --git a/linden/indra/llinventory/llinventory.h b/linden/indra/llinventory/llinventory.h new file mode 100644 index 0000000..1ebcabf --- /dev/null +++ b/linden/indra/llinventory/llinventory.h | |||
@@ -0,0 +1,430 @@ | |||
1 | /** | ||
2 | * @file llinventory.h | ||
3 | * @brief LLInventoryItem and LLInventoryCategory class declaration. | ||
4 | * | ||
5 | * Copyright (c) 2001-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 | #ifndef LL_LLINVENTORY_H | ||
29 | #define LL_LLINVENTORY_H | ||
30 | |||
31 | #include <functional> | ||
32 | |||
33 | #include "llassetstorage.h" | ||
34 | #include "lldarray.h" | ||
35 | #include "llpermissions.h" | ||
36 | #include "llsaleinfo.h" | ||
37 | #include "llsd.h" | ||
38 | #include "lluuid.h" | ||
39 | #include "llxmlnode.h" | ||
40 | |||
41 | // consts for Key field in the task inventory update message | ||
42 | extern const U8 TASK_INVENTORY_ITEM_KEY; | ||
43 | extern const U8 TASK_INVENTORY_ASSET_KEY; | ||
44 | |||
45 | // anonymous enumeration to specify a max inventory buffer size for | ||
46 | // use in packBinaryBucket() | ||
47 | enum | ||
48 | { | ||
49 | MAX_INVENTORY_BUFFER_SIZE = 1024 | ||
50 | }; | ||
51 | |||
52 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
53 | // Class LLInventoryType | ||
54 | // | ||
55 | // Class used to encapsulate operations around inventory type. | ||
56 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
57 | |||
58 | class LLInventoryType | ||
59 | { | ||
60 | public: | ||
61 | enum EType | ||
62 | { | ||
63 | IT_TEXTURE = 0, | ||
64 | IT_SOUND = 1, | ||
65 | IT_CALLINGCARD = 2, | ||
66 | IT_LANDMARK = 3, | ||
67 | //IT_SCRIPT = 4, | ||
68 | //IT_CLOTHING = 5, | ||
69 | IT_OBJECT = 6, | ||
70 | IT_NOTECARD = 7, | ||
71 | IT_CATEGORY = 8, | ||
72 | IT_ROOT_CATEGORY = 9, | ||
73 | IT_LSL = 10, | ||
74 | //IT_LSL_BYTECODE = 11, | ||
75 | //IT_TEXTURE_TGA = 12, | ||
76 | //IT_BODYPART = 13, | ||
77 | //IT_TRASH = 14, | ||
78 | IT_SNAPSHOT = 15, | ||
79 | //IT_LOST_AND_FOUND = 16, | ||
80 | IT_ATTACHMENT = 17, | ||
81 | IT_WEARABLE = 18, | ||
82 | IT_ANIMATION = 19, | ||
83 | IT_GESTURE = 20, | ||
84 | IT_COUNT = 21, | ||
85 | |||
86 | IT_NONE = -1 | ||
87 | }; | ||
88 | |||
89 | // machine transation between type and strings | ||
90 | static EType lookup(const char* name); | ||
91 | static const char* lookup(EType type); | ||
92 | |||
93 | // translation from a type to a human readable form. | ||
94 | static const char* lookupHumanReadable(EType type); | ||
95 | |||
96 | // return the default inventory for the given asset type. | ||
97 | static EType defaultForAssetType(LLAssetType::EType asset_type); | ||
98 | |||
99 | private: | ||
100 | // don't instantiate or derive one of these objects | ||
101 | LLInventoryType( void ) {} | ||
102 | ~LLInventoryType( void ) {} | ||
103 | |||
104 | //private: | ||
105 | // static const char* mInventoryTypeNames[]; | ||
106 | // static const char* mInventoryTypeHumanNames[]; | ||
107 | // static LLInventoryType::EType mInventoryAssetType[]; | ||
108 | }; | ||
109 | |||
110 | |||
111 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
112 | // Class LLInventoryObject | ||
113 | // | ||
114 | // This is the base class for inventory objects that handles the | ||
115 | // common code between items and categories. The 'mParentUUID' member | ||
116 | // means the parent category since all inventory objects except each | ||
117 | // user's root category are in some category. Each user's root | ||
118 | // category will have mParentUUID==LLUUID::null. | ||
119 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
120 | |||
121 | class LLMessageSystem; | ||
122 | |||
123 | class LLInventoryObject : public LLRefCount | ||
124 | { | ||
125 | protected: | ||
126 | LLUUID mUUID; | ||
127 | LLUUID mParentUUID; | ||
128 | LLAssetType::EType mType; | ||
129 | LLString mName; | ||
130 | |||
131 | protected: | ||
132 | virtual ~LLInventoryObject( void ); | ||
133 | |||
134 | public: | ||
135 | MEM_TYPE_NEW(LLMemType::MTYPE_INVENTORY); | ||
136 | LLInventoryObject(const LLUUID& uuid, const LLUUID& parent_uuid, | ||
137 | LLAssetType::EType type, const LLString& name); | ||
138 | LLInventoryObject(); | ||
139 | virtual void copy(const LLInventoryObject* other); // LLRefCount requires custom copy | ||
140 | |||
141 | // accessors | ||
142 | const LLUUID& getUUID() const; | ||
143 | const LLUUID& getParentUUID() const; | ||
144 | const LLString& getName() const; | ||
145 | LLAssetType::EType getType() const; | ||
146 | |||
147 | // mutators - will not call updateServer(); | ||
148 | void setUUID(const LLUUID& new_uuid); | ||
149 | void rename(const LLString& new_name); | ||
150 | void setParent(const LLUUID& new_parent); | ||
151 | void setType(LLAssetType::EType type); | ||
152 | |||
153 | // file support - implemented here so that a minimal information | ||
154 | // set can be transmitted between simulator and viewer. | ||
155 | // virtual BOOL importFile(FILE* fp); | ||
156 | virtual BOOL exportFile(FILE* fp, BOOL include_asset_key = TRUE) const; | ||
157 | |||
158 | virtual BOOL importLegacyStream(std::istream& input_stream); | ||
159 | virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const; | ||
160 | |||
161 | // virtual methods | ||
162 | virtual void removeFromServer(); | ||
163 | virtual void updateParentOnServer(BOOL) const; | ||
164 | virtual void updateServer(BOOL) const; | ||
165 | }; | ||
166 | |||
167 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
168 | // Class LLInventoryItem | ||
169 | // | ||
170 | // An inventory item represents something that the current user has in | ||
171 | // their inventory. | ||
172 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
173 | |||
174 | class LLInventoryItem : public LLInventoryObject | ||
175 | { | ||
176 | public: | ||
177 | typedef LLDynamicArray<LLPointer<LLInventoryItem> > item_array_t; | ||
178 | |||
179 | protected: | ||
180 | LLPermissions mPermissions; | ||
181 | LLUUID mAssetUUID; | ||
182 | LLString mDescription; | ||
183 | LLSaleInfo mSaleInfo; | ||
184 | LLInventoryType::EType mInventoryType; | ||
185 | U32 mFlags; | ||
186 | S32 mCreationDate; // seconds from 1/1/1970, UTC | ||
187 | |||
188 | public: | ||
189 | enum | ||
190 | { | ||
191 | // The meaning of LLInventoryItem::mFlags is distinct for each | ||
192 | // inventory type. | ||
193 | II_FLAGS_NONE = 0, | ||
194 | |||
195 | // landmark flags | ||
196 | II_FLAGS_LANDMARK_VISITED = 1, | ||
197 | |||
198 | // flag to indicate that object permissions should have next | ||
199 | // owner perm be more restrictive on rez. We bump this into | ||
200 | // the second byte of the flags since the low byte is used to | ||
201 | // track attachment points. | ||
202 | II_FLAGS_OBJECT_SLAM_PERM = 0x100, | ||
203 | |||
204 | // These flags specify which permissions masks to overwrite | ||
205 | // upon rez. Normally, if no permissions slam (above) or | ||
206 | // overwrite flags are set, the asset's permissions are | ||
207 | // used and the inventory's permissions are ignored. If | ||
208 | // any of these flags are set, the inventory's permissions | ||
209 | // take precedence. | ||
210 | II_FLAGS_OBJECT_PERM_OVERWRITE_BASE = 0x010000, | ||
211 | II_FLAGS_OBJECT_PERM_OVERWRITE_OWNER = 0x020000, | ||
212 | II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP = 0x040000, | ||
213 | II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE = 0x080000, | ||
214 | II_FLAGS_OBJECT_PERM_OVERWRITE_NEXT_OWNER = 0x100000, | ||
215 | |||
216 | // wearables use the low order byte of flags to store the | ||
217 | // EWearableType enumeration found in newview/llwearable.h | ||
218 | }; | ||
219 | |||
220 | protected: | ||
221 | ~LLInventoryItem(); // ref counted | ||
222 | |||
223 | public: | ||
224 | MEM_TYPE_NEW(LLMemType::MTYPE_INVENTORY); | ||
225 | LLInventoryItem(const LLUUID& uuid, | ||
226 | const LLUUID& parent_uuid, | ||
227 | const LLPermissions& permissions, | ||
228 | const LLUUID& asset_uuid, | ||
229 | LLAssetType::EType type, | ||
230 | LLInventoryType::EType inv_type, | ||
231 | const LLString& name, | ||
232 | const LLString& desc, | ||
233 | const LLSaleInfo& sale_info, | ||
234 | U32 flags, | ||
235 | S32 creation_date_utc); | ||
236 | LLInventoryItem(); | ||
237 | // Create a copy of an inventory item from a pointer to another item | ||
238 | // Note: Because InventoryItems are ref counted, reference copy (a = b) | ||
239 | // is prohibited | ||
240 | LLInventoryItem(const LLInventoryItem* other); | ||
241 | virtual void copy(const LLInventoryItem* other); // LLRefCount requires custom copy | ||
242 | |||
243 | // As a constructor alternative, the clone() method works like a | ||
244 | // copy constructor, but gens a new UUID. | ||
245 | // It is up to the caller to delete (unref) the item. | ||
246 | virtual void clone(LLPointer<LLInventoryItem>& newitem) const; | ||
247 | |||
248 | // accessors | ||
249 | const LLPermissions& getPermissions() const; | ||
250 | const LLUUID& getCreatorUUID() const; | ||
251 | const LLUUID& getAssetUUID() const; | ||
252 | const LLString& getDescription() const; | ||
253 | const LLSaleInfo& getSaleInfo() const; | ||
254 | LLInventoryType::EType getInventoryType() const; | ||
255 | U32 getFlags() const; | ||
256 | S32 getCreationDate() const; | ||
257 | U32 getCRC32() const; // really more of a checksum. | ||
258 | |||
259 | // mutators - will not call updateServer(), and will never fail | ||
260 | // (though it may correct to sane values) | ||
261 | void setAssetUUID(const LLUUID& asset_id); | ||
262 | void setDescription(const LLString& new_desc); | ||
263 | void setSaleInfo(const LLSaleInfo& sale_info); | ||
264 | void setPermissions(const LLPermissions& perm); | ||
265 | void setInventoryType(LLInventoryType::EType inv_type); | ||
266 | void setFlags(U32 flags); | ||
267 | void setCreationDate(S32 creation_date_utc); | ||
268 | |||
269 | // Put this inventory item onto the current outgoing mesage. It | ||
270 | // assumes you have already called nextBlock(). | ||
271 | virtual void packMessage(LLMessageSystem* msg) const; | ||
272 | |||
273 | // unpack returns TRUE if the inventory item came through the | ||
274 | // network ok. It uses a simple crc check which is defeatable, but | ||
275 | // we want to detect network mangling somehow. | ||
276 | virtual BOOL unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); | ||
277 | |||
278 | // file support | ||
279 | virtual BOOL importFile(FILE* fp); | ||
280 | virtual BOOL exportFile(FILE* fp, BOOL include_asset_key = TRUE) const; | ||
281 | |||
282 | virtual BOOL importLegacyStream(std::istream& input_stream); | ||
283 | virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const; | ||
284 | |||
285 | virtual LLXMLNode *exportFileXML(BOOL include_asset_key = TRUE) const; | ||
286 | BOOL importXML(LLXMLNode* node); | ||
287 | |||
288 | // helper functions | ||
289 | |||
290 | // pack all information needed to reconstruct this item into the given binary bucket. | ||
291 | // perm_override is optional | ||
292 | S32 packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override = NULL) const; | ||
293 | void unpackBinaryBucket(U8* bin_bucket, S32 bin_bucket_size); | ||
294 | LLSD asLLSD() const; | ||
295 | bool fromLLSD(LLSD& sd); | ||
296 | |||
297 | }; | ||
298 | |||
299 | BOOL item_dictionary_sort(LLInventoryItem* a,LLInventoryItem* b); | ||
300 | BOOL item_date_sort(LLInventoryItem* a, LLInventoryItem* b); | ||
301 | |||
302 | |||
303 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
304 | // Class LLInventoryCategory | ||
305 | // | ||
306 | // An instance of this class represents a category of inventory | ||
307 | // items. Users come with a set of default categories, and can create | ||
308 | // new ones as needed. | ||
309 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
310 | |||
311 | class LLInventoryCategory : public LLInventoryObject | ||
312 | { | ||
313 | public: | ||
314 | typedef LLDynamicArray<LLPointer<LLInventoryCategory> > cat_array_t; | ||
315 | |||
316 | protected: | ||
317 | ~LLInventoryCategory(); | ||
318 | |||
319 | public: | ||
320 | MEM_TYPE_NEW(LLMemType::MTYPE_INVENTORY); | ||
321 | LLInventoryCategory(const LLUUID& uuid, const LLUUID& parent_uuid, | ||
322 | LLAssetType::EType preferred_type, | ||
323 | const LLString& name); | ||
324 | LLInventoryCategory(); | ||
325 | LLInventoryCategory(const LLInventoryCategory* other); | ||
326 | virtual void copy(const LLInventoryCategory* other); // LLRefCount requires custom copy | ||
327 | |||
328 | // accessors and mutators | ||
329 | LLAssetType::EType getPreferredType() const; | ||
330 | void setPreferredType(LLAssetType::EType type); | ||
331 | // For messaging system support | ||
332 | virtual void packMessage(LLMessageSystem* msg) const; | ||
333 | virtual void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); | ||
334 | |||
335 | // file support | ||
336 | virtual BOOL importFile(FILE* fp); | ||
337 | virtual BOOL exportFile(FILE* fp, BOOL include_asset_key = TRUE) const; | ||
338 | |||
339 | virtual BOOL importLegacyStream(std::istream& input_stream); | ||
340 | virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const; | ||
341 | |||
342 | protected: | ||
343 | // The type of asset that this category was "meant" to hold | ||
344 | // (although it may in fact hold any type). | ||
345 | LLAssetType::EType mPreferredType; | ||
346 | |||
347 | }; | ||
348 | |||
349 | |||
350 | //----------------------------------------------------------------------------- | ||
351 | // Useful bits | ||
352 | //----------------------------------------------------------------------------- | ||
353 | |||
354 | // This functor tests if an item is transferrable and returns true if | ||
355 | // it is. Derived from unary_function<> so that the object can be used | ||
356 | // in stl-compliant adaptable predicates (eg, not1<>). You might want | ||
357 | // to use this in std::partition() or similar logic. | ||
358 | struct IsItemTransferable : public std::unary_function<LLInventoryItem*, bool> | ||
359 | { | ||
360 | LLUUID mDestID; | ||
361 | IsItemTransferable(const LLUUID& dest_id) : mDestID(dest_id) {} | ||
362 | bool operator()(const LLInventoryItem* item) const | ||
363 | { | ||
364 | return (item->getPermissions().allowTransferTo(mDestID)) ? true:false; | ||
365 | } | ||
366 | }; | ||
367 | |||
368 | // This functor is used to set the owner and group of inventory items, | ||
369 | // for example, in a simple std::for_each() loop. Note that the call | ||
370 | // to setOwnerAndGroup can fail if authority_id != LLUUID::null. | ||
371 | struct SetItemOwnerAndGroup | ||
372 | { | ||
373 | LLUUID mAuthorityID; | ||
374 | LLUUID mOwnerID; | ||
375 | LLUUID mGroupID; | ||
376 | SetItemOwnerAndGroup(const LLUUID& authority_id, | ||
377 | const LLUUID& owner_id, | ||
378 | const LLUUID& group_id) : | ||
379 | mAuthorityID(authority_id), mOwnerID(owner_id), mGroupID(group_id) {} | ||
380 | void operator()(LLInventoryItem* item) const | ||
381 | { | ||
382 | LLPermissions perm = item->getPermissions(); | ||
383 | bool is_atomic = (LLAssetType::AT_OBJECT == item->getType()) ? false : true; | ||
384 | perm.setOwnerAndGroup(mAuthorityID, mOwnerID, mGroupID, is_atomic); | ||
385 | item->setPermissions(perm); | ||
386 | } | ||
387 | }; | ||
388 | |||
389 | // This functor is used to unset the share with group, everyone perms, and | ||
390 | // for sale info for objects being sold through contents. | ||
391 | struct SetNotForSale | ||
392 | { | ||
393 | LLUUID mAgentID; | ||
394 | LLUUID mGroupID; | ||
395 | SetNotForSale(const LLUUID& agent_id, | ||
396 | const LLUUID& group_id) : | ||
397 | mAgentID(agent_id), mGroupID(group_id) {} | ||
398 | void operator()(LLInventoryItem* item) const | ||
399 | { | ||
400 | // Clear group & everyone permissions. | ||
401 | LLPermissions perm = item->getPermissions(); | ||
402 | perm.setGroupBits(mAgentID, mGroupID, FALSE, PERM_MODIFY | PERM_MOVE | PERM_COPY); | ||
403 | perm.setEveryoneBits(mAgentID, mGroupID, FALSE, PERM_MOVE | PERM_COPY); | ||
404 | item->setPermissions(perm); | ||
405 | |||
406 | // Mark group & everyone permissions for overwrite on the next | ||
407 | // rez if it is an object. | ||
408 | if(LLAssetType::AT_OBJECT == item->getType()) | ||
409 | { | ||
410 | U32 flags = item->getFlags(); | ||
411 | flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP; | ||
412 | flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE; | ||
413 | item->setFlags(flags); | ||
414 | } | ||
415 | |||
416 | // Clear for sale info. | ||
417 | item->setSaleInfo(LLSaleInfo::DEFAULT); | ||
418 | } | ||
419 | }; | ||
420 | |||
421 | typedef std::list<LLPointer<LLInventoryObject> > InventoryObjectList; | ||
422 | |||
423 | // These functions convert between structured data and an inventroy | ||
424 | // item, appropriate for serialization. | ||
425 | LLSD ll_create_sd_from_inventory_item(LLPointer<LLInventoryItem> item); | ||
426 | LLPointer<LLInventoryItem> ll_create_item_from_sd(const LLSD& sd_item); | ||
427 | LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat); | ||
428 | LLPointer<LLInventoryCategory> ll_create_category_from_sd(const LLSD& sd_cat); | ||
429 | |||
430 | #endif // LL_LLINVENTORY_H | ||
diff --git a/linden/indra/llinventory/llinventory.vcproj b/linden/indra/llinventory/llinventory.vcproj new file mode 100644 index 0000000..1c76808 --- /dev/null +++ b/linden/indra/llinventory/llinventory.vcproj | |||
@@ -0,0 +1,234 @@ | |||
1 | <?xml version="1.0" encoding="Windows-1252"?> | ||
2 | <VisualStudioProject | ||
3 | ProjectType="Visual C++" | ||
4 | Version="7.10" | ||
5 | Name="llinventory" | ||
6 | ProjectGUID="{328D1968-924F-4863-AAE8-5F9A95BA68E5}" | ||
7 | Keyword="Win32Proj"> | ||
8 | <Platforms> | ||
9 | <Platform | ||
10 | Name="Win32"/> | ||
11 | </Platforms> | ||
12 | <Configurations> | ||
13 | <Configuration | ||
14 | Name="Debug|Win32" | ||
15 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" | ||
16 | IntermediateDirectory="Debug" | ||
17 | ConfigurationType="4" | ||
18 | CharacterSet="1"> | ||
19 | <Tool | ||
20 | Name="VCCLCompilerTool" | ||
21 | Optimization="0" | ||
22 | AdditionalIncludeDirectories="..\llcommon;..\llmath;..\llvfs;..\llmessage;..\llxml;..\..\libraries\i686-win32\include;..\..\libraries\include" | ||
23 | PreprocessorDefinitions="WIN32;_DEBUG;_LIB;LL_WINDOWS;LL_DEBUG" | ||
24 | MinimalRebuild="TRUE" | ||
25 | BasicRuntimeChecks="3" | ||
26 | RuntimeLibrary="1" | ||
27 | StructMemberAlignment="4" | ||
28 | ForceConformanceInForLoopScope="TRUE" | ||
29 | UsePrecompiledHeader="0" | ||
30 | WarningLevel="3" | ||
31 | WarnAsError="TRUE" | ||
32 | Detect64BitPortabilityProblems="FALSE" | ||
33 | DebugInformationFormat="4"/> | ||
34 | <Tool | ||
35 | Name="VCCustomBuildTool"/> | ||
36 | <Tool | ||
37 | Name="VCLibrarianTool" | ||
38 | OutputFile="$(OutDir)/llinventory.lib"/> | ||
39 | <Tool | ||
40 | Name="VCMIDLTool"/> | ||
41 | <Tool | ||
42 | Name="VCPostBuildEventTool"/> | ||
43 | <Tool | ||
44 | Name="VCPreBuildEventTool"/> | ||
45 | <Tool | ||
46 | Name="VCPreLinkEventTool"/> | ||
47 | <Tool | ||
48 | Name="VCResourceCompilerTool"/> | ||
49 | <Tool | ||
50 | Name="VCWebServiceProxyGeneratorTool"/> | ||
51 | <Tool | ||
52 | Name="VCXMLDataGeneratorTool"/> | ||
53 | <Tool | ||
54 | Name="VCManagedWrapperGeneratorTool"/> | ||
55 | <Tool | ||
56 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | ||
57 | </Configuration> | ||
58 | <Configuration | ||
59 | Name="Release|Win32" | ||
60 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" | ||
61 | IntermediateDirectory="Release" | ||
62 | ConfigurationType="4" | ||
63 | CharacterSet="1"> | ||
64 | <Tool | ||
65 | Name="VCCLCompilerTool" | ||
66 | AdditionalIncludeDirectories="..\llcommon;..\llmath;..\llvfs;..\llmessage;..\llxml;..\..\libraries\i686-win32\include;..\..\libraries\include" | ||
67 | PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;LL_RELEASE" | ||
68 | RuntimeLibrary="0" | ||
69 | StructMemberAlignment="0" | ||
70 | ForceConformanceInForLoopScope="TRUE" | ||
71 | UsePrecompiledHeader="0" | ||
72 | WarningLevel="3" | ||
73 | WarnAsError="TRUE" | ||
74 | Detect64BitPortabilityProblems="FALSE" | ||
75 | DebugInformationFormat="3"/> | ||
76 | <Tool | ||
77 | Name="VCCustomBuildTool"/> | ||
78 | <Tool | ||
79 | Name="VCLibrarianTool" | ||
80 | OutputFile="$(OutDir)/llinventory.lib"/> | ||
81 | <Tool | ||
82 | Name="VCMIDLTool"/> | ||
83 | <Tool | ||
84 | Name="VCPostBuildEventTool"/> | ||
85 | <Tool | ||
86 | Name="VCPreBuildEventTool"/> | ||
87 | <Tool | ||
88 | Name="VCPreLinkEventTool"/> | ||
89 | <Tool | ||
90 | Name="VCResourceCompilerTool"/> | ||
91 | <Tool | ||
92 | Name="VCWebServiceProxyGeneratorTool"/> | ||
93 | <Tool | ||
94 | Name="VCXMLDataGeneratorTool"/> | ||
95 | <Tool | ||
96 | Name="VCManagedWrapperGeneratorTool"/> | ||
97 | <Tool | ||
98 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | ||
99 | </Configuration> | ||
100 | <Configuration | ||
101 | Name="ReleaseNoOpt|Win32" | ||
102 | OutputDirectory="../lib_$(ConfigurationName)/i686-win32" | ||
103 | IntermediateDirectory="$(ConfigurationName)" | ||
104 | ConfigurationType="4" | ||
105 | CharacterSet="1"> | ||
106 | <Tool | ||
107 | Name="VCCLCompilerTool" | ||
108 | Optimization="0" | ||
109 | AdditionalIncludeDirectories="..\llcommon;..\llmath;..\llvfs;..\llmessage;..\llxml;..\..\libraries\i686-win32\include;..\..\libraries\include" | ||
110 | PreprocessorDefinitions="WIN32;NDEBUG;_LIB;LL_WINDOWS;LL_RELEASE" | ||
111 | RuntimeLibrary="0" | ||
112 | StructMemberAlignment="0" | ||
113 | ForceConformanceInForLoopScope="TRUE" | ||
114 | UsePrecompiledHeader="0" | ||
115 | WarningLevel="3" | ||
116 | WarnAsError="TRUE" | ||
117 | Detect64BitPortabilityProblems="FALSE" | ||
118 | DebugInformationFormat="3"/> | ||
119 | <Tool | ||
120 | Name="VCCustomBuildTool"/> | ||
121 | <Tool | ||
122 | Name="VCLibrarianTool" | ||
123 | OutputFile="$(OutDir)/llinventory.lib"/> | ||
124 | <Tool | ||
125 | Name="VCMIDLTool"/> | ||
126 | <Tool | ||
127 | Name="VCPostBuildEventTool"/> | ||
128 | <Tool | ||
129 | Name="VCPreBuildEventTool"/> | ||
130 | <Tool | ||
131 | Name="VCPreLinkEventTool"/> | ||
132 | <Tool | ||
133 | Name="VCResourceCompilerTool"/> | ||
134 | <Tool | ||
135 | Name="VCWebServiceProxyGeneratorTool"/> | ||
136 | <Tool | ||
137 | Name="VCXMLDataGeneratorTool"/> | ||
138 | <Tool | ||
139 | Name="VCManagedWrapperGeneratorTool"/> | ||
140 | <Tool | ||
141 | Name="VCAuxiliaryManagedWrapperGeneratorTool"/> | ||
142 | </Configuration> | ||
143 | </Configurations> | ||
144 | <References> | ||
145 | </References> | ||
146 | <Files> | ||
147 | <Filter | ||
148 | Name="Source Files" | ||
149 | Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx" | ||
150 | UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"> | ||
151 | <File | ||
152 | RelativePath=".\llcategory.cpp"> | ||
153 | </File> | ||
154 | <File | ||
155 | RelativePath=".\lleconomy.cpp"> | ||
156 | </File> | ||
157 | <File | ||
158 | RelativePath=".\llinventory.cpp"> | ||
159 | </File> | ||
160 | <File | ||
161 | RelativePath=".\lllandmark.cpp"> | ||
162 | </File> | ||
163 | <File | ||
164 | RelativePath=".\llnotecard.cpp"> | ||
165 | </File> | ||
166 | <File | ||
167 | RelativePath=".\llparcel.cpp"> | ||
168 | </File> | ||
169 | <File | ||
170 | RelativePath=".\llpermissions.cpp"> | ||
171 | </File> | ||
172 | <File | ||
173 | RelativePath=".\llsaleinfo.cpp"> | ||
174 | </File> | ||
175 | <File | ||
176 | RelativePath=".\lltransactionflags.cpp"> | ||
177 | </File> | ||
178 | <File | ||
179 | RelativePath=".\lluserrelations.cpp"> | ||
180 | </File> | ||
181 | </Filter> | ||
182 | <Filter | ||
183 | Name="Header Files" | ||
184 | Filter="h;hpp;hxx;hm;inl;inc;xsd" | ||
185 | UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"> | ||
186 | <File | ||
187 | RelativePath=".\llcategory.h"> | ||
188 | </File> | ||
189 | <File | ||
190 | RelativePath=".\lleconomy.h"> | ||
191 | </File> | ||
192 | <File | ||
193 | RelativePath=".\llinventory.h"> | ||
194 | </File> | ||
195 | <File | ||
196 | RelativePath=".\lllandmark.h"> | ||
197 | </File> | ||
198 | <File | ||
199 | RelativePath=".\llnotecard.h"> | ||
200 | </File> | ||
201 | <File | ||
202 | RelativePath=".\llparcel.h"> | ||
203 | </File> | ||
204 | <File | ||
205 | RelativePath=".\llparcelflags.h"> | ||
206 | </File> | ||
207 | <File | ||
208 | RelativePath=".\llpermissions.h"> | ||
209 | </File> | ||
210 | <File | ||
211 | RelativePath=".\llpermissionsflags.h"> | ||
212 | </File> | ||
213 | <File | ||
214 | RelativePath=".\llsaleinfo.h"> | ||
215 | </File> | ||
216 | <File | ||
217 | RelativePath=".\lltransactionflags.h"> | ||
218 | </File> | ||
219 | <File | ||
220 | RelativePath=".\lltransactiontypes.h"> | ||
221 | </File> | ||
222 | <File | ||
223 | RelativePath=".\lluserrelations.h"> | ||
224 | </File> | ||
225 | </Filter> | ||
226 | <Filter | ||
227 | Name="Resource Files" | ||
228 | Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" | ||
229 | UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"> | ||
230 | </Filter> | ||
231 | </Files> | ||
232 | <Globals> | ||
233 | </Globals> | ||
234 | </VisualStudioProject> | ||
diff --git a/linden/indra/llinventory/lllandmark.cpp b/linden/indra/llinventory/lllandmark.cpp new file mode 100644 index 0000000..bca64d1 --- /dev/null +++ b/linden/indra/llinventory/lllandmark.cpp | |||
@@ -0,0 +1,277 @@ | |||
1 | /** | ||
2 | * @file lllandmark.cpp | ||
3 | * @brief Landmark asset class | ||
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 | #include "lllandmark.h" | ||
30 | |||
31 | #include <stdlib.h> | ||
32 | #include <string.h> | ||
33 | #include <errno.h> | ||
34 | #include <stdio.h> // for sscanf() on linux | ||
35 | |||
36 | #include "message.h" | ||
37 | #include "llregionhandle.h" | ||
38 | |||
39 | std::pair<LLUUID, U64> LLLandmark::mLocalRegion; | ||
40 | LLLandmark::region_map_t LLLandmark::mRegions; | ||
41 | LLLandmark::region_callback_t LLLandmark::mRegionCallback; | ||
42 | |||
43 | LLLandmark::LLLandmark() : | ||
44 | mGlobalPositionKnown(false) | ||
45 | { | ||
46 | } | ||
47 | |||
48 | LLLandmark::LLLandmark(const LLVector3d& pos) : | ||
49 | mGlobalPositionKnown(true), | ||
50 | mGlobalPos( pos ) | ||
51 | { | ||
52 | } | ||
53 | |||
54 | bool LLLandmark::getGlobalPos(LLVector3d& pos) | ||
55 | { | ||
56 | if(mGlobalPositionKnown) | ||
57 | { | ||
58 | pos = mGlobalPos; | ||
59 | } | ||
60 | else if(mRegionID.notNull()) | ||
61 | { | ||
62 | F32 g_x = -1.0; | ||
63 | F32 g_y = -1.0; | ||
64 | if(mRegionID == mLocalRegion.first) | ||
65 | { | ||
66 | from_region_handle(mLocalRegion.second, &g_x, &g_y); | ||
67 | } | ||
68 | else | ||
69 | { | ||
70 | region_map_t::iterator it = mRegions.find(mRegionID); | ||
71 | if(it != mRegions.end()) | ||
72 | { | ||
73 | from_region_handle((*it).second.mRegionHandle, &g_x, &g_y); | ||
74 | } | ||
75 | } | ||
76 | if((g_x > 0.f) && (g_y > 0.f)) | ||
77 | { | ||
78 | pos.mdV[0] = g_x + mRegionPos.mV[0]; | ||
79 | pos.mdV[1] = g_y + mRegionPos.mV[1]; | ||
80 | pos.mdV[2] = mRegionPos.mV[2]; | ||
81 | setGlobalPos(pos); | ||
82 | } | ||
83 | } | ||
84 | return mGlobalPositionKnown; | ||
85 | } | ||
86 | |||
87 | void LLLandmark::setGlobalPos(const LLVector3d& pos) | ||
88 | { | ||
89 | mGlobalPos = pos; | ||
90 | mGlobalPositionKnown = true; | ||
91 | } | ||
92 | |||
93 | bool LLLandmark::getRegionID(LLUUID& region_id) | ||
94 | { | ||
95 | if(mRegionID.notNull()) | ||
96 | { | ||
97 | region_id = mRegionID; | ||
98 | return true; | ||
99 | } | ||
100 | return false; | ||
101 | } | ||
102 | |||
103 | LLVector3 LLLandmark::getRegionPos() const | ||
104 | { | ||
105 | return mRegionPos; | ||
106 | } | ||
107 | |||
108 | |||
109 | // static | ||
110 | LLLandmark* LLLandmark::constructFromString(const char *buffer) | ||
111 | { | ||
112 | const char* cur = buffer; | ||
113 | S32 chars_read = 0; | ||
114 | S32 count = 0; | ||
115 | U32 version = 0; | ||
116 | |||
117 | // read version | ||
118 | count = sscanf( cur, "Landmark version %u\n%n", &version, &chars_read ); | ||
119 | if(count != 1) | ||
120 | { | ||
121 | goto error; | ||
122 | } | ||
123 | |||
124 | if(version == 1) | ||
125 | { | ||
126 | LLVector3d pos; | ||
127 | cur += chars_read; | ||
128 | // read position | ||
129 | count = sscanf( cur, "position %lf %lf %lf\n%n", pos.mdV+VX, pos.mdV+VY, pos.mdV+VZ, &chars_read ); | ||
130 | if( count != 3 ) | ||
131 | { | ||
132 | goto error; | ||
133 | } | ||
134 | cur += chars_read; | ||
135 | // llinfos << "Landmark read: " << pos << llendl; | ||
136 | |||
137 | return new LLLandmark(pos); | ||
138 | } | ||
139 | else if(version == 2) | ||
140 | { | ||
141 | char region_id_str[MAX_STRING]; | ||
142 | LLVector3 pos; | ||
143 | cur += chars_read; | ||
144 | count = sscanf(cur, "region_id %s\n%n", region_id_str, &chars_read); | ||
145 | if(count != 1) goto error; | ||
146 | cur += chars_read; | ||
147 | count = sscanf(cur, "local_pos %f %f %f\n%n", pos.mV+VX, pos.mV+VY, pos.mV+VZ, &chars_read); | ||
148 | if(count != 3) goto error; | ||
149 | cur += chars_read; | ||
150 | LLLandmark* lm = new LLLandmark; | ||
151 | lm->mRegionID.set(region_id_str); | ||
152 | lm->mRegionPos = pos; | ||
153 | return lm; | ||
154 | } | ||
155 | |||
156 | error: | ||
157 | llinfos << "Bad Landmark Asset: bad _DATA_ block." << llendl; | ||
158 | return NULL; | ||
159 | } | ||
160 | |||
161 | |||
162 | // static | ||
163 | void LLLandmark::registerCallbacks(LLMessageSystem* msg) | ||
164 | { | ||
165 | msg->setHandlerFunc("RegionIDAndHandleReply", &processRegionIDAndHandle); | ||
166 | } | ||
167 | |||
168 | // static | ||
169 | void LLLandmark::requestRegionHandle( | ||
170 | LLMessageSystem* msg, | ||
171 | const LLHost& upstream_host, | ||
172 | const LLUUID& region_id, | ||
173 | LLRegionHandleCallback* callback) | ||
174 | { | ||
175 | if(region_id.isNull()) | ||
176 | { | ||
177 | // don't bother with checking - it's 0. | ||
178 | lldebugs << "requestRegionHandle: null" << llendl; | ||
179 | if(callback) | ||
180 | { | ||
181 | const U64 U64_ZERO = 0; | ||
182 | callback->dataReady(region_id, U64_ZERO); | ||
183 | } | ||
184 | } | ||
185 | else | ||
186 | { | ||
187 | if(region_id == mLocalRegion.first) | ||
188 | { | ||
189 | lldebugs << "requestRegionHandle: local" << llendl; | ||
190 | if(callback) | ||
191 | { | ||
192 | callback->dataReady(region_id, mLocalRegion.second); | ||
193 | } | ||
194 | } | ||
195 | else | ||
196 | { | ||
197 | region_map_t::iterator it = mRegions.find(region_id); | ||
198 | if(it == mRegions.end()) | ||
199 | { | ||
200 | lldebugs << "requestRegionHandle: upstream" << llendl; | ||
201 | if(callback) | ||
202 | { | ||
203 | region_callback_t::value_type vt(region_id, callback); | ||
204 | mRegionCallback.insert(vt); | ||
205 | } | ||
206 | lldebugs << "Landmark requesting information about: " | ||
207 | << region_id << llendl; | ||
208 | msg->newMessage("RegionHandleRequest"); | ||
209 | msg->nextBlock("RequestBlock"); | ||
210 | msg->addUUID("RegionID", region_id); | ||
211 | msg->sendReliable(upstream_host); | ||
212 | } | ||
213 | else if(callback) | ||
214 | { | ||
215 | // we have the answer locally - just call the callack. | ||
216 | lldebugs << "requestRegionHandle: ready" << llendl; | ||
217 | callback->dataReady(region_id, (*it).second.mRegionHandle); | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | |||
222 | // As good a place as any to expire old entries. | ||
223 | expireOldEntries(); | ||
224 | } | ||
225 | |||
226 | // static | ||
227 | void LLLandmark::setRegionHandle(const LLUUID& region_id, U64 region_handle) | ||
228 | { | ||
229 | mLocalRegion.first = region_id; | ||
230 | mLocalRegion.second = region_handle; | ||
231 | } | ||
232 | |||
233 | |||
234 | // static | ||
235 | void LLLandmark::processRegionIDAndHandle(LLMessageSystem* msg, void**) | ||
236 | { | ||
237 | LLUUID region_id; | ||
238 | msg->getUUID("ReplyBlock", "RegionID", region_id); | ||
239 | mRegions.erase(region_id); | ||
240 | CacheInfo info; | ||
241 | const F32 CACHE_EXPIRY_SECONDS = 60.0f * 10.0f; // ten minutes | ||
242 | info.mTimer.setTimerExpirySec(CACHE_EXPIRY_SECONDS); | ||
243 | msg->getU64("ReplyBlock", "RegionHandle", info.mRegionHandle); | ||
244 | region_map_t::value_type vt(region_id, info); | ||
245 | mRegions.insert(vt); | ||
246 | |||
247 | #if LL_DEBUG | ||
248 | U32 grid_x, grid_y; | ||
249 | grid_from_region_handle(info.mRegionHandle, &grid_x, &grid_y); | ||
250 | lldebugs << "Landmark got reply for region: " << region_id << " " | ||
251 | << grid_x << "," << grid_y << llendl; | ||
252 | #endif | ||
253 | |||
254 | // make all the callbacks here. | ||
255 | region_callback_t::iterator it; | ||
256 | while((it = mRegionCallback.find(region_id)) != mRegionCallback.end()) | ||
257 | { | ||
258 | (*it).second->dataReady(region_id, info.mRegionHandle); | ||
259 | mRegionCallback.erase(it); | ||
260 | } | ||
261 | } | ||
262 | |||
263 | // static | ||
264 | void LLLandmark::expireOldEntries() | ||
265 | { | ||
266 | for(region_map_t::iterator it = mRegions.begin(); it != mRegions.end(); ) | ||
267 | { | ||
268 | if((*it).second.mTimer.hasExpired()) | ||
269 | { | ||
270 | mRegions.erase(it++); | ||
271 | } | ||
272 | else | ||
273 | { | ||
274 | ++it; | ||
275 | } | ||
276 | } | ||
277 | } | ||
diff --git a/linden/indra/llinventory/lllandmark.h b/linden/indra/llinventory/lllandmark.h new file mode 100644 index 0000000..eea0600 --- /dev/null +++ b/linden/indra/llinventory/lllandmark.h | |||
@@ -0,0 +1,120 @@ | |||
1 | /** | ||
2 | * @file lllandmark.h | ||
3 | * @brief Landmark asset class | ||
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 | |||
29 | #ifndef LL_LLLANDMARK_H | ||
30 | #define LL_LLLANDMARK_H | ||
31 | |||
32 | #include <map> | ||
33 | #include "llframetimer.h" | ||
34 | #include "lluuid.h" | ||
35 | #include "v3dmath.h" | ||
36 | |||
37 | class LLMessageSystem; | ||
38 | class LLHost; | ||
39 | |||
40 | // virutal base class used for calling back interested parties when a | ||
41 | // region handle comes back. | ||
42 | class LLRegionHandleCallback | ||
43 | { | ||
44 | public: | ||
45 | LLRegionHandleCallback() {} | ||
46 | virtual ~LLRegionHandleCallback() {} | ||
47 | virtual bool dataReady( | ||
48 | const LLUUID& region_id, | ||
49 | const U64& region_handle) | ||
50 | { | ||
51 | return true; | ||
52 | } | ||
53 | }; | ||
54 | |||
55 | class LLLandmark | ||
56 | { | ||
57 | public: | ||
58 | ~LLLandmark() {} | ||
59 | |||
60 | // returns true if the position is known. | ||
61 | bool getGlobalPos(LLVector3d& pos); | ||
62 | |||
63 | // setter used in conjunction if more information needs to be | ||
64 | // collected from the server. | ||
65 | void setGlobalPos(const LLVector3d& pos); | ||
66 | |||
67 | // return true if the region is known | ||
68 | bool getRegionID(LLUUID& region_id); | ||
69 | |||
70 | // return the local coordinates if known | ||
71 | LLVector3 getRegionPos() const; | ||
72 | |||
73 | // constructs a new LLLandmark from a string | ||
74 | // return NULL if there's an error | ||
75 | static LLLandmark* constructFromString(const char *buffer); | ||
76 | |||
77 | // register callbacks that this class handles | ||
78 | static void registerCallbacks(LLMessageSystem* msg); | ||
79 | |||
80 | // request information about region_id to region_handle.Pass in a | ||
81 | // callback pointer which will be erase but NOT deleted after the | ||
82 | // callback is made. This function may call into the message | ||
83 | // system to get the information. | ||
84 | static void requestRegionHandle( | ||
85 | LLMessageSystem* msg, | ||
86 | const LLHost& upstream_host, | ||
87 | const LLUUID& region_id, | ||
88 | LLRegionHandleCallback* callback); | ||
89 | |||
90 | // Call this method to create a lookup for this region. This | ||
91 | // simplifies a lot of the code. | ||
92 | static void setRegionHandle(const LLUUID& region_id, U64 region_handle); | ||
93 | |||
94 | private: | ||
95 | LLLandmark(); | ||
96 | LLLandmark(const LLVector3d& pos); | ||
97 | |||
98 | static void processRegionIDAndHandle(LLMessageSystem* msg, void**); | ||
99 | static void expireOldEntries(); | ||
100 | |||
101 | private: | ||
102 | LLUUID mRegionID; | ||
103 | LLVector3 mRegionPos; | ||
104 | bool mGlobalPositionKnown; | ||
105 | LLVector3d mGlobalPos; | ||
106 | |||
107 | struct CacheInfo | ||
108 | { | ||
109 | U64 mRegionHandle; | ||
110 | LLFrameTimer mTimer; | ||
111 | }; | ||
112 | |||
113 | static std::pair<LLUUID, U64> mLocalRegion; | ||
114 | typedef std::map<LLUUID, CacheInfo> region_map_t; | ||
115 | static region_map_t mRegions; | ||
116 | typedef std::multimap<LLUUID, LLRegionHandleCallback*> region_callback_t; | ||
117 | static region_callback_t mRegionCallback; | ||
118 | }; | ||
119 | |||
120 | #endif | ||
diff --git a/linden/indra/llinventory/llnotecard.cpp b/linden/indra/llinventory/llnotecard.cpp new file mode 100644 index 0000000..5f48f0e --- /dev/null +++ b/linden/indra/llinventory/llnotecard.cpp | |||
@@ -0,0 +1,305 @@ | |||
1 | /** | ||
2 | * @file llnotecard.cpp | ||
3 | * @brief LLNotecard class definition | ||
4 | * | ||
5 | * Copyright (c) 2006-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 | #include "llinventory.h" | ||
30 | #include "llnotecard.h" | ||
31 | #include "llstreamtools.h" | ||
32 | |||
33 | LLNotecard::LLNotecard(U32 max_text) | ||
34 | : mMaxText(max_text) | ||
35 | { | ||
36 | } | ||
37 | |||
38 | LLNotecard::~LLNotecard() | ||
39 | { | ||
40 | } | ||
41 | |||
42 | bool LLNotecard::importEmbeddedItemsStream(std::istream& str) | ||
43 | { | ||
44 | // Version 1 format: | ||
45 | // LLEmbeddedItems version 1 | ||
46 | // { | ||
47 | // count <number of entries being used and not deleted> | ||
48 | // { | ||
49 | // ext char index <index> | ||
50 | // <InventoryItem chunk> | ||
51 | // } | ||
52 | // } | ||
53 | |||
54 | S32 i; | ||
55 | S32 count = 0; | ||
56 | |||
57 | str >> std::ws >> "LLEmbeddedItems version" >> mEmbeddedVersion >> "\n"; | ||
58 | if (str.fail()) | ||
59 | { | ||
60 | llwarns << "Invalid Linden text file header" << llendl; | ||
61 | goto import_file_failed; | ||
62 | } | ||
63 | |||
64 | if( 1 != mEmbeddedVersion ) | ||
65 | { | ||
66 | llwarns << "Invalid LLEmbeddedItems version: " << mEmbeddedVersion << llendl; | ||
67 | goto import_file_failed; | ||
68 | } | ||
69 | |||
70 | str >> std::ws >> "{\n"; | ||
71 | if(str.fail()) | ||
72 | { | ||
73 | llwarns << "Invalid Linden text file format: missing {" << llendl; | ||
74 | goto import_file_failed; | ||
75 | } | ||
76 | |||
77 | str >> std::ws >> "count " >> count >> "\n"; | ||
78 | if(str.fail()) | ||
79 | { | ||
80 | llwarns << "Invalid LLEmbeddedItems count" << llendl; | ||
81 | goto import_file_failed; | ||
82 | } | ||
83 | |||
84 | if((count < 0)) | ||
85 | { | ||
86 | llwarns << "Invalid LLEmbeddedItems count value: " << count << llendl; | ||
87 | goto import_file_failed; | ||
88 | } | ||
89 | |||
90 | for(i = 0; i < count; i++) | ||
91 | { | ||
92 | str >> std::ws >> "{\n"; | ||
93 | if(str.fail()) | ||
94 | { | ||
95 | llwarns << "Invalid LLEmbeddedItems file format: missing {" << llendl; | ||
96 | goto import_file_failed; | ||
97 | } | ||
98 | |||
99 | U32 index = 0; | ||
100 | str >> std::ws >> "ext char index " >> index >> "\n"; | ||
101 | if(str.fail()) | ||
102 | { | ||
103 | llwarns << "Invalid LLEmbeddedItems file format: missing ext char index" << llendl; | ||
104 | goto import_file_failed; | ||
105 | } | ||
106 | |||
107 | if( (index < 0) ) | ||
108 | { | ||
109 | llwarns << "Invalid LLEmbeddedItems file format: invalid ext char index: " << index << llendl; | ||
110 | goto import_file_failed; | ||
111 | } | ||
112 | |||
113 | str >> std::ws >> "inv_item\t0\n"; | ||
114 | if(str.fail()) | ||
115 | { | ||
116 | llwarns << "Invalid LLEmbeddedItems file format: missing inv_item" << llendl; | ||
117 | goto import_file_failed; | ||
118 | } | ||
119 | |||
120 | LLPointer<LLInventoryItem> item = new LLInventoryItem; | ||
121 | if (!item->importLegacyStream(str)) | ||
122 | { | ||
123 | llinfos << "notecard import failed" << llendl; | ||
124 | goto import_file_failed; | ||
125 | } | ||
126 | mItems.push_back(item); | ||
127 | |||
128 | str >> std::ws >> "}\n"; | ||
129 | if(str.fail()) | ||
130 | { | ||
131 | llwarns << "Invalid LLEmbeddedItems file format: missing }" << llendl; | ||
132 | goto import_file_failed; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | str >> std::ws >> "}\n"; | ||
137 | if(str.fail()) | ||
138 | { | ||
139 | llwarns << "Invalid LLEmbeddedItems file format: missing }" << llendl; | ||
140 | goto import_file_failed; | ||
141 | } | ||
142 | |||
143 | return true; | ||
144 | |||
145 | import_file_failed: | ||
146 | return false; | ||
147 | } | ||
148 | |||
149 | bool LLNotecard::importStream(std::istream& str) | ||
150 | { | ||
151 | // Version 1 format: | ||
152 | // Linden text version 1 | ||
153 | // { | ||
154 | // <EmbeddedItemList chunk> | ||
155 | // Text length | ||
156 | // <ASCII text; 0x80 | index = embedded item> | ||
157 | // } | ||
158 | |||
159 | // Version 2 format: (NOTE: Imports identically to version 1) | ||
160 | // Linden text version 2 | ||
161 | // { | ||
162 | // <EmbeddedItemList chunk> | ||
163 | // Text length | ||
164 | // <UTF8 text; FIRST_EMBEDDED_CHAR + index = embedded item> | ||
165 | // } | ||
166 | |||
167 | str >> std::ws >> "Linden text version " >> mVersion >> "\n"; | ||
168 | if(str.fail()) | ||
169 | { | ||
170 | llwarns << "Invalid Linden text file header " << llendl; | ||
171 | return FALSE; | ||
172 | } | ||
173 | |||
174 | if( 1 != mVersion && 2 != mVersion) | ||
175 | { | ||
176 | llwarns << "Invalid Linden text file version: " << mVersion << llendl; | ||
177 | return FALSE; | ||
178 | } | ||
179 | |||
180 | str >> std::ws >> "{\n"; | ||
181 | if(str.fail()) | ||
182 | { | ||
183 | llwarns << "Invalid Linden text file format" << llendl; | ||
184 | return FALSE; | ||
185 | } | ||
186 | |||
187 | if(!importEmbeddedItemsStream(str)) | ||
188 | { | ||
189 | return FALSE; | ||
190 | } | ||
191 | |||
192 | char line_buf[STD_STRING_BUF_SIZE]; | ||
193 | str.getline(line_buf, STD_STRING_BUF_SIZE); | ||
194 | if(str.fail()) | ||
195 | { | ||
196 | llwarns << "Invalid Linden text length field" << llendl; | ||
197 | return FALSE; | ||
198 | } | ||
199 | line_buf[STD_STRING_STR_LEN] = '\0'; | ||
200 | |||
201 | U32 text_len = 0; | ||
202 | if( 1 != sscanf(line_buf, "Text length %d", &text_len) ) | ||
203 | { | ||
204 | llwarns << "Invalid Linden text length field" << llendl; | ||
205 | return FALSE; | ||
206 | } | ||
207 | |||
208 | if(text_len > mMaxText) | ||
209 | { | ||
210 | llwarns << "Invalid Linden text length: " << text_len << llendl; | ||
211 | return FALSE; | ||
212 | } | ||
213 | |||
214 | BOOL success = TRUE; | ||
215 | |||
216 | char* text = new char[text_len + 1]; | ||
217 | fullread(str, text, text_len); | ||
218 | if(str.fail()) | ||
219 | { | ||
220 | llwarns << "Invalid Linden text: text shorter than text length: " << text_len << llendl; | ||
221 | success = FALSE; | ||
222 | } | ||
223 | text[text_len] = '\0'; | ||
224 | |||
225 | if(success) | ||
226 | { | ||
227 | // Actually set the text | ||
228 | mText = text; | ||
229 | } | ||
230 | |||
231 | delete[] text; | ||
232 | |||
233 | return success; | ||
234 | } | ||
235 | |||
236 | //////////////////////////////////////////////////////////////////////////// | ||
237 | |||
238 | bool LLNotecard::exportEmbeddedItemsStream( std::ostream& out_stream ) | ||
239 | { | ||
240 | out_stream << "LLEmbeddedItems version 1\n"; | ||
241 | out_stream << "{\n"; | ||
242 | |||
243 | out_stream << llformat("count %d\n", mItems.size() ); | ||
244 | |||
245 | S32 idx = 0; | ||
246 | for (std::vector<LLPointer<LLInventoryItem> >::iterator iter = mItems.begin(); | ||
247 | iter != mItems.end(); ++iter) | ||
248 | { | ||
249 | LLInventoryItem* item = *iter; | ||
250 | if (item) | ||
251 | { | ||
252 | out_stream << "{\n"; | ||
253 | out_stream << llformat("ext char index %d\n", idx ); | ||
254 | if( !item->exportLegacyStream( out_stream ) ) | ||
255 | { | ||
256 | return FALSE; | ||
257 | } | ||
258 | out_stream << "}\n"; | ||
259 | } | ||
260 | ++idx; | ||
261 | } | ||
262 | |||
263 | out_stream << "}\n"; | ||
264 | |||
265 | return TRUE; | ||
266 | } | ||
267 | |||
268 | bool LLNotecard::exportStream( std::ostream& out_stream ) | ||
269 | { | ||
270 | out_stream << "Linden text version 2\n"; | ||
271 | out_stream << "{\n"; | ||
272 | |||
273 | if( !exportEmbeddedItemsStream( out_stream ) ) | ||
274 | { | ||
275 | return FALSE; | ||
276 | } | ||
277 | |||
278 | out_stream << llformat("Text length %d\n", mText.length() ); | ||
279 | out_stream << mText; | ||
280 | out_stream << "}\n"; | ||
281 | |||
282 | return TRUE; | ||
283 | } | ||
284 | |||
285 | //////////////////////////////////////////////////////////////////////////// | ||
286 | |||
287 | const std::vector<LLPointer<LLInventoryItem> >& LLNotecard::getItems() const | ||
288 | { | ||
289 | return mItems; | ||
290 | } | ||
291 | |||
292 | LLString& LLNotecard::getText() | ||
293 | { | ||
294 | return mText; | ||
295 | } | ||
296 | |||
297 | void LLNotecard::setItems(const std::vector<LLPointer<LLInventoryItem> >& items) | ||
298 | { | ||
299 | mItems = items; | ||
300 | } | ||
301 | |||
302 | void LLNotecard::setText(const LLString& text) | ||
303 | { | ||
304 | mText = text; | ||
305 | } | ||
diff --git a/linden/indra/llinventory/llnotecard.h b/linden/indra/llinventory/llnotecard.h new file mode 100644 index 0000000..2475fd1 --- /dev/null +++ b/linden/indra/llinventory/llnotecard.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /** | ||
2 | * @file llnotecard.h | ||
3 | * @brief LLNotecard class declaration | ||
4 | * | ||
5 | * Copyright (c) 2006-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 | #ifndef LL_NOTECARD_H | ||
29 | #define LL_NOTECARD_H | ||
30 | |||
31 | const S32 MAX_NOTECARD_SIZE = 65536; | ||
32 | |||
33 | class LLNotecard | ||
34 | { | ||
35 | public: | ||
36 | LLNotecard(U32 max_text); | ||
37 | virtual ~LLNotecard(); | ||
38 | |||
39 | bool importStream(std::istream& str); | ||
40 | bool exportStream(std::ostream& str); | ||
41 | |||
42 | const std::vector<LLPointer<LLInventoryItem> >& getItems() const; | ||
43 | LLString& getText(); | ||
44 | |||
45 | void setItems(const std::vector<LLPointer<LLInventoryItem> >& items); | ||
46 | void setText(const LLString& text); | ||
47 | S32 getVersion() { return mVersion; } | ||
48 | S32 getEmbeddedVersion() { return mEmbeddedVersion; } | ||
49 | |||
50 | private: | ||
51 | bool importEmbeddedItemsStream(std::istream& str); | ||
52 | bool exportEmbeddedItemsStream(std::ostream& str); | ||
53 | std::vector<LLPointer<LLInventoryItem> > mItems; | ||
54 | LLString mText; | ||
55 | U32 mMaxText; | ||
56 | S32 mVersion; | ||
57 | S32 mEmbeddedVersion; | ||
58 | }; | ||
59 | |||
60 | #endif /* LL_NOTECARD_H */ | ||
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 | |||
42 | static const F32 SOME_BIG_NUMBER = 1000.0f; | ||
43 | static const F32 SOME_BIG_NEG_NUMBER = -1000.0f; | ||
44 | static 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 | ||
54 | static 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 | }; | ||
71 | static 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 | |||
90 | static 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 | ||
106 | const 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 | ||
111 | const 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 | ||
116 | const 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. | ||
121 | const 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. | ||
125 | const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000; | ||
126 | |||
127 | |||
128 | const char* ownership_status_to_string(LLParcel::EOwnershipStatus status); | ||
129 | LLParcel::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); | ||
132 | const char* category_to_string(LLParcel::ECategory category); | ||
133 | const char* category_to_ui_string(LLParcel::ECategory category); | ||
134 | LLParcel::ECategory category_string_to_category(const char* s); | ||
135 | LLParcel::ECategory category_ui_string_to_category(const char* s); | ||
136 | |||
137 | LLParcel::LLParcel() | ||
138 | { | ||
139 | init(LLUUID::null, TRUE, FALSE, FALSE, 0, 0, 0, 0, 0, 1.f, 0); | ||
140 | } | ||
141 | |||
142 | |||
143 | LLParcel::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 | ||
156 | LLParcel::~LLParcel() | ||
157 | { | ||
158 | // user list cleaned up by LLDynamicArray destructor. | ||
159 | } | ||
160 | |||
161 | void 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 | |||
237 | void 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 | |||
254 | void LLParcel::overrideParcelFlags(U32 flags) | ||
255 | { | ||
256 | mParcelFlags = flags; | ||
257 | } | ||
258 | |||
259 | void 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 | |||
275 | void 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 | |||
283 | void 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 | |||
291 | void 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 | |||
302 | void 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 | ||
314 | void LLParcel::setLocalID(S32 local_id) | ||
315 | { | ||
316 | mLocalID = local_id; | ||
317 | } | ||
318 | |||
319 | void 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 | |||
332 | BOOL 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 | |||
361 | BOOL 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 | |||
388 | bool 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 | |||
411 | BOOL 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 | } | ||
422 | S32 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 | |||
504 | void 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 | |||
510 | void 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. | ||
525 | BOOL 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 | |||
974 | BOOL 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 | |||
1017 | BOOL 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" | ||
1227 | void 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 | |||
1249 | void 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 | |||
1284 | void 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 | |||
1311 | void 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 | |||
1339 | void 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 | |||
1358 | bool 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 | ||
1379 | S32 LLParcel::getTotalRent() const | ||
1380 | { | ||
1381 | return (S32)floor(0.5f + (F32)mArea * (F32)mRentPricePerMeter * (1.0f - mDiscountRate)); | ||
1382 | } | ||
1383 | |||
1384 | F32 LLParcel::getAdjustedRentPerMeter() const | ||
1385 | { | ||
1386 | return ((F32)mRentPricePerMeter * (1.0f - mDiscountRate)); | ||
1387 | } | ||
1388 | |||
1389 | LLVector3 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 | |||
1398 | void 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 | |||
1420 | BOOL 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 | |||
1465 | BOOL 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 | |||
1511 | BOOL 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 | |||
1532 | BOOL LLParcel::removeFromAccessList(const LLUUID& agent_id) | ||
1533 | { | ||
1534 | return remove_from_access_array(&mAccessList, agent_id); | ||
1535 | } | ||
1536 | |||
1537 | BOOL LLParcel::removeFromBanList(const LLUUID& agent_id) | ||
1538 | { | ||
1539 | return remove_from_access_array(&mBanList, agent_id); | ||
1540 | } | ||
1541 | |||
1542 | // static | ||
1543 | const char* LLParcel::getOwnershipStatusString(EOwnershipStatus status) | ||
1544 | { | ||
1545 | return ownership_status_to_string(status); | ||
1546 | } | ||
1547 | |||
1548 | // static | ||
1549 | const char* LLParcel::getCategoryString(ECategory category) | ||
1550 | { | ||
1551 | return category_to_string(category); | ||
1552 | } | ||
1553 | |||
1554 | // static | ||
1555 | const char* LLParcel::getCategoryUIString(ECategory category) | ||
1556 | { | ||
1557 | return category_to_ui_string(category); | ||
1558 | } | ||
1559 | |||
1560 | // static | ||
1561 | LLParcel::ECategory LLParcel::getCategoryFromString(const char* string) | ||
1562 | { | ||
1563 | return category_string_to_category(string); | ||
1564 | } | ||
1565 | |||
1566 | // static | ||
1567 | LLParcel::ECategory LLParcel::getCategoryFromUIString(const char* string) | ||
1568 | { | ||
1569 | return category_ui_string_to_category(string); | ||
1570 | } | ||
1571 | |||
1572 | // static | ||
1573 | const 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 | |||
1587 | BOOL 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 | |||
1602 | void 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 | |||
1628 | void 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 | |||
1645 | void 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 | |||
1671 | void 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 | |||
1691 | BOOL LLParcel::isPublic() const | ||
1692 | { | ||
1693 | return (mOwnerID.isNull()); | ||
1694 | } | ||
1695 | |||
1696 | BOOL LLParcel::isBuyerAuthorized(const LLUUID& buyer_id) const | ||
1697 | { | ||
1698 | if(mAuthBuyerID.isNull()) | ||
1699 | { | ||
1700 | return TRUE; | ||
1701 | } | ||
1702 | return (mAuthBuyerID == buyer_id); | ||
1703 | } | ||
1704 | |||
1705 | void 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 | |||
1731 | void LLParcel::dump() | ||
1732 | { | ||
1733 | llinfos << "parcel " << mLocalID << " area " << mArea << llendl; | ||
1734 | llinfos << " name <" << mName << ">" << llendl; | ||
1735 | llinfos << " desc <" << mDesc << ">" << llendl; | ||
1736 | } | ||
1737 | |||
1738 | const 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 | |||
1747 | LLParcel::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 | |||
1781 | const 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 | |||
1791 | const 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 | |||
1806 | LLParcel::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 | |||
1819 | LLParcel::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 | |||
diff --git a/linden/indra/llinventory/llparcel.h b/linden/indra/llinventory/llparcel.h new file mode 100644 index 0000000..54936e2 --- /dev/null +++ b/linden/indra/llinventory/llparcel.h | |||
@@ -0,0 +1,595 @@ | |||
1 | /** | ||
2 | * @file llparcel.h | ||
3 | * | ||
4 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
5 | * | ||
6 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
7 | * to you under the terms of the GNU General Public License, version 2.0 | ||
8 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
9 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
10 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
11 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
12 | * | ||
13 | * There are special exceptions to the terms and conditions of the GPL as | ||
14 | * it is applied to this Source Code. View the full text of the exception | ||
15 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/flossexception | ||
17 | * | ||
18 | * By copying, modifying or distributing this software, you acknowledge | ||
19 | * that you have read and understood your obligations described above, | ||
20 | * and agree to abide by those obligations. | ||
21 | * | ||
22 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
23 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
24 | * COMPLETENESS OR PERFORMANCE. | ||
25 | */ | ||
26 | |||
27 | #ifndef LL_LLPARCEL_H | ||
28 | #define LL_LLPARCEL_H | ||
29 | |||
30 | #include <time.h> | ||
31 | #include <iostream> | ||
32 | |||
33 | #include "lldarray.h" | ||
34 | #include "lluuid.h" | ||
35 | #include "llparcelflags.h" | ||
36 | #include "llpermissions.h" | ||
37 | #include "v3math.h" | ||
38 | |||
39 | |||
40 | // Grid out of which parcels taken is stepped every 4 meters. | ||
41 | const F32 PARCEL_GRID_STEP_METERS = 4.f; | ||
42 | |||
43 | // Area of one "square" of parcel | ||
44 | const S32 PARCEL_UNIT_AREA = 16; | ||
45 | |||
46 | // Height _above_ground_ that parcel boundary ends | ||
47 | const F32 PARCEL_HEIGHT = 50.f; | ||
48 | |||
49 | //Height above ground which parcel boundries exist for explicitly banned avatars | ||
50 | const F32 BAN_HEIGHT = 768.f; | ||
51 | |||
52 | // Maximum number of entries in an access list | ||
53 | const S32 PARCEL_MAX_ACCESS_LIST = 300; | ||
54 | //Maximum number of entires in an update packet | ||
55 | //for access/ban lists. | ||
56 | const F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f; | ||
57 | |||
58 | // Weekly charge for listing a parcel in the directory | ||
59 | const S32 PARCEL_DIRECTORY_FEE = 30; | ||
60 | |||
61 | const S32 PARCEL_PASS_PRICE_DEFAULT = 10; | ||
62 | const F32 PARCEL_PASS_HOURS_DEFAULT = 1.f; | ||
63 | |||
64 | // Number of "chunks" in which parcel overlay data is sent | ||
65 | // Chunk 0 = southern rows, entire width | ||
66 | const S32 PARCEL_OVERLAY_CHUNKS = 4; | ||
67 | |||
68 | // Bottom three bits are a color index for the land overlay | ||
69 | const U8 PARCEL_COLOR_MASK = 0x07; | ||
70 | const U8 PARCEL_PUBLIC = 0x00; | ||
71 | const U8 PARCEL_OWNED = 0x01; | ||
72 | const U8 PARCEL_GROUP = 0x02; | ||
73 | const U8 PARCEL_SELF = 0x03; | ||
74 | const U8 PARCEL_FOR_SALE = 0x04; | ||
75 | const U8 PARCEL_AUCTION = 0x05; | ||
76 | // unused 0x06 | ||
77 | // unused 0x07 | ||
78 | // flag, unused 0x08 | ||
79 | // flag, unused 0x10 | ||
80 | const U8 PARCEL_SOUND_LOCAL = 0x20; | ||
81 | const U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge | ||
82 | const U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge | ||
83 | |||
84 | // Transmission results for parcel properties | ||
85 | const S32 PARCEL_RESULT_NO_DATA = -1; | ||
86 | const S32 PARCEL_RESULT_SUCCESS = 0; // got exactly one parcel | ||
87 | const S32 PARCEL_RESULT_MULTIPLE = 1; // got multiple parcels | ||
88 | |||
89 | const S32 SELECTED_PARCEL_SEQ_ID = -10000; | ||
90 | const S32 COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID = -20000; | ||
91 | const S32 COLLISION_BANNED_PARCEL_SEQ_ID = -30000; | ||
92 | const S32 COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID = -40000; | ||
93 | const S32 HOVERED_PARCEL_SEQ_ID = -50000; | ||
94 | |||
95 | const U32 RT_NONE = 0x1 << 0; | ||
96 | const U32 RT_OWNER = 0x1 << 1; | ||
97 | const U32 RT_GROUP = 0x1 << 2; | ||
98 | const U32 RT_OTHER = 0x1 << 3; | ||
99 | const U32 RT_LIST = 0x1 << 4; | ||
100 | const U32 RT_SELL = 0x1 << 5; | ||
101 | |||
102 | class LLMessageSystem; | ||
103 | |||
104 | class LLAccessEntry | ||
105 | { | ||
106 | public: | ||
107 | LLUUID mID; | ||
108 | S32 mTime; | ||
109 | U32 mFlags; | ||
110 | }; | ||
111 | |||
112 | typedef std::map<LLUUID,LLAccessEntry>::iterator access_map_iterator; | ||
113 | typedef std::map<LLUUID,LLAccessEntry>::const_iterator access_map_const_iterator; | ||
114 | |||
115 | class LLParcel | ||
116 | { | ||
117 | public: | ||
118 | enum EOwnershipStatus | ||
119 | { | ||
120 | OS_LEASED = 0, | ||
121 | OS_LEASE_PENDING = 1, | ||
122 | OS_ABANDONED = 2, | ||
123 | OS_COUNT = 3, | ||
124 | OS_NONE = -1 | ||
125 | }; | ||
126 | enum ECategory | ||
127 | { | ||
128 | C_NONE = 0, | ||
129 | C_LINDEN, | ||
130 | C_ADULT, | ||
131 | C_ARTS, // "arts & culture" | ||
132 | C_BUSINESS, // was "store" | ||
133 | C_EDUCATIONAL, | ||
134 | C_GAMING, // was "game" | ||
135 | C_HANGOUT, // was "gathering place" | ||
136 | C_NEWCOMER, | ||
137 | C_PARK, // "parks & nature" | ||
138 | C_RESIDENTIAL, // was "homestead" | ||
139 | C_SHOPPING, | ||
140 | C_STAGE, | ||
141 | C_OTHER, | ||
142 | C_COUNT, | ||
143 | C_ANY = -1 // only useful in queries | ||
144 | }; | ||
145 | enum EAction | ||
146 | { | ||
147 | A_CREATE = 0, | ||
148 | A_RELEASE = 1, | ||
149 | A_ABSORB = 2, | ||
150 | A_ABSORBED = 3, | ||
151 | A_DIVIDE = 4, | ||
152 | A_DIVISION = 5, | ||
153 | A_ACQUIRE = 6, | ||
154 | A_RELINQUISH = 7, | ||
155 | A_CONFIRM = 8, | ||
156 | A_COUNT = 9, | ||
157 | A_UNKNOWN = -1 | ||
158 | }; | ||
159 | |||
160 | enum ELandingType | ||
161 | { | ||
162 | L_NONE = 0, | ||
163 | L_LANDING_POINT = 1, | ||
164 | L_DIRECT = 2 | ||
165 | }; | ||
166 | |||
167 | // CREATORS | ||
168 | LLParcel(); | ||
169 | LLParcel( const LLUUID &owner_id, | ||
170 | BOOL modify, BOOL terraform, BOOL damage, | ||
171 | time_t claim_date, S32 claim_price, S32 rent_price, S32 area, S32 sim_object_limit, F32 parcel_object_bonus, | ||
172 | BOOL is_group_owned = FALSE); | ||
173 | virtual ~LLParcel(); | ||
174 | |||
175 | void init( const LLUUID &owner_id, | ||
176 | BOOL modify, BOOL terraform, BOOL damage, | ||
177 | time_t claim_date, S32 claim_price, S32 rent_price, | ||
178 | S32 area, S32 sim_object_limit, F32 parcel_object_bonus, BOOL is_group_owned = FALSE); | ||
179 | |||
180 | // TODO: make an actual copy constructor for this | ||
181 | void overrideParcelFlags(U32 flags); | ||
182 | // if you specify an agent id here, the group id will be zeroed | ||
183 | void overrideOwner(const LLUUID& owner_id, BOOL is_group_owned = FALSE); | ||
184 | void overrideSaleTimerExpires(F32 secs_left) { mSaleTimerExpires.setTimerExpirySec(secs_left); } | ||
185 | |||
186 | // MANIPULATORS | ||
187 | void generateNewID() { mID.generate(); } | ||
188 | void setName(const char* name); | ||
189 | void setDesc(const char* desc); | ||
190 | void setMusicURL(const char* url); | ||
191 | void setMediaURL(const char* url); | ||
192 | void setMediaID(const LLUUID& id) { mMediaID = id; } | ||
193 | void setMediaAutoScale ( U8 flagIn ) { mMediaAutoScale = flagIn; } | ||
194 | virtual void setLocalID(S32 local_id); | ||
195 | |||
196 | // blow away all the extra crap lurking in parcels, including urls, access lists, etc | ||
197 | void clearParcel(); | ||
198 | |||
199 | // This value is not persisted out to the parcel file, it is only | ||
200 | // a per-process blocker for attempts to purchase. | ||
201 | void setInEscrow(bool in_escrow) { mInEscrow = in_escrow; } | ||
202 | |||
203 | void setAuthorizedBuyerID(const LLUUID& id) { mAuthBuyerID = id; } | ||
204 | //void overrideBuyerID(const LLUUID& id) { mBuyerID = id; } | ||
205 | void setCategory(ECategory category) { mCategory = category; } | ||
206 | void setSnapshotID(const LLUUID& id) { mSnapshotID = id; } | ||
207 | void setUserLocation(const LLVector3& pos) { mUserLocation = pos; } | ||
208 | void setUserLookAt(const LLVector3& rot) { mUserLookAt = rot; } | ||
209 | void setLandingType(const ELandingType type) { mLandingType = type; } | ||
210 | |||
211 | void setAuctionID(U32 auction_id) { mAuctionID = auction_id;} | ||
212 | void setReservedForNewbie(BOOL reserve) { mIsReservedForNewbie = reserve; } | ||
213 | |||
214 | void setAllParcelFlags(U32 flags) { mParcelFlags = flags; } | ||
215 | void setParcelFlag(U32 flag, BOOL b); | ||
216 | |||
217 | void setArea(S32 area, S32 sim_object_limit); | ||
218 | void setDiscountRate(F32 rate); | ||
219 | |||
220 | void setAllowModify(BOOL b) { setParcelFlag(PF_CREATE_OBJECTS, b); } | ||
221 | void setAllowGroupModify(BOOL b) { setParcelFlag(PF_CREATE_GROUP_OBJECTS, b); } | ||
222 | void setAllowAllObjectEntry(BOOL b) { setParcelFlag(PF_ALLOW_ALL_OBJECT_ENTRY, b); } | ||
223 | void setAllowGroupObjectEntry(BOOL b) { setParcelFlag(PF_ALLOW_GROUP_OBJECT_ENTRY, b); } | ||
224 | void setAllowTerraform(BOOL b){setParcelFlag(PF_ALLOW_TERRAFORM, b); } | ||
225 | void setAllowDamage(BOOL b) { setParcelFlag(PF_ALLOW_DAMAGE, b); } | ||
226 | void setAllowFly(BOOL b) { setParcelFlag(PF_ALLOW_FLY, b); } | ||
227 | void setAllowLandmark(BOOL b){ setParcelFlag(PF_ALLOW_LANDMARK, b); } | ||
228 | void setAllowGroupScripts(BOOL b) { setParcelFlag(PF_ALLOW_GROUP_SCRIPTS, b); } | ||
229 | void setAllowOtherScripts(BOOL b) { setParcelFlag(PF_ALLOW_OTHER_SCRIPTS, b); } | ||
230 | void setAllowDeedToGroup(BOOL b) { setParcelFlag(PF_ALLOW_DEED_TO_GROUP, b); } | ||
231 | void setContributeWithDeed(BOOL b) { setParcelFlag(PF_CONTRIBUTE_WITH_DEED, b); } | ||
232 | void setForSale(BOOL b) { setParcelFlag(PF_FOR_SALE, b); } | ||
233 | void setSoundOnly(BOOL b) { setParcelFlag(PF_SOUND_LOCAL, b); } | ||
234 | void setDenyAnonymous(BOOL b) { setParcelFlag(PF_DENY_ANONYMOUS, b); } | ||
235 | void setDenyIdentified(BOOL b) { setParcelFlag(PF_DENY_IDENTIFIED, b); } | ||
236 | void setDenyTransacted(BOOL b) { setParcelFlag(PF_DENY_TRANSACTED, b); } | ||
237 | void setRestrictPushObject(BOOL b) { setParcelFlag(PF_RESTRICT_PUSHOBJECT, b); } | ||
238 | |||
239 | void setDrawDistance(F32 dist) { mDrawDistance = dist; } | ||
240 | void setSalePrice(S32 price) { mSalePrice = price; } | ||
241 | void setGroupID(const LLUUID& id) { mGroupID = id; } | ||
242 | //void setGroupName(const char* s) { mGroupName.assign(s); } | ||
243 | void setPassPrice(S32 price) { mPassPrice = price; } | ||
244 | void setPassHours(F32 hours) { mPassHours = hours; } | ||
245 | |||
246 | BOOL importStream(std::istream& input_stream); | ||
247 | BOOL importAccessEntry(std::istream& input_stream, LLAccessEntry* entry); | ||
248 | BOOL exportStream(std::ostream& output_stream); | ||
249 | |||
250 | void packMessage(LLMessageSystem* msg); | ||
251 | void unpackMessage(LLMessageSystem* msg); | ||
252 | |||
253 | void packAccessEntries(LLMessageSystem* msg, | ||
254 | const std::map<LLUUID,LLAccessEntry>& list); | ||
255 | void unpackAccessEntries(LLMessageSystem* msg, | ||
256 | std::map<LLUUID,LLAccessEntry>* list); | ||
257 | |||
258 | void setAABBMin(const LLVector3& min) { mAABBMin = min; } | ||
259 | void setAABBMax(const LLVector3& max) { mAABBMax = max; } | ||
260 | |||
261 | // Extend AABB to include rectangle from min to max. | ||
262 | void extendAABB(const LLVector3& box_min, const LLVector3& box_max); | ||
263 | |||
264 | void dump(); | ||
265 | |||
266 | // Scans the pass list and removes any items with an expiration | ||
267 | // time earlier than "now". | ||
268 | void expirePasses(S32 now); | ||
269 | |||
270 | // Add to list, suppressing duplicates. Returns TRUE if added. | ||
271 | BOOL addToAccessList(const LLUUID& agent_id, S32 time); | ||
272 | BOOL addToBanList(const LLUUID& agent_id, S32 time); | ||
273 | BOOL removeFromAccessList(const LLUUID& agent_id); | ||
274 | BOOL removeFromBanList(const LLUUID& agent_id); | ||
275 | |||
276 | // ACCESSORS | ||
277 | const LLUUID& getID() { return mID; } | ||
278 | const char* getName() const { return mName.c_str(); } | ||
279 | const char* getDesc() const { return mDesc.c_str(); } | ||
280 | const char* getMusicURL() const { return mMusicURL.c_str(); } | ||
281 | const char* getMediaURL() const { return mMediaURL.c_str(); } | ||
282 | const LLUUID& getMediaID() const { return mMediaID; } | ||
283 | const U8 getMediaAutoScale() const { return mMediaAutoScale; } | ||
284 | S32 getLocalID() const { return mLocalID; } | ||
285 | const LLUUID& getOwnerID() const { return mOwnerID; } | ||
286 | const LLUUID& getGroupID() const { return mGroupID; } | ||
287 | //const char* getGroupName() const { return mGroupName.c_str(); } | ||
288 | S32 getPassPrice() const { return mPassPrice; } | ||
289 | F32 getPassHours() const { return mPassHours; } | ||
290 | BOOL getIsGroupOwned() const { return mGroupOwned; } | ||
291 | |||
292 | U32 getAuctionID() { return mAuctionID; } | ||
293 | BOOL getReservedForNewbie() { return mIsReservedForNewbie; } | ||
294 | bool isInEscrow() const { return mInEscrow; } | ||
295 | |||
296 | BOOL isPublic() const; | ||
297 | |||
298 | // Region-local user-specified position | ||
299 | const LLVector3& getUserLocation() const { return mUserLocation; } | ||
300 | const LLVector3& getUserLookAt() const { return mUserLookAt; } | ||
301 | ELandingType getLandingType() const { return mLandingType; } | ||
302 | |||
303 | // User-specified snapshot | ||
304 | const LLUUID& getSnapshotID() const { return mSnapshotID; } | ||
305 | |||
306 | // the authorized buyer id is the person who is the only | ||
307 | // agent/group that has authority to purchase. (ie, ui specified a | ||
308 | // particular agent could buy the plot). | ||
309 | const LLUUID& getAuthorizedBuyerID() const { return mAuthBuyerID; } | ||
310 | |||
311 | // helper function | ||
312 | BOOL isBuyerAuthorized(const LLUUID& buyer_id) const; | ||
313 | |||
314 | // The buyer of a plot is set when someone indicates they want to | ||
315 | // buy the plot, and the system is simply waiting for tier-up | ||
316 | // approval | ||
317 | //const LLUUID& getBuyerID() const { return mBuyerID; } | ||
318 | |||
319 | // functions to deal with ownership status. | ||
320 | EOwnershipStatus getOwnershipStatus() const { return mStatus; } | ||
321 | static const char* getOwnershipStatusString(EOwnershipStatus status); | ||
322 | void setOwnershipStatus(EOwnershipStatus status) { mStatus = status; } | ||
323 | |||
324 | // dealing with parcel category information | ||
325 | ECategory getCategory() const {return mCategory; } | ||
326 | static const char* getCategoryString(ECategory category); | ||
327 | static const char* getCategoryUIString(ECategory category); | ||
328 | static ECategory getCategoryFromString(const char* string); | ||
329 | static ECategory getCategoryFromUIString(const char* string); | ||
330 | |||
331 | // functions for parcel action (used for logging) | ||
332 | static const char* getActionString(EAction action); | ||
333 | |||
334 | // dealing with sales and parcel conversion. | ||
335 | // | ||
336 | // the isSaleTimerExpired will trivially return FALSE if there is | ||
337 | // no sale going on. Pass in the current time in usec which will | ||
338 | // be used for comparison. | ||
339 | BOOL isSaleTimerExpired(const U64& time); | ||
340 | |||
341 | F32 getSaleTimerExpires() { return mSaleTimerExpires.getRemainingTimeF32(); } | ||
342 | |||
343 | // should the parcel join on complete? | ||
344 | //U32 getJoinNeighbors() const { return mJoinNeighbors; } | ||
345 | |||
346 | // need to record a few things with the parcel when a sale | ||
347 | // starts. | ||
348 | void startSale(const LLUUID& buyer_id, BOOL is_buyer_group); | ||
349 | |||
350 | // do the expiration logic, which needs to return values usable in | ||
351 | // a money transaction. | ||
352 | void expireSale(U32& type, U8& flags, LLUUID& from_id, LLUUID& to_id); | ||
353 | void completeSale(U32& type, U8& flags, LLUUID& to_id); | ||
354 | void clearSale(); | ||
355 | |||
356 | // this function returns TRUE if the parcel needs conversion to a | ||
357 | // lease from a non-owned-status state. | ||
358 | BOOL getRecordTransaction() const { return mRecordTransaction; } | ||
359 | void setRecordTransaction(BOOL record) { mRecordTransaction = record; } | ||
360 | |||
361 | |||
362 | // more accessors | ||
363 | U32 getParcelFlags() const { return mParcelFlags; } | ||
364 | |||
365 | BOOL getParcelFlag(U32 flag) const | ||
366 | { return (mParcelFlags & flag) ? TRUE : FALSE; } | ||
367 | |||
368 | // objects can be added or modified by anyone (only parcel owner if disabled) | ||
369 | BOOL getAllowModify() const | ||
370 | { return (mParcelFlags & PF_CREATE_OBJECTS) ? TRUE : FALSE; } | ||
371 | |||
372 | // objects can be added or modified by group members | ||
373 | BOOL getAllowGroupModify() const | ||
374 | { return (mParcelFlags & PF_CREATE_GROUP_OBJECTS) ? TRUE : FALSE; } | ||
375 | |||
376 | // the parcel can be deeded to the group | ||
377 | BOOL getAllowDeedToGroup() const | ||
378 | { return (mParcelFlags & PF_ALLOW_DEED_TO_GROUP) ? TRUE : FALSE; } | ||
379 | |||
380 | // Does the owner want to make a contribution along with the deed. | ||
381 | BOOL getContributeWithDeed() const | ||
382 | { return (mParcelFlags & PF_CONTRIBUTE_WITH_DEED) ? TRUE : FALSE; } | ||
383 | |||
384 | // heightfield can be modified | ||
385 | BOOL getAllowTerraform() const | ||
386 | { return (mParcelFlags & PF_ALLOW_TERRAFORM) ? TRUE : FALSE; } | ||
387 | |||
388 | // avatars can be hurt here | ||
389 | BOOL getAllowDamage() const | ||
390 | { return (mParcelFlags & PF_ALLOW_DAMAGE) ? TRUE : FALSE; } | ||
391 | |||
392 | BOOL getAllowFly() const | ||
393 | { return (mParcelFlags & PF_ALLOW_FLY) ? TRUE : FALSE; } | ||
394 | |||
395 | BOOL getAllowLandmark() const | ||
396 | { return (mParcelFlags & PF_ALLOW_LANDMARK) ? TRUE : FALSE; } | ||
397 | |||
398 | BOOL getAllowGroupScripts() const | ||
399 | { return (mParcelFlags & PF_ALLOW_GROUP_SCRIPTS) ? TRUE : FALSE; } | ||
400 | |||
401 | BOOL getAllowOtherScripts() const | ||
402 | { return (mParcelFlags & PF_ALLOW_OTHER_SCRIPTS) ? TRUE : FALSE; } | ||
403 | |||
404 | BOOL getAllowAllObjectEntry() const | ||
405 | { return (mParcelFlags & PF_ALLOW_ALL_OBJECT_ENTRY) ? TRUE : FALSE; } | ||
406 | |||
407 | BOOL getAllowGroupObjectEntry() const | ||
408 | { return (mParcelFlags & PF_ALLOW_GROUP_OBJECT_ENTRY) ? TRUE : FALSE; } | ||
409 | |||
410 | BOOL getForSale() const | ||
411 | { return (mParcelFlags & PF_FOR_SALE) ? TRUE : FALSE; } | ||
412 | BOOL getSoundLocal() const | ||
413 | { return (mParcelFlags & PF_SOUND_LOCAL) ? TRUE : FALSE; } | ||
414 | BOOL getAllowPublish() const | ||
415 | { return (mParcelFlags & PF_ALLOW_PUBLISH) ? TRUE : FALSE; } | ||
416 | BOOL getMaturePublish() const | ||
417 | { return (mParcelFlags & PF_MATURE_PUBLISH) ? TRUE : FALSE; } | ||
418 | BOOL getRestrictPushObject() const | ||
419 | { return (mParcelFlags & PF_RESTRICT_PUSHOBJECT) ? TRUE : FALSE; } | ||
420 | BOOL getRegionPushOverride() const | ||
421 | { return mRegionPushOverride; } | ||
422 | BOOL getRegionDenyAnonymousOverride() const | ||
423 | { return mRegionDenyAnonymousOverride; } | ||
424 | BOOL getRegionDenyIdentifiedOverride() const | ||
425 | { return mRegionDenyIdentifiedOverride; } | ||
426 | BOOL getRegionDenyTransactedOverride() const | ||
427 | { return mRegionDenyTransactedOverride; } | ||
428 | |||
429 | F32 getDrawDistance() const { return mDrawDistance; } | ||
430 | S32 getSalePrice() const { return mSalePrice; } | ||
431 | time_t getClaimDate() const { return mClaimDate; } | ||
432 | S32 getClaimPricePerMeter() const { return mClaimPricePerMeter; } | ||
433 | S32 getRentPricePerMeter() const { return mRentPricePerMeter; } | ||
434 | |||
435 | // Area is NOT automatically calculated. You must calculate it | ||
436 | // and store it with setArea. | ||
437 | S32 getArea() const { return mArea; } | ||
438 | |||
439 | // deprecated 12/11/2003 | ||
440 | //F32 getDiscountRate() const { return mDiscountRate; } | ||
441 | |||
442 | S32 getClaimPrice() const { return mClaimPricePerMeter * mArea; } | ||
443 | |||
444 | // Can this agent create objects here? | ||
445 | BOOL allowModifyBy(const LLUUID &agent_id, const LLUUID &group_id) const; | ||
446 | |||
447 | // Can this agent change the shape of the land? | ||
448 | BOOL allowTerraformBy(const LLUUID &agent_id) const; | ||
449 | |||
450 | // Returns 0 if access is OK, otherwise a BA_ return code above. | ||
451 | S32 blockAccess(const LLUUID& agent_id, const LLUUID& group_id, const BOOL is_agent_identified, const BOOL is_agent_transacted) const; | ||
452 | |||
453 | // Only checks if the agent is explicitly banned from this parcel | ||
454 | BOOL isAgentBanned(const LLUUID& agent_id) const; | ||
455 | |||
456 | static bool isAgentBlockedFromParcel(LLParcel* parcelp, | ||
457 | const LLUUID& agent_id, | ||
458 | const std::vector<LLUUID>& group_ids, | ||
459 | const BOOL is_agent_identified, | ||
460 | const BOOL is_agent_transacted); | ||
461 | |||
462 | bool operator==(const LLParcel &rhs) const; | ||
463 | |||
464 | // Calculate rent - area * rent * discount rate | ||
465 | S32 getTotalRent() const; | ||
466 | F32 getAdjustedRentPerMeter() const; | ||
467 | |||
468 | const LLVector3& getAABBMin() const { return mAABBMin; } | ||
469 | const LLVector3& getAABBMax() const { return mAABBMax; } | ||
470 | LLVector3 getCenterpoint() const; | ||
471 | |||
472 | // simwide | ||
473 | S32 getSimWideMaxPrimCapacity() const { return mSimWideMaxPrimCapacity; } | ||
474 | S32 getSimWidePrimCount() const { return mSimWidePrimCount; } | ||
475 | |||
476 | // this parcel only (not simwide) | ||
477 | S32 getMaxPrimCapacity() const { return mMaxPrimCapacity; } | ||
478 | S32 getPrimCount() const { return mOwnerPrimCount + mGroupPrimCount + mOtherPrimCount + mSelectedPrimCount; } | ||
479 | S32 getOwnerPrimCount() const { return mOwnerPrimCount; } | ||
480 | S32 getGroupPrimCount() const { return mGroupPrimCount; } | ||
481 | S32 getOtherPrimCount() const { return mOtherPrimCount; } | ||
482 | S32 getSelectedPrimCount() const{ return mSelectedPrimCount; } | ||
483 | S32 getTempPrimCount() const { return mTempPrimCount; } | ||
484 | F32 getParcelPrimBonus() const { return mParcelPrimBonus; } | ||
485 | |||
486 | S32 getCleanOtherTime() const { return mCleanOtherTime; } | ||
487 | |||
488 | void setMaxPrimCapacity(S32 max) { mMaxPrimCapacity = max; } | ||
489 | // simwide | ||
490 | void setSimWideMaxPrimCapacity(S32 current) { mSimWideMaxPrimCapacity = current; } | ||
491 | void setSimWidePrimCount(S32 current) { mSimWidePrimCount = current; } | ||
492 | |||
493 | // this parcel only (not simwide) | ||
494 | void setOwnerPrimCount(S32 current) { mOwnerPrimCount = current; } | ||
495 | void setGroupPrimCount(S32 current) { mGroupPrimCount = current; } | ||
496 | void setOtherPrimCount(S32 current) { mOtherPrimCount = current; } | ||
497 | void setSelectedPrimCount(S32 current) { mSelectedPrimCount = current; } | ||
498 | void setTempPrimCount(S32 current) { mTempPrimCount = current; } | ||
499 | void setParcelPrimBonus(F32 bonus) { mParcelPrimBonus = bonus; } | ||
500 | |||
501 | void setCleanOtherTime(S32 time) { mCleanOtherTime = time; } | ||
502 | void setRegionPushOverride(BOOL override) {mRegionPushOverride = override; } | ||
503 | void setRegionDenyAnonymousOverride(BOOL override) { mRegionDenyAnonymousOverride = override; } | ||
504 | void setRegionDenyIdentifiedOverride(BOOL override) { mRegionDenyIdentifiedOverride = override; } | ||
505 | void setRegionDenyTransactedOverride(BOOL override) { mRegionDenyTransactedOverride = override; } | ||
506 | |||
507 | // Accessors for parcel sellWithObjects | ||
508 | void setPreviousOwnerID(LLUUID prev_owner) { mPreviousOwnerID = prev_owner; } | ||
509 | void setPreviouslyGroupOwned(BOOL b) { mPreviouslyGroupOwned = b; } | ||
510 | void setSellWithObjects(BOOL b) { setParcelFlag(PF_SELL_PARCEL_OBJECTS, b); } | ||
511 | |||
512 | LLUUID getPreviousOwnerID() const { return mPreviousOwnerID; } | ||
513 | BOOL getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; } | ||
514 | BOOL getSellWithObjects() const { return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; } | ||
515 | |||
516 | protected: | ||
517 | LLUUID mID; | ||
518 | LLUUID mOwnerID; | ||
519 | LLUUID mGroupID; | ||
520 | BOOL mGroupOwned; // TRUE if mOwnerID is a group_id | ||
521 | LLUUID mPreviousOwnerID; | ||
522 | BOOL mPreviouslyGroupOwned; | ||
523 | |||
524 | EOwnershipStatus mStatus; | ||
525 | ECategory mCategory; | ||
526 | LLUUID mAuthBuyerID; | ||
527 | LLUUID mSnapshotID; | ||
528 | LLVector3 mUserLocation; | ||
529 | LLVector3 mUserLookAt; | ||
530 | ELandingType mLandingType; | ||
531 | LLTimer mSaleTimerExpires; | ||
532 | S32 mGraceExtension; | ||
533 | BOOL mRecordTransaction; | ||
534 | |||
535 | |||
536 | // This value is non-zero if there is an auction associated with | ||
537 | // the parcel. | ||
538 | U32 mAuctionID; | ||
539 | |||
540 | // This value is TRUE if the land is reserved for a newbie. | ||
541 | BOOL mIsReservedForNewbie; | ||
542 | |||
543 | // value used to temporarily lock attempts to purchase the parcel. | ||
544 | bool mInEscrow; | ||
545 | |||
546 | time_t mClaimDate; // UTC Unix-format time | ||
547 | S32 mClaimPricePerMeter; // meter squared | ||
548 | S32 mRentPricePerMeter; // meter squared | ||
549 | S32 mArea; // meter squared | ||
550 | F32 mDiscountRate; // 0.0-1.0 | ||
551 | F32 mDrawDistance; | ||
552 | U32 mParcelFlags; | ||
553 | S32 mSalePrice; // linden dollars | ||
554 | std::string mName; | ||
555 | std::string mDesc; | ||
556 | std::string mMusicURL; | ||
557 | std::string mMediaURL; | ||
558 | U8 mMediaAutoScale; | ||
559 | LLUUID mMediaID; | ||
560 | S32 mPassPrice; | ||
561 | F32 mPassHours; | ||
562 | LLVector3 mAABBMin; | ||
563 | LLVector3 mAABBMax; | ||
564 | S32 mMaxPrimCapacity; | ||
565 | S32 mSimWidePrimCount; | ||
566 | S32 mSimWideMaxPrimCapacity; | ||
567 | //S32 mSimWidePrimCorrection; | ||
568 | S32 mOwnerPrimCount; | ||
569 | S32 mGroupPrimCount; | ||
570 | S32 mOtherPrimCount; | ||
571 | S32 mSelectedPrimCount; | ||
572 | S32 mTempPrimCount; | ||
573 | F32 mParcelPrimBonus; | ||
574 | S32 mCleanOtherTime; | ||
575 | BOOL mRegionPushOverride; | ||
576 | BOOL mRegionDenyAnonymousOverride; | ||
577 | BOOL mRegionDenyIdentifiedOverride; | ||
578 | BOOL mRegionDenyTransactedOverride; | ||
579 | |||
580 | |||
581 | public: | ||
582 | // HACK, make private | ||
583 | S32 mLocalID; | ||
584 | LLUUID mBanListTransactionID; | ||
585 | LLUUID mAccessListTransactionID; | ||
586 | std::map<LLUUID,LLAccessEntry> mAccessList; | ||
587 | std::map<LLUUID,LLAccessEntry> mBanList; | ||
588 | std::map<LLUUID,LLAccessEntry> mTempBanList; | ||
589 | std::map<LLUUID,LLAccessEntry> mTempAccessList; | ||
590 | |||
591 | //LLDynamicArray<LLAccessEntry> mRenterList; | ||
592 | }; | ||
593 | |||
594 | |||
595 | #endif | ||
diff --git a/linden/indra/llinventory/llparcelflags.h b/linden/indra/llinventory/llparcelflags.h new file mode 100644 index 0000000..66158d8 --- /dev/null +++ b/linden/indra/llinventory/llparcelflags.h | |||
@@ -0,0 +1,124 @@ | |||
1 | /** | ||
2 | * @file llparcelflags.h | ||
3 | * | ||
4 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
5 | * | ||
6 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
7 | * to you under the terms of the GNU General Public License, version 2.0 | ||
8 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
9 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
10 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
11 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
12 | * | ||
13 | * There are special exceptions to the terms and conditions of the GPL as | ||
14 | * it is applied to this Source Code. View the full text of the exception | ||
15 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/flossexception | ||
17 | * | ||
18 | * By copying, modifying or distributing this software, you acknowledge | ||
19 | * that you have read and understood your obligations described above, | ||
20 | * and agree to abide by those obligations. | ||
21 | * | ||
22 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
23 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
24 | * COMPLETENESS OR PERFORMANCE. | ||
25 | */ | ||
26 | |||
27 | #ifndef LL_LLPARCEL_FLAGS_H | ||
28 | #define LL_LLPARCEL_FLAGS_H | ||
29 | |||
30 | //--------------------------------------------------------------------------- | ||
31 | // Parcel Flags (PF) constants | ||
32 | //--------------------------------------------------------------------------- | ||
33 | const U32 PF_ALLOW_FLY = 1 << 0;// Can start flying | ||
34 | const U32 PF_ALLOW_OTHER_SCRIPTS= 1 << 1;// Scripts by others can run. | ||
35 | const U32 PF_FOR_SALE = 1 << 2;// Can buy this land | ||
36 | const U32 PF_FOR_SALE_OBJECTS = 1 << 7;// Can buy all objects on this land | ||
37 | const U32 PF_ALLOW_LANDMARK = 1 << 3; | ||
38 | const U32 PF_ALLOW_TERRAFORM = 1 << 4; | ||
39 | const U32 PF_ALLOW_DAMAGE = 1 << 5; | ||
40 | const U32 PF_CREATE_OBJECTS = 1 << 6; | ||
41 | // 7 is moved above | ||
42 | const U32 PF_USE_ACCESS_GROUP = 1 << 8; | ||
43 | const U32 PF_USE_ACCESS_LIST = 1 << 9; | ||
44 | const U32 PF_USE_BAN_LIST = 1 << 10; | ||
45 | const U32 PF_USE_PASS_LIST = 1 << 11; | ||
46 | const U32 PF_SHOW_DIRECTORY = 1 << 12; | ||
47 | const U32 PF_ALLOW_DEED_TO_GROUP = 1 << 13; | ||
48 | const U32 PF_CONTRIBUTE_WITH_DEED = 1 << 14; | ||
49 | const U32 PF_SOUND_LOCAL = 1 << 15; // Hear sounds in this parcel only | ||
50 | const U32 PF_SELL_PARCEL_OBJECTS = 1 << 16; // Objects on land are included as part of the land when the land is sold | ||
51 | const U32 PF_ALLOW_PUBLISH = 1 << 17; // Allow publishing of parcel information on the web | ||
52 | const U32 PF_MATURE_PUBLISH = 1 << 18; // The information on this parcel is mature | ||
53 | const U32 PF_URL_WEB_PAGE = 1 << 19; // The "media URL" is an HTML page | ||
54 | const U32 PF_URL_RAW_HTML = 1 << 20; // The "media URL" is a raw HTML string like <H1>Foo</H1> | ||
55 | const U32 PF_RESTRICT_PUSHOBJECT = 1 << 21; // Restrict push object to either on agent or on scripts owned by parcel owner | ||
56 | const U32 PF_DENY_ANONYMOUS = 1 << 22; // Deny all non identified/transacted accounts | ||
57 | const U32 PF_DENY_IDENTIFIED = 1 << 23; // Deny identified accounts | ||
58 | const U32 PF_DENY_TRANSACTED = 1 << 24; // Deny identified accounts | ||
59 | const U32 PF_ALLOW_GROUP_SCRIPTS = 1 << 25; // Allow scripts owned by group | ||
60 | const U32 PF_CREATE_GROUP_OBJECTS = 1 << 26; // Allow object creation by group members or objects | ||
61 | const U32 PF_ALLOW_ALL_OBJECT_ENTRY = 1 << 27; // Allow all objects to enter a parcel | ||
62 | const U32 PF_ALLOW_GROUP_OBJECT_ENTRY = 1 << 28; // Only allow group (and owner) objects to enter the parcel | ||
63 | |||
64 | |||
65 | const U32 PF_RESERVED = 1 << 31; | ||
66 | |||
67 | // If any of these are true the parcel is restricting access in some maner. | ||
68 | const U32 PF_USE_RESTRICTED_ACCESS = PF_USE_ACCESS_GROUP | ||
69 | | PF_USE_ACCESS_LIST | ||
70 | | PF_USE_BAN_LIST | ||
71 | | PF_USE_PASS_LIST | ||
72 | | PF_DENY_ANONYMOUS | ||
73 | | PF_DENY_IDENTIFIED | ||
74 | | PF_DENY_TRANSACTED; | ||
75 | const U32 PF_NONE = 0x00000000; | ||
76 | const U32 PF_ALL = 0x7FFFFFFF; | ||
77 | const U32 PF_DEFAULT = PF_ALLOW_FLY | ||
78 | | PF_ALLOW_OTHER_SCRIPTS | ||
79 | | PF_ALLOW_GROUP_SCRIPTS | ||
80 | | PF_ALLOW_LANDMARK | ||
81 | | PF_CREATE_OBJECTS | ||
82 | | PF_CREATE_GROUP_OBJECTS | ||
83 | | PF_USE_BAN_LIST | ||
84 | | PF_ALLOW_ALL_OBJECT_ENTRY | ||
85 | | PF_ALLOW_GROUP_OBJECT_ENTRY; | ||
86 | |||
87 | // Access list flags | ||
88 | const U32 AL_ACCESS = (1 << 0); | ||
89 | const U32 AL_BAN = (1 << 1); | ||
90 | //const U32 AL_RENTER = (1 << 2); | ||
91 | |||
92 | // Block access return values. BA_ALLOWED is the only success case | ||
93 | // since some code in the simulator relies on that assumption. All | ||
94 | // other BA_ values should be reasons why you are not allowed. | ||
95 | const S32 BA_ALLOWED = 0; | ||
96 | const S32 BA_NOT_IN_GROUP = 1; | ||
97 | const S32 BA_NOT_ON_LIST = 2; | ||
98 | const S32 BA_BANNED = 3; | ||
99 | const S32 BA_NO_ACCESS_LEVEL = 4; | ||
100 | |||
101 | // ParcelRelease flags | ||
102 | const U32 PR_NONE = 0x0; | ||
103 | const U32 PR_GOD_FORCE = (1 << 0); | ||
104 | |||
105 | enum EObjectCategory | ||
106 | { | ||
107 | OC_INVALID = -1, | ||
108 | OC_NONE = 0, | ||
109 | OC_TOTAL = 0, // yes zero, like OC_NONE | ||
110 | OC_OWNER, | ||
111 | OC_GROUP, | ||
112 | OC_OTHER, | ||
113 | OC_SELECTED, | ||
114 | OC_TEMP, | ||
115 | OC_COUNT | ||
116 | }; | ||
117 | |||
118 | const S32 PARCEL_DETAILS_NAME = 0; | ||
119 | const S32 PARCEL_DETAILS_DESC = 1; | ||
120 | const S32 PARCEL_DETAILS_OWNER = 2; | ||
121 | const S32 PARCEL_DETAILS_GROUP = 3; | ||
122 | const S32 PARCEL_DETAILS_AREA = 4; | ||
123 | |||
124 | #endif | ||
diff --git a/linden/indra/llinventory/llpermissions.cpp b/linden/indra/llinventory/llpermissions.cpp new file mode 100644 index 0000000..39e7a72 --- /dev/null +++ b/linden/indra/llinventory/llpermissions.cpp | |||
@@ -0,0 +1,1190 @@ | |||
1 | /** | ||
2 | * @file llpermissions.cpp | ||
3 | * @author Phoenix | ||
4 | * @brief Permissions for objects and inventory. | ||
5 | * | ||
6 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
7 | * | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #include "linden_common.h" | ||
30 | |||
31 | #include "llpermissions.h" | ||
32 | |||
33 | // library includes | ||
34 | #include "message.h" | ||
35 | #include "metapropertyt.h" | ||
36 | |||
37 | ///---------------------------------------------------------------------------- | ||
38 | /// Class LLPermissions | ||
39 | ///---------------------------------------------------------------------------- | ||
40 | |||
41 | const LLPermissions LLPermissions::DEFAULT; | ||
42 | |||
43 | // No creator = created by system | ||
44 | LLPermissions::LLPermissions() | ||
45 | { | ||
46 | init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); | ||
47 | } | ||
48 | |||
49 | |||
50 | // Default to created by system | ||
51 | void LLPermissions::init(const LLUUID& creator, const LLUUID& owner, const LLUUID& last_owner, const LLUUID& group) | ||
52 | { | ||
53 | mCreator = creator; | ||
54 | mOwner = owner; | ||
55 | mLastOwner = last_owner; | ||
56 | mGroup = group; | ||
57 | |||
58 | mMaskBase = PERM_ALL; | ||
59 | mMaskOwner = PERM_ALL; | ||
60 | mMaskEveryone = PERM_ALL; | ||
61 | mMaskGroup = PERM_ALL; | ||
62 | mMaskNextOwner = PERM_ALL; | ||
63 | fixOwnership(); | ||
64 | } | ||
65 | |||
66 | |||
67 | void LLPermissions::initMasks(PermissionMask base, PermissionMask owner, | ||
68 | PermissionMask everyone, PermissionMask group, | ||
69 | PermissionMask next) | ||
70 | { | ||
71 | mMaskBase = base; | ||
72 | mMaskOwner = owner; | ||
73 | mMaskEveryone = everyone; | ||
74 | mMaskGroup = group; | ||
75 | mMaskNextOwner = next; | ||
76 | fixFairUse(); | ||
77 | fix(); | ||
78 | } | ||
79 | |||
80 | BOOL LLPermissions::getOwnership(LLUUID& owner_id, BOOL& is_group_owned) const | ||
81 | { | ||
82 | if(mOwner.notNull()) | ||
83 | { | ||
84 | owner_id = mOwner; | ||
85 | is_group_owned = FALSE; | ||
86 | return TRUE; | ||
87 | } | ||
88 | else if(mIsGroupOwned) | ||
89 | { | ||
90 | owner_id = mGroup; | ||
91 | is_group_owned = TRUE; | ||
92 | return TRUE; | ||
93 | } | ||
94 | return FALSE; | ||
95 | } | ||
96 | |||
97 | LLUUID LLPermissions::getSafeOwner() const | ||
98 | { | ||
99 | if(mOwner.notNull()) | ||
100 | { | ||
101 | return mOwner; | ||
102 | } | ||
103 | else if(mIsGroupOwned) | ||
104 | { | ||
105 | return mGroup; | ||
106 | } | ||
107 | else | ||
108 | { | ||
109 | llwarns << "LLPermissions::getSafeOwner() called with no valid owner!" << llendl; | ||
110 | LLUUID unused_uuid; | ||
111 | unused_uuid.generate(); | ||
112 | |||
113 | return unused_uuid; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | U32 LLPermissions::getCRC32() const | ||
118 | { | ||
119 | U32 rv = mCreator.getCRC32(); | ||
120 | rv += mOwner.getCRC32(); | ||
121 | rv += mLastOwner.getCRC32(); | ||
122 | rv += mGroup.getCRC32(); | ||
123 | rv += mMaskBase + mMaskOwner + mMaskEveryone + mMaskGroup; | ||
124 | return rv; | ||
125 | } | ||
126 | |||
127 | void LLPermissions::set(const LLPermissions& from) | ||
128 | { | ||
129 | mCreator = from.mCreator; | ||
130 | mOwner = from.mOwner; | ||
131 | mLastOwner = from.mLastOwner; | ||
132 | mGroup = from.mGroup; | ||
133 | |||
134 | mMaskBase = from.mMaskBase; | ||
135 | mMaskOwner = from.mMaskOwner; | ||
136 | mMaskEveryone = from.mMaskEveryone; | ||
137 | mMaskGroup = from.mMaskGroup; | ||
138 | mMaskNextOwner = from.mMaskNextOwner; | ||
139 | mIsGroupOwned = from.mIsGroupOwned; | ||
140 | } | ||
141 | |||
142 | // Fix hierarchy of permissions. | ||
143 | void LLPermissions::fix() | ||
144 | { | ||
145 | mMaskOwner &= mMaskBase; | ||
146 | mMaskGroup &= mMaskOwner; | ||
147 | // next owner uses base, since you may want to sell locked objects. | ||
148 | mMaskNextOwner &= mMaskBase; | ||
149 | mMaskEveryone &= mMaskOwner; | ||
150 | mMaskEveryone &= ~PERM_MODIFY; | ||
151 | if(!(mMaskBase & PERM_TRANSFER) && !mIsGroupOwned) | ||
152 | { | ||
153 | mMaskGroup &= ~PERM_COPY; | ||
154 | mMaskEveryone &= ~PERM_COPY; | ||
155 | // Do not set mask next owner to too restrictive because if we | ||
156 | // rez an object, it may require an ownership transfer during | ||
157 | // rez, which will note the overly restrictive perms, and then | ||
158 | // fix them to allow fair use, which may be different than the | ||
159 | // original intention. | ||
160 | } | ||
161 | } | ||
162 | |||
163 | // Correct for fair use - you can never take away the right to move | ||
164 | // stuff you own, and you can never take away the right to transfer | ||
165 | // something you cannot otherwise copy. | ||
166 | void LLPermissions::fixFairUse() | ||
167 | { | ||
168 | mMaskBase |= PERM_MOVE; | ||
169 | if(!(mMaskBase & PERM_COPY)) | ||
170 | { | ||
171 | mMaskBase |= PERM_TRANSFER; | ||
172 | } | ||
173 | // (mask next owner == PERM_NONE) iff mask base is no transfer | ||
174 | if(mMaskNextOwner != PERM_NONE) | ||
175 | { | ||
176 | mMaskNextOwner |= PERM_MOVE; | ||
177 | } | ||
178 | } | ||
179 | |||
180 | void LLPermissions::fixOwnership() | ||
181 | { | ||
182 | if(mOwner.isNull() && mGroup.notNull()) | ||
183 | { | ||
184 | mIsGroupOwned = true; | ||
185 | } | ||
186 | else | ||
187 | { | ||
188 | mIsGroupOwned = false; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | // Allow accumulation of permissions. Results in the tightest | ||
193 | // permissions possible. In the case of clashing UUIDs, it sets the ID | ||
194 | // to LLUUID::null. | ||
195 | void LLPermissions::accumulate(const LLPermissions& perm) | ||
196 | { | ||
197 | if(perm.mCreator != mCreator) | ||
198 | { | ||
199 | mCreator = LLUUID::null; | ||
200 | } | ||
201 | if(perm.mOwner != mOwner) | ||
202 | { | ||
203 | mOwner = LLUUID::null; | ||
204 | } | ||
205 | if(perm.mLastOwner != mLastOwner) | ||
206 | { | ||
207 | mLastOwner = LLUUID::null; | ||
208 | } | ||
209 | if(perm.mGroup != mGroup) | ||
210 | { | ||
211 | mGroup = LLUUID::null; | ||
212 | } | ||
213 | |||
214 | mMaskBase &= perm.mMaskBase; | ||
215 | mMaskOwner &= perm.mMaskOwner; | ||
216 | mMaskGroup &= perm.mMaskGroup; | ||
217 | mMaskEveryone &= perm.mMaskEveryone; | ||
218 | mMaskNextOwner &= perm.mMaskNextOwner; | ||
219 | fix(); | ||
220 | } | ||
221 | |||
222 | // saves last owner, sets current owner, and sets the group. note | ||
223 | // that this function has to more cleverly apply the fair use | ||
224 | // permissions. | ||
225 | BOOL LLPermissions::setOwnerAndGroup( | ||
226 | const LLUUID& agent, | ||
227 | const LLUUID& owner, | ||
228 | const LLUUID& group, | ||
229 | bool is_atomic) | ||
230 | { | ||
231 | BOOL allowed = FALSE; | ||
232 | |||
233 | if( agent.isNull() || mOwner.isNull() | ||
234 | || ((agent == mOwner) && ((owner == mOwner) || (mMaskOwner & PERM_TRANSFER)) ) ) | ||
235 | { | ||
236 | // ...system can alway set owner | ||
237 | // ...public objects can be claimed by anyone | ||
238 | // ...otherwise, agent must own it and have transfer ability | ||
239 | allowed = TRUE; | ||
240 | } | ||
241 | |||
242 | if (allowed) | ||
243 | { | ||
244 | if(mLastOwner.isNull() || (!mOwner.isNull() && (owner != mLastOwner))) | ||
245 | { | ||
246 | mLastOwner = mOwner; | ||
247 | } | ||
248 | if((mOwner != owner) | ||
249 | || (mOwner.isNull() && owner.isNull() && (mGroup != group))) | ||
250 | { | ||
251 | mMaskBase = mMaskNextOwner; | ||
252 | mOwner = owner; | ||
253 | // this is a selective use of fair use for atomic | ||
254 | // permissions. | ||
255 | if(is_atomic && !(mMaskBase & PERM_COPY)) | ||
256 | { | ||
257 | mMaskBase |= PERM_TRANSFER; | ||
258 | } | ||
259 | } | ||
260 | mGroup = group; | ||
261 | fixOwnership(); | ||
262 | // if it's not atomic and we fix fair use, it blows away | ||
263 | //objects as inventory items which have different permissions | ||
264 | //than it's contents. :( | ||
265 | // fixFairUse(); | ||
266 | mMaskBase |= PERM_MOVE; | ||
267 | if(mMaskNextOwner != PERM_NONE) mMaskNextOwner |= PERM_MOVE; | ||
268 | fix(); | ||
269 | } | ||
270 | |||
271 | return allowed; | ||
272 | } | ||
273 | |||
274 | BOOL LLPermissions::deedToGroup(const LLUUID& agent, const LLUUID& group) | ||
275 | { | ||
276 | if(group.notNull() && (agent.isNull() || ((group == mGroup) | ||
277 | && (mMaskOwner & PERM_TRANSFER) | ||
278 | && (mMaskGroup & PERM_MOVE)))) | ||
279 | { | ||
280 | if(mOwner.notNull()) | ||
281 | { | ||
282 | mLastOwner = mOwner; | ||
283 | mOwner.setNull(); | ||
284 | } | ||
285 | mMaskBase = mMaskNextOwner; | ||
286 | mGroup = group; | ||
287 | mIsGroupOwned = true; | ||
288 | fixFairUse(); | ||
289 | fix(); | ||
290 | return TRUE; | ||
291 | } | ||
292 | return FALSE; | ||
293 | } | ||
294 | |||
295 | BOOL LLPermissions::setBaseBits(const LLUUID& agent, BOOL set, PermissionMask bits) | ||
296 | { | ||
297 | BOOL ownership = FALSE; | ||
298 | if(agent.isNull()) | ||
299 | { | ||
300 | // only the system is always allowed to change base bits | ||
301 | ownership = TRUE; | ||
302 | } | ||
303 | |||
304 | if (ownership) | ||
305 | { | ||
306 | if (set) | ||
307 | { | ||
308 | mMaskBase |= bits; // turn on bits | ||
309 | } | ||
310 | else | ||
311 | { | ||
312 | mMaskBase &= ~bits; // turn off bits | ||
313 | } | ||
314 | fix(); | ||
315 | } | ||
316 | |||
317 | return ownership; | ||
318 | } | ||
319 | |||
320 | |||
321 | // Note: If you attempt to set bits that the base bits doesn't allow, | ||
322 | // the function will succeed, but those bits will not be set. | ||
323 | BOOL LLPermissions::setOwnerBits(const LLUUID& agent, BOOL set, PermissionMask bits) | ||
324 | { | ||
325 | BOOL ownership = FALSE; | ||
326 | |||
327 | if(agent.isNull()) | ||
328 | { | ||
329 | // ...system always allowed to change things | ||
330 | ownership = TRUE; | ||
331 | } | ||
332 | else if (agent == mOwner) | ||
333 | { | ||
334 | // ...owner bits can only be set by owner | ||
335 | ownership = TRUE; | ||
336 | } | ||
337 | |||
338 | // If we have correct ownership and | ||
339 | if (ownership) | ||
340 | { | ||
341 | if (set) | ||
342 | { | ||
343 | mMaskOwner |= bits; // turn on bits | ||
344 | } | ||
345 | else | ||
346 | { | ||
347 | mMaskOwner &= ~bits; // turn off bits | ||
348 | } | ||
349 | fix(); | ||
350 | } | ||
351 | |||
352 | return (ownership); | ||
353 | } | ||
354 | |||
355 | BOOL LLPermissions::setGroupBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits) | ||
356 | { | ||
357 | BOOL ownership = FALSE; | ||
358 | if((agent.isNull()) || (agent == mOwner) | ||
359 | || ((group == mGroup) && (!mGroup.isNull()))) | ||
360 | { | ||
361 | // The group bits can be set by the system, the owner, or a | ||
362 | // group member. | ||
363 | ownership = TRUE; | ||
364 | } | ||
365 | |||
366 | if (ownership) | ||
367 | { | ||
368 | if (set) | ||
369 | { | ||
370 | mMaskGroup |= bits; | ||
371 | } | ||
372 | else | ||
373 | { | ||
374 | mMaskGroup &= ~bits; | ||
375 | } | ||
376 | fix(); | ||
377 | } | ||
378 | return ownership; | ||
379 | } | ||
380 | |||
381 | |||
382 | // Note: If you attempt to set bits that the creator or owner doesn't allow, | ||
383 | // the function will succeed, but those bits will not be set. | ||
384 | BOOL LLPermissions::setEveryoneBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits) | ||
385 | { | ||
386 | BOOL ownership = FALSE; | ||
387 | if((agent.isNull()) || (agent == mOwner) | ||
388 | || ((group == mGroup) && (!mGroup.isNull()))) | ||
389 | { | ||
390 | // The everyone bits can be set by the system, the owner, or a | ||
391 | // group member. | ||
392 | ownership = TRUE; | ||
393 | } | ||
394 | if (ownership) | ||
395 | { | ||
396 | if (set) | ||
397 | { | ||
398 | mMaskEveryone |= bits; | ||
399 | } | ||
400 | else | ||
401 | { | ||
402 | mMaskEveryone &= ~bits; | ||
403 | } | ||
404 | |||
405 | // Fix hierarchy of permissions | ||
406 | fix(); | ||
407 | } | ||
408 | return ownership; | ||
409 | } | ||
410 | |||
411 | // Note: If you attempt to set bits that the creator or owner doesn't allow, | ||
412 | // the function will succeed, but those bits will not be set. | ||
413 | BOOL LLPermissions::setNextOwnerBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits) | ||
414 | { | ||
415 | BOOL ownership = FALSE; | ||
416 | if((agent.isNull()) || (agent == mOwner) | ||
417 | || ((group == mGroup) && (!mGroup.isNull()))) | ||
418 | { | ||
419 | // The next owner bits can be set by the system, the owner, or | ||
420 | // a group member. | ||
421 | ownership = TRUE; | ||
422 | } | ||
423 | if (ownership) | ||
424 | { | ||
425 | if (set) | ||
426 | { | ||
427 | mMaskNextOwner |= bits; | ||
428 | } | ||
429 | else | ||
430 | { | ||
431 | mMaskNextOwner &= ~bits; | ||
432 | } | ||
433 | |||
434 | // Fix-up permissions | ||
435 | if(!(mMaskNextOwner & PERM_COPY)) | ||
436 | { | ||
437 | mMaskNextOwner |= PERM_TRANSFER; | ||
438 | } | ||
439 | fix(); | ||
440 | } | ||
441 | return ownership; | ||
442 | } | ||
443 | |||
444 | BOOL LLPermissions::allowOperationBy(PermissionBit op, const LLUUID& requester, const LLUUID& group) const | ||
445 | { | ||
446 | if(requester.isNull()) | ||
447 | { | ||
448 | // ...system making request | ||
449 | // ...not owned | ||
450 | return TRUE; | ||
451 | } | ||
452 | else if (mIsGroupOwned && (mGroup == requester)) | ||
453 | { | ||
454 | // group checking ownership permissions | ||
455 | return (mMaskOwner & op); | ||
456 | } | ||
457 | else if (!mIsGroupOwned && (mOwner == requester)) | ||
458 | { | ||
459 | // ...owner making request | ||
460 | return (mMaskOwner & op); | ||
461 | } | ||
462 | else if(mGroup.notNull() && (mGroup == group)) | ||
463 | { | ||
464 | // group member making request | ||
465 | return ((mMaskGroup & op) || (mMaskEveryone & op)); | ||
466 | } | ||
467 | return (mMaskEveryone & op); | ||
468 | } | ||
469 | |||
470 | // | ||
471 | // Messaging support | ||
472 | // | ||
473 | void LLPermissions::packMessage(LLMessageSystem* msg) const | ||
474 | { | ||
475 | msg->addUUIDFast(_PREHASH_CreatorID, mCreator); | ||
476 | msg->addUUIDFast(_PREHASH_OwnerID, mOwner); | ||
477 | msg->addUUIDFast(_PREHASH_GroupID, mGroup); | ||
478 | |||
479 | msg->addU32Fast(_PREHASH_BaseMask, mMaskBase ); | ||
480 | msg->addU32Fast(_PREHASH_OwnerMask, mMaskOwner ); | ||
481 | msg->addU32Fast(_PREHASH_GroupMask, mMaskGroup ); | ||
482 | msg->addU32Fast(_PREHASH_EveryoneMask, mMaskEveryone ); | ||
483 | msg->addU32Fast(_PREHASH_NextOwnerMask, mMaskNextOwner ); | ||
484 | msg->addBOOLFast(_PREHASH_GroupOwned, (BOOL)mIsGroupOwned); | ||
485 | } | ||
486 | |||
487 | |||
488 | void LLPermissions::unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num) | ||
489 | { | ||
490 | msg->getUUIDFast(block, _PREHASH_CreatorID, mCreator, block_num); | ||
491 | msg->getUUIDFast(block, _PREHASH_OwnerID, mOwner, block_num); | ||
492 | msg->getUUIDFast(block, _PREHASH_GroupID, mGroup, block_num); | ||
493 | |||
494 | msg->getU32Fast(block, _PREHASH_BaseMask, mMaskBase, block_num ); | ||
495 | msg->getU32Fast(block, _PREHASH_OwnerMask, mMaskOwner, block_num ); | ||
496 | msg->getU32Fast(block, _PREHASH_GroupMask, mMaskGroup, block_num ); | ||
497 | msg->getU32Fast(block, _PREHASH_EveryoneMask, mMaskEveryone, block_num ); | ||
498 | msg->getU32Fast(block, _PREHASH_NextOwnerMask, mMaskNextOwner, block_num ); | ||
499 | BOOL tmp; | ||
500 | msg->getBOOLFast(block, _PREHASH_GroupOwned, tmp, block_num); | ||
501 | mIsGroupOwned = (bool)tmp; | ||
502 | } | ||
503 | |||
504 | |||
505 | // | ||
506 | // File support | ||
507 | // | ||
508 | |||
509 | BOOL LLPermissions::importFile(FILE *fp) | ||
510 | { | ||
511 | init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); | ||
512 | const S32 BUFSIZE = 16384; | ||
513 | |||
514 | char buffer[BUFSIZE]; | ||
515 | char keyword[256]; | ||
516 | char valuestr[256]; | ||
517 | char uuid_str[256]; | ||
518 | U32 mask; | ||
519 | |||
520 | keyword[0] = '\0'; | ||
521 | valuestr[0] = '\0'; | ||
522 | |||
523 | while (!feof(fp)) | ||
524 | { | ||
525 | fgets(buffer, BUFSIZE, fp); | ||
526 | sscanf(buffer, " %s %s", keyword, valuestr); | ||
527 | if (!keyword) | ||
528 | { | ||
529 | continue; | ||
530 | } | ||
531 | if (!strcmp("{", keyword)) | ||
532 | { | ||
533 | continue; | ||
534 | } | ||
535 | if (!strcmp("}",keyword)) | ||
536 | { | ||
537 | break; | ||
538 | } | ||
539 | else if (!strcmp("creator_mask", keyword)) | ||
540 | { | ||
541 | // legacy support for "creator" masks | ||
542 | sscanf(valuestr, "%x", &mask); | ||
543 | mMaskBase = mask; | ||
544 | fixFairUse(); | ||
545 | } | ||
546 | else if (!strcmp("base_mask", keyword)) | ||
547 | { | ||
548 | sscanf(valuestr, "%x", &mask); | ||
549 | mMaskBase = mask; | ||
550 | //fixFairUse(); | ||
551 | } | ||
552 | else if (!strcmp("owner_mask", keyword)) | ||
553 | { | ||
554 | sscanf(valuestr, "%x", &mask); | ||
555 | mMaskOwner = mask; | ||
556 | } | ||
557 | else if (!strcmp("group_mask", keyword)) | ||
558 | { | ||
559 | sscanf(valuestr, "%x", &mask); | ||
560 | mMaskGroup = mask; | ||
561 | } | ||
562 | else if (!strcmp("everyone_mask", keyword)) | ||
563 | { | ||
564 | sscanf(valuestr, "%x", &mask); | ||
565 | mMaskEveryone = mask; | ||
566 | } | ||
567 | else if (!strcmp("next_owner_mask", keyword)) | ||
568 | { | ||
569 | sscanf(valuestr, "%x", &mask); | ||
570 | mMaskNextOwner = mask; | ||
571 | } | ||
572 | else if (!strcmp("creator_id", keyword)) | ||
573 | { | ||
574 | sscanf(valuestr, "%s", uuid_str); | ||
575 | mCreator.set(uuid_str); | ||
576 | } | ||
577 | else if (!strcmp("owner_id", keyword)) | ||
578 | { | ||
579 | sscanf(valuestr, "%s", uuid_str); | ||
580 | mOwner.set(uuid_str); | ||
581 | } | ||
582 | else if (!strcmp("last_owner_id", keyword)) | ||
583 | { | ||
584 | sscanf(valuestr, "%s", uuid_str); | ||
585 | mLastOwner.set(uuid_str); | ||
586 | } | ||
587 | else if (!strcmp("group_id", keyword)) | ||
588 | { | ||
589 | sscanf(valuestr, "%s", uuid_str); | ||
590 | mGroup.set(uuid_str); | ||
591 | } | ||
592 | else if (!strcmp("group_owned", keyword)) | ||
593 | { | ||
594 | sscanf(valuestr, "%d", &mask); | ||
595 | if(mask) mIsGroupOwned = true; | ||
596 | else mIsGroupOwned = false; | ||
597 | } | ||
598 | else | ||
599 | { | ||
600 | llinfos << "unknown keyword " << keyword << " in permissions import" << llendl; | ||
601 | } | ||
602 | } | ||
603 | fix(); | ||
604 | return TRUE; | ||
605 | } | ||
606 | |||
607 | |||
608 | BOOL LLPermissions::exportFile(FILE *fp) const | ||
609 | { | ||
610 | char uuid_str[256]; | ||
611 | |||
612 | fprintf(fp, "\tpermissions 0\n"); | ||
613 | fprintf(fp, "\t{\n"); | ||
614 | |||
615 | fprintf(fp, "\t\tbase_mask\t%08x\n", mMaskBase); | ||
616 | fprintf(fp, "\t\towner_mask\t%08x\n", mMaskOwner); | ||
617 | fprintf(fp, "\t\tgroup_mask\t%08x\n", mMaskGroup); | ||
618 | fprintf(fp, "\t\teveryone_mask\t%08x\n", mMaskEveryone); | ||
619 | fprintf(fp, "\t\tnext_owner_mask\t%08x\n", mMaskNextOwner); | ||
620 | |||
621 | mCreator.toString(uuid_str); | ||
622 | fprintf(fp, "\t\tcreator_id\t%s\n", uuid_str); | ||
623 | |||
624 | mOwner.toString(uuid_str); | ||
625 | fprintf(fp, "\t\towner_id\t%s\n", uuid_str); | ||
626 | |||
627 | mLastOwner.toString(uuid_str); | ||
628 | fprintf(fp, "\t\tlast_owner_id\t%s\n", uuid_str); | ||
629 | |||
630 | mGroup.toString(uuid_str); | ||
631 | fprintf(fp, "\t\tgroup_id\t%s\n", uuid_str); | ||
632 | |||
633 | if(mIsGroupOwned) | ||
634 | { | ||
635 | fprintf(fp, "\t\tgroup_owned\t1\n"); | ||
636 | } | ||
637 | fprintf(fp,"\t}\n"); | ||
638 | return TRUE; | ||
639 | } | ||
640 | |||
641 | |||
642 | BOOL LLPermissions::importLegacyStream(std::istream& input_stream) | ||
643 | { | ||
644 | init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null); | ||
645 | const S32 BUFSIZE = 16384; | ||
646 | |||
647 | char buffer[BUFSIZE]; | ||
648 | char keyword[256]; | ||
649 | char valuestr[256]; | ||
650 | char uuid_str[256]; | ||
651 | U32 mask; | ||
652 | |||
653 | keyword[0] = '\0'; | ||
654 | valuestr[0] = '\0'; | ||
655 | |||
656 | while (input_stream.good()) | ||
657 | { | ||
658 | input_stream.getline(buffer, BUFSIZE); | ||
659 | sscanf(buffer, " %s %s", keyword, valuestr); | ||
660 | if (!keyword) | ||
661 | { | ||
662 | continue; | ||
663 | } | ||
664 | if (!strcmp("{", keyword)) | ||
665 | { | ||
666 | continue; | ||
667 | } | ||
668 | if (!strcmp("}",keyword)) | ||
669 | { | ||
670 | break; | ||
671 | } | ||
672 | else if (!strcmp("creator_mask", keyword)) | ||
673 | { | ||
674 | // legacy support for "creator" masks | ||
675 | sscanf(valuestr, "%x", &mask); | ||
676 | mMaskBase = mask; | ||
677 | fixFairUse(); | ||
678 | } | ||
679 | else if (!strcmp("base_mask", keyword)) | ||
680 | { | ||
681 | sscanf(valuestr, "%x", &mask); | ||
682 | mMaskBase = mask; | ||
683 | //fixFairUse(); | ||
684 | } | ||
685 | else if (!strcmp("owner_mask", keyword)) | ||
686 | { | ||
687 | sscanf(valuestr, "%x", &mask); | ||
688 | mMaskOwner = mask; | ||
689 | } | ||
690 | else if (!strcmp("group_mask", keyword)) | ||
691 | { | ||
692 | sscanf(valuestr, "%x", &mask); | ||
693 | mMaskGroup = mask; | ||
694 | } | ||
695 | else if (!strcmp("everyone_mask", keyword)) | ||
696 | { | ||
697 | sscanf(valuestr, "%x", &mask); | ||
698 | mMaskEveryone = mask; | ||
699 | } | ||
700 | else if (!strcmp("next_owner_mask", keyword)) | ||
701 | { | ||
702 | sscanf(valuestr, "%x", &mask); | ||
703 | mMaskNextOwner = mask; | ||
704 | } | ||
705 | else if (!strcmp("creator_id", keyword)) | ||
706 | { | ||
707 | sscanf(valuestr, "%s", uuid_str); | ||
708 | mCreator.set(uuid_str); | ||
709 | } | ||
710 | else if (!strcmp("owner_id", keyword)) | ||
711 | { | ||
712 | sscanf(valuestr, "%s", uuid_str); | ||
713 | mOwner.set(uuid_str); | ||
714 | } | ||
715 | else if (!strcmp("last_owner_id", keyword)) | ||
716 | { | ||
717 | sscanf(valuestr, "%s", uuid_str); | ||
718 | mLastOwner.set(uuid_str); | ||
719 | } | ||
720 | else if (!strcmp("group_id", keyword)) | ||
721 | { | ||
722 | sscanf(valuestr, "%s", uuid_str); | ||
723 | mGroup.set(uuid_str); | ||
724 | } | ||
725 | else if (!strcmp("group_owned", keyword)) | ||
726 | { | ||
727 | sscanf(valuestr, "%d", &mask); | ||
728 | if(mask) mIsGroupOwned = true; | ||
729 | else mIsGroupOwned = false; | ||
730 | } | ||
731 | else | ||
732 | { | ||
733 | llinfos << "unknown keyword " << keyword << " in permissions import" << llendl; | ||
734 | } | ||
735 | } | ||
736 | fix(); | ||
737 | return TRUE; | ||
738 | } | ||
739 | |||
740 | |||
741 | BOOL LLPermissions::exportLegacyStream(std::ostream& output_stream) const | ||
742 | { | ||
743 | char uuid_str[256]; | ||
744 | |||
745 | output_stream << "\tpermissions 0\n"; | ||
746 | output_stream << "\t{\n"; | ||
747 | |||
748 | char buffer[256]; | ||
749 | sprintf(buffer, "\t\tbase_mask\t%08x\n", mMaskBase); | ||
750 | output_stream << buffer; | ||
751 | sprintf(buffer, "\t\towner_mask\t%08x\n", mMaskOwner); | ||
752 | output_stream << buffer; | ||
753 | sprintf(buffer, "\t\tgroup_mask\t%08x\n", mMaskGroup); | ||
754 | output_stream << buffer; | ||
755 | sprintf(buffer, "\t\teveryone_mask\t%08x\n", mMaskEveryone); | ||
756 | output_stream << buffer; | ||
757 | sprintf(buffer, "\t\tnext_owner_mask\t%08x\n", mMaskNextOwner); | ||
758 | output_stream << buffer; | ||
759 | |||
760 | mCreator.toString(uuid_str); | ||
761 | output_stream << "\t\tcreator_id\t" << uuid_str << "\n"; | ||
762 | |||
763 | mOwner.toString(uuid_str); | ||
764 | output_stream << "\t\towner_id\t" << uuid_str << "\n"; | ||
765 | |||
766 | mLastOwner.toString(uuid_str); | ||
767 | output_stream << "\t\tlast_owner_id\t" << uuid_str << "\n"; | ||
768 | |||
769 | mGroup.toString(uuid_str); | ||
770 | output_stream << "\t\tgroup_id\t" << uuid_str << "\n"; | ||
771 | |||
772 | if(mIsGroupOwned) | ||
773 | { | ||
774 | output_stream << "\t\tgroup_owned\t1\n"; | ||
775 | } | ||
776 | output_stream << "\t}\n"; | ||
777 | return TRUE; | ||
778 | } | ||
779 | |||
780 | |||
781 | LLXMLNode *LLPermissions::exportFileXML() const | ||
782 | { | ||
783 | LLXMLNode *ret = new LLXMLNode("permissions", FALSE); | ||
784 | |||
785 | ret->createChild("group_owned", TRUE)->setBoolValue(1, (const BOOL*)&mIsGroupOwned); | ||
786 | |||
787 | ret->createChild("base_mask", FALSE)->setByteValue(4, (U8*)&mMaskBase, LLXMLNode::ENCODING_HEX); | ||
788 | ret->createChild("owner_mask", FALSE)->setByteValue(4, (U8*)&mMaskOwner, LLXMLNode::ENCODING_HEX); | ||
789 | ret->createChild("group_mask", FALSE)->setByteValue(4, (U8*)&mMaskGroup, LLXMLNode::ENCODING_HEX); | ||
790 | ret->createChild("everyone_mask", FALSE)->setByteValue(4, (U8*)&mMaskEveryone, LLXMLNode::ENCODING_HEX); | ||
791 | ret->createChild("next_owner_mask", FALSE)->setByteValue(4, (U8*)&mMaskNextOwner, LLXMLNode::ENCODING_HEX); | ||
792 | |||
793 | ret->createChild("creator_id", FALSE)->setUUIDValue(1, &mCreator); | ||
794 | ret->createChild("owner_id", FALSE)->setUUIDValue(1, &mOwner); | ||
795 | ret->createChild("last_owner_id", FALSE)->setUUIDValue(1, &mLastOwner); | ||
796 | ret->createChild("group_id", FALSE)->setUUIDValue(1, &mGroup); | ||
797 | |||
798 | return ret; | ||
799 | } | ||
800 | |||
801 | bool LLPermissions::importXML(LLXMLNode* node) | ||
802 | { | ||
803 | bool success = false; | ||
804 | if (node) | ||
805 | { | ||
806 | success = true; | ||
807 | LLXMLNodePtr sub_node; | ||
808 | if (node->getChild("base_mask", sub_node)) | ||
809 | success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskBase)); | ||
810 | if (node->getChild("owner_mask", sub_node)) | ||
811 | success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskOwner)); | ||
812 | if (node->getChild("group_mask", sub_node)) | ||
813 | success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskGroup)); | ||
814 | if (node->getChild("everyone_mask", sub_node)) | ||
815 | success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskEveryone)); | ||
816 | if (node->getChild("next_owner_mask", sub_node)) | ||
817 | success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskNextOwner)); | ||
818 | |||
819 | if (node->getChild("creator_id", sub_node)) | ||
820 | success = success && (1 == sub_node->getUUIDValue(1, &mCreator)); | ||
821 | if (node->getChild("owner_id", sub_node)) | ||
822 | success = success && (1 == sub_node->getUUIDValue(1, &mOwner)); | ||
823 | if (node->getChild("last_owner_id", sub_node)) | ||
824 | success = success && (1 == sub_node->getUUIDValue(1, &mLastOwner)); | ||
825 | if (node->getChild("group_id", sub_node)) | ||
826 | success = success && (1 == sub_node->getUUIDValue(1, &mGroup)); | ||
827 | if (node->getChild("group_owned", sub_node)) | ||
828 | success = success && (1 == sub_node->getBoolValue(1, (BOOL*)&mIsGroupOwned)); | ||
829 | if (!success) | ||
830 | { | ||
831 | lldebugs << "LLPermissions::importXML() failed for node named '" | ||
832 | << node->getName() << "'" << llendl; | ||
833 | } | ||
834 | } | ||
835 | return success; | ||
836 | } | ||
837 | |||
838 | bool LLPermissions::operator==(const LLPermissions &rhs) const | ||
839 | { | ||
840 | return | ||
841 | (mCreator == rhs.mCreator) && | ||
842 | (mOwner == rhs.mOwner) && | ||
843 | (mLastOwner == rhs.mLastOwner ) && | ||
844 | (mGroup == rhs.mGroup ) && | ||
845 | (mMaskBase == rhs.mMaskBase ) && | ||
846 | (mMaskOwner == rhs.mMaskOwner ) && | ||
847 | (mMaskGroup == rhs.mMaskGroup ) && | ||
848 | (mMaskEveryone == rhs.mMaskEveryone ) && | ||
849 | (mMaskNextOwner == rhs.mMaskNextOwner ) && | ||
850 | (mIsGroupOwned == rhs.mIsGroupOwned); | ||
851 | } | ||
852 | |||
853 | |||
854 | bool LLPermissions::operator!=(const LLPermissions &rhs) const | ||
855 | { | ||
856 | return | ||
857 | (mCreator != rhs.mCreator) || | ||
858 | (mOwner != rhs.mOwner) || | ||
859 | (mLastOwner != rhs.mLastOwner ) || | ||
860 | (mGroup != rhs.mGroup ) || | ||
861 | (mMaskBase != rhs.mMaskBase ) || | ||
862 | (mMaskOwner != rhs.mMaskOwner ) || | ||
863 | (mMaskGroup != rhs.mMaskGroup ) || | ||
864 | (mMaskEveryone != rhs.mMaskEveryone ) || | ||
865 | (mMaskNextOwner != rhs.mMaskNextOwner) || | ||
866 | (mIsGroupOwned != rhs.mIsGroupOwned); | ||
867 | } | ||
868 | |||
869 | std::ostream& operator<<(std::ostream &s, const LLPermissions &perm) | ||
870 | { | ||
871 | s << "{Creator=" << perm.getCreator(); | ||
872 | s << ", Owner=" << perm.getOwner(); | ||
873 | s << ", Group=" << perm.getGroup(); | ||
874 | s << std::hex << ", BaseMask=0x" << perm.getMaskBase(); | ||
875 | s << ", OwnerMask=0x" << perm.getMaskOwner(); | ||
876 | s << ", EveryoneMask=0x" << perm.getMaskEveryone(); | ||
877 | s << ", GroupMask=0x" << perm.getMaskGroup(); | ||
878 | s << ", NextOwnerMask=0x" << perm.getMaskNextOwner() << std::dec; | ||
879 | s << "}"; | ||
880 | return s; | ||
881 | } | ||
882 | |||
883 | template <> | ||
884 | void LLMetaClassT<LLPermissions>::reflectProperties(LLMetaClass& meta_class) | ||
885 | { | ||
886 | reflectProperty(meta_class, "mCreator", &LLPermissions::mCreator); | ||
887 | reflectProperty(meta_class, "mOwner", &LLPermissions::mOwner); | ||
888 | } | ||
889 | |||
890 | // virtual | ||
891 | const LLMetaClass& LLPermissions::getMetaClass() const | ||
892 | { | ||
893 | return LLMetaClassT<LLPermissions>::instance(); | ||
894 | } | ||
895 | |||
896 | ///---------------------------------------------------------------------------- | ||
897 | /// Class LLAggregatePermissions | ||
898 | ///---------------------------------------------------------------------------- | ||
899 | |||
900 | const LLAggregatePermissions LLAggregatePermissions::empty; | ||
901 | |||
902 | |||
903 | LLAggregatePermissions::LLAggregatePermissions() | ||
904 | { | ||
905 | for(S32 i = 0; i < PI_COUNT; ++i) | ||
906 | { | ||
907 | mBits[i] = AP_EMPTY; | ||
908 | } | ||
909 | } | ||
910 | |||
911 | LLAggregatePermissions::EValue LLAggregatePermissions::getValue(PermissionBit bit) const | ||
912 | { | ||
913 | EPermIndex idx = perm2PermIndex(bit); | ||
914 | EValue rv = AP_EMPTY; | ||
915 | if(idx != PI_END) | ||
916 | { | ||
917 | rv = (LLAggregatePermissions::EValue)(mBits[idx]); | ||
918 | } | ||
919 | return rv; | ||
920 | } | ||
921 | |||
922 | // returns the bits compressed into a single byte: 00TTMMCC | ||
923 | // where TT = transfer, MM = modify, and CC = copy | ||
924 | // LSB is to the right | ||
925 | U8 LLAggregatePermissions::getU8() const | ||
926 | { | ||
927 | U8 byte = mBits[PI_TRANSFER]; | ||
928 | byte <<= 2; | ||
929 | byte |= mBits[PI_MODIFY]; | ||
930 | byte <<= 2; | ||
931 | byte |= mBits[PI_COPY]; | ||
932 | return byte; | ||
933 | } | ||
934 | |||
935 | BOOL LLAggregatePermissions::isEmpty() const | ||
936 | { | ||
937 | for(S32 i = 0; i < PI_END; ++i) | ||
938 | { | ||
939 | if(mBits[i] != AP_EMPTY) | ||
940 | { | ||
941 | return FALSE; | ||
942 | } | ||
943 | } | ||
944 | return TRUE; | ||
945 | } | ||
946 | |||
947 | void LLAggregatePermissions::aggregate(PermissionMask mask) | ||
948 | { | ||
949 | BOOL is_allowed = mask & PERM_COPY; | ||
950 | aggregateBit(PI_COPY, is_allowed); | ||
951 | is_allowed = mask & PERM_MODIFY; | ||
952 | aggregateBit(PI_MODIFY, is_allowed); | ||
953 | is_allowed = mask & PERM_TRANSFER; | ||
954 | aggregateBit(PI_TRANSFER, is_allowed); | ||
955 | } | ||
956 | |||
957 | void LLAggregatePermissions::aggregate(const LLAggregatePermissions& ag) | ||
958 | { | ||
959 | for(S32 idx = PI_COPY; idx != PI_END; ++idx) | ||
960 | { | ||
961 | aggregateIndex((EPermIndex)idx, ag.mBits[idx]); | ||
962 | } | ||
963 | } | ||
964 | |||
965 | void LLAggregatePermissions::aggregateBit(EPermIndex idx, BOOL allowed) | ||
966 | { | ||
967 | //if(AP_SOME == mBits[idx]) return; // P4 branch prediction optimization | ||
968 | switch(mBits[idx]) | ||
969 | { | ||
970 | case AP_EMPTY: | ||
971 | mBits[idx] = allowed ? AP_ALL : AP_NONE; | ||
972 | break; | ||
973 | case AP_NONE: | ||
974 | mBits[idx] = allowed ? AP_SOME: AP_NONE; | ||
975 | break; | ||
976 | case AP_SOME: | ||
977 | // no-op | ||
978 | break; | ||
979 | case AP_ALL: | ||
980 | mBits[idx] = allowed ? AP_ALL : AP_SOME; | ||
981 | break; | ||
982 | default: | ||
983 | llwarns << "Bad aggregateBit " << (S32)idx << " " | ||
984 | << (allowed ? "true" : "false") << llendl; | ||
985 | break; | ||
986 | } | ||
987 | } | ||
988 | |||
989 | void LLAggregatePermissions::aggregateIndex(EPermIndex idx, U8 bits) | ||
990 | { | ||
991 | switch(mBits[idx]) | ||
992 | { | ||
993 | case AP_EMPTY: | ||
994 | mBits[idx] = bits; | ||
995 | break; | ||
996 | case AP_NONE: | ||
997 | switch(bits) | ||
998 | { | ||
999 | case AP_SOME: | ||
1000 | case AP_ALL: | ||
1001 | mBits[idx] = AP_SOME; | ||
1002 | break; | ||
1003 | case AP_EMPTY: | ||
1004 | case AP_NONE: | ||
1005 | default: | ||
1006 | // no-op | ||
1007 | break; | ||
1008 | } | ||
1009 | break; | ||
1010 | case AP_SOME: | ||
1011 | // no-op | ||
1012 | break; | ||
1013 | case AP_ALL: | ||
1014 | switch(bits) | ||
1015 | { | ||
1016 | case AP_NONE: | ||
1017 | case AP_SOME: | ||
1018 | mBits[idx] = AP_SOME; | ||
1019 | break; | ||
1020 | case AP_EMPTY: | ||
1021 | case AP_ALL: | ||
1022 | default: | ||
1023 | // no-op | ||
1024 | break; | ||
1025 | } | ||
1026 | break; | ||
1027 | default: | ||
1028 | llwarns << "Bad aggregate index " << (S32)idx << " " | ||
1029 | << (S32)bits << llendl; | ||
1030 | break; | ||
1031 | } | ||
1032 | } | ||
1033 | |||
1034 | // static | ||
1035 | LLAggregatePermissions::EPermIndex LLAggregatePermissions::perm2PermIndex(PermissionBit bit) | ||
1036 | { | ||
1037 | EPermIndex idx = PI_END; // past any good value. | ||
1038 | switch(bit) | ||
1039 | { | ||
1040 | case PERM_COPY: | ||
1041 | idx = PI_COPY; | ||
1042 | break; | ||
1043 | case PERM_MODIFY: | ||
1044 | idx = PI_MODIFY; | ||
1045 | break; | ||
1046 | case PERM_TRANSFER: | ||
1047 | idx = PI_TRANSFER; | ||
1048 | break; | ||
1049 | default: | ||
1050 | break; | ||
1051 | } | ||
1052 | return idx; | ||
1053 | } | ||
1054 | |||
1055 | |||
1056 | void LLAggregatePermissions::packMessage(LLMessageSystem* msg, const char* field) const | ||
1057 | { | ||
1058 | msg->addU8Fast(field, getU8()); | ||
1059 | } | ||
1060 | |||
1061 | void LLAggregatePermissions::unpackMessage(LLMessageSystem* msg, const char* block, const char* field, S32 block_num) | ||
1062 | { | ||
1063 | const U8 TWO_BITS = 0x3; // binary 00000011 | ||
1064 | U8 bits = 0; | ||
1065 | msg->getU8Fast(block, field, bits, block_num); | ||
1066 | mBits[PI_COPY] = bits & TWO_BITS; | ||
1067 | bits >>= 2; | ||
1068 | mBits[PI_MODIFY] = bits & TWO_BITS; | ||
1069 | bits >>= 2; | ||
1070 | mBits[PI_TRANSFER] = bits & TWO_BITS; | ||
1071 | } | ||
1072 | |||
1073 | const LLString AGGREGATE_VALUES[4] = | ||
1074 | { | ||
1075 | LLString( "Empty" ), | ||
1076 | LLString( "None" ), | ||
1077 | LLString( "Some" ), | ||
1078 | LLString( "All" ) | ||
1079 | }; | ||
1080 | |||
1081 | std::ostream& operator<<(std::ostream &s, const LLAggregatePermissions &perm) | ||
1082 | { | ||
1083 | s << "{PI_COPY=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_COPY]]; | ||
1084 | s << ", PI_MODIFY=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_MODIFY]]; | ||
1085 | s << ", PI_TRANSFER=" << AGGREGATE_VALUES[perm.mBits[LLAggregatePermissions::PI_TRANSFER]]; | ||
1086 | s << "}"; | ||
1087 | return s; | ||
1088 | } | ||
1089 | |||
1090 | // This converts a permissions mask into a string for debugging use. | ||
1091 | void mask_to_string(U32 mask, char* str) | ||
1092 | { | ||
1093 | if (mask & PERM_MOVE) | ||
1094 | { | ||
1095 | *str = 'V'; | ||
1096 | } | ||
1097 | else | ||
1098 | { | ||
1099 | *str = ' '; | ||
1100 | } | ||
1101 | str++; | ||
1102 | |||
1103 | if (mask & PERM_MODIFY) | ||
1104 | { | ||
1105 | *str = 'M'; | ||
1106 | } | ||
1107 | else | ||
1108 | { | ||
1109 | *str = ' '; | ||
1110 | } | ||
1111 | str++; | ||
1112 | |||
1113 | if (mask & PERM_COPY) | ||
1114 | { | ||
1115 | *str = 'C'; | ||
1116 | } | ||
1117 | else | ||
1118 | { | ||
1119 | *str = ' '; | ||
1120 | } | ||
1121 | str++; | ||
1122 | |||
1123 | if (mask & PERM_TRANSFER) | ||
1124 | { | ||
1125 | *str = 'T'; | ||
1126 | } | ||
1127 | else | ||
1128 | { | ||
1129 | *str = ' '; | ||
1130 | } | ||
1131 | str++; | ||
1132 | *str = '\0'; | ||
1133 | } | ||
1134 | |||
1135 | |||
1136 | ///---------------------------------------------------------------------------- | ||
1137 | /// exported functions | ||
1138 | ///---------------------------------------------------------------------------- | ||
1139 | static const std::string PERM_CREATOR_ID_LABEL("creator_id"); | ||
1140 | static const std::string PERM_OWNER_ID_LABEL("owner_id"); | ||
1141 | static const std::string PERM_LAST_OWNER_ID_LABEL("last_owner_id"); | ||
1142 | static const std::string PERM_GROUP_ID_LABEL("group_id"); | ||
1143 | static const std::string PERM_IS_OWNER_GROUP_LABEL("is_owner_group"); | ||
1144 | static const std::string PERM_BASE_MASK_LABEL("base_mask"); | ||
1145 | static const std::string PERM_OWNER_MASK_LABEL("owner_mask"); | ||
1146 | static const std::string PERM_GROUP_MASK_LABEL("group_mask"); | ||
1147 | static const std::string PERM_EVERYONE_MASK_LABEL("everyone_mask"); | ||
1148 | static const std::string PERM_NEXT_OWNER_MASK_LABEL("next_owner_mask"); | ||
1149 | |||
1150 | LLSD ll_create_sd_from_permissions(const LLPermissions& perm) | ||
1151 | { | ||
1152 | LLSD rv; | ||
1153 | rv[PERM_CREATOR_ID_LABEL] = perm.getCreator(); | ||
1154 | rv[PERM_OWNER_ID_LABEL] = perm.getOwner(); | ||
1155 | rv[PERM_LAST_OWNER_ID_LABEL] = perm.getLastOwner(); | ||
1156 | rv[PERM_GROUP_ID_LABEL] = perm.getGroup(); | ||
1157 | rv[PERM_IS_OWNER_GROUP_LABEL] = perm.isGroupOwned(); | ||
1158 | rv[PERM_BASE_MASK_LABEL] = (S32)perm.getMaskBase(); | ||
1159 | rv[PERM_OWNER_MASK_LABEL] = (S32)perm.getMaskOwner(); | ||
1160 | rv[PERM_GROUP_MASK_LABEL] = (S32)perm.getMaskGroup(); | ||
1161 | rv[PERM_EVERYONE_MASK_LABEL] = (S32)perm.getMaskEveryone(); | ||
1162 | rv[PERM_NEXT_OWNER_MASK_LABEL] = (S32)perm.getMaskNextOwner(); | ||
1163 | return rv; | ||
1164 | } | ||
1165 | |||
1166 | LLPermissions ll_permissions_from_sd(const LLSD& sd_perm) | ||
1167 | { | ||
1168 | LLPermissions rv; | ||
1169 | rv.init( | ||
1170 | sd_perm[PERM_CREATOR_ID_LABEL].asUUID(), | ||
1171 | sd_perm[PERM_OWNER_ID_LABEL].asUUID(), | ||
1172 | sd_perm[PERM_LAST_OWNER_ID_LABEL].asUUID(), | ||
1173 | sd_perm[PERM_GROUP_ID_LABEL].asUUID()); | ||
1174 | |||
1175 | // We do a cast to U32 here since LLSD does not attempt to | ||
1176 | // represent unsigned ints. | ||
1177 | PermissionMask mask; | ||
1178 | mask = (U32)(sd_perm[PERM_BASE_MASK_LABEL].asInteger()); | ||
1179 | rv.setMaskBase(mask); | ||
1180 | mask = (U32)(sd_perm[PERM_OWNER_MASK_LABEL].asInteger()); | ||
1181 | rv.setMaskOwner(mask); | ||
1182 | mask = (U32)(sd_perm[PERM_EVERYONE_MASK_LABEL].asInteger()); | ||
1183 | rv.setMaskEveryone(mask); | ||
1184 | mask = (U32)(sd_perm[PERM_GROUP_MASK_LABEL].asInteger()); | ||
1185 | rv.setMaskGroup(mask); | ||
1186 | mask = (U32)(sd_perm[PERM_NEXT_OWNER_MASK_LABEL].asInteger()); | ||
1187 | rv.setMaskNext(mask); | ||
1188 | rv.fix(); | ||
1189 | return rv; | ||
1190 | } | ||
diff --git a/linden/indra/llinventory/llpermissions.h b/linden/indra/llinventory/llpermissions.h new file mode 100644 index 0000000..d8a6b0a --- /dev/null +++ b/linden/indra/llinventory/llpermissions.h | |||
@@ -0,0 +1,445 @@ | |||
1 | /** | ||
2 | * @file llpermissions.h | ||
3 | * @brief Permissions structures for objects. | ||
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 | #ifndef LL_LLPERMISSIONS_H | ||
29 | #define LL_LLPERMISSIONS_H | ||
30 | |||
31 | #include <stdio.h> | ||
32 | #include <iostream> | ||
33 | |||
34 | #include "llpermissionsflags.h" | ||
35 | #include "llsd.h" | ||
36 | #include "lluuid.h" | ||
37 | #include "llxmlnode.h" | ||
38 | #include "reflective.h" | ||
39 | |||
40 | // prototypes | ||
41 | class LLMessageSystem; | ||
42 | extern void mask_to_string(U32 mask, char* str); | ||
43 | template<class T> class LLMetaClassT; | ||
44 | |||
45 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
46 | // Class LLPermissions | ||
47 | // | ||
48 | // Class which encapsulates object and inventory permissions/ownership/etc. | ||
49 | // | ||
50 | // Permissions where originally a static state creator/owner and set | ||
51 | // of cap bits. Since then, it has grown to include group information, | ||
52 | // last owner, masks for different people. The implementation has been | ||
53 | // chosen such that a uuid is stored for each current/past owner, and | ||
54 | // a bitmask is stored for the base permissions, owner permissions, | ||
55 | // group permissions, and everyone else permissions. | ||
56 | // | ||
57 | // The base permissions represent the most permissive state that the | ||
58 | // permissions can possibly be in. Thus, if the base permissions do | ||
59 | // not allow copying, no one can ever copy the object. The permissions | ||
60 | // also maintain a tree-like hierarchy of permissions, thus, if we | ||
61 | // (for sake of discussions) denote more permissive as '>', then this | ||
62 | // is invariant: | ||
63 | // | ||
64 | // base mask >= owner mask >= group mask | ||
65 | // >= everyone mask | ||
66 | // >= next owner mask | ||
67 | // NOTE: the group mask does not effect everyone or next, everyone | ||
68 | // does not effect group or next, etc. | ||
69 | // | ||
70 | // It is considered a fair use right to move or delete any object you | ||
71 | // own. Another fair use right is the ability to give away anything | ||
72 | // which you cannot copy. One way to look at that is that if you have | ||
73 | // a unique item, you can always give that one copy you have to | ||
74 | // someone else. | ||
75 | // | ||
76 | // Most of the bitmask is easy to understand, PERM_COPY means you can | ||
77 | // copy !PERM_TRANSFER means you cannot transfer, etc. Given that we | ||
78 | // now track the concept of 'next owner' inside of the permissions | ||
79 | // object, we can describe some new meta-meaning to the PERM_MODIFY | ||
80 | // flag. PERM_MODIFY is usually meant to note if you can change an | ||
81 | // item, but since we record next owner permissions, we can interpret | ||
82 | // a no-modify object as 'you cannot modify this object and you cannot | ||
83 | // make derivative works.' When evaluating functionality, and | ||
84 | // comparisons against permissions, keep this concept in mind for | ||
85 | // logical consistency. | ||
86 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
87 | |||
88 | class LLPermissions : public LLReflective | ||
89 | { | ||
90 | private: | ||
91 | LLUUID mCreator; // null if object created by system | ||
92 | LLUUID mOwner; // null if object "unowned" (owned by system) | ||
93 | LLUUID mLastOwner; // object's last owner | ||
94 | LLUUID mGroup; // The group association | ||
95 | |||
96 | PermissionMask mMaskBase; // initially permissive, progressively AND restricted by each owner | ||
97 | |||
98 | PermissionMask mMaskOwner; // set by owner, applies to owner only, restricts lower permissions | ||
99 | PermissionMask mMaskEveryone; // set by owner, applies to everyone else | ||
100 | |||
101 | PermissionMask mMaskGroup; // set by owner, applies to group that is associated with permissions | ||
102 | |||
103 | PermissionMask mMaskNextOwner; // set by owner, applied to base on transfer. | ||
104 | |||
105 | // Usually set in the fixOwnership() method based on current uuid | ||
106 | // values. | ||
107 | bool mIsGroupOwned; | ||
108 | |||
109 | // Correct for fair use - you can never take away the right to | ||
110 | // move stuff you own, and you can never take away the right to | ||
111 | // transfer something you cannot otherwise copy. | ||
112 | void fixFairUse(); | ||
113 | |||
114 | // Fix internal consistency for group/agent ownership | ||
115 | void fixOwnership(); | ||
116 | |||
117 | public: | ||
118 | static const LLPermissions DEFAULT; | ||
119 | |||
120 | LLPermissions(); // defaults to created by system | ||
121 | //~LLPermissions(); | ||
122 | |||
123 | // base initialization code | ||
124 | void init(const LLUUID& creator, const LLUUID& owner, | ||
125 | const LLUUID& last_owner, const LLUUID& group); | ||
126 | void initMasks(PermissionMask base, PermissionMask owner, | ||
127 | PermissionMask everyone, PermissionMask group, | ||
128 | PermissionMask next); | ||
129 | |||
130 | // | ||
131 | // ACCESSORS | ||
132 | // | ||
133 | |||
134 | // return the agent_id of the agent that created the item | ||
135 | const LLUUID& getCreator() const { return mCreator; } | ||
136 | |||
137 | // return the agent_id of the owner. returns LLUUID::null if group | ||
138 | // owned or public (a really big group). | ||
139 | const LLUUID& getOwner() const { return mOwner; } | ||
140 | |||
141 | // return the group_id of the group associated with the | ||
142 | // object. group_id == owner_id if the object is group owned. | ||
143 | const LLUUID& getGroup() const { return mGroup; } | ||
144 | |||
145 | // return the agent_id of the last agent owner. Only returns | ||
146 | // LLUUID::null if there has never been a previous owner. | ||
147 | const LLUUID& getLastOwner() const { return mLastOwner; } | ||
148 | |||
149 | U32 getMaskBase() const { return mMaskBase; } | ||
150 | U32 getMaskOwner() const { return mMaskOwner; } | ||
151 | U32 getMaskGroup() const { return mMaskGroup; } | ||
152 | U32 getMaskEveryone() const { return mMaskEveryone; } | ||
153 | U32 getMaskNextOwner() const { return mMaskNextOwner; } | ||
154 | |||
155 | // return TRUE if the object has any owner | ||
156 | bool isOwned() const { return (mOwner.notNull() || mIsGroupOwned); } | ||
157 | |||
158 | // return TRUE if group_id is owner. | ||
159 | bool isGroupOwned() const { return mIsGroupOwned; } | ||
160 | |||
161 | // This API returns TRUE if the object is owned at all, and FALSE | ||
162 | // otherwise. If it is owned at all, owner id is filled with | ||
163 | // either the owner id or the group id, and the is_group_owned | ||
164 | // parameter is appropriately filled. The values of owner_id and | ||
165 | // is_group_owned are not changed if the object is not owned. | ||
166 | BOOL getOwnership(LLUUID& owner_id, BOOL& is_group_owned) const; | ||
167 | |||
168 | // Gets the 'safe' owner. This should never return LLUUID::null. | ||
169 | // If no group owned, return the agent owner id normally. | ||
170 | // If group owned, return the group id. | ||
171 | // If not owned, return a random uuid which should have no power. | ||
172 | LLUUID getSafeOwner() const; | ||
173 | |||
174 | // return a cheap crc | ||
175 | U32 getCRC32() const; | ||
176 | |||
177 | |||
178 | // | ||
179 | // MANIPULATORS | ||
180 | // | ||
181 | |||
182 | // Fix hierarchy of permissions, applies appropriate permissions | ||
183 | // at each level to ensure that base permissions are respected, | ||
184 | // and also ensures that if base cannot transfer, then group and | ||
185 | // other cannot copy. | ||
186 | void fix(); | ||
187 | |||
188 | // All of these methods just do exactly what they say. There is no | ||
189 | // permissions checking to see if the operation is allowed, and do | ||
190 | // not fix the permissions hierarchy. So please only use these | ||
191 | // methods when you are know what you're doing and coding on | ||
192 | // behalf of the system - ie, acting as god. | ||
193 | void set(const LLPermissions& permissions); | ||
194 | void setMaskBase(U32 mask) { mMaskBase = mask; } | ||
195 | void setMaskOwner(U32 mask) { mMaskOwner = mask; } | ||
196 | void setMaskEveryone(U32 mask) { mMaskEveryone = mask;} | ||
197 | void setMaskGroup(U32 mask) { mMaskGroup = mask;} | ||
198 | void setMaskNext(U32 mask) { mMaskNextOwner = mask; } | ||
199 | |||
200 | // Allow accumulation of permissions. Results in the tightest | ||
201 | // permissions possible. In the case of clashing UUIDs, it sets | ||
202 | // the ID to LLUUID::null. | ||
203 | void accumulate(const LLPermissions& perm); | ||
204 | |||
205 | // | ||
206 | // CHECKED MANIPULATORS | ||
207 | // | ||
208 | |||
209 | // These functions return true on success. They return false if | ||
210 | // the given agent isn't allowed to make the change. You can pass | ||
211 | // LLUUID::null as the agent id if the change is being made by the | ||
212 | // simulator itself, not on behalf of any agent - this will always | ||
213 | // succeed. Passing in group id of LLUUID:null means no group, and | ||
214 | // does not offer special permission to do anything. | ||
215 | |||
216 | // saves last owner, sets current owner, and sets the group. | ||
217 | // set is_atomic = true means that this permission represents | ||
218 | // an atomic permission and not a collection of permissions. | ||
219 | // Currently, the only way to have a collection is when an object | ||
220 | // has inventory and is then itself rolled up into an inventory | ||
221 | // item. | ||
222 | BOOL setOwnerAndGroup(const LLUUID& agent, const LLUUID& owner, const LLUUID& group, bool is_atomic); | ||
223 | |||
224 | // saves last owner, sets owner to uuid null, sets group | ||
225 | // owned. group_id must be the group of the object (that's who it | ||
226 | // is being deeded to) and the object must be group | ||
227 | // modify. Technically, the agent id and group id are not | ||
228 | // necessary, but I wanted this function to look like the other | ||
229 | // checked manipulators (since that is how it is used.) If the | ||
230 | // agent is the system or (group == mGroup and group modify and | ||
231 | // owner transfer) then this function will deed the permissions, | ||
232 | // set the next owner mask, and return TRUE. Otherwise, no change | ||
233 | // is effected, and the function returns FALSE. | ||
234 | BOOL deedToGroup(const LLUUID& agent, const LLUUID& group); | ||
235 | // Attempt to set or clear the given bitmask. Returns TRUE if you | ||
236 | // are allowed to modify the permissions. If you attempt to turn | ||
237 | // on bits not allowed by the base bits, the function will return | ||
238 | // TRUE, but those bits will not be set. | ||
239 | BOOL setBaseBits( const LLUUID& agent, BOOL set, PermissionMask bits); | ||
240 | BOOL setOwnerBits( const LLUUID& agent, BOOL set, PermissionMask bits); | ||
241 | BOOL setGroupBits( const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits); | ||
242 | BOOL setEveryoneBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits); | ||
243 | BOOL setNextOwnerBits(const LLUUID& agent, const LLUUID& group, BOOL set, PermissionMask bits); | ||
244 | |||
245 | // | ||
246 | // METHODS | ||
247 | // | ||
248 | |||
249 | // All the allow* functions return true if the given agent or | ||
250 | // group can perform the function. Prefer using this set of | ||
251 | // operations to check permissions on an object. These return | ||
252 | // true if the given agent or group can perform the function. | ||
253 | // They also return true if the object isn't owned, or the | ||
254 | // requesting agent is a system agent. See llpermissionsflags.h | ||
255 | // for bits. | ||
256 | BOOL allowOperationBy(PermissionBit op, const LLUUID& agent, const LLUUID& group = LLUUID::null) const; | ||
257 | |||
258 | inline BOOL allowModifyBy(const LLUUID &agent_id) const; | ||
259 | inline BOOL allowCopyBy(const LLUUID& agent_id) const; | ||
260 | inline BOOL allowMoveBy(const LLUUID& agent_id) const; | ||
261 | inline BOOL allowModifyBy(const LLUUID &agent_id, const LLUUID& group) const; | ||
262 | inline BOOL allowCopyBy(const LLUUID& agent_id, const LLUUID& group) const; | ||
263 | inline BOOL allowMoveBy(const LLUUID &agent_id, const LLUUID &group) const; | ||
264 | |||
265 | // This somewhat specialized function is meant for testing if the | ||
266 | // current owner is allowed to transfer to the specified agent id. | ||
267 | inline BOOL allowTransferTo(const LLUUID &agent_id) const; | ||
268 | |||
269 | // | ||
270 | // DEPRECATED. | ||
271 | // | ||
272 | // These return true if the given agent can perform the function. | ||
273 | // They also return true if the object isn't owned, or the | ||
274 | // requesting agent is a system agent. See llpermissionsflags.h | ||
275 | // for bits. | ||
276 | //BOOL allowDeleteBy(const LLUUID& agent_id) const { return allowModifyBy(agent_id); } | ||
277 | //BOOL allowEditBy(const LLUUID& agent_id) const { return allowModifyBy(agent_id); } | ||
278 | // saves last owner and sets current owner | ||
279 | //BOOL setOwner(const LLUUID& agent, const LLUUID& owner); | ||
280 | // This method saves the last owner, sets the current owner to the | ||
281 | // one provided, and sets the base mask as indicated. | ||
282 | //BOOL setOwner(const LLUUID& agent, const LLUUID& owner, U32 new_base_mask); | ||
283 | |||
284 | // Attempt to set or clear the given bitmask. Returns TRUE if you | ||
285 | // are allowed to modify the permissions. If you attempt to turn | ||
286 | // on bits not allowed by the base bits, the function will return | ||
287 | // TRUE, but those bits will not be set. | ||
288 | //BOOL setGroupBits( const LLUUID& agent, BOOL set, PermissionMask bits); | ||
289 | //BOOL setEveryoneBits(const LLUUID& agent, BOOL set, PermissionMask bits); | ||
290 | |||
291 | // | ||
292 | // MISC METHODS and OPERATORS | ||
293 | // | ||
294 | |||
295 | // For messaging system support | ||
296 | void packMessage(LLMessageSystem* msg) const; | ||
297 | void unpackMessage(LLMessageSystem* msg, const char* block, S32 block_num = 0); | ||
298 | |||
299 | // Load/save support | ||
300 | BOOL importFile(FILE* fp); | ||
301 | BOOL exportFile(FILE* fp) const; | ||
302 | |||
303 | BOOL importLegacyStream(std::istream& input_stream); | ||
304 | BOOL exportLegacyStream(std::ostream& output_stream) const; | ||
305 | |||
306 | LLXMLNode *exportFileXML() const; | ||
307 | bool importXML(LLXMLNode* node); | ||
308 | |||
309 | bool operator==(const LLPermissions &rhs) const; | ||
310 | bool operator!=(const LLPermissions &rhs) const; | ||
311 | |||
312 | friend std::ostream& operator<<(std::ostream &s, const LLPermissions &perm); | ||
313 | |||
314 | // Reflection. | ||
315 | friend class LLMetaClassT<LLPermissions>; | ||
316 | virtual const LLMetaClass& getMetaClass() const; | ||
317 | }; | ||
318 | |||
319 | // Inlines | ||
320 | BOOL LLPermissions::allowModifyBy(const LLUUID& agent, const LLUUID& group) const | ||
321 | { | ||
322 | return allowOperationBy(PERM_MODIFY, agent, group); | ||
323 | } | ||
324 | |||
325 | BOOL LLPermissions::allowCopyBy(const LLUUID& agent, const LLUUID& group) const | ||
326 | { | ||
327 | return allowOperationBy(PERM_COPY, agent, group); | ||
328 | } | ||
329 | |||
330 | |||
331 | BOOL LLPermissions::allowMoveBy(const LLUUID& agent, const LLUUID& group) const | ||
332 | { | ||
333 | return allowOperationBy(PERM_MOVE, agent, group); | ||
334 | } | ||
335 | |||
336 | BOOL LLPermissions::allowModifyBy(const LLUUID& agent) const | ||
337 | { | ||
338 | return allowOperationBy(PERM_MODIFY, agent, LLUUID::null); | ||
339 | } | ||
340 | |||
341 | BOOL LLPermissions::allowCopyBy(const LLUUID& agent) const | ||
342 | { | ||
343 | return allowOperationBy(PERM_COPY, agent, LLUUID::null); | ||
344 | } | ||
345 | |||
346 | BOOL LLPermissions::allowMoveBy(const LLUUID& agent) const | ||
347 | { | ||
348 | return allowOperationBy(PERM_MOVE, agent, LLUUID::null); | ||
349 | } | ||
350 | |||
351 | BOOL LLPermissions::allowTransferTo(const LLUUID &agent_id) const | ||
352 | { | ||
353 | if (mIsGroupOwned) | ||
354 | { | ||
355 | return allowOperationBy(PERM_TRANSFER, mGroup, mGroup); | ||
356 | } | ||
357 | else | ||
358 | { | ||
359 | return ((mOwner == agent_id) ? TRUE : allowOperationBy(PERM_TRANSFER, mOwner)); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
364 | // Class LLAggregatePermissions | ||
365 | // | ||
366 | // Class which encapsulates object and inventory permissions, | ||
367 | // ownership, etc. Currently, it only aggregates PERM_COPY, | ||
368 | // PERM_MODIFY, and PERM_TRANSFER. | ||
369 | // | ||
370 | // Usually you will construct an instance and hand the object several | ||
371 | // permissions masks to aggregate the copy, modify, and | ||
372 | // transferability into a nice trinary value. | ||
373 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
374 | |||
375 | class LLAggregatePermissions | ||
376 | { | ||
377 | public: | ||
378 | enum EValue | ||
379 | { | ||
380 | AP_EMPTY = 0x00, | ||
381 | AP_NONE = 0x01, | ||
382 | AP_SOME = 0x02, | ||
383 | AP_ALL = 0x03 | ||
384 | }; | ||
385 | |||
386 | // construct an empty aggregate permissions | ||
387 | LLAggregatePermissions(); | ||
388 | |||
389 | // pass in a PERM_COPY, PERM_TRANSFER, etc, and get out a EValue | ||
390 | // enumeration describing the current aggregate permissions. | ||
391 | EValue getValue(PermissionBit bit) const; | ||
392 | |||
393 | // returns the permissions packed into the 6 LSB of a U8: | ||
394 | // 00TTMMCC | ||
395 | // where TT = transfer, MM = modify, and CC = copy | ||
396 | // LSB is to the right | ||
397 | U8 getU8() const; | ||
398 | |||
399 | // return TRUE is the aggregate permissions are empty, otherwise FALSE. | ||
400 | BOOL isEmpty() const ; | ||
401 | |||
402 | // pass in a PERM_COPY, PERM_TRANSFER, etc, and an EValue | ||
403 | // enumeration to specifically set that value. Not implemented | ||
404 | // because I'm not sure it's a useful api. | ||
405 | //void setValue(PermissionBit bit, EValue); | ||
406 | |||
407 | // Given a mask, aggregate the useful permissions. | ||
408 | void aggregate(PermissionMask mask); | ||
409 | |||
410 | // Aggregate aggregates | ||
411 | void aggregate(const LLAggregatePermissions& ag); | ||
412 | |||
413 | // message handling | ||
414 | void packMessage(LLMessageSystem* msg, const char* field) const; | ||
415 | void unpackMessage(LLMessageSystem* msg, const char* block, const char *field, S32 block_num = 0); | ||
416 | |||
417 | static const LLAggregatePermissions empty; | ||
418 | |||
419 | friend std::ostream& operator<<(std::ostream &s, const LLAggregatePermissions &perm); | ||
420 | |||
421 | protected: | ||
422 | enum EPermIndex | ||
423 | { | ||
424 | PI_COPY = 0, | ||
425 | PI_MODIFY = 1, | ||
426 | PI_TRANSFER = 2, | ||
427 | PI_END = 3, | ||
428 | PI_COUNT = 3 | ||
429 | }; | ||
430 | void aggregateBit(EPermIndex idx, BOOL allowed); | ||
431 | void aggregateIndex(EPermIndex idx, U8 bits); | ||
432 | static EPermIndex perm2PermIndex(PermissionBit bit); | ||
433 | |||
434 | // structure used to store the aggregate so far. | ||
435 | U8 mBits[PI_COUNT]; | ||
436 | }; | ||
437 | |||
438 | // These functions convert between structured data and permissions as | ||
439 | // appropriate for serialization. The permissions are a map of things | ||
440 | // like 'creator_id', 'owner_id', etc, with the value copied from the | ||
441 | // permission object. | ||
442 | LLSD ll_create_sd_from_permissions(const LLPermissions& perm); | ||
443 | LLPermissions ll_permissions_from_sd(const LLSD& sd_perm); | ||
444 | |||
445 | #endif | ||
diff --git a/linden/indra/llinventory/llpermissionsflags.h b/linden/indra/llinventory/llpermissionsflags.h new file mode 100644 index 0000000..2af16fb --- /dev/null +++ b/linden/indra/llinventory/llpermissionsflags.h | |||
@@ -0,0 +1,97 @@ | |||
1 | /** | ||
2 | * @file llpermissionsflags.h | ||
3 | * | ||
4 | * Copyright (c) 2002-2007, Linden Research, Inc. | ||
5 | * | ||
6 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
7 | * to you under the terms of the GNU General Public License, version 2.0 | ||
8 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
9 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
10 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
11 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
12 | * | ||
13 | * There are special exceptions to the terms and conditions of the GPL as | ||
14 | * it is applied to this Source Code. View the full text of the exception | ||
15 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/flossexception | ||
17 | * | ||
18 | * By copying, modifying or distributing this software, you acknowledge | ||
19 | * that you have read and understood your obligations described above, | ||
20 | * and agree to abide by those obligations. | ||
21 | * | ||
22 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
23 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
24 | * COMPLETENESS OR PERFORMANCE. | ||
25 | */ | ||
26 | |||
27 | #ifndef LL_LLPERMISSIONSFLAGS_H | ||
28 | #define LL_LLPERMISSIONSFLAGS_H | ||
29 | |||
30 | // llpermissionsflags.h | ||
31 | // Copyright 2002, Linden Research, Inc. | ||
32 | // | ||
33 | // Flags for various permissions bits. | ||
34 | // Shared between viewer and simulator. | ||
35 | |||
36 | // permission bits | ||
37 | typedef U32 PermissionMask; | ||
38 | typedef U32 PermissionBit; | ||
39 | |||
40 | |||
41 | // Do you have permission to transfer ownership of the object or | ||
42 | // item. Fair use rules dictate that if you cannot copy, you can | ||
43 | // always transfer. | ||
44 | const PermissionBit PERM_TRANSFER = (1 << 13); // 0x00002000 | ||
45 | |||
46 | // objects, scale or change textures | ||
47 | // parcels, allow building on it | ||
48 | const PermissionBit PERM_MODIFY = (1 << 14); // 0x00004000 | ||
49 | |||
50 | // objects, allow copy | ||
51 | const PermissionBit PERM_COPY = (1 << 15); // 0x00008000 | ||
52 | |||
53 | // parcels, allow entry, deprecated | ||
54 | //const PermissionBit PERM_ENTER = (1 << 16); // 0x00010000 | ||
55 | |||
56 | // parcels, allow terraform, deprecated | ||
57 | //const PermissionBit PERM_TERRAFORM = (1 << 17); // 0x00020000 | ||
58 | |||
59 | // NOTA BENE: This flag is NO LONGER USED!!! However, it is possible that some | ||
60 | // objects in the universe have it set so DON"T USE IT going forward. | ||
61 | //const PermissionBit PERM_OWNER_DEBIT = (1 << 18); // 0x00040000 | ||
62 | |||
63 | // objects, can grab/translate/rotate | ||
64 | const PermissionBit PERM_MOVE = (1 << 19); // 0x00080000 | ||
65 | |||
66 | // parcels, avatars take damage, deprecated | ||
67 | //const PermissionBit PERM_DAMAGE = (1 << 20); // 0x00100000 | ||
68 | |||
69 | // don't use bit 31 -- printf/scanf with "%x" assume signed numbers | ||
70 | const PermissionBit PERM_RESERVED = ((U32)1) << 31; | ||
71 | |||
72 | const PermissionMask PERM_NONE = 0x00000000; | ||
73 | const PermissionMask PERM_ALL = 0x7FFFFFFF; | ||
74 | //const PermissionMask PERM_ALL_PARCEL = PERM_MODIFY | PERM_ENTER | PERM_TERRAFORM | PERM_DAMAGE; | ||
75 | const PermissionMask PERM_ITEM_UNRESTRICTED = PERM_MODIFY | PERM_COPY | PERM_TRANSFER; | ||
76 | |||
77 | |||
78 | // Useful stuff for transmission. | ||
79 | // Which permissions field are we trying to change? | ||
80 | const U8 PERM_BASE = 0x01; | ||
81 | // TODO: Add another PERM_OWNER operation type for allowOperationBy DK 04/03/06 | ||
82 | const U8 PERM_OWNER = 0x02; | ||
83 | const U8 PERM_GROUP = 0x04; | ||
84 | const U8 PERM_EVERYONE = 0x08; | ||
85 | const U8 PERM_NEXT_OWNER = 0x10; | ||
86 | |||
87 | // This is just a quickie debugging key | ||
88 | // no modify: PERM_ALL & ~PERM_MODIFY = 0x7fffbfff | ||
89 | // no copy: PERM_ALL & ~PERM_COPY = 0x7fff7fff | ||
90 | // no modify or copy: = 0x7fff3fff | ||
91 | // no transfer: PERM_ALL & ~PERM_TRANSFER = 0x7fffdfff | ||
92 | // no modify, no transfer = 0x7fff9fff | ||
93 | // no copy, no transfer (INVALID!) = 0x7fff5fff | ||
94 | // no modify, no copy, no transfer (INVALID!) = 0x7fff1fff | ||
95 | |||
96 | |||
97 | #endif | ||
diff --git a/linden/indra/llinventory/llsaleinfo.cpp b/linden/indra/llinventory/llsaleinfo.cpp new file mode 100644 index 0000000..b82bd18 --- /dev/null +++ b/linden/indra/llinventory/llsaleinfo.cpp | |||
@@ -0,0 +1,375 @@ | |||
1 | /** | ||
2 | * @file llsaleinfo.cpp | ||
3 | * @brief | ||
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 <iostream> | ||
29 | #include "linden_common.h" | ||
30 | |||
31 | #include "llsaleinfo.h" | ||
32 | |||
33 | #include "llerror.h" | ||
34 | #include "message.h" | ||
35 | #include "llsdutil.h" | ||
36 | |||
37 | // use this to avoid temporary object creation | ||
38 | const LLSaleInfo LLSaleInfo::DEFAULT; | ||
39 | |||
40 | ///---------------------------------------------------------------------------- | ||
41 | /// Local function declarations, constants, enums, and typedefs | ||
42 | ///---------------------------------------------------------------------------- | ||
43 | |||
44 | const char* FOR_SALE_NAMES[] = | ||
45 | { | ||
46 | "not", | ||
47 | "orig", | ||
48 | "copy", | ||
49 | "cntn" | ||
50 | }; | ||
51 | |||
52 | ///---------------------------------------------------------------------------- | ||
53 | /// Class llsaleinfo | ||
54 | ///---------------------------------------------------------------------------- | ||
55 | |||
56 | // Default constructor | ||
57 | LLSaleInfo::LLSaleInfo() : | ||
58 | mSaleType(LLSaleInfo::FS_NOT), | ||
59 | mSalePrice(DEFAULT_PRICE) | ||
60 | { | ||
61 | } | ||
62 | |||
63 | LLSaleInfo::LLSaleInfo(EForSale sale_type, S32 sale_price) : | ||
64 | mSaleType(sale_type), | ||
65 | mSalePrice(sale_price) | ||
66 | { | ||
67 | mSalePrice = llclamp(mSalePrice, 0, S32_MAX); | ||
68 | } | ||
69 | |||
70 | BOOL LLSaleInfo::isForSale() const | ||
71 | { | ||
72 | return (FS_NOT != mSaleType); | ||
73 | } | ||
74 | |||
75 | U32 LLSaleInfo::getCRC32() const | ||
76 | { | ||
77 | U32 rv = (U32)mSalePrice; | ||
78 | rv += (mSaleType * 0x07073096); | ||
79 | return rv; | ||
80 | } | ||
81 | |||
82 | |||
83 | BOOL LLSaleInfo::exportFile(FILE* fp) const | ||
84 | { | ||
85 | fprintf(fp, "\tsale_info\t0\n\t{\n"); | ||
86 | fprintf(fp, "\t\tsale_type\t%s\n", lookup(mSaleType)); | ||
87 | fprintf(fp, "\t\tsale_price\t%d\n", mSalePrice); | ||
88 | fprintf(fp,"\t}\n"); | ||
89 | return TRUE; | ||
90 | } | ||
91 | |||
92 | BOOL LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const | ||
93 | { | ||
94 | output_stream << "\tsale_info\t0\n\t{\n"; | ||
95 | output_stream << "\t\tsale_type\t" << lookup(mSaleType) << "\n"; | ||
96 | output_stream << "\t\tsale_price\t" << mSalePrice << "\n"; | ||
97 | output_stream <<"\t}\n"; | ||
98 | return TRUE; | ||
99 | } | ||
100 | |||
101 | LLSD LLSaleInfo::asLLSD() const | ||
102 | { | ||
103 | LLSD sd = LLSD(); | ||
104 | sd["sale_type"] = lookup(mSaleType); | ||
105 | sd["sale_price"] = mSalePrice; | ||
106 | return sd; | ||
107 | } | ||
108 | |||
109 | bool LLSaleInfo::fromLLSD(LLSD& sd, BOOL& has_perm_mask, U32& perm_mask) | ||
110 | { | ||
111 | const char *w; | ||
112 | |||
113 | mSaleType = lookup(sd["sale_type"].asString().c_str()); | ||
114 | mSalePrice = llclamp(sd["sale_price"].asInteger(), 0, S32_MAX); | ||
115 | w = "perm_mask"; | ||
116 | if (sd.has(w)) | ||
117 | { | ||
118 | has_perm_mask = TRUE; | ||
119 | perm_mask = ll_U32_from_sd(sd[w]); | ||
120 | } | ||
121 | return true; | ||
122 | } | ||
123 | |||
124 | LLXMLNode *LLSaleInfo::exportFileXML() const | ||
125 | { | ||
126 | LLXMLNode *ret = new LLXMLNode("sale_info", FALSE); | ||
127 | LLString type_str = lookup(mSaleType); | ||
128 | ret->createChild("type", TRUE)->setStringValue(1, &type_str); | ||
129 | ret->createChild("price", TRUE)->setIntValue(1, &mSalePrice); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | BOOL LLSaleInfo::importXML(LLXMLNode* node) | ||
134 | { | ||
135 | BOOL success = FALSE; | ||
136 | if (node) | ||
137 | { | ||
138 | success = TRUE; | ||
139 | LLXMLNodePtr sub_node; | ||
140 | if (node->getChild("type", sub_node)) | ||
141 | { | ||
142 | mSaleType = lookup(sub_node->getValue().c_str()); | ||
143 | } | ||
144 | if (node->getChild("price", sub_node)) | ||
145 | { | ||
146 | success &= (1 == sub_node->getIntValue(1, &mSalePrice)); | ||
147 | } | ||
148 | if (!success) | ||
149 | { | ||
150 | lldebugs << "LLSaleInfo::importXML() failed for node named '" | ||
151 | << node->getName() << "'" << llendl; | ||
152 | } | ||
153 | } | ||
154 | return success; | ||
155 | } | ||
156 | |||
157 | BOOL LLSaleInfo::importFile(FILE* fp, BOOL& has_perm_mask, U32& perm_mask) | ||
158 | { | ||
159 | has_perm_mask = FALSE; | ||
160 | |||
161 | char buffer[MAX_STRING]; | ||
162 | char keyword[MAX_STRING]; | ||
163 | char valuestr[MAX_STRING]; | ||
164 | BOOL success = TRUE; | ||
165 | |||
166 | keyword[0] = '\0'; | ||
167 | valuestr[0] = '\0'; | ||
168 | while(success && (!feof(fp))) | ||
169 | { | ||
170 | fgets(buffer, MAX_STRING, fp); | ||
171 | sscanf(buffer, " %s %s", keyword, valuestr); | ||
172 | if(!keyword) | ||
173 | { | ||
174 | continue; | ||
175 | } | ||
176 | if(0 == strcmp("{",keyword)) | ||
177 | { | ||
178 | continue; | ||
179 | } | ||
180 | if(0 == strcmp("}", keyword)) | ||
181 | { | ||
182 | break; | ||
183 | } | ||
184 | else if(0 == strcmp("sale_type", keyword)) | ||
185 | { | ||
186 | mSaleType = lookup(valuestr); | ||
187 | } | ||
188 | else if(0 == strcmp("sale_price", keyword)) | ||
189 | { | ||
190 | sscanf(valuestr, "%d", &mSalePrice); | ||
191 | mSalePrice = llclamp(mSalePrice, 0, S32_MAX); | ||
192 | } | ||
193 | else if (!strcmp("perm_mask", keyword)) | ||
194 | { | ||
195 | //llinfos << "found deprecated keyword perm_mask" << llendl; | ||
196 | has_perm_mask = TRUE; | ||
197 | sscanf(valuestr, "%x", &perm_mask); | ||
198 | } | ||
199 | else | ||
200 | { | ||
201 | llwarns << "unknown keyword '" << keyword | ||
202 | << "' in sale info import" << llendl; | ||
203 | } | ||
204 | } | ||
205 | return success; | ||
206 | } | ||
207 | |||
208 | BOOL LLSaleInfo::importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask) | ||
209 | { | ||
210 | has_perm_mask = FALSE; | ||
211 | |||
212 | char buffer[MAX_STRING]; | ||
213 | char keyword[MAX_STRING]; | ||
214 | char valuestr[MAX_STRING]; | ||
215 | BOOL success = TRUE; | ||
216 | |||
217 | keyword[0] = '\0'; | ||
218 | valuestr[0] = '\0'; | ||
219 | while(success && input_stream.good()) | ||
220 | { | ||
221 | input_stream.getline(buffer, MAX_STRING); | ||
222 | sscanf(buffer, " %s %s", keyword, valuestr); | ||
223 | if(!keyword) | ||
224 | { | ||
225 | continue; | ||
226 | } | ||
227 | if(0 == strcmp("{",keyword)) | ||
228 | { | ||
229 | continue; | ||
230 | } | ||
231 | if(0 == strcmp("}", keyword)) | ||
232 | { | ||
233 | break; | ||
234 | } | ||
235 | else if(0 == strcmp("sale_type", keyword)) | ||
236 | { | ||
237 | mSaleType = lookup(valuestr); | ||
238 | } | ||
239 | else if(0 == strcmp("sale_price", keyword)) | ||
240 | { | ||
241 | sscanf(valuestr, "%d", &mSalePrice); | ||
242 | mSalePrice = llclamp(mSalePrice, 0, S32_MAX); | ||
243 | } | ||
244 | else if (!strcmp("perm_mask", keyword)) | ||
245 | { | ||
246 | //llinfos << "found deprecated keyword perm_mask" << llendl; | ||
247 | has_perm_mask = TRUE; | ||
248 | sscanf(valuestr, "%x", &perm_mask); | ||
249 | } | ||
250 | else | ||
251 | { | ||
252 | llwarns << "unknown keyword '" << keyword | ||
253 | << "' in sale info import" << llendl; | ||
254 | } | ||
255 | } | ||
256 | return success; | ||
257 | } | ||
258 | |||
259 | void LLSaleInfo::setSalePrice(S32 price) | ||
260 | { | ||
261 | mSalePrice = price; | ||
262 | mSalePrice = llclamp(mSalePrice, 0, S32_MAX); | ||
263 | } | ||
264 | |||
265 | void LLSaleInfo::packMessage(LLMessageSystem* msg) const | ||
266 | { | ||
267 | U8 sale_type = static_cast<U8>(mSaleType); | ||
268 | msg->addU8Fast(_PREHASH_SaleType, sale_type); | ||
269 | msg->addS32Fast(_PREHASH_SalePrice, mSalePrice); | ||
270 | //msg->addU32Fast(_PREHASH_NextOwnerMask, mNextOwnerPermMask); | ||
271 | } | ||
272 | |||
273 | void LLSaleInfo::unpackMessage(LLMessageSystem* msg, const char* block) | ||
274 | { | ||
275 | U8 sale_type; | ||
276 | msg->getU8Fast(block, _PREHASH_SaleType, sale_type); | ||
277 | mSaleType = static_cast<EForSale>(sale_type); | ||
278 | msg->getS32Fast(block, _PREHASH_SalePrice, mSalePrice); | ||
279 | mSalePrice = llclamp(mSalePrice, 0, S32_MAX); | ||
280 | //msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask); | ||
281 | } | ||
282 | |||
283 | void LLSaleInfo::unpackMultiMessage(LLMessageSystem* msg, const char* block, | ||
284 | S32 block_num) | ||
285 | { | ||
286 | U8 sale_type; | ||
287 | msg->getU8Fast(block, _PREHASH_SaleType, sale_type, block_num); | ||
288 | mSaleType = static_cast<EForSale>(sale_type); | ||
289 | msg->getS32Fast(block, _PREHASH_SalePrice, mSalePrice, block_num); | ||
290 | mSalePrice = llclamp(mSalePrice, 0, S32_MAX); | ||
291 | //msg->getU32Fast(block, _PREHASH_NextOwnerMask, mNextOwnerPermMask, block_num); | ||
292 | } | ||
293 | |||
294 | LLSaleInfo::EForSale LLSaleInfo::lookup(const char* name) | ||
295 | { | ||
296 | for(S32 i = 0; i < FS_COUNT; i++) | ||
297 | { | ||
298 | if(0 == strcmp(name, FOR_SALE_NAMES[i])) | ||
299 | { | ||
300 | // match | ||
301 | return (EForSale)i; | ||
302 | } | ||
303 | } | ||
304 | return FS_NOT; | ||
305 | } | ||
306 | |||
307 | const char* LLSaleInfo::lookup(EForSale type) | ||
308 | { | ||
309 | if((type >= 0) && (type < FS_COUNT)) | ||
310 | { | ||
311 | return FOR_SALE_NAMES[S32(type)]; | ||
312 | } | ||
313 | else | ||
314 | { | ||
315 | return NULL; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | // Allow accumulation of sale info. The price of each is added, | ||
320 | // conflict in sale type results in FS_NOT, and the permissions are | ||
321 | // tightened. | ||
322 | void LLSaleInfo::accumulate(const LLSaleInfo& sale_info) | ||
323 | { | ||
324 | if(mSaleType != sale_info.mSaleType) | ||
325 | { | ||
326 | mSaleType = FS_NOT; | ||
327 | } | ||
328 | mSalePrice += sale_info.mSalePrice; | ||
329 | //mNextOwnerPermMask &= sale_info.mNextOwnerPermMask; | ||
330 | } | ||
331 | |||
332 | bool LLSaleInfo::operator==(const LLSaleInfo &rhs) const | ||
333 | { | ||
334 | return ( | ||
335 | (mSaleType == rhs.mSaleType) && | ||
336 | (mSalePrice == rhs.mSalePrice) | ||
337 | ); | ||
338 | } | ||
339 | |||
340 | bool LLSaleInfo::operator!=(const LLSaleInfo &rhs) const | ||
341 | { | ||
342 | return ( | ||
343 | (mSaleType != rhs.mSaleType) || | ||
344 | (mSalePrice != rhs.mSalePrice) | ||
345 | ); | ||
346 | } | ||
347 | |||
348 | |||
349 | ///---------------------------------------------------------------------------- | ||
350 | /// Local function definitions | ||
351 | ///---------------------------------------------------------------------------- | ||
352 | |||
353 | ///---------------------------------------------------------------------------- | ||
354 | /// exported functions | ||
355 | ///---------------------------------------------------------------------------- | ||
356 | static const std::string ST_TYPE_LABEL("sale_type"); | ||
357 | static const std::string ST_PRICE_LABEL("sale_price"); | ||
358 | |||
359 | LLSD ll_create_sd_from_sale_info(const LLSaleInfo& sale) | ||
360 | { | ||
361 | LLSD rv; | ||
362 | const char* type = LLSaleInfo::lookup(sale.getSaleType()); | ||
363 | if(!type) type = LLSaleInfo::lookup(LLSaleInfo::FS_NOT); | ||
364 | rv[ST_TYPE_LABEL] = type; | ||
365 | rv[ST_PRICE_LABEL] = sale.getSalePrice(); | ||
366 | return rv; | ||
367 | } | ||
368 | |||
369 | LLSaleInfo ll_sale_info_from_sd(const LLSD& sd) | ||
370 | { | ||
371 | LLSaleInfo rv; | ||
372 | rv.setSaleType(LLSaleInfo::lookup(sd[ST_TYPE_LABEL].asString().c_str())); | ||
373 | rv.setSalePrice(llclamp((S32)sd[ST_PRICE_LABEL], 0, S32_MAX)); | ||
374 | return rv; | ||
375 | } | ||
diff --git a/linden/indra/llinventory/llsaleinfo.h b/linden/indra/llinventory/llsaleinfo.h new file mode 100644 index 0000000..5e80108 --- /dev/null +++ b/linden/indra/llinventory/llsaleinfo.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /** | ||
2 | * @file llsaleinfo.h | ||
3 | * @brief LLSaleInfo class header file. | ||
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 | #ifndef LL_LLSALEINFO_H | ||
29 | #define LL_LLSALEINFO_H | ||
30 | |||
31 | #include <stdio.h> | ||
32 | #include <iostream> | ||
33 | |||
34 | #include "llpermissionsflags.h" | ||
35 | #include "llsd.h" | ||
36 | #include "llxmlnode.h" | ||
37 | |||
38 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
39 | // Class LLSaleInfo | ||
40 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
41 | |||
42 | // L$ default price for objects | ||
43 | const S32 DEFAULT_PRICE = 10; | ||
44 | |||
45 | class LLMessageSystem; | ||
46 | |||
47 | class LLSaleInfo | ||
48 | { | ||
49 | public: | ||
50 | // use this to avoid temporary object creation | ||
51 | static const LLSaleInfo DEFAULT; | ||
52 | |||
53 | enum EForSale | ||
54 | { | ||
55 | // item is not to be considered for transactions | ||
56 | FS_NOT = 0, | ||
57 | |||
58 | // the origional is on sale | ||
59 | FS_ORIGINAL = 1, | ||
60 | |||
61 | // A copy is for sale | ||
62 | FS_COPY = 2, | ||
63 | |||
64 | // Valid only for tasks, the inventory is for sale | ||
65 | // at the price in this structure. | ||
66 | FS_CONTENTS = 3, | ||
67 | |||
68 | FS_COUNT | ||
69 | }; | ||
70 | |||
71 | protected: | ||
72 | EForSale mSaleType; | ||
73 | S32 mSalePrice; | ||
74 | |||
75 | public: | ||
76 | // default constructor is fine usually | ||
77 | LLSaleInfo(); | ||
78 | LLSaleInfo(EForSale sale_type, S32 sale_price); | ||
79 | |||
80 | // accessors | ||
81 | BOOL isForSale() const; | ||
82 | EForSale getSaleType() const { return mSaleType; } | ||
83 | S32 getSalePrice() const { return mSalePrice; } | ||
84 | U32 getCRC32() const; | ||
85 | |||
86 | // mutators | ||
87 | void setSaleType(EForSale type) { mSaleType = type; } | ||
88 | void setSalePrice(S32 price); | ||
89 | //void setNextOwnerPermMask(U32 mask) { mNextOwnerPermMask = mask; } | ||
90 | |||
91 | |||
92 | // file serialization | ||
93 | BOOL exportFile(FILE* fp) const; | ||
94 | BOOL importFile(FILE* fp, BOOL& has_perm_mask, U32& perm_mask); | ||
95 | |||
96 | BOOL exportLegacyStream(std::ostream& output_stream) const; | ||
97 | LLSD asLLSD() const; | ||
98 | operator LLSD() const { return asLLSD(); } | ||
99 | bool fromLLSD(LLSD& sd, BOOL& has_perm_mask, U32& perm_mask); | ||
100 | BOOL importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask); | ||
101 | |||
102 | LLXMLNode *exportFileXML() const; | ||
103 | BOOL importXML(LLXMLNode* node); | ||
104 | |||
105 | // message serialization | ||
106 | void packMessage(LLMessageSystem* msg) const; | ||
107 | void unpackMessage(LLMessageSystem* msg, const char* block); | ||
108 | void unpackMultiMessage(LLMessageSystem* msg, const char* block, | ||
109 | S32 block_num); | ||
110 | |||
111 | // static functionality for determine for sale status. | ||
112 | static EForSale lookup(const char* name); | ||
113 | static const char* lookup(EForSale type); | ||
114 | |||
115 | // Allow accumulation of sale info. The price of each is added, | ||
116 | // conflict in sale type results in FS_NOT, and the permissions | ||
117 | // are tightened. | ||
118 | void accumulate(const LLSaleInfo& sale_info); | ||
119 | |||
120 | bool operator==(const LLSaleInfo &rhs) const; | ||
121 | bool operator!=(const LLSaleInfo &rhs) const; | ||
122 | }; | ||
123 | |||
124 | // These functions convert between structured data and sale info as | ||
125 | // appropriate for serialization. | ||
126 | LLSD ll_create_sd_from_sale_info(const LLSaleInfo& sale); | ||
127 | LLSaleInfo ll_sale_info_from_sd(const LLSD& sd); | ||
128 | |||
129 | #endif // LL_LLSALEINFO_H | ||
diff --git a/linden/indra/llinventory/lltransactionflags.cpp b/linden/indra/llinventory/lltransactionflags.cpp new file mode 100644 index 0000000..16d6101 --- /dev/null +++ b/linden/indra/llinventory/lltransactionflags.cpp | |||
@@ -0,0 +1,62 @@ | |||
1 | /** | ||
2 | * @file lltransactionflags.cpp | ||
3 | * @brief Some exported symbols and functions for dealing with | ||
4 | * transaction flags. | ||
5 | * | ||
6 | * Copyright (c) 2003-2007, Linden Research, Inc. | ||
7 | * | ||
8 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
9 | * to you under the terms of the GNU General Public License, version 2.0 | ||
10 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
11 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
12 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
13 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
14 | * | ||
15 | * There are special exceptions to the terms and conditions of the GPL as | ||
16 | * it is applied to this Source Code. View the full text of the exception | ||
17 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
18 | * online at http://secondlife.com/developers/opensource/flossexception | ||
19 | * | ||
20 | * By copying, modifying or distributing this software, you acknowledge | ||
21 | * that you have read and understood your obligations described above, | ||
22 | * and agree to abide by those obligations. | ||
23 | * | ||
24 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
25 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
26 | * COMPLETENESS OR PERFORMANCE. | ||
27 | */ | ||
28 | |||
29 | #include "linden_common.h" | ||
30 | |||
31 | #include "lltransactionflags.h" | ||
32 | |||
33 | const U8 TRANSACTION_FLAGS_NONE = 0; | ||
34 | const U8 TRANSACTION_FLAG_SOURCE_GROUP = 1; | ||
35 | const U8 TRANSACTION_FLAG_DEST_GROUP = 2; | ||
36 | const U8 TRANSACTION_FLAG_OWNER_GROUP = 4; | ||
37 | const U8 TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION = 8; | ||
38 | const U8 TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION_REMOVAL = 16; | ||
39 | |||
40 | U8 pack_transaction_flags(BOOL is_source_group, BOOL is_dest_group) | ||
41 | { | ||
42 | U8 rv = 0; | ||
43 | if(is_source_group) rv |= TRANSACTION_FLAG_SOURCE_GROUP; | ||
44 | if(is_dest_group) rv |= TRANSACTION_FLAG_DEST_GROUP; | ||
45 | return rv; | ||
46 | } | ||
47 | |||
48 | BOOL is_tf_source_group(TransactionFlags flags) | ||
49 | { | ||
50 | return ((flags & TRANSACTION_FLAG_SOURCE_GROUP) == TRANSACTION_FLAG_SOURCE_GROUP); | ||
51 | } | ||
52 | |||
53 | BOOL is_tf_dest_group(TransactionFlags flags) | ||
54 | { | ||
55 | return ((flags & TRANSACTION_FLAG_DEST_GROUP) == TRANSACTION_FLAG_DEST_GROUP); | ||
56 | } | ||
57 | |||
58 | BOOL is_tf_owner_group(TransactionFlags flags) | ||
59 | { | ||
60 | return ((flags & TRANSACTION_FLAG_OWNER_GROUP) == TRANSACTION_FLAG_OWNER_GROUP); | ||
61 | } | ||
62 | |||
diff --git a/linden/indra/llinventory/lltransactionflags.h b/linden/indra/llinventory/lltransactionflags.h new file mode 100644 index 0000000..ed47995 --- /dev/null +++ b/linden/indra/llinventory/lltransactionflags.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /** | ||
2 | * @file lltransactionflags.h | ||
3 | * | ||
4 | * Copyright (c) 2003-2007, Linden Research, Inc. | ||
5 | * | ||
6 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
7 | * to you under the terms of the GNU General Public License, version 2.0 | ||
8 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
9 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
10 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
11 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
12 | * | ||
13 | * There are special exceptions to the terms and conditions of the GPL as | ||
14 | * it is applied to this Source Code. View the full text of the exception | ||
15 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/flossexception | ||
17 | * | ||
18 | * By copying, modifying or distributing this software, you acknowledge | ||
19 | * that you have read and understood your obligations described above, | ||
20 | * and agree to abide by those obligations. | ||
21 | * | ||
22 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
23 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
24 | * COMPLETENESS OR PERFORMANCE. | ||
25 | */ | ||
26 | |||
27 | #ifndef LL_LLTRANSACTIONFLAGS_H | ||
28 | #define LL_LLTRANSACTIONFLAGS_H | ||
29 | |||
30 | typedef U8 TransactionFlags; | ||
31 | |||
32 | // defined in common/llinventory/lltransactionflags.cpp | ||
33 | extern const TransactionFlags TRANSACTION_FLAGS_NONE; | ||
34 | extern const TransactionFlags TRANSACTION_FLAG_SOURCE_GROUP; | ||
35 | extern const TransactionFlags TRANSACTION_FLAG_DEST_GROUP; | ||
36 | extern const TransactionFlags TRANSACTION_FLAG_OWNER_GROUP; | ||
37 | extern const TransactionFlags TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION; | ||
38 | extern const TransactionFlags TRANSACTION_FLAG_SIMULTANEOUS_CONTRIBUTION_REMOVAL; | ||
39 | |||
40 | // very simple helper functions | ||
41 | TransactionFlags pack_transaction_flags(BOOL is_source_group, BOOL is_dest_group); | ||
42 | BOOL is_tf_source_group(TransactionFlags flags); | ||
43 | BOOL is_tf_dest_group(TransactionFlags flags); | ||
44 | BOOL is_tf_owner_group(TransactionFlags flags); | ||
45 | |||
46 | #endif // LL_LLTRANSACTIONFLAGS_H | ||
diff --git a/linden/indra/llinventory/lltransactiontypes.h b/linden/indra/llinventory/lltransactiontypes.h new file mode 100644 index 0000000..345fe89 --- /dev/null +++ b/linden/indra/llinventory/lltransactiontypes.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /** | ||
2 | * @file lltransactiontypes.h | ||
3 | * | ||
4 | * Copyright (c) 2003-2007, Linden Research, Inc. | ||
5 | * | ||
6 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
7 | * to you under the terms of the GNU General Public License, version 2.0 | ||
8 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
9 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
10 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
11 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
12 | * | ||
13 | * There are special exceptions to the terms and conditions of the GPL as | ||
14 | * it is applied to this Source Code. View the full text of the exception | ||
15 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
16 | * online at http://secondlife.com/developers/opensource/flossexception | ||
17 | * | ||
18 | * By copying, modifying or distributing this software, you acknowledge | ||
19 | * that you have read and understood your obligations described above, | ||
20 | * and agree to abide by those obligations. | ||
21 | * | ||
22 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
23 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
24 | * COMPLETENESS OR PERFORMANCE. | ||
25 | */ | ||
26 | |||
27 | #ifndef LL_LLTRANSACTIONTYPES_H | ||
28 | #define LL_LLTRANSACTIONTYPES_H | ||
29 | |||
30 | // *NOTE: The constants in this file are also in the | ||
31 | // transaction_description table in the database. If you add a | ||
32 | // constant here, please add it to the database. eg: | ||
33 | // | ||
34 | // insert into transaction_description | ||
35 | // set type = 1000, description = 'Object Claim'; | ||
36 | // | ||
37 | // Also add it to the various money string lookups on the dataserver | ||
38 | // in lldatamoney | ||
39 | |||
40 | // Money transaction failure codes | ||
41 | const U8 TRANS_FAIL_SIMULATOR_TIMEOUT = 1; | ||
42 | const U8 TRANS_FAIL_DATASERVER_TIMEOUT = 2; | ||
43 | |||
44 | // Codes up to 999 for error conditions | ||
45 | const S32 TRANS_NULL = 0; | ||
46 | |||
47 | // Codes 1000-1999 reserved for one-time charges | ||
48 | const S32 TRANS_OBJECT_CLAIM = 1000; | ||
49 | const S32 TRANS_LAND_CLAIM = 1001; | ||
50 | const S32 TRANS_GROUP_CREATE = 1002; | ||
51 | const S32 TRANS_OBJECT_PUBLIC_CLAIM = 1003; | ||
52 | const S32 TRANS_GROUP_JOIN = 1004; // May be moved to group transactions eventually | ||
53 | const S32 TRANS_TELEPORT_CHARGE = 1100; // FF not sure why this jumps to 1100... | ||
54 | const S32 TRANS_UPLOAD_CHARGE = 1101; | ||
55 | const S32 TRANS_LAND_AUCTION = 1102; | ||
56 | const S32 TRANS_CLASSIFIED_CHARGE = 1103; | ||
57 | |||
58 | // Codes 2000-2999 reserved for recurrent charges | ||
59 | const S32 TRANS_OBJECT_TAX = 2000; | ||
60 | const S32 TRANS_LAND_TAX = 2001; | ||
61 | const S32 TRANS_LIGHT_TAX = 2002; | ||
62 | const S32 TRANS_PARCEL_DIR_FEE = 2003; | ||
63 | const S32 TRANS_GROUP_TAX = 2004; // Taxes incurred as part of group membership | ||
64 | const S32 TRANS_CLASSIFIED_RENEW = 2005; | ||
65 | |||
66 | // Codes 3000-3999 reserved for inventory transactions | ||
67 | const S32 TRANS_GIVE_INVENTORY = 3000; | ||
68 | |||
69 | // Codes 5000-5999 reserved for transfers between users | ||
70 | const S32 TRANS_OBJECT_SALE = 5000; | ||
71 | const S32 TRANS_GIFT = 5001; | ||
72 | const S32 TRANS_LAND_SALE = 5002; | ||
73 | const S32 TRANS_REFER_BONUS = 5003; | ||
74 | const S32 TRANS_INVENTORY_SALE = 5004; | ||
75 | const S32 TRANS_REFUND_PURCHASE = 5005; | ||
76 | const S32 TRANS_LAND_PASS_SALE = 5006; | ||
77 | const S32 TRANS_DWELL_BONUS = 5007; | ||
78 | const S32 TRANS_PAY_OBJECT = 5008; | ||
79 | const S32 TRANS_OBJECT_PAYS = 5009; | ||
80 | |||
81 | // Codes 6000-6999 reserved for group transactions | ||
82 | //const S32 TRANS_GROUP_JOIN = 6000; //reserved for future use | ||
83 | const S32 TRANS_GROUP_LAND_DEED = 6001; | ||
84 | const S32 TRANS_GROUP_OBJECT_DEED = 6002; | ||
85 | const S32 TRANS_GROUP_LIABILITY = 6003; | ||
86 | const S32 TRANS_GROUP_DIVIDEND = 6004; | ||
87 | const S32 TRANS_MEMBERSHIP_DUES = 6005; | ||
88 | |||
89 | // Codes 8000-8999 reserved for one-type credits | ||
90 | const S32 TRANS_OBJECT_RELEASE = 8000; | ||
91 | const S32 TRANS_LAND_RELEASE = 8001; | ||
92 | const S32 TRANS_OBJECT_DELETE = 8002; | ||
93 | const S32 TRANS_OBJECT_PUBLIC_DECAY = 8003; | ||
94 | const S32 TRANS_OBJECT_PUBLIC_DELETE= 8004; | ||
95 | |||
96 | // Code 9000-9099 reserved for usertool transactions | ||
97 | const S32 TRANS_LINDEN_ADJUSTMENT = 9000; | ||
98 | const S32 TRANS_LINDEN_GRANT = 9001; | ||
99 | const S32 TRANS_LINDEN_PENALTY = 9002; | ||
100 | const S32 TRANS_EVENT_FEE = 9003; | ||
101 | const S32 TRANS_EVENT_PRIZE = 9004; | ||
102 | |||
103 | // These must match entries in money_stipend table in MySQL | ||
104 | // Codes 10000-10999 reserved for stipend credits | ||
105 | const S32 TRANS_STIPEND_BASIC = 10000; | ||
106 | const S32 TRANS_STIPEND_DEVELOPER = 10001; | ||
107 | const S32 TRANS_STIPEND_ALWAYS = 10002; | ||
108 | const S32 TRANS_STIPEND_DAILY = 10003; | ||
109 | const S32 TRANS_STIPEND_RATING = 10004; | ||
110 | const S32 TRANS_STIPEND_DELTA = 10005; | ||
111 | |||
112 | #endif | ||
diff --git a/linden/indra/llinventory/lluserrelations.cpp b/linden/indra/llinventory/lluserrelations.cpp new file mode 100644 index 0000000..e9248c3 --- /dev/null +++ b/linden/indra/llinventory/lluserrelations.cpp | |||
@@ -0,0 +1,108 @@ | |||
1 | /** | ||
2 | * @file lluserrealations.cpp | ||
3 | * @author Phoenix | ||
4 | * @date 2006-10-12 | ||
5 | * @brief Implementation of a simple cache of user relations. | ||
6 | * | ||
7 | * Copyright (c) 2006-2007, Linden Research, Inc. | ||
8 | * | ||
9 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
10 | * to you under the terms of the GNU General Public License, version 2.0 | ||
11 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
12 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
13 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
14 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
15 | * | ||
16 | * There are special exceptions to the terms and conditions of the GPL as | ||
17 | * it is applied to this Source Code. View the full text of the exception | ||
18 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
19 | * online at http://secondlife.com/developers/opensource/flossexception | ||
20 | * | ||
21 | * By copying, modifying or distributing this software, you acknowledge | ||
22 | * that you have read and understood your obligations described above, | ||
23 | * and agree to abide by those obligations. | ||
24 | * | ||
25 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
26 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
27 | * COMPLETENESS OR PERFORMANCE. | ||
28 | */ | ||
29 | |||
30 | #include "linden_common.h" | ||
31 | #include "lluserrelations.h" | ||
32 | |||
33 | // static | ||
34 | const U8 LLRelationship::GRANTED_VISIBLE_MASK = LLRelationship::GRANT_MODIFY_OBJECTS | LLRelationship::GRANT_MAP_LOCATION; | ||
35 | const LLRelationship LLRelationship::DEFAULT_RELATIONSHIP = LLRelationship(GRANT_ONLINE_STATUS, GRANT_ONLINE_STATUS, false); | ||
36 | |||
37 | LLRelationship::LLRelationship() : | ||
38 | mGrantToAgent(0), | ||
39 | mGrantFromAgent(0), | ||
40 | mIsOnline(false) | ||
41 | { | ||
42 | } | ||
43 | |||
44 | LLRelationship::LLRelationship(S32 grant_to, S32 grant_from, bool is_online) : | ||
45 | mGrantToAgent(grant_to), | ||
46 | mGrantFromAgent(grant_from), | ||
47 | mIsOnline(is_online) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | bool LLRelationship::isOnline() const | ||
52 | { | ||
53 | return mIsOnline; | ||
54 | } | ||
55 | |||
56 | void LLRelationship::online(bool is_online) | ||
57 | { | ||
58 | mIsOnline = is_online; | ||
59 | } | ||
60 | |||
61 | bool LLRelationship::isRightGrantedTo(S32 rights) const | ||
62 | { | ||
63 | return ((mGrantToAgent & rights) == rights); | ||
64 | } | ||
65 | |||
66 | bool LLRelationship::isRightGrantedFrom(S32 rights) const | ||
67 | { | ||
68 | return ((mGrantFromAgent & rights) == rights); | ||
69 | } | ||
70 | |||
71 | S32 LLRelationship::getRightsGrantedTo() const | ||
72 | { | ||
73 | return mGrantToAgent; | ||
74 | } | ||
75 | |||
76 | S32 LLRelationship::getRightsGrantedFrom() const | ||
77 | { | ||
78 | return mGrantFromAgent; | ||
79 | } | ||
80 | |||
81 | void LLRelationship::grantRights(S32 to_agent, S32 from_agent) | ||
82 | { | ||
83 | mGrantToAgent |= to_agent; | ||
84 | mGrantFromAgent |= from_agent; | ||
85 | } | ||
86 | |||
87 | void LLRelationship::revokeRights(S32 to_agent, S32 from_agent) | ||
88 | { | ||
89 | mGrantToAgent &= ~to_agent; | ||
90 | mGrantFromAgent &= ~from_agent; | ||
91 | } | ||
92 | |||
93 | |||
94 | |||
95 | /* | ||
96 | bool LLGrantedRights::getNextRights( | ||
97 | LLUUID& agent_id, | ||
98 | S32& to_agent, | ||
99 | S32& from_agent) const | ||
100 | { | ||
101 | rights_map_t::const_iterator iter = mRights.upper_bound(agent_id); | ||
102 | if(iter == mRights.end()) return false; | ||
103 | agent_id = (*iter).first; | ||
104 | to_agent = (*iter).second.mToAgent; | ||
105 | from_agent = (*iter).second.mFromAgent; | ||
106 | return true; | ||
107 | } | ||
108 | */ | ||
diff --git a/linden/indra/llinventory/lluserrelations.h b/linden/indra/llinventory/lluserrelations.h new file mode 100644 index 0000000..9363ab5 --- /dev/null +++ b/linden/indra/llinventory/lluserrelations.h | |||
@@ -0,0 +1,173 @@ | |||
1 | /** | ||
2 | * @file llluserrelations.h | ||
3 | * @author Phoenix | ||
4 | * @date 2006-10-12 | ||
5 | * @brief Declaration of a class for handling granted rights. | ||
6 | * | ||
7 | * Copyright (c) 2006-2007, Linden Research, Inc. | ||
8 | * | ||
9 | * The source code in this file ("Source Code") is provided by Linden Lab | ||
10 | * to you under the terms of the GNU General Public License, version 2.0 | ||
11 | * ("GPL"), unless you have obtained a separate licensing agreement | ||
12 | * ("Other License"), formally executed by you and Linden Lab. Terms of | ||
13 | * the GPL can be found in doc/GPL-license.txt in this distribution, or | ||
14 | * online at http://secondlife.com/developers/opensource/gplv2 | ||
15 | * | ||
16 | * There are special exceptions to the terms and conditions of the GPL as | ||
17 | * it is applied to this Source Code. View the full text of the exception | ||
18 | * in the file doc/FLOSS-exception.txt in this software distribution, or | ||
19 | * online at http://secondlife.com/developers/opensource/flossexception | ||
20 | * | ||
21 | * By copying, modifying or distributing this software, you acknowledge | ||
22 | * that you have read and understood your obligations described above, | ||
23 | * and agree to abide by those obligations. | ||
24 | * | ||
25 | * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO | ||
26 | * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, | ||
27 | * COMPLETENESS OR PERFORMANCE. | ||
28 | */ | ||
29 | |||
30 | #ifndef LL_LLUSERRELAIONS_H | ||
31 | #define LL_LLUSERRELAIONS_H | ||
32 | |||
33 | #include <map> | ||
34 | #include "lluuid.h" | ||
35 | |||
36 | /** | ||
37 | * @class LLRelationship | ||
38 | * | ||
39 | * This class represents a relationship between two agents, where the | ||
40 | * related agent is stored and the other agent is the relationship is | ||
41 | * implicit by container ownership. | ||
42 | * This is merely a cache of this information used by the sim | ||
43 | * and viewer. | ||
44 | * | ||
45 | * You are expected to use this in a map or similar structure, eg: | ||
46 | * typedef std::map<LLUUID, LLRelationship> agent_relationship_map; | ||
47 | */ | ||
48 | class LLRelationship | ||
49 | { | ||
50 | public: | ||
51 | /** | ||
52 | * @brief Constructors. | ||
53 | */ | ||
54 | LLRelationship(); | ||
55 | LLRelationship(S32 grant_to, S32 grant_from, bool is_online); | ||
56 | |||
57 | static const LLRelationship DEFAULT_RELATIONSHIP; | ||
58 | |||
59 | /** | ||
60 | * @name Status functionality | ||
61 | * | ||
62 | * I thought it would be keen to have a generic status interface, | ||
63 | * but the only thing we currently cache is online status. As this | ||
64 | * assumption changes, this API may evolve. | ||
65 | */ | ||
66 | //@{ | ||
67 | /** | ||
68 | * @brief Does this instance believe the related agent is currently | ||
69 | * online or available. | ||
70 | * | ||
71 | * NOTE: This API may be deprecated if there is any transient status | ||
72 | * other than online status, for example, away/busy/etc. | ||
73 | * | ||
74 | * This call does not check any kind of central store or make any | ||
75 | * deep information calls - it simply checks a cache of online | ||
76 | * status. | ||
77 | * @return Returns true if this relationship believes the agent is | ||
78 | * online. | ||
79 | */ | ||
80 | bool isOnline() const; | ||
81 | |||
82 | /** | ||
83 | * @brief Set the online status. | ||
84 | * | ||
85 | * NOTE: This API may be deprecated if there is any transient status | ||
86 | * other than online status. | ||
87 | * @param is_online Se the online status | ||
88 | */ | ||
89 | void online(bool is_online); | ||
90 | //@} | ||
91 | |||
92 | /* @name Granted rights | ||
93 | */ | ||
94 | //@{ | ||
95 | /** | ||
96 | * @brief Anonymous enumeration for specifying rights. | ||
97 | */ | ||
98 | enum | ||
99 | { | ||
100 | GRANT_NONE = 0x0, | ||
101 | GRANT_ONLINE_STATUS = 0x1, | ||
102 | GRANT_MAP_LOCATION = 0x2, | ||
103 | GRANT_MODIFY_OBJECTS = 0x4, | ||
104 | }; | ||
105 | |||
106 | /** | ||
107 | * ??? | ||
108 | */ | ||
109 | static const U8 GRANTED_VISIBLE_MASK; | ||
110 | |||
111 | /** | ||
112 | * @brief Check for a set of rights granted to agent. | ||
113 | * | ||
114 | * @param rights A bitfield to check for rights. | ||
115 | * @return Returns true if all rights have been granted. | ||
116 | */ | ||
117 | bool isRightGrantedTo(S32 rights) const; | ||
118 | |||
119 | /** | ||
120 | * @brief Check for a set of rights granted from an agent. | ||
121 | * | ||
122 | * @param rights A bitfield to check for rights. | ||
123 | * @return Returns true if all rights have been granted. | ||
124 | */ | ||
125 | bool isRightGrantedFrom(S32 rights) const; | ||
126 | |||
127 | /** | ||
128 | * @brief Get the rights granted to the other agent. | ||
129 | * | ||
130 | * @return Returns the bitmask of granted rights. | ||
131 | */ | ||
132 | S32 getRightsGrantedTo() const; | ||
133 | |||
134 | /** | ||
135 | * @brief Get the rights granted from the other agent. | ||
136 | * | ||
137 | * @return Returns the bitmask of granted rights. | ||
138 | */ | ||
139 | S32 getRightsGrantedFrom() const; | ||
140 | |||
141 | void setRightsTo(S32 to_agent) { mGrantToAgent = to_agent; } | ||
142 | void setRightsFrom(S32 from_agent) { mGrantFromAgent = from_agent; } | ||
143 | |||
144 | /** | ||
145 | * @brief Grant a set of rights. | ||
146 | * | ||
147 | * Any bit which is set will grant that right if it is set in the | ||
148 | * instance. You can pass in LLGrantedRights::NONE to not change | ||
149 | * that field. | ||
150 | * @param to_agent The rights to grant to agent_id. | ||
151 | * @param from_agent The rights granted from agent_id. | ||
152 | */ | ||
153 | void grantRights(S32 to_agent, S32 from_agent); | ||
154 | |||
155 | /** | ||
156 | * @brief Revoke a set of rights. | ||
157 | * | ||
158 | * Any bit which is set will revoke that right if it is set in the | ||
159 | * instance. You can pass in LLGrantedRights::NONE to not change | ||
160 | * that field. | ||
161 | * @param to_agent The rights to grant to agent_id. | ||
162 | * @param from_agent The rights granted from agent_id. | ||
163 | */ | ||
164 | void revokeRights(S32 to_agent, S32 from_agent); | ||
165 | //@} | ||
166 | |||
167 | protected: | ||
168 | S32 mGrantToAgent; | ||
169 | S32 mGrantFromAgent; | ||
170 | bool mIsOnline; | ||
171 | }; | ||
172 | |||
173 | #endif // LL_LLUSERRELAIONS_H | ||