diff options
author | David Walter Seikel | 2013-02-23 19:18:44 +1000 |
---|---|---|
committer | David Walter Seikel | 2013-02-23 19:18:44 +1000 |
commit | 958c10d0f13489c2ab3a26b802911df8144528ef (patch) | |
tree | 85692f95b4461eab57fac13a807a7eca074732a6 /addon-modules/OpenSimSearch/Modules | |
parent | No, we don't need to enshrine viewer bugs in the server, we need to fix the v... (diff) | |
download | opensim-SC_OLD-958c10d0f13489c2ab3a26b802911df8144528ef.zip opensim-SC_OLD-958c10d0f13489c2ab3a26b802911df8144528ef.tar.gz opensim-SC_OLD-958c10d0f13489c2ab3a26b802911df8144528ef.tar.bz2 opensim-SC_OLD-958c10d0f13489c2ab3a26b802911df8144528ef.tar.xz |
Add profile and search modules.
Diffstat (limited to 'addon-modules/OpenSimSearch/Modules')
-rw-r--r-- | addon-modules/OpenSimSearch/Modules/SearchModule/OpenSearch.cs | 753 |
1 files changed, 753 insertions, 0 deletions
diff --git a/addon-modules/OpenSimSearch/Modules/SearchModule/OpenSearch.cs b/addon-modules/OpenSimSearch/Modules/SearchModule/OpenSearch.cs new file mode 100644 index 0000000..2544614 --- /dev/null +++ b/addon-modules/OpenSimSearch/Modules/SearchModule/OpenSearch.cs | |||
@@ -0,0 +1,753 @@ | |||
1 | using System; | ||
2 | using System.Collections; | ||
3 | using System.Collections.Generic; | ||
4 | using System.Globalization; | ||
5 | using System.Net; | ||
6 | using System.Net.Sockets; | ||
7 | using System.Reflection; | ||
8 | using System.Xml; | ||
9 | using OpenMetaverse; | ||
10 | using log4net; | ||
11 | using Nini.Config; | ||
12 | using Nwc.XmlRpc; | ||
13 | using OpenSim.Framework; | ||
14 | using OpenSim.Region.Framework.Interfaces; | ||
15 | using OpenSim.Region.Framework.Scenes; | ||
16 | using OpenSim.Services.Interfaces; | ||
17 | using Mono.Addins; | ||
18 | |||
19 | [assembly: Addin("OpenSearchModule", "0.1")] | ||
20 | [assembly: AddinDependency("OpenSim", "0.5")] | ||
21 | |||
22 | namespace OpenSimSearch.Modules.OpenSearch | ||
23 | { | ||
24 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] | ||
25 | public class OpenSearchModule : ISearchModule, ISharedRegionModule | ||
26 | { | ||
27 | // | ||
28 | // Log module | ||
29 | // | ||
30 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
31 | |||
32 | // | ||
33 | // Module vars | ||
34 | // | ||
35 | private List<Scene> m_Scenes = new List<Scene>(); | ||
36 | private string m_SearchServer = ""; | ||
37 | private bool m_Enabled = true; | ||
38 | |||
39 | public void Initialise(IConfigSource config) | ||
40 | { | ||
41 | IConfig searchConfig = config.Configs["Search"]; | ||
42 | |||
43 | if (searchConfig == null) | ||
44 | { | ||
45 | m_Enabled = false; | ||
46 | return; | ||
47 | } | ||
48 | if (searchConfig.GetString("Module", "OpenSimSearch") != "OpenSimSearch") | ||
49 | { | ||
50 | m_Enabled = false; | ||
51 | return; | ||
52 | } | ||
53 | |||
54 | m_SearchServer = searchConfig.GetString("SearchURL", ""); | ||
55 | if (m_SearchServer == "") | ||
56 | { | ||
57 | m_log.Error("[SEARCH] No search server, disabling search"); | ||
58 | m_Enabled = false; | ||
59 | return; | ||
60 | } | ||
61 | else | ||
62 | { | ||
63 | m_log.Info("[SEARCH] Search module is activated"); | ||
64 | m_Enabled = true; | ||
65 | } | ||
66 | } | ||
67 | |||
68 | public void AddRegion(Scene scene) | ||
69 | { | ||
70 | if (!m_Enabled) | ||
71 | return; | ||
72 | |||
73 | // Hook up events | ||
74 | scene.EventManager.OnNewClient += OnNewClient; | ||
75 | |||
76 | // Take ownership of the ISearchModule service | ||
77 | scene.RegisterModuleInterface<ISearchModule>(this); | ||
78 | |||
79 | // Add our scene to our list... | ||
80 | lock(m_Scenes) | ||
81 | { | ||
82 | m_Scenes.Add(scene); | ||
83 | } | ||
84 | |||
85 | } | ||
86 | |||
87 | public void RemoveRegion(Scene scene) | ||
88 | { | ||
89 | if (!m_Enabled) | ||
90 | return; | ||
91 | |||
92 | scene.UnregisterModuleInterface<ISearchModule>(this); | ||
93 | m_Scenes.Remove(scene); | ||
94 | } | ||
95 | |||
96 | public void RegionLoaded(Scene scene) | ||
97 | { | ||
98 | } | ||
99 | |||
100 | public Type ReplaceableInterface | ||
101 | { | ||
102 | get { return null; } | ||
103 | } | ||
104 | |||
105 | public void PostInitialise() | ||
106 | { | ||
107 | } | ||
108 | |||
109 | public void Close() | ||
110 | { | ||
111 | } | ||
112 | |||
113 | public string Name | ||
114 | { | ||
115 | get { return "SearchModule"; } | ||
116 | } | ||
117 | |||
118 | public bool IsSharedModule | ||
119 | { | ||
120 | get { return true; } | ||
121 | } | ||
122 | |||
123 | /// New Client Event Handler | ||
124 | private void OnNewClient(IClientAPI client) | ||
125 | { | ||
126 | // Subscribe to messages | ||
127 | client.OnDirPlacesQuery += DirPlacesQuery; | ||
128 | client.OnDirFindQuery += DirFindQuery; | ||
129 | client.OnDirPopularQuery += DirPopularQuery; | ||
130 | client.OnDirLandQuery += DirLandQuery; | ||
131 | client.OnDirClassifiedQuery += DirClassifiedQuery; | ||
132 | // Response after Directory Queries | ||
133 | client.OnEventInfoRequest += EventInfoRequest; | ||
134 | client.OnClassifiedInfoRequest += ClassifiedInfoRequest; | ||
135 | client.OnMapItemRequest += HandleMapItemRequest; | ||
136 | } | ||
137 | |||
138 | // | ||
139 | // Make external XMLRPC request | ||
140 | // | ||
141 | private Hashtable GenericXMLRPCRequest(Hashtable ReqParams, string method) | ||
142 | { | ||
143 | ArrayList SendParams = new ArrayList(); | ||
144 | SendParams.Add(ReqParams); | ||
145 | |||
146 | // Send Request | ||
147 | XmlRpcResponse Resp; | ||
148 | try | ||
149 | { | ||
150 | XmlRpcRequest Req = new XmlRpcRequest(method, SendParams); | ||
151 | Resp = Req.Send(m_SearchServer, 30000); | ||
152 | } | ||
153 | catch (WebException ex) | ||
154 | { | ||
155 | m_log.ErrorFormat("[SEARCH]: Unable to connect to Search " + | ||
156 | "Server {0}. Exception {1}", m_SearchServer, ex); | ||
157 | |||
158 | Hashtable ErrorHash = new Hashtable(); | ||
159 | ErrorHash["success"] = false; | ||
160 | ErrorHash["errorMessage"] = "Unable to search at this time. "; | ||
161 | ErrorHash["errorURI"] = ""; | ||
162 | |||
163 | return ErrorHash; | ||
164 | } | ||
165 | catch (SocketException ex) | ||
166 | { | ||
167 | m_log.ErrorFormat( | ||
168 | "[SEARCH]: Unable to connect to Search Server {0}. " + | ||
169 | "Exception {1}", m_SearchServer, ex); | ||
170 | |||
171 | Hashtable ErrorHash = new Hashtable(); | ||
172 | ErrorHash["success"] = false; | ||
173 | ErrorHash["errorMessage"] = "Unable to search at this time. "; | ||
174 | ErrorHash["errorURI"] = ""; | ||
175 | |||
176 | return ErrorHash; | ||
177 | } | ||
178 | catch (XmlException ex) | ||
179 | { | ||
180 | m_log.ErrorFormat( | ||
181 | "[SEARCH]: Unable to connect to Search Server {0}. " + | ||
182 | "Exception {1}", m_SearchServer, ex); | ||
183 | |||
184 | Hashtable ErrorHash = new Hashtable(); | ||
185 | ErrorHash["success"] = false; | ||
186 | ErrorHash["errorMessage"] = "Unable to search at this time. "; | ||
187 | ErrorHash["errorURI"] = ""; | ||
188 | |||
189 | return ErrorHash; | ||
190 | } | ||
191 | if (Resp.IsFault) | ||
192 | { | ||
193 | Hashtable ErrorHash = new Hashtable(); | ||
194 | ErrorHash["success"] = false; | ||
195 | ErrorHash["errorMessage"] = "Unable to search at this time. "; | ||
196 | ErrorHash["errorURI"] = ""; | ||
197 | return ErrorHash; | ||
198 | } | ||
199 | Hashtable RespData = (Hashtable)Resp.Value; | ||
200 | |||
201 | return RespData; | ||
202 | } | ||
203 | |||
204 | protected void DirPlacesQuery(IClientAPI remoteClient, UUID queryID, | ||
205 | string queryText, int queryFlags, int category, string simName, | ||
206 | int queryStart) | ||
207 | { | ||
208 | Hashtable ReqHash = new Hashtable(); | ||
209 | ReqHash["text"] = queryText; | ||
210 | ReqHash["flags"] = queryFlags.ToString(); | ||
211 | ReqHash["category"] = category.ToString(); | ||
212 | ReqHash["sim_name"] = simName; | ||
213 | ReqHash["query_start"] = queryStart.ToString(); | ||
214 | |||
215 | Hashtable result = GenericXMLRPCRequest(ReqHash, | ||
216 | "dir_places_query"); | ||
217 | |||
218 | if (!Convert.ToBoolean(result["success"])) | ||
219 | { | ||
220 | remoteClient.SendAgentAlertMessage( | ||
221 | result["errorMessage"].ToString(), false); | ||
222 | return; | ||
223 | } | ||
224 | |||
225 | ArrayList dataArray = (ArrayList)result["data"]; | ||
226 | |||
227 | int count = dataArray.Count; | ||
228 | if (count > 100) | ||
229 | count = 101; | ||
230 | |||
231 | DirPlacesReplyData[] data = new DirPlacesReplyData[count]; | ||
232 | |||
233 | int i = 0; | ||
234 | |||
235 | foreach (Object o in dataArray) | ||
236 | { | ||
237 | Hashtable d = (Hashtable)o; | ||
238 | |||
239 | data[i] = new DirPlacesReplyData(); | ||
240 | data[i].parcelID = new UUID(d["parcel_id"].ToString()); | ||
241 | data[i].name = d["name"].ToString(); | ||
242 | data[i].forSale = Convert.ToBoolean(d["for_sale"]); | ||
243 | data[i].auction = Convert.ToBoolean(d["auction"]); | ||
244 | data[i].dwell = Convert.ToSingle(d["dwell"]); | ||
245 | |||
246 | if (++i >= count) | ||
247 | break; | ||
248 | } | ||
249 | |||
250 | remoteClient.SendDirPlacesReply(queryID, data); | ||
251 | } | ||
252 | |||
253 | public void DirPopularQuery(IClientAPI remoteClient, UUID queryID, uint queryFlags) | ||
254 | { | ||
255 | Hashtable ReqHash = new Hashtable(); | ||
256 | ReqHash["flags"] = queryFlags.ToString(); | ||
257 | |||
258 | Hashtable result = GenericXMLRPCRequest(ReqHash, | ||
259 | "dir_popular_query"); | ||
260 | |||
261 | if (!Convert.ToBoolean(result["success"])) | ||
262 | { | ||
263 | remoteClient.SendAgentAlertMessage( | ||
264 | result["errorMessage"].ToString(), false); | ||
265 | return; | ||
266 | } | ||
267 | |||
268 | ArrayList dataArray = (ArrayList)result["data"]; | ||
269 | |||
270 | int count = dataArray.Count; | ||
271 | if (count > 100) | ||
272 | count = 101; | ||
273 | |||
274 | DirPopularReplyData[] data = new DirPopularReplyData[count]; | ||
275 | |||
276 | int i = 0; | ||
277 | |||
278 | foreach (Object o in dataArray) | ||
279 | { | ||
280 | Hashtable d = (Hashtable)o; | ||
281 | |||
282 | data[i] = new DirPopularReplyData(); | ||
283 | data[i].parcelID = new UUID(d["parcel_id"].ToString()); | ||
284 | data[i].name = d["name"].ToString(); | ||
285 | data[i].dwell = Convert.ToSingle(d["dwell"]); | ||
286 | |||
287 | if (++i >= count) | ||
288 | break; | ||
289 | } | ||
290 | |||
291 | remoteClient.SendDirPopularReply(queryID, data); | ||
292 | } | ||
293 | |||
294 | public void DirLandQuery(IClientAPI remoteClient, UUID queryID, | ||
295 | uint queryFlags, uint searchType, int price, int area, | ||
296 | int queryStart) | ||
297 | { | ||
298 | Hashtable ReqHash = new Hashtable(); | ||
299 | ReqHash["flags"] = queryFlags.ToString(); | ||
300 | ReqHash["type"] = searchType.ToString(); | ||
301 | ReqHash["price"] = price.ToString(); | ||
302 | ReqHash["area"] = area.ToString(); | ||
303 | ReqHash["query_start"] = queryStart.ToString(); | ||
304 | |||
305 | Hashtable result = GenericXMLRPCRequest(ReqHash, | ||
306 | "dir_land_query"); | ||
307 | |||
308 | if (!Convert.ToBoolean(result["success"])) | ||
309 | { | ||
310 | remoteClient.SendAgentAlertMessage( | ||
311 | result["errorMessage"].ToString(), false); | ||
312 | return; | ||
313 | } | ||
314 | |||
315 | ArrayList dataArray = (ArrayList)result["data"]; | ||
316 | int count = 0; | ||
317 | |||
318 | /* Count entries in dataArray with valid region name to */ | ||
319 | /* prevent allocating data array with too many entries. */ | ||
320 | foreach (Object o in dataArray) | ||
321 | { | ||
322 | Hashtable d = (Hashtable)o; | ||
323 | |||
324 | if (d["name"] != null) | ||
325 | ++count; | ||
326 | } | ||
327 | |||
328 | if (count > 100) | ||
329 | count = 101; | ||
330 | |||
331 | DirLandReplyData[] data = new DirLandReplyData[count]; | ||
332 | |||
333 | int i = 0; | ||
334 | |||
335 | foreach (Object o in dataArray) | ||
336 | { | ||
337 | Hashtable d = (Hashtable)o; | ||
338 | |||
339 | if (d["name"] == null) | ||
340 | continue; | ||
341 | |||
342 | data[i] = new DirLandReplyData(); | ||
343 | data[i].parcelID = new UUID(d["parcel_id"].ToString()); | ||
344 | data[i].name = d["name"].ToString(); | ||
345 | data[i].auction = Convert.ToBoolean(d["auction"]); | ||
346 | data[i].forSale = Convert.ToBoolean(d["for_sale"]); | ||
347 | data[i].salePrice = Convert.ToInt32(d["sale_price"]); | ||
348 | data[i].actualArea = Convert.ToInt32(d["area"]); | ||
349 | |||
350 | if (++i >= count) | ||
351 | break; | ||
352 | } | ||
353 | |||
354 | remoteClient.SendDirLandReply(queryID, data); | ||
355 | } | ||
356 | |||
357 | public void DirFindQuery(IClientAPI remoteClient, UUID queryID, | ||
358 | string queryText, uint queryFlags, int queryStart) | ||
359 | { | ||
360 | if ((queryFlags & 1) != 0) //People (1 << 0) | ||
361 | { | ||
362 | DirPeopleQuery(remoteClient, queryID, queryText, queryFlags, | ||
363 | queryStart); | ||
364 | return; | ||
365 | } | ||
366 | else if ((queryFlags & 32) != 0) //DateEvents (1 << 5) | ||
367 | { | ||
368 | DirEventsQuery(remoteClient, queryID, queryText, queryFlags, | ||
369 | queryStart); | ||
370 | return; | ||
371 | } | ||
372 | } | ||
373 | |||
374 | public void DirPeopleQuery(IClientAPI remoteClient, UUID queryID, | ||
375 | string queryText, uint queryFlags, int queryStart) | ||
376 | { | ||
377 | List<UserAccount> accounts = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, queryText); | ||
378 | |||
379 | DirPeopleReplyData[] data = | ||
380 | new DirPeopleReplyData[accounts.Count]; | ||
381 | |||
382 | int i = 0; | ||
383 | |||
384 | foreach (UserAccount item in accounts) | ||
385 | { | ||
386 | data[i] = new DirPeopleReplyData(); | ||
387 | |||
388 | data[i].agentID = item.PrincipalID; | ||
389 | data[i].firstName = item.FirstName; | ||
390 | data[i].lastName = item.LastName; | ||
391 | data[i].group = ""; | ||
392 | data[i].online = false; | ||
393 | data[i].reputation = 0; | ||
394 | i++; | ||
395 | } | ||
396 | |||
397 | remoteClient.SendDirPeopleReply(queryID, data); | ||
398 | } | ||
399 | |||
400 | public void DirEventsQuery(IClientAPI remoteClient, UUID queryID, | ||
401 | string queryText, uint queryFlags, int queryStart) | ||
402 | { | ||
403 | Hashtable ReqHash = new Hashtable(); | ||
404 | ReqHash["text"] = queryText; | ||
405 | ReqHash["flags"] = queryFlags.ToString(); | ||
406 | ReqHash["query_start"] = queryStart.ToString(); | ||
407 | |||
408 | Hashtable result = GenericXMLRPCRequest(ReqHash, | ||
409 | "dir_events_query"); | ||
410 | |||
411 | if (!Convert.ToBoolean(result["success"])) | ||
412 | { | ||
413 | remoteClient.SendAgentAlertMessage( | ||
414 | result["errorMessage"].ToString(), false); | ||
415 | return; | ||
416 | } | ||
417 | |||
418 | ArrayList dataArray = (ArrayList)result["data"]; | ||
419 | |||
420 | int count = dataArray.Count; | ||
421 | if (count > 100) | ||
422 | count = 101; | ||
423 | |||
424 | DirEventsReplyData[] data = new DirEventsReplyData[count]; | ||
425 | |||
426 | int i = 0; | ||
427 | |||
428 | foreach (Object o in dataArray) | ||
429 | { | ||
430 | Hashtable d = (Hashtable)o; | ||
431 | |||
432 | data[i] = new DirEventsReplyData(); | ||
433 | data[i].ownerID = new UUID(d["owner_id"].ToString()); | ||
434 | data[i].name = d["name"].ToString(); | ||
435 | data[i].eventID = Convert.ToUInt32(d["event_id"]); | ||
436 | data[i].date = d["date"].ToString(); | ||
437 | data[i].unixTime = Convert.ToUInt32(d["unix_time"]); | ||
438 | data[i].eventFlags = Convert.ToUInt32(d["event_flags"]); | ||
439 | |||
440 | if (++i >= count) | ||
441 | break; | ||
442 | } | ||
443 | |||
444 | remoteClient.SendDirEventsReply(queryID, data); | ||
445 | } | ||
446 | |||
447 | public void DirClassifiedQuery(IClientAPI remoteClient, UUID queryID, | ||
448 | string queryText, uint queryFlags, uint category, | ||
449 | int queryStart) | ||
450 | { | ||
451 | Hashtable ReqHash = new Hashtable(); | ||
452 | ReqHash["text"] = queryText; | ||
453 | ReqHash["flags"] = queryFlags.ToString(); | ||
454 | ReqHash["category"] = category.ToString(); | ||
455 | ReqHash["query_start"] = queryStart.ToString(); | ||
456 | |||
457 | Hashtable result = GenericXMLRPCRequest(ReqHash, | ||
458 | "dir_classified_query"); | ||
459 | |||
460 | if (!Convert.ToBoolean(result["success"])) | ||
461 | { | ||
462 | remoteClient.SendAgentAlertMessage( | ||
463 | result["errorMessage"].ToString(), false); | ||
464 | return; | ||
465 | } | ||
466 | |||
467 | ArrayList dataArray = (ArrayList)result["data"]; | ||
468 | |||
469 | int count = dataArray.Count; | ||
470 | if (count > 100) | ||
471 | count = 101; | ||
472 | |||
473 | DirClassifiedReplyData[] data = new DirClassifiedReplyData[count]; | ||
474 | |||
475 | int i = 0; | ||
476 | |||
477 | foreach (Object o in dataArray) | ||
478 | { | ||
479 | Hashtable d = (Hashtable)o; | ||
480 | |||
481 | data[i] = new DirClassifiedReplyData(); | ||
482 | data[i].classifiedID = new UUID(d["classifiedid"].ToString()); | ||
483 | data[i].name = d["name"].ToString(); | ||
484 | data[i].classifiedFlags = Convert.ToByte(d["classifiedflags"]); | ||
485 | data[i].creationDate = Convert.ToUInt32(d["creation_date"]); | ||
486 | data[i].expirationDate = Convert.ToUInt32(d["expiration_date"]); | ||
487 | data[i].price = Convert.ToInt32(d["priceforlisting"]); | ||
488 | |||
489 | if (++i >= count) | ||
490 | break; | ||
491 | } | ||
492 | |||
493 | remoteClient.SendDirClassifiedReply(queryID, data); | ||
494 | } | ||
495 | |||
496 | public void EventInfoRequest(IClientAPI remoteClient, uint queryEventID) | ||
497 | { | ||
498 | Hashtable ReqHash = new Hashtable(); | ||
499 | ReqHash["eventID"] = queryEventID.ToString(); | ||
500 | |||
501 | Hashtable result = GenericXMLRPCRequest(ReqHash, | ||
502 | "event_info_query"); | ||
503 | |||
504 | if (!Convert.ToBoolean(result["success"])) | ||
505 | { | ||
506 | remoteClient.SendAgentAlertMessage( | ||
507 | result["errorMessage"].ToString(), false); | ||
508 | return; | ||
509 | } | ||
510 | |||
511 | ArrayList dataArray = (ArrayList)result["data"]; | ||
512 | if (dataArray.Count == 0) | ||
513 | { | ||
514 | // something bad happened here, if we could return an | ||
515 | // event after the search, | ||
516 | // we should be able to find it here | ||
517 | // TODO do some (more) sensible error-handling here | ||
518 | remoteClient.SendAgentAlertMessage("Couldn't find this event.", | ||
519 | false); | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | Hashtable d = (Hashtable)dataArray[0]; | ||
524 | EventData data = new EventData(); | ||
525 | data.eventID = Convert.ToUInt32(d["event_id"]); | ||
526 | data.creator = d["creator"].ToString(); | ||
527 | data.name = d["name"].ToString(); | ||
528 | data.category = d["category"].ToString(); | ||
529 | data.description = d["description"].ToString(); | ||
530 | data.date = d["date"].ToString(); | ||
531 | data.dateUTC = Convert.ToUInt32(d["dateUTC"]); | ||
532 | data.duration = Convert.ToUInt32(d["duration"]); | ||
533 | data.cover = Convert.ToUInt32(d["covercharge"]); | ||
534 | data.amount = Convert.ToUInt32(d["coveramount"]); | ||
535 | data.simName = d["simname"].ToString(); | ||
536 | Vector3.TryParse(d["globalposition"].ToString(), out data.globalPos); | ||
537 | data.eventFlags = Convert.ToUInt32(d["eventflags"]); | ||
538 | |||
539 | remoteClient.SendEventInfoReply(data); | ||
540 | } | ||
541 | |||
542 | public void ClassifiedInfoRequest(UUID queryClassifiedID, IClientAPI remoteClient) | ||
543 | { | ||
544 | Hashtable ReqHash = new Hashtable(); | ||
545 | ReqHash["classifiedID"] = queryClassifiedID.ToString(); | ||
546 | |||
547 | Hashtable result = GenericXMLRPCRequest(ReqHash, | ||
548 | "classifieds_info_query"); | ||
549 | |||
550 | if (!Convert.ToBoolean(result["success"])) | ||
551 | { | ||
552 | remoteClient.SendAgentAlertMessage( | ||
553 | result["errorMessage"].ToString(), false); | ||
554 | return; | ||
555 | } | ||
556 | |||
557 | //The viewer seems to issue an info request even when it is | ||
558 | //creating a new classified which means the data hasn't been | ||
559 | //saved to the database yet so there is no info to find. | ||
560 | ArrayList dataArray = (ArrayList)result["data"]; | ||
561 | if (dataArray.Count == 0) | ||
562 | { | ||
563 | // Something bad happened here if we could not return an | ||
564 | // event after the search. We should be able to find it here. | ||
565 | // TODO do some (more) sensible error-handling here | ||
566 | // remoteClient.SendAgentAlertMessage("Couldn't find data for classified ad.", | ||
567 | // false); | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | Hashtable d = (Hashtable)dataArray[0]; | ||
572 | |||
573 | Vector3 globalPos = new Vector3(); | ||
574 | Vector3.TryParse(d["posglobal"].ToString(), out globalPos); | ||
575 | |||
576 | remoteClient.SendClassifiedInfoReply( | ||
577 | new UUID(d["classifieduuid"].ToString()), | ||
578 | new UUID(d["creatoruuid"].ToString()), | ||
579 | Convert.ToUInt32(d["creationdate"]), | ||
580 | Convert.ToUInt32(d["expirationdate"]), | ||
581 | Convert.ToUInt32(d["category"]), | ||
582 | d["name"].ToString(), | ||
583 | d["description"].ToString(), | ||
584 | new UUID(d["parceluuid"].ToString()), | ||
585 | Convert.ToUInt32(d["parentestate"]), | ||
586 | new UUID(d["snapshotuuid"].ToString()), | ||
587 | d["simname"].ToString(), | ||
588 | globalPos, | ||
589 | d["parcelname"].ToString(), | ||
590 | Convert.ToByte(d["classifiedflags"]), | ||
591 | Convert.ToInt32(d["priceforlisting"])); | ||
592 | } | ||
593 | |||
594 | public void HandleMapItemRequest(IClientAPI remoteClient, uint flags, | ||
595 | uint EstateID, bool godlike, | ||
596 | uint itemtype, ulong regionhandle) | ||
597 | { | ||
598 | //The following constant appears to be from GridLayerType enum | ||
599 | //defined in OpenMetaverse/GridManager.cs of libopenmetaverse. | ||
600 | if (itemtype == (uint)OpenMetaverse.GridItemType.LandForSale) | ||
601 | { | ||
602 | Hashtable ReqHash = new Hashtable(); | ||
603 | |||
604 | //The flags are: SortAsc (1 << 15), PerMeterSort (1 << 17) | ||
605 | ReqHash["flags"] = "163840"; | ||
606 | ReqHash["type"] = "4294967295"; //This is -1 in 32 bits | ||
607 | ReqHash["price"] = "0"; | ||
608 | ReqHash["area"] = "0"; | ||
609 | ReqHash["query_start"] = "0"; | ||
610 | |||
611 | Hashtable result = GenericXMLRPCRequest(ReqHash, | ||
612 | "dir_land_query"); | ||
613 | |||
614 | if (!Convert.ToBoolean(result["success"])) | ||
615 | { | ||
616 | remoteClient.SendAgentAlertMessage( | ||
617 | result["errorMessage"].ToString(), false); | ||
618 | return; | ||
619 | } | ||
620 | |||
621 | ArrayList dataArray = (ArrayList)result["data"]; | ||
622 | |||
623 | int count = dataArray.Count; | ||
624 | if (count > 100) | ||
625 | count = 101; | ||
626 | |||
627 | List<mapItemReply> mapitems = new List<mapItemReply>(); | ||
628 | string ParcelRegionUUID; | ||
629 | string[] landingpoint; | ||
630 | |||
631 | foreach (Object o in dataArray) | ||
632 | { | ||
633 | Hashtable d = (Hashtable)o; | ||
634 | |||
635 | if (d["name"] == null) | ||
636 | continue; | ||
637 | |||
638 | mapItemReply mapitem = new mapItemReply(); | ||
639 | |||
640 | ParcelRegionUUID = d["region_UUID"].ToString(); | ||
641 | |||
642 | foreach (Scene scene in m_Scenes) | ||
643 | { | ||
644 | if (scene.RegionInfo.RegionID.ToString() == ParcelRegionUUID) | ||
645 | { | ||
646 | landingpoint = d["landing_point"].ToString().Split('/'); | ||
647 | |||
648 | mapitem.x = (uint)((scene.RegionInfo.RegionLocX * 256) + | ||
649 | Convert.ToDecimal(landingpoint[0])); | ||
650 | mapitem.y = (uint)((scene.RegionInfo.RegionLocY * 256) + | ||
651 | Convert.ToDecimal(landingpoint[1])); | ||
652 | break; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | mapitem.id = new UUID(d["parcel_id"].ToString()); | ||
657 | mapitem.Extra = Convert.ToInt32(d["area"]); | ||
658 | mapitem.Extra2 = Convert.ToInt32(d["sale_price"]); | ||
659 | mapitem.name = d["name"].ToString(); | ||
660 | |||
661 | mapitems.Add(mapitem); | ||
662 | } | ||
663 | |||
664 | remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); | ||
665 | mapitems.Clear(); | ||
666 | } | ||
667 | |||
668 | if (itemtype == (uint)OpenMetaverse.GridItemType.PgEvent || | ||
669 | itemtype == (uint)OpenMetaverse.GridItemType.MatureEvent || | ||
670 | itemtype == (uint)OpenMetaverse.GridItemType.AdultEvent) | ||
671 | { | ||
672 | Hashtable ReqHash = new Hashtable(); | ||
673 | |||
674 | //Find the maturity level | ||
675 | int maturity = (1 << 24); | ||
676 | |||
677 | //Find the maturity level | ||
678 | if (itemtype == (uint)OpenMetaverse.GridItemType.MatureEvent) | ||
679 | maturity = (1 << 25); | ||
680 | else | ||
681 | { | ||
682 | if (itemtype == (uint)OpenMetaverse.GridItemType.AdultEvent) | ||
683 | maturity = (1 << 26); | ||
684 | } | ||
685 | |||
686 | //The flags are: SortAsc (1 << 15), PerMeterSort (1 << 17) | ||
687 | maturity |= 163840; | ||
688 | |||
689 | //Character before | is number of days before/after current date | ||
690 | //Characters after | is the number for a category | ||
691 | ReqHash["text"] = "0|0"; | ||
692 | ReqHash["flags"] = maturity.ToString(); | ||
693 | ReqHash["query_start"] = "0"; | ||
694 | |||
695 | Hashtable result = GenericXMLRPCRequest(ReqHash, | ||
696 | "dir_events_query"); | ||
697 | |||
698 | if (!Convert.ToBoolean(result["success"])) | ||
699 | { | ||
700 | remoteClient.SendAgentAlertMessage( | ||
701 | result["errorMessage"].ToString(), false); | ||
702 | return; | ||
703 | } | ||
704 | |||
705 | ArrayList dataArray = (ArrayList)result["data"]; | ||
706 | |||
707 | List<mapItemReply> mapitems = new List<mapItemReply>(); | ||
708 | string ParcelRegionUUID; | ||
709 | string[] landingpoint; | ||
710 | |||
711 | foreach (Object o in dataArray) | ||
712 | { | ||
713 | Hashtable d = (Hashtable)o; | ||
714 | |||
715 | if (d["name"] == null) | ||
716 | continue; | ||
717 | |||
718 | mapItemReply mapitem = new mapItemReply(); | ||
719 | |||
720 | ParcelRegionUUID = d["region_UUID"].ToString(); | ||
721 | |||
722 | foreach (Scene scene in m_Scenes) | ||
723 | { | ||
724 | if (scene.RegionInfo.RegionID.ToString() == ParcelRegionUUID) | ||
725 | { | ||
726 | landingpoint = d["landing_point"].ToString().Split('/'); | ||
727 | |||
728 | mapitem.x = (uint)((scene.RegionInfo.RegionLocX * 256) + | ||
729 | Convert.ToDecimal(landingpoint[0])); | ||
730 | mapitem.y = (uint)((scene.RegionInfo.RegionLocY * 256) + | ||
731 | Convert.ToDecimal(landingpoint[1])); | ||
732 | break; | ||
733 | } | ||
734 | } | ||
735 | |||
736 | mapitem.id = UUID.Random(); | ||
737 | mapitem.Extra = (int)Convert.ToInt32(d["unix_time"]); | ||
738 | mapitem.Extra2 = (int)Convert.ToInt32(d["event_id"]); | ||
739 | mapitem.name = d["name"].ToString(); | ||
740 | |||
741 | mapitems.Add(mapitem); | ||
742 | } | ||
743 | |||
744 | remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); | ||
745 | mapitems.Clear(); | ||
746 | } | ||
747 | } | ||
748 | |||
749 | public void Refresh() | ||
750 | { | ||
751 | } | ||
752 | } | ||
753 | } | ||