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