diff options
Diffstat (limited to '')
3 files changed, 292 insertions, 292 deletions
diff --git a/OpenSim/Region/Communications/Local/LocalInventoryService.cs b/OpenSim/Region/Communications/Local/LocalInventoryService.cs index dc91663..1f5b298 100644 --- a/OpenSim/Region/Communications/Local/LocalInventoryService.cs +++ b/OpenSim/Region/Communications/Local/LocalInventoryService.cs | |||
@@ -1,67 +1,67 @@ | |||
1 | using System.Collections.Generic; | 1 | using System.Collections.Generic; |
2 | using libsecondlife; | 2 | using libsecondlife; |
3 | using OpenSim.Framework.Communications; | 3 | using OpenSim.Framework.Communications; |
4 | using OpenSim.Framework.Types; | 4 | using OpenSim.Framework.Types; |
5 | using InventoryFolder=OpenSim.Framework.Communications.Caches.InventoryFolder; | 5 | using InventoryFolder=OpenSim.Framework.Communications.Caches.InventoryFolder; |
6 | 6 | ||
7 | namespace OpenSim.Region.Communications.Local | 7 | namespace OpenSim.Region.Communications.Local |
8 | { | 8 | { |
9 | public class LocalInventoryService : InventoryServiceBase | 9 | public class LocalInventoryService : InventoryServiceBase |
10 | { | 10 | { |
11 | 11 | ||
12 | public LocalInventoryService() | 12 | public LocalInventoryService() |
13 | { | 13 | { |
14 | 14 | ||
15 | } | 15 | } |
16 | 16 | ||
17 | public override void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, InventoryItemInfo itemCallBack) | 17 | public override void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, InventoryItemInfo itemCallBack) |
18 | { | 18 | { |
19 | List<InventoryFolderBase> folders = this.RequestFirstLevelFolders(userID); | 19 | List<InventoryFolderBase> folders = this.RequestFirstLevelFolders(userID); |
20 | InventoryFolder rootFolder = null; | 20 | InventoryFolder rootFolder = null; |
21 | 21 | ||
22 | //need to make sure we send root folder first | 22 | //need to make sure we send root folder first |
23 | foreach (InventoryFolderBase folder in folders) | 23 | foreach (InventoryFolderBase folder in folders) |
24 | { | 24 | { |
25 | if (folder.parentID == libsecondlife.LLUUID.Zero) | 25 | if (folder.parentID == libsecondlife.LLUUID.Zero) |
26 | { | 26 | { |
27 | InventoryFolder newfolder = new InventoryFolder(folder); | 27 | InventoryFolder newfolder = new InventoryFolder(folder); |
28 | rootFolder = newfolder; | 28 | rootFolder = newfolder; |
29 | folderCallBack(userID, newfolder); | 29 | folderCallBack(userID, newfolder); |
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | if (rootFolder != null) | 33 | if (rootFolder != null) |
34 | { | 34 | { |
35 | foreach (InventoryFolderBase folder in folders) | 35 | foreach (InventoryFolderBase folder in folders) |
36 | { | 36 | { |
37 | if (folder.folderID != rootFolder.folderID) | 37 | if (folder.folderID != rootFolder.folderID) |
38 | { | 38 | { |
39 | InventoryFolder newfolder = new InventoryFolder(folder); | 39 | InventoryFolder newfolder = new InventoryFolder(folder); |
40 | folderCallBack(userID, newfolder); | 40 | folderCallBack(userID, newfolder); |
41 | 41 | ||
42 | List<InventoryItemBase> items = this.RequestFolderItems(newfolder.folderID); | 42 | List<InventoryItemBase> items = this.RequestFolderItems(newfolder.folderID); |
43 | foreach (InventoryItemBase item in items) | 43 | foreach (InventoryItemBase item in items) |
44 | { | 44 | { |
45 | itemCallBack(userID, item); | 45 | itemCallBack(userID, item); |
46 | } | 46 | } |
47 | } | 47 | } |
48 | } | 48 | } |
49 | } | 49 | } |
50 | } | 50 | } |
51 | 51 | ||
52 | public override void AddNewInventoryFolder(LLUUID userID, InventoryFolder folder) | 52 | public override void AddNewInventoryFolder(LLUUID userID, InventoryFolder folder) |
53 | { | 53 | { |
54 | this.AddFolder(folder); | 54 | this.AddFolder(folder); |
55 | } | 55 | } |
56 | 56 | ||
57 | public override void AddNewInventoryItem(LLUUID userID, InventoryItemBase item) | 57 | public override void AddNewInventoryItem(LLUUID userID, InventoryItemBase item) |
58 | { | 58 | { |
59 | this.AddItem(item); | 59 | this.AddItem(item); |
60 | } | 60 | } |
61 | 61 | ||
62 | public override void DeleteInventoryItem(LLUUID userID, InventoryItemBase item) | 62 | public override void DeleteInventoryItem(LLUUID userID, InventoryItemBase item) |
63 | { | 63 | { |
64 | this.deleteItem(item); | 64 | this.deleteItem(item); |
65 | } | 65 | } |
66 | } | 66 | } |
67 | } | 67 | } |
diff --git a/OpenSim/Region/Communications/Local/LocalLoginService.cs b/OpenSim/Region/Communications/Local/LocalLoginService.cs index 6829598..6ad39b0 100644 --- a/OpenSim/Region/Communications/Local/LocalLoginService.cs +++ b/OpenSim/Region/Communications/Local/LocalLoginService.cs | |||
@@ -1,173 +1,173 @@ | |||
1 | using System; | 1 | using System; |
2 | using System.Collections; | 2 | using System.Collections; |
3 | using System.Collections.Generic; | 3 | using System.Collections.Generic; |
4 | using libsecondlife; | 4 | using libsecondlife; |
5 | using OpenSim.Framework.Communications; | 5 | using OpenSim.Framework.Communications; |
6 | using OpenSim.Framework.Types; | 6 | using OpenSim.Framework.Types; |
7 | using OpenSim.Framework.UserManagement; | 7 | using OpenSim.Framework.UserManagement; |
8 | using OpenSim.Framework.Utilities; | 8 | using OpenSim.Framework.Utilities; |
9 | using OpenSim.Framework.Inventory; | 9 | using OpenSim.Framework.Inventory; |
10 | 10 | ||
11 | namespace OpenSim.Region.Communications.Local | 11 | namespace OpenSim.Region.Communications.Local |
12 | { | 12 | { |
13 | public delegate void LoginToRegionEvent(ulong regionHandle, Login login); | 13 | public delegate void LoginToRegionEvent(ulong regionHandle, Login login); |
14 | 14 | ||
15 | public class LocalLoginService : LoginService | 15 | public class LocalLoginService : LoginService |
16 | { | 16 | { |
17 | private CommunicationsLocal m_Parent; | 17 | private CommunicationsLocal m_Parent; |
18 | 18 | ||
19 | private NetworkServersInfo serversInfo; | 19 | private NetworkServersInfo serversInfo; |
20 | private uint defaultHomeX; | 20 | private uint defaultHomeX; |
21 | private uint defaultHomeY; | 21 | private uint defaultHomeY; |
22 | private bool authUsers = false; | 22 | private bool authUsers = false; |
23 | 23 | ||
24 | public event LoginToRegionEvent OnLoginToRegion; | 24 | public event LoginToRegionEvent OnLoginToRegion; |
25 | 25 | ||
26 | public LocalLoginService(UserManagerBase userManager, string welcomeMess, CommunicationsLocal parent, NetworkServersInfo serversInfo, bool authenticate) | 26 | public LocalLoginService(UserManagerBase userManager, string welcomeMess, CommunicationsLocal parent, NetworkServersInfo serversInfo, bool authenticate) |
27 | : base(userManager, welcomeMess) | 27 | : base(userManager, welcomeMess) |
28 | { | 28 | { |
29 | m_Parent = parent; | 29 | m_Parent = parent; |
30 | this.serversInfo = serversInfo; | 30 | this.serversInfo = serversInfo; |
31 | defaultHomeX = this.serversInfo.DefaultHomeLocX; | 31 | defaultHomeX = this.serversInfo.DefaultHomeLocX; |
32 | defaultHomeY = this.serversInfo.DefaultHomeLocY; | 32 | defaultHomeY = this.serversInfo.DefaultHomeLocY; |
33 | this.authUsers = authenticate; | 33 | this.authUsers = authenticate; |
34 | } | 34 | } |
35 | 35 | ||
36 | 36 | ||
37 | public override UserProfileData GetTheUser(string firstname, string lastname) | 37 | public override UserProfileData GetTheUser(string firstname, string lastname) |
38 | { | 38 | { |
39 | UserProfileData profile = this.m_userManager.GetUserProfile(firstname, lastname); | 39 | UserProfileData profile = this.m_userManager.GetUserProfile(firstname, lastname); |
40 | if (profile != null) | 40 | if (profile != null) |
41 | { | 41 | { |
42 | 42 | ||
43 | return profile; | 43 | return profile; |
44 | } | 44 | } |
45 | 45 | ||
46 | if (!authUsers) | 46 | if (!authUsers) |
47 | { | 47 | { |
48 | //no current user account so make one | 48 | //no current user account so make one |
49 | Console.WriteLine("No User account found so creating a new one "); | 49 | Console.WriteLine("No User account found so creating a new one "); |
50 | this.m_userManager.AddUserProfile(firstname, lastname, "test", defaultHomeX, defaultHomeY); | 50 | this.m_userManager.AddUserProfile(firstname, lastname, "test", defaultHomeX, defaultHomeY); |
51 | 51 | ||
52 | profile = this.m_userManager.GetUserProfile(firstname, lastname); | 52 | profile = this.m_userManager.GetUserProfile(firstname, lastname); |
53 | if (profile != null) | 53 | if (profile != null) |
54 | { | 54 | { |
55 | m_Parent.InventoryService.CreateNewUserInventory(profile.UUID); | 55 | m_Parent.InventoryService.CreateNewUserInventory(profile.UUID); |
56 | } | 56 | } |
57 | 57 | ||
58 | return profile; | 58 | return profile; |
59 | } | 59 | } |
60 | return null; | 60 | return null; |
61 | } | 61 | } |
62 | 62 | ||
63 | public override bool AuthenticateUser(UserProfileData profile, string password) | 63 | public override bool AuthenticateUser(UserProfileData profile, string password) |
64 | { | 64 | { |
65 | if (!authUsers) | 65 | if (!authUsers) |
66 | { | 66 | { |
67 | //for now we will accept any password in sandbox mode | 67 | //for now we will accept any password in sandbox mode |
68 | Console.WriteLine("authorising user"); | 68 | Console.WriteLine("authorising user"); |
69 | return true; | 69 | return true; |
70 | } | 70 | } |
71 | else | 71 | else |
72 | { | 72 | { |
73 | Console.WriteLine("Authenticating " + profile.username + " " + profile.surname); | 73 | Console.WriteLine("Authenticating " + profile.username + " " + profile.surname); |
74 | 74 | ||
75 | password = password.Remove(0, 3); //remove $1$ | 75 | password = password.Remove(0, 3); //remove $1$ |
76 | 76 | ||
77 | string s = Util.Md5Hash(password + ":" + profile.passwordSalt); | 77 | string s = Util.Md5Hash(password + ":" + profile.passwordSalt); |
78 | 78 | ||
79 | return profile.passwordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase); | 79 | return profile.passwordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase); |
80 | } | 80 | } |
81 | } | 81 | } |
82 | 82 | ||
83 | public override void CustomiseResponse(LoginResponse response, UserProfileData theUser) | 83 | public override void CustomiseResponse(LoginResponse response, UserProfileData theUser) |
84 | { | 84 | { |
85 | ulong currentRegion = theUser.currentAgent.currentHandle; | 85 | ulong currentRegion = theUser.currentAgent.currentHandle; |
86 | RegionInfo reg = m_Parent.GridService.RequestNeighbourInfo(currentRegion); | 86 | RegionInfo reg = m_Parent.GridService.RequestNeighbourInfo(currentRegion); |
87 | 87 | ||
88 | if (reg != null) | 88 | if (reg != null) |
89 | { | 89 | { |
90 | response.Home = "{'region_handle':[r" + (reg.RegionLocX * 256).ToString() + ",r" + (reg.RegionLocY * 256).ToString() + "], " + | 90 | response.Home = "{'region_handle':[r" + (reg.RegionLocX * 256).ToString() + ",r" + (reg.RegionLocY * 256).ToString() + "], " + |
91 | "'position':[r" + theUser.homeLocation.X.ToString() + ",r" + theUser.homeLocation.Y.ToString() + ",r" + theUser.homeLocation.Z.ToString() + "], " + | 91 | "'position':[r" + theUser.homeLocation.X.ToString() + ",r" + theUser.homeLocation.Y.ToString() + ",r" + theUser.homeLocation.Z.ToString() + "], " + |
92 | "'look_at':[r" + theUser.homeLocation.X.ToString() + ",r" + theUser.homeLocation.Y.ToString() + ",r" + theUser.homeLocation.Z.ToString() + "]}"; | 92 | "'look_at':[r" + theUser.homeLocation.X.ToString() + ",r" + theUser.homeLocation.Y.ToString() + ",r" + theUser.homeLocation.Z.ToString() + "]}"; |
93 | string capsPath = Util.GetRandomCapsPath(); | 93 | string capsPath = Util.GetRandomCapsPath(); |
94 | response.SimAddress = reg.ExternalEndPoint.Address.ToString(); | 94 | response.SimAddress = reg.ExternalEndPoint.Address.ToString(); |
95 | response.SimPort = (Int32)reg.ExternalEndPoint.Port; | 95 | response.SimPort = (Int32)reg.ExternalEndPoint.Port; |
96 | response.RegionX = reg.RegionLocX; | 96 | response.RegionX = reg.RegionLocX; |
97 | response.RegionY = reg.RegionLocY; | 97 | response.RegionY = reg.RegionLocY; |
98 | 98 | ||
99 | 99 | ||
100 | response.SeedCapability = "http://" + reg.ExternalHostName + ":" + this.serversInfo.HttpListenerPort.ToString() + "/CAPS/" + capsPath + "0000/"; | 100 | response.SeedCapability = "http://" + reg.ExternalHostName + ":" + this.serversInfo.HttpListenerPort.ToString() + "/CAPS/" + capsPath + "0000/"; |
101 | // response.SeedCapability = "http://" + reg.ExternalHostName + ":" + this.serversInfo.HttpListenerPort.ToString() + "/CapsSeed/" + capsPath + "0000/"; | 101 | // response.SeedCapability = "http://" + reg.ExternalHostName + ":" + this.serversInfo.HttpListenerPort.ToString() + "/CapsSeed/" + capsPath + "0000/"; |
102 | theUser.currentAgent.currentRegion = reg.SimUUID; | 102 | theUser.currentAgent.currentRegion = reg.SimUUID; |
103 | theUser.currentAgent.currentHandle = reg.RegionHandle; | 103 | theUser.currentAgent.currentHandle = reg.RegionHandle; |
104 | 104 | ||
105 | Login _login = new Login(); | 105 | Login _login = new Login(); |
106 | //copy data to login object | 106 | //copy data to login object |
107 | _login.First = response.Firstname; | 107 | _login.First = response.Firstname; |
108 | _login.Last = response.Lastname; | 108 | _login.Last = response.Lastname; |
109 | _login.Agent = response.AgentID; | 109 | _login.Agent = response.AgentID; |
110 | _login.Session = response.SessionID; | 110 | _login.Session = response.SessionID; |
111 | _login.SecureSession = response.SecureSessionID; | 111 | _login.SecureSession = response.SecureSessionID; |
112 | _login.CircuitCode = (uint)response.CircuitCode; | 112 | _login.CircuitCode = (uint)response.CircuitCode; |
113 | _login.CapsPath = capsPath; | 113 | _login.CapsPath = capsPath; |
114 | 114 | ||
115 | if( OnLoginToRegion != null ) | 115 | if( OnLoginToRegion != null ) |
116 | { | 116 | { |
117 | OnLoginToRegion(currentRegion, _login); | 117 | OnLoginToRegion(currentRegion, _login); |
118 | } | 118 | } |
119 | } | 119 | } |
120 | else | 120 | else |
121 | { | 121 | { |
122 | Console.WriteLine("not found region " + currentRegion); | 122 | Console.WriteLine("not found region " + currentRegion); |
123 | } | 123 | } |
124 | 124 | ||
125 | } | 125 | } |
126 | 126 | ||
127 | protected override InventoryData CreateInventoryData(LLUUID userID) | 127 | protected override InventoryData CreateInventoryData(LLUUID userID) |
128 | { | 128 | { |
129 | List<InventoryFolderBase> folders = m_Parent.InventoryService.RequestFirstLevelFolders(userID); | 129 | List<InventoryFolderBase> folders = m_Parent.InventoryService.RequestFirstLevelFolders(userID); |
130 | if (folders.Count > 0) | 130 | if (folders.Count > 0) |
131 | { | 131 | { |
132 | LLUUID rootID = LLUUID.Zero; | 132 | LLUUID rootID = LLUUID.Zero; |
133 | ArrayList AgentInventoryArray = new ArrayList(); | 133 | ArrayList AgentInventoryArray = new ArrayList(); |
134 | Hashtable TempHash; | 134 | Hashtable TempHash; |
135 | foreach (InventoryFolderBase InvFolder in folders) | 135 | foreach (InventoryFolderBase InvFolder in folders) |
136 | { | 136 | { |
137 | if (InvFolder.parentID == LLUUID.Zero) | 137 | if (InvFolder.parentID == LLUUID.Zero) |
138 | { | 138 | { |
139 | rootID = InvFolder.folderID; | 139 | rootID = InvFolder.folderID; |
140 | } | 140 | } |
141 | TempHash = new Hashtable(); | 141 | TempHash = new Hashtable(); |
142 | TempHash["name"] = InvFolder.name; | 142 | TempHash["name"] = InvFolder.name; |
143 | TempHash["parent_id"] = InvFolder.parentID.ToStringHyphenated(); | 143 | TempHash["parent_id"] = InvFolder.parentID.ToStringHyphenated(); |
144 | TempHash["version"] = (Int32)InvFolder.version; | 144 | TempHash["version"] = (Int32)InvFolder.version; |
145 | TempHash["type_default"] = (Int32)InvFolder.type; | 145 | TempHash["type_default"] = (Int32)InvFolder.type; |
146 | TempHash["folder_id"] = InvFolder.folderID.ToStringHyphenated(); | 146 | TempHash["folder_id"] = InvFolder.folderID.ToStringHyphenated(); |
147 | AgentInventoryArray.Add(TempHash); | 147 | AgentInventoryArray.Add(TempHash); |
148 | } | 148 | } |
149 | return new InventoryData(AgentInventoryArray, rootID); | 149 | return new InventoryData(AgentInventoryArray, rootID); |
150 | } | 150 | } |
151 | else | 151 | else |
152 | { | 152 | { |
153 | AgentInventory userInventory = new AgentInventory(); | 153 | AgentInventory userInventory = new AgentInventory(); |
154 | userInventory.CreateRootFolder(userID, false); | 154 | userInventory.CreateRootFolder(userID, false); |
155 | 155 | ||
156 | ArrayList AgentInventoryArray = new ArrayList(); | 156 | ArrayList AgentInventoryArray = new ArrayList(); |
157 | Hashtable TempHash; | 157 | Hashtable TempHash; |
158 | foreach (OpenSim.Framework.Inventory.InventoryFolder InvFolder in userInventory.InventoryFolders.Values) | 158 | foreach (OpenSim.Framework.Inventory.InventoryFolder InvFolder in userInventory.InventoryFolders.Values) |
159 | { | 159 | { |
160 | TempHash = new Hashtable(); | 160 | TempHash = new Hashtable(); |
161 | TempHash["name"] = InvFolder.FolderName; | 161 | TempHash["name"] = InvFolder.FolderName; |
162 | TempHash["parent_id"] = InvFolder.ParentID.ToStringHyphenated(); | 162 | TempHash["parent_id"] = InvFolder.ParentID.ToStringHyphenated(); |
163 | TempHash["version"] = (Int32)InvFolder.Version; | 163 | TempHash["version"] = (Int32)InvFolder.Version; |
164 | TempHash["type_default"] = (Int32)InvFolder.DefaultType; | 164 | TempHash["type_default"] = (Int32)InvFolder.DefaultType; |
165 | TempHash["folder_id"] = InvFolder.FolderID.ToStringHyphenated(); | 165 | TempHash["folder_id"] = InvFolder.FolderID.ToStringHyphenated(); |
166 | AgentInventoryArray.Add(TempHash); | 166 | AgentInventoryArray.Add(TempHash); |
167 | } | 167 | } |
168 | 168 | ||
169 | return new InventoryData(AgentInventoryArray, userInventory.InventoryRoot.FolderID); | 169 | return new InventoryData(AgentInventoryArray, userInventory.InventoryRoot.FolderID); |
170 | } | 170 | } |
171 | } | 171 | } |
172 | } | 172 | } |
173 | } | 173 | } |
diff --git a/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs b/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs index f364771..56e1740 100644 --- a/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs +++ b/OpenSim/Region/Communications/OGS1/OGS1InventoryService.cs | |||
@@ -1,52 +1,52 @@ | |||
1 | using System.Collections.Generic; | 1 | using System.Collections.Generic; |
2 | using libsecondlife; | 2 | using libsecondlife; |
3 | using OpenSim.Framework.Communications; | 3 | using OpenSim.Framework.Communications; |
4 | using OpenSim.Framework.Types; | 4 | using OpenSim.Framework.Types; |
5 | using InventoryFolder = OpenSim.Framework.Communications.Caches.InventoryFolder; | 5 | using InventoryFolder = OpenSim.Framework.Communications.Caches.InventoryFolder; |
6 | 6 | ||
7 | 7 | ||
8 | namespace OpenSim.Region.Communications.OGS1 | 8 | namespace OpenSim.Region.Communications.OGS1 |
9 | { | 9 | { |
10 | public class OGS1InventoryService : IInventoryServices | 10 | public class OGS1InventoryService : IInventoryServices |
11 | { | 11 | { |
12 | 12 | ||
13 | public OGS1InventoryService() | 13 | public OGS1InventoryService() |
14 | { | 14 | { |
15 | 15 | ||
16 | } | 16 | } |
17 | 17 | ||
18 | #region IInventoryServices Members | 18 | #region IInventoryServices Members |
19 | 19 | ||
20 | public void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, InventoryItemInfo itemCallBack) | 20 | public void RequestInventoryForUser(LLUUID userID, InventoryFolderInfo folderCallBack, InventoryItemInfo itemCallBack) |
21 | { | 21 | { |
22 | 22 | ||
23 | } | 23 | } |
24 | 24 | ||
25 | public void AddNewInventoryFolder(LLUUID userID, InventoryFolder folder) | 25 | public void AddNewInventoryFolder(LLUUID userID, InventoryFolder folder) |
26 | { | 26 | { |
27 | 27 | ||
28 | } | 28 | } |
29 | 29 | ||
30 | public void AddNewInventoryItem(LLUUID userID, InventoryItemBase item) | 30 | public void AddNewInventoryItem(LLUUID userID, InventoryItemBase item) |
31 | { | 31 | { |
32 | 32 | ||
33 | } | 33 | } |
34 | 34 | ||
35 | public void DeleteInventoryItem(LLUUID userID, InventoryItemBase item) | 35 | public void DeleteInventoryItem(LLUUID userID, InventoryItemBase item) |
36 | { | 36 | { |
37 | 37 | ||
38 | } | 38 | } |
39 | 39 | ||
40 | public void CreateNewUserInventory(LLUUID user) | 40 | public void CreateNewUserInventory(LLUUID user) |
41 | { | 41 | { |
42 | 42 | ||
43 | } | 43 | } |
44 | 44 | ||
45 | public List<InventoryFolderBase> RequestFirstLevelFolders(LLUUID userID) | 45 | public List<InventoryFolderBase> RequestFirstLevelFolders(LLUUID userID) |
46 | { | 46 | { |
47 | return new List<InventoryFolderBase>(); | 47 | return new List<InventoryFolderBase>(); |
48 | } | 48 | } |
49 | 49 | ||
50 | #endregion | 50 | #endregion |
51 | } | 51 | } |
52 | } | 52 | } |