diff options
author | Melanie Thielker | 2016-12-22 15:39:49 +0000 |
---|---|---|
committer | Melanie Thielker | 2016-12-22 15:39:49 +0000 |
commit | c3e8406f413fc6db8141bc9b1e2fb94cda92e79c (patch) | |
tree | 805011a6aa5a2825fdcb6a32321dfbf4472bc81f | |
parent | Update the ini examples to add options missing from one to the other. (diff) | |
parent | UserProfileModule refuse changes to classifieds outside home grid ( viewers m... (diff) | |
download | opensim-SC-c3e8406f413fc6db8141bc9b1e2fb94cda92e79c.zip opensim-SC-c3e8406f413fc6db8141bc9b1e2fb94cda92e79c.tar.gz opensim-SC-c3e8406f413fc6db8141bc9b1e2fb94cda92e79c.tar.bz2 opensim-SC-c3e8406f413fc6db8141bc9b1e2fb94cda92e79c.tar.xz |
Merge branch 'master' of opensimulator.org:/var/git/opensim
-rw-r--r-- | OpenSim/Framework/UserProfiles.cs | 14 | ||||
-rw-r--r-- | OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs | 442 |
2 files changed, 359 insertions, 97 deletions
diff --git a/OpenSim/Framework/UserProfiles.cs b/OpenSim/Framework/UserProfiles.cs index 98ab651..6d46fe9 100644 --- a/OpenSim/Framework/UserProfiles.cs +++ b/OpenSim/Framework/UserProfiles.cs | |||
@@ -27,6 +27,8 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using OpenMetaverse; | 29 | using OpenMetaverse; |
30 | using System.Collections.Generic; | ||
31 | |||
30 | 32 | ||
31 | namespace OpenSim.Framework | 33 | namespace OpenSim.Framework |
32 | { | 34 | { |
@@ -122,5 +124,17 @@ namespace OpenSim.Framework | |||
122 | public string UserId = UUID.Zero.ToString(); | 124 | public string UserId = UUID.Zero.ToString(); |
123 | public string DataVal = string.Empty; | 125 | public string DataVal = string.Empty; |
124 | } | 126 | } |
127 | |||
128 | public class UserProfileCacheEntry | ||
129 | { | ||
130 | public Dictionary<UUID, string> picksList; | ||
131 | public Dictionary<UUID, UserProfilePick> picks; | ||
132 | public Dictionary<UUID, string> classifiedsLists; | ||
133 | public Dictionary<UUID, UserClassifiedAdd> classifieds; | ||
134 | public UserProfileProperties props; | ||
135 | public string born; | ||
136 | public byte[] membershipType; | ||
137 | public uint flags; | ||
138 | } | ||
125 | } | 139 | } |
126 | 140 | ||
diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs index 57025bf..1ea1306 100644 --- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs | |||
@@ -57,6 +57,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
57 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")] | 57 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserProfilesModule")] |
58 | public class UserProfileModule : IProfileModule, INonSharedRegionModule | 58 | public class UserProfileModule : IProfileModule, INonSharedRegionModule |
59 | { | 59 | { |
60 | const double PROFILECACHEEXPIRE = 300; | ||
60 | /// <summary> | 61 | /// <summary> |
61 | /// Logging | 62 | /// Logging |
62 | /// </summary> | 63 | /// </summary> |
@@ -67,6 +68,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
67 | // count. The entries are removed when the interest count reaches 0. | 68 | // count. The entries are removed when the interest count reaches 0. |
68 | Dictionary<UUID, UUID> m_classifiedCache = new Dictionary<UUID, UUID>(); | 69 | Dictionary<UUID, UUID> m_classifiedCache = new Dictionary<UUID, UUID>(); |
69 | Dictionary<UUID, int> m_classifiedInterest = new Dictionary<UUID, int>(); | 70 | Dictionary<UUID, int> m_classifiedInterest = new Dictionary<UUID, int>(); |
71 | ExpiringCache<UUID, UserProfileCacheEntry> m_profilesCache = new ExpiringCache<UUID, UserProfileCacheEntry>(); | ||
72 | IImprovedAssetCache m_assetCache; | ||
70 | 73 | ||
71 | private JsonRpcRequestManager rpc = new JsonRpcRequestManager(); | 74 | private JsonRpcRequestManager rpc = new JsonRpcRequestManager(); |
72 | private bool m_allowUserProfileWebURLs = true; | 75 | private bool m_allowUserProfileWebURLs = true; |
@@ -128,7 +131,6 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
128 | get; private set; | 131 | get; private set; |
129 | } | 132 | } |
130 | 133 | ||
131 | |||
132 | #region IRegionModuleBase implementation | 134 | #region IRegionModuleBase implementation |
133 | /// <summary> | 135 | /// <summary> |
134 | /// This is called to initialize the region module. For shared modules, this is called exactly once, after | 136 | /// This is called to initialize the region module. For shared modules, this is called exactly once, after |
@@ -185,22 +187,11 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
185 | Scene = scene; | 187 | Scene = scene; |
186 | Scene.RegisterModuleInterface<IProfileModule>(this); | 188 | Scene.RegisterModuleInterface<IProfileModule>(this); |
187 | Scene.EventManager.OnNewClient += OnNewClient; | 189 | Scene.EventManager.OnNewClient += OnNewClient; |
188 | Scene.EventManager.OnMakeRootAgent += HandleOnMakeRootAgent; | 190 | Scene.EventManager.OnClientClosed += OnClientClosed; |
189 | 191 | ||
190 | UserManagementModule = Scene.RequestModuleInterface<IUserManagement>(); | 192 | UserManagementModule = Scene.RequestModuleInterface<IUserManagement>(); |
191 | } | 193 | } |
192 | 194 | ||
193 | void HandleOnMakeRootAgent (ScenePresence obj) | ||
194 | { | ||
195 | if(obj.PresenceType == PresenceType.Npc) | ||
196 | return; | ||
197 | |||
198 | Util.FireAndForget(delegate | ||
199 | { | ||
200 | GetImageAssets(((IScenePresence)obj).UUID); | ||
201 | }, null, "UserProfileModule.GetImageAssets"); | ||
202 | } | ||
203 | |||
204 | /// <summary> | 195 | /// <summary> |
205 | /// Removes the region. | 196 | /// Removes the region. |
206 | /// </summary> | 197 | /// </summary> |
@@ -211,6 +202,10 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
211 | { | 202 | { |
212 | if(!Enabled) | 203 | if(!Enabled) |
213 | return; | 204 | return; |
205 | |||
206 | m_profilesCache.Clear(); | ||
207 | m_classifiedCache.Clear(); | ||
208 | m_classifiedInterest.Clear(); | ||
214 | } | 209 | } |
215 | 210 | ||
216 | /// <summary> | 211 | /// <summary> |
@@ -226,6 +221,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
226 | { | 221 | { |
227 | if(!Enabled) | 222 | if(!Enabled) |
228 | return; | 223 | return; |
224 | m_assetCache = Scene.RequestModuleInterface<IImprovedAssetCache>(); | ||
229 | } | 225 | } |
230 | 226 | ||
231 | /// <summary> | 227 | /// <summary> |
@@ -297,6 +293,40 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
297 | client.OnUserInfoRequest += UserPreferencesRequest; | 293 | client.OnUserInfoRequest += UserPreferencesRequest; |
298 | client.OnUpdateUserInfo += UpdateUserPreferences; | 294 | client.OnUpdateUserInfo += UpdateUserPreferences; |
299 | } | 295 | } |
296 | |||
297 | void OnClientClosed(UUID AgentId, Scene scene) | ||
298 | { | ||
299 | ScenePresence sp = scene.GetScenePresence(AgentId); | ||
300 | IClientAPI client = sp.ControllingClient; | ||
301 | if (client == null) | ||
302 | return; | ||
303 | |||
304 | //Profile | ||
305 | client.OnRequestAvatarProperties -= RequestAvatarProperties; | ||
306 | client.OnUpdateAvatarProperties -= AvatarPropertiesUpdate; | ||
307 | client.OnAvatarInterestUpdate -= AvatarInterestsUpdate; | ||
308 | |||
309 | // Classifieds | ||
310 | // client.r GenericPacketHandler("avatarclassifiedsrequest", ClassifiedsRequest); | ||
311 | client.OnClassifiedInfoUpdate -= ClassifiedInfoUpdate; | ||
312 | client.OnClassifiedInfoRequest -= ClassifiedInfoRequest; | ||
313 | client.OnClassifiedDelete -= ClassifiedDelete; | ||
314 | |||
315 | // Picks | ||
316 | // client.AddGenericPacketHandler("avatarpicksrequest", PicksRequest); | ||
317 | // client.AddGenericPacketHandler("pickinforequest", PickInfoRequest); | ||
318 | client.OnPickInfoUpdate -= PickInfoUpdate; | ||
319 | client.OnPickDelete -= PickDelete; | ||
320 | |||
321 | // Notes | ||
322 | // client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest); | ||
323 | client.OnAvatarNotesUpdate -= NotesUpdate; | ||
324 | |||
325 | // Preferences | ||
326 | client.OnUserInfoRequest -= UserPreferencesRequest; | ||
327 | client.OnUpdateUserInfo -= UpdateUserPreferences; | ||
328 | } | ||
329 | |||
300 | #endregion Region Event Handlers | 330 | #endregion Region Event Handlers |
301 | 331 | ||
302 | #region Classified | 332 | #region Classified |
@@ -332,6 +362,34 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
332 | return; | 362 | return; |
333 | } | 363 | } |
334 | 364 | ||
365 | UserProfileCacheEntry uce = null; | ||
366 | lock(m_profilesCache) | ||
367 | { | ||
368 | if(m_profilesCache.TryGetValue(targetID, out uce) && uce != null) | ||
369 | { | ||
370 | if(uce.classifiedsLists != null) | ||
371 | { | ||
372 | foreach(KeyValuePair<UUID,string> kvp in uce.classifiedsLists) | ||
373 | { | ||
374 | UUID kvpkey = kvp.Key; | ||
375 | classifieds[kvpkey] = kvp.Value; | ||
376 | lock (m_classifiedCache) | ||
377 | { | ||
378 | if (!m_classifiedCache.ContainsKey(kvpkey)) | ||
379 | { | ||
380 | m_classifiedCache.Add(kvpkey,targetID); | ||
381 | m_classifiedInterest.Add(kvpkey, 0); | ||
382 | } | ||
383 | |||
384 | m_classifiedInterest[kvpkey]++; | ||
385 | } | ||
386 | } | ||
387 | remoteClient.SendAvatarClassifiedReply(targetID, uce.classifiedsLists); | ||
388 | return; | ||
389 | } | ||
390 | } | ||
391 | } | ||
392 | |||
335 | string serverURI = string.Empty; | 393 | string serverURI = string.Empty; |
336 | GetUserProfileServerURI(targetID, out serverURI); | 394 | GetUserProfileServerURI(targetID, out serverURI); |
337 | if(string.IsNullOrWhiteSpace(serverURI)) | 395 | if(string.IsNullOrWhiteSpace(serverURI)) |
@@ -380,6 +438,13 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
380 | } | 438 | } |
381 | } | 439 | } |
382 | 440 | ||
441 | if(uce == null) | ||
442 | uce = new UserProfileCacheEntry(); | ||
443 | uce.classifiedsLists = classifieds; | ||
444 | |||
445 | lock(m_profilesCache) | ||
446 | m_profilesCache.AddOrUpdate(targetID, uce, PROFILECACHEEXPIRE); | ||
447 | |||
383 | remoteClient.SendAvatarClassifiedReply(targetID, classifieds); | 448 | remoteClient.SendAvatarClassifiedReply(targetID, classifieds); |
384 | } | 449 | } |
385 | 450 | ||
@@ -404,9 +469,29 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
404 | } | 469 | } |
405 | } | 470 | } |
406 | } | 471 | } |
407 | 472 | ||
473 | UserProfileCacheEntry uce = null; | ||
474 | lock(m_profilesCache) | ||
475 | { | ||
476 | if(m_profilesCache.TryGetValue(target, out uce) && uce != null) | ||
477 | { | ||
478 | if(uce.classifieds != null && uce.classifieds.ContainsKey(queryClassifiedID)) | ||
479 | { | ||
480 | ad = uce.classifieds[queryClassifiedID]; | ||
481 | Vector3 gPos = new Vector3(); | ||
482 | Vector3.TryParse(ad.GlobalPos, out gPos); | ||
483 | |||
484 | remoteClient.SendClassifiedInfoReply(ad.ClassifiedId, ad.CreatorId, (uint)ad.CreationDate, | ||
485 | (uint)ad.ExpirationDate, (uint)ad.Category, ad.Name, ad.Description, | ||
486 | ad.ParcelId, (uint)ad.ParentEstate, ad.SnapshotId, ad.SimName, | ||
487 | gPos, ad.ParcelName, ad.Flags, ad.Price); | ||
488 | return; | ||
489 | } | ||
490 | } | ||
491 | } | ||
492 | |||
408 | string serverURI = string.Empty; | 493 | string serverURI = string.Empty; |
409 | GetUserProfileServerURI(target, out serverURI); | 494 | bool foreign = GetUserProfileServerURI(target, out serverURI); |
410 | if(string.IsNullOrWhiteSpace(serverURI)) | 495 | if(string.IsNullOrWhiteSpace(serverURI)) |
411 | { | 496 | { |
412 | return; | 497 | return; |
@@ -424,6 +509,18 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
424 | if(ad.CreatorId == UUID.Zero) | 509 | if(ad.CreatorId == UUID.Zero) |
425 | return; | 510 | return; |
426 | 511 | ||
512 | if(foreign) | ||
513 | cacheForeignImage(target, ad.SnapshotId); | ||
514 | |||
515 | if(uce == null) | ||
516 | uce = new UserProfileCacheEntry(); | ||
517 | if(uce.classifieds == null) | ||
518 | uce.classifieds = new Dictionary<UUID, UserClassifiedAdd>(); | ||
519 | uce.classifieds[ad.ClassifiedId] = ad; | ||
520 | |||
521 | lock(m_profilesCache) | ||
522 | m_profilesCache.AddOrUpdate(ad.ClassifiedId, uce, PROFILECACHEEXPIRE); | ||
523 | |||
427 | Vector3 globalPos = new Vector3(); | 524 | Vector3 globalPos = new Vector3(); |
428 | Vector3.TryParse(ad.GlobalPos, out globalPos); | 525 | Vector3.TryParse(ad.GlobalPos, out globalPos); |
429 | 526 | ||
@@ -479,13 +576,25 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
479 | UUID creatorId = remoteClient.AgentId; | 576 | UUID creatorId = remoteClient.AgentId; |
480 | ScenePresence p = FindPresence(creatorId); | 577 | ScenePresence p = FindPresence(creatorId); |
481 | 578 | ||
579 | UserProfileCacheEntry uce = null; | ||
580 | lock(m_profilesCache) | ||
581 | m_profilesCache.TryGetValue(remoteClient.AgentId, out uce); | ||
582 | |||
482 | string serverURI = string.Empty; | 583 | string serverURI = string.Empty; |
483 | GetUserProfileServerURI(remoteClient.AgentId, out serverURI); | 584 | bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI); |
484 | if(string.IsNullOrWhiteSpace(serverURI)) | 585 | if(string.IsNullOrWhiteSpace(serverURI)) |
485 | { | 586 | { |
486 | return; | 587 | return; |
487 | } | 588 | } |
488 | 589 | ||
590 | if(foreign) | ||
591 | { | ||
592 | remoteClient.SendAgentAlertMessage("Please change classifieds on your home grid", true); | ||
593 | if(uce != null && uce.classifiedsLists != null) | ||
594 | remoteClient.SendAvatarClassifiedReply(remoteClient.AgentId, uce.classifiedsLists); | ||
595 | return; | ||
596 | } | ||
597 | |||
489 | OSDMap parameters = new OSDMap {{"creatorId", OSD.FromUUID(creatorId)}}; | 598 | OSDMap parameters = new OSDMap {{"creatorId", OSD.FromUUID(creatorId)}}; |
490 | OSD Params = (OSD)parameters; | 599 | OSD Params = (OSD)parameters; |
491 | if (!rpc.JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString())) | 600 | if (!rpc.JsonRpcRequest(ref Params, "avatarclassifiedsrequest", serverURI, UUID.Random().ToString())) |
@@ -498,17 +607,20 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
498 | bool exists = list.Cast<OSDMap>().Where(map => map.ContainsKey("classifieduuid")) | 607 | bool exists = list.Cast<OSDMap>().Where(map => map.ContainsKey("classifieduuid")) |
499 | .Any(map => map["classifieduuid"].AsUUID().Equals(queryclassifiedID)); | 608 | .Any(map => map["classifieduuid"].AsUUID().Equals(queryclassifiedID)); |
500 | 609 | ||
610 | IMoneyModule money = null; | ||
501 | if (!exists) | 611 | if (!exists) |
502 | { | 612 | { |
503 | IMoneyModule money = s.RequestModuleInterface<IMoneyModule>(); | 613 | money = s.RequestModuleInterface<IMoneyModule>(); |
504 | if (money != null) | 614 | if (money != null) |
505 | { | 615 | { |
506 | if (!money.AmountCovered(remoteClient.AgentId, queryclassifiedPrice)) | 616 | if (!money.AmountCovered(remoteClient.AgentId, queryclassifiedPrice)) |
507 | { | 617 | { |
508 | remoteClient.SendAgentAlertMessage("You do not have enough money to create this classified.", false); | 618 | remoteClient.SendAgentAlertMessage("You do not have enough money to create this classified.", false); |
619 | if(uce != null && uce.classifiedsLists != null) | ||
620 | remoteClient.SendAvatarClassifiedReply(remoteClient.AgentId, uce.classifiedsLists); | ||
509 | return; | 621 | return; |
510 | } | 622 | } |
511 | money.ApplyCharge(remoteClient.AgentId, queryclassifiedPrice, MoneyTransactionType.ClassifiedCharge); | 623 | // money.ApplyCharge(remoteClient.AgentId, queryclassifiedPrice, MoneyTransactionType.ClassifiedCharge); |
512 | } | 624 | } |
513 | } | 625 | } |
514 | 626 | ||
@@ -535,7 +647,25 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
535 | if(!rpc.JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString())) | 647 | if(!rpc.JsonRpcRequest(ref Ad, "classified_update", serverURI, UUID.Random().ToString())) |
536 | { | 648 | { |
537 | remoteClient.SendAgentAlertMessage("Error updating classified", false); | 649 | remoteClient.SendAgentAlertMessage("Error updating classified", false); |
650 | if(uce != null && uce.classifiedsLists != null) | ||
651 | remoteClient.SendAvatarClassifiedReply(remoteClient.AgentId, uce.classifiedsLists); | ||
652 | return; | ||
538 | } | 653 | } |
654 | |||
655 | // only charge if it worked | ||
656 | if (money != null) | ||
657 | money.ApplyCharge(remoteClient.AgentId, queryclassifiedPrice, MoneyTransactionType.ClassifiedCharge); | ||
658 | |||
659 | // just flush cache for now | ||
660 | lock(m_profilesCache) | ||
661 | { | ||
662 | if(uce != null) | ||
663 | { | ||
664 | uce.classifieds = null; | ||
665 | uce.classifiedsLists = null; | ||
666 | } | ||
667 | } | ||
668 | |||
539 | } | 669 | } |
540 | 670 | ||
541 | /// <summary> | 671 | /// <summary> |
@@ -549,11 +679,27 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
549 | /// </param> | 679 | /// </param> |
550 | public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient) | 680 | public void ClassifiedDelete(UUID queryClassifiedID, IClientAPI remoteClient) |
551 | { | 681 | { |
682 | // just flush cache for now | ||
683 | UserProfileCacheEntry uce = null; | ||
684 | lock(m_profilesCache) | ||
685 | { | ||
686 | if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null) | ||
687 | { | ||
688 | uce.classifieds = null; | ||
689 | uce.classifiedsLists = null; | ||
690 | } | ||
691 | } | ||
692 | |||
552 | string serverURI = string.Empty; | 693 | string serverURI = string.Empty; |
553 | GetUserProfileServerURI(remoteClient.AgentId, out serverURI); | 694 | bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI); |
554 | if(string.IsNullOrWhiteSpace(serverURI)) | 695 | if(string.IsNullOrWhiteSpace(serverURI)) |
555 | return; | 696 | return; |
556 | 697 | ||
698 | if(foreign) | ||
699 | { | ||
700 | remoteClient.SendAgentAlertMessage("Please change classifieds on your home grid", true); | ||
701 | return; | ||
702 | } | ||
557 | UUID classifiedId; | 703 | UUID classifiedId; |
558 | if(!UUID.TryParse(queryClassifiedID.ToString(), out classifiedId)) | 704 | if(!UUID.TryParse(queryClassifiedID.ToString(), out classifiedId)) |
559 | return; | 705 | return; |
@@ -605,6 +751,19 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
605 | return; | 751 | return; |
606 | } | 752 | } |
607 | 753 | ||
754 | UserProfileCacheEntry uce = null; | ||
755 | lock(m_profilesCache) | ||
756 | { | ||
757 | if(m_profilesCache.TryGetValue(targetId, out uce) && uce != null) | ||
758 | { | ||
759 | if(uce != null && uce.picksList != null) | ||
760 | { | ||
761 | remoteClient.SendAvatarPicksReply(targetId, uce.picksList); | ||
762 | return; | ||
763 | } | ||
764 | } | ||
765 | } | ||
766 | |||
608 | string serverURI = string.Empty; | 767 | string serverURI = string.Empty; |
609 | GetUserProfileServerURI(targetId, out serverURI); | 768 | GetUserProfileServerURI(targetId, out serverURI); |
610 | if(string.IsNullOrWhiteSpace(serverURI)) | 769 | if(string.IsNullOrWhiteSpace(serverURI)) |
@@ -637,6 +796,14 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
637 | string name = m["name"].AsString(); | 796 | string name = m["name"].AsString(); |
638 | picks[cid] = name; | 797 | picks[cid] = name; |
639 | } | 798 | } |
799 | |||
800 | if (uce == null) | ||
801 | uce = new UserProfileCacheEntry(); | ||
802 | uce.picksList = picks; | ||
803 | |||
804 | lock(m_profilesCache) | ||
805 | m_profilesCache.AddOrUpdate(targetId, uce, PROFILECACHEEXPIRE); | ||
806 | |||
640 | remoteClient.SendAvatarPicksReply(targetId, picks); | 807 | remoteClient.SendAvatarPicksReply(targetId, picks); |
641 | } | 808 | } |
642 | 809 | ||
@@ -667,8 +834,27 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
667 | if(!UUID.TryParse (args [1], out pick.PickId)) | 834 | if(!UUID.TryParse (args [1], out pick.PickId)) |
668 | return; | 835 | return; |
669 | 836 | ||
837 | IClientAPI remoteClient = (IClientAPI)sender; | ||
838 | UserProfileCacheEntry uce = null; | ||
839 | lock(m_profilesCache) | ||
840 | { | ||
841 | if(m_profilesCache.TryGetValue(targetID, out uce) && uce != null) | ||
842 | { | ||
843 | if(uce != null && uce.picks != null && uce.picks.ContainsKey(pick.PickId)) | ||
844 | { | ||
845 | pick = uce.picks[pick.PickId]; | ||
846 | Vector3 gPos = new Vector3(Vector3.Zero); | ||
847 | Vector3.TryParse(pick.GlobalPos, out gPos); | ||
848 | remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name, | ||
849 | pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName, | ||
850 | gPos,pick.SortOrder,pick.Enabled); | ||
851 | return; | ||
852 | } | ||
853 | } | ||
854 | } | ||
855 | |||
670 | string serverURI = string.Empty; | 856 | string serverURI = string.Empty; |
671 | GetUserProfileServerURI (targetID, out serverURI); | 857 | bool foreign = GetUserProfileServerURI (targetID, out serverURI); |
672 | if(string.IsNullOrWhiteSpace(serverURI)) | 858 | if(string.IsNullOrWhiteSpace(serverURI)) |
673 | { | 859 | { |
674 | return; | 860 | return; |
@@ -676,8 +862,6 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
676 | 862 | ||
677 | string theirGatekeeperURI; | 863 | string theirGatekeeperURI; |
678 | GetUserGatekeeperURI(targetID, out theirGatekeeperURI); | 864 | GetUserGatekeeperURI(targetID, out theirGatekeeperURI); |
679 | |||
680 | IClientAPI remoteClient = (IClientAPI)sender; | ||
681 | 865 | ||
682 | object Pick = (object)pick; | 866 | object Pick = (object)pick; |
683 | if (!rpc.JsonRpcRequest (ref Pick, "pickinforequest", serverURI, UUID.Random ().ToString ())) { | 867 | if (!rpc.JsonRpcRequest (ref Pick, "pickinforequest", serverURI, UUID.Random ().ToString ())) { |
@@ -686,6 +870,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
686 | return; | 870 | return; |
687 | } | 871 | } |
688 | pick = (UserProfilePick)Pick; | 872 | pick = (UserProfilePick)Pick; |
873 | if(foreign) | ||
874 | cacheForeignImage(targetID, pick.SnapshotId); | ||
689 | 875 | ||
690 | Vector3 globalPos = new Vector3(Vector3.Zero); | 876 | Vector3 globalPos = new Vector3(Vector3.Zero); |
691 | Vector3.TryParse(pick.GlobalPos, out globalPos); | 877 | Vector3.TryParse(pick.GlobalPos, out globalPos); |
@@ -716,6 +902,16 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
716 | 902 | ||
717 | m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString()); | 903 | m_log.DebugFormat("[PROFILES]: PickInfoRequest: {0} : {1}", pick.Name.ToString(), pick.SnapshotId.ToString()); |
718 | 904 | ||
905 | pick.GlobalPos = globalPos.ToString(); | ||
906 | if (uce == null) | ||
907 | uce = new UserProfileCacheEntry(); | ||
908 | if(uce.picks == null) | ||
909 | uce.picks = new Dictionary<UUID, UserProfilePick>(); | ||
910 | uce.picks[pick.PickId] = pick; | ||
911 | |||
912 | lock(m_profilesCache) | ||
913 | m_profilesCache.AddOrUpdate(targetID, uce, PROFILECACHEEXPIRE); | ||
914 | |||
719 | // Pull the rabbit out of the hat | 915 | // Pull the rabbit out of the hat |
720 | remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name, | 916 | remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name, |
721 | pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName, | 917 | pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName, |
@@ -774,15 +970,19 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
774 | avaPos.Z); | 970 | avaPos.Z); |
775 | 971 | ||
776 | string landParcelName = "My Parcel"; | 972 | string landParcelName = "My Parcel"; |
777 | UUID landParcelID = p.currentParcelUUID; | 973 | // UUID landParcelID = p.currentParcelUUID; |
778 | 974 | ||
975 | // to locate parcels we use a fake id that encodes the region handle | ||
976 | // since we do not have a global locator | ||
977 | // this fails on HG | ||
978 | UUID landParcelID = Util.BuildFakeParcelID(remoteClient.Scene.RegionInfo.RegionHandle, (uint)avaPos.X, (uint)avaPos.Y); | ||
779 | ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y); | 979 | ILandObject land = p.Scene.LandChannel.GetLandObject(avaPos.X, avaPos.Y); |
780 | 980 | ||
781 | if (land != null) | 981 | if (land != null) |
782 | { | 982 | { |
783 | // If land found, use parcel uuid from here because the value from SP will be blank if the avatar hasnt moved | 983 | // If land found, use parcel uuid from here because the value from SP will be blank if the avatar hasnt moved |
784 | landParcelName = land.LandData.Name; | 984 | landParcelName = land.LandData.Name; |
785 | landParcelID = land.LandData.GlobalID; | 985 | // landParcelID = land.LandData.GlobalID; |
786 | } | 986 | } |
787 | else | 987 | else |
788 | { | 988 | { |
@@ -791,7 +991,6 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
791 | avaPos.X, avaPos.Y, p.Scene.Name); | 991 | avaPos.X, avaPos.Y, p.Scene.Name); |
792 | } | 992 | } |
793 | 993 | ||
794 | |||
795 | pick.PickId = pickID; | 994 | pick.PickId = pickID; |
796 | pick.CreatorId = creatorID; | 995 | pick.CreatorId = creatorID; |
797 | pick.TopPick = topPick; | 996 | pick.TopPick = topPick; |
@@ -814,6 +1013,24 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
814 | return; | 1013 | return; |
815 | } | 1014 | } |
816 | 1015 | ||
1016 | UserProfileCacheEntry uce = null; | ||
1017 | lock(m_profilesCache) | ||
1018 | { | ||
1019 | if(!m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) || uce == null) | ||
1020 | uce = new UserProfileCacheEntry(); | ||
1021 | if(uce.picks == null) | ||
1022 | uce.picks = new Dictionary<UUID, UserProfilePick>(); | ||
1023 | if(uce.picksList == null) | ||
1024 | uce.picksList = new Dictionary<UUID, string>(); | ||
1025 | uce.picks[pick.PickId] = pick; | ||
1026 | uce.picksList[pick.PickId] = pick.Name; | ||
1027 | m_profilesCache.AddOrUpdate(remoteClient.AgentId, uce, PROFILECACHEEXPIRE); | ||
1028 | } | ||
1029 | remoteClient.SendAvatarPicksReply(remoteClient.AgentId, uce.picksList); | ||
1030 | remoteClient.SendPickInfoReply(pick.PickId,pick.CreatorId,pick.TopPick,pick.ParcelId,pick.Name, | ||
1031 | pick.Desc,pick.SnapshotId,pick.ParcelName,pick.OriginalName,pick.SimName, | ||
1032 | posGlobal,pick.SortOrder,pick.Enabled); | ||
1033 | |||
817 | m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString()); | 1034 | m_log.DebugFormat("[PROFILES]: Finish PickInfoUpdate {0} {1}", pick.Name, pick.PickId.ToString()); |
818 | } | 1035 | } |
819 | 1036 | ||
@@ -844,6 +1061,23 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
844 | "Error picks delete", false); | 1061 | "Error picks delete", false); |
845 | return; | 1062 | return; |
846 | } | 1063 | } |
1064 | |||
1065 | UserProfileCacheEntry uce = null; | ||
1066 | lock(m_profilesCache) | ||
1067 | { | ||
1068 | if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null) | ||
1069 | { | ||
1070 | if(uce.picks != null && uce.picks.ContainsKey(queryPickID)) | ||
1071 | uce.picks.Remove(queryPickID); | ||
1072 | if(uce.picksList != null && uce.picksList.ContainsKey(queryPickID)) | ||
1073 | uce.picksList.Remove(queryPickID); | ||
1074 | m_profilesCache.AddOrUpdate(remoteClient.AgentId, uce, PROFILECACHEEXPIRE); | ||
1075 | } | ||
1076 | } | ||
1077 | if(uce != null && uce.picksList != null) | ||
1078 | remoteClient.SendAvatarPicksReply(remoteClient.AgentId, uce.picksList); | ||
1079 | else | ||
1080 | remoteClient.SendAvatarPicksReply(remoteClient.AgentId, new Dictionary<UUID, string>()); | ||
847 | } | 1081 | } |
848 | #endregion Picks | 1082 | #endregion Picks |
849 | 1083 | ||
@@ -1025,6 +1259,16 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1025 | /// </param> | 1259 | /// </param> |
1026 | public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages) | 1260 | public void AvatarInterestsUpdate(IClientAPI remoteClient, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages) |
1027 | { | 1261 | { |
1262 | // flush cache for now | ||
1263 | UserProfileCacheEntry uce = null; | ||
1264 | lock(m_profilesCache) | ||
1265 | { | ||
1266 | if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null) | ||
1267 | { | ||
1268 | uce.props = null; | ||
1269 | } | ||
1270 | } | ||
1271 | |||
1028 | UserProfileProperties prop = new UserProfileProperties(); | 1272 | UserProfileProperties prop = new UserProfileProperties(); |
1029 | 1273 | ||
1030 | prop.UserId = remoteClient.AgentId; | 1274 | prop.UserId = remoteClient.AgentId; |
@@ -1067,6 +1311,27 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1067 | 0, "Getting into trouble", "Droidspeak"); | 1311 | 0, "Getting into trouble", "Droidspeak"); |
1068 | return; | 1312 | return; |
1069 | } | 1313 | } |
1314 | UserProfileProperties props; | ||
1315 | UserProfileCacheEntry uce = null; | ||
1316 | lock(m_profilesCache) | ||
1317 | { | ||
1318 | if(m_profilesCache.TryGetValue(avatarID, out uce) && uce != null) | ||
1319 | { | ||
1320 | if(uce.props != null) | ||
1321 | { | ||
1322 | props = uce.props; | ||
1323 | remoteClient.SendAvatarProperties(props.UserId, props.AboutText, | ||
1324 | uce.born, uce.membershipType , props.FirstLifeText, uce.flags, | ||
1325 | props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); | ||
1326 | |||
1327 | |||
1328 | remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, | ||
1329 | props.WantToText, (uint)props.SkillsMask, | ||
1330 | props.SkillsText, props.Language); | ||
1331 | return; | ||
1332 | } | ||
1333 | } | ||
1334 | } | ||
1070 | 1335 | ||
1071 | string serverURI = string.Empty; | 1336 | string serverURI = string.Empty; |
1072 | bool foreign = GetUserProfileServerURI(avatarID, out serverURI); | 1337 | bool foreign = GetUserProfileServerURI(avatarID, out serverURI); |
@@ -1118,13 +1383,13 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1118 | } | 1383 | } |
1119 | } | 1384 | } |
1120 | 1385 | ||
1121 | UserProfileProperties props = new UserProfileProperties(); | 1386 | props = new UserProfileProperties(); |
1122 | props.UserId = avatarID; | 1387 | props.UserId = avatarID; |
1123 | 1388 | ||
1124 | string result = string.Empty; | 1389 | string result = string.Empty; |
1125 | if(!GetProfileData(ref props, foreign, out result)) | 1390 | if(!GetProfileData(ref props, foreign, serverURI, out result)) |
1126 | { | 1391 | { |
1127 | props.AboutText ="Profile not avaible at this time. User may still be unknown to this grid"; | 1392 | props.AboutText ="Profile not available at this time. User may still be unknown to this grid"; |
1128 | } | 1393 | } |
1129 | 1394 | ||
1130 | // if on same region force online | 1395 | // if on same region force online |
@@ -1134,10 +1399,19 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1134 | if(!m_allowUserProfileWebURLs) | 1399 | if(!m_allowUserProfileWebURLs) |
1135 | props.WebUrl =""; | 1400 | props.WebUrl =""; |
1136 | 1401 | ||
1402 | if(uce == null) | ||
1403 | uce = new UserProfileCacheEntry(); | ||
1404 | uce.props = props; | ||
1405 | uce.born = born; | ||
1406 | uce.membershipType = membershipType; | ||
1407 | uce.flags = flags; | ||
1408 | |||
1409 | lock(m_profilesCache) | ||
1410 | m_profilesCache.AddOrUpdate(props.UserId, uce, PROFILECACHEEXPIRE); | ||
1411 | |||
1137 | remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags, | 1412 | remoteClient.SendAvatarProperties(props.UserId, props.AboutText, born, membershipType , props.FirstLifeText, flags, |
1138 | props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); | 1413 | props.FirstLifeImageId, props.ImageId, props.WebUrl, props.PartnerId); |
1139 | 1414 | ||
1140 | |||
1141 | remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask, | 1415 | remoteClient.SendAvatarInterestsReply(props.UserId, (uint)props.WantToMask, props.WantToText, (uint)props.SkillsMask, |
1142 | props.SkillsText, props.Language); | 1416 | props.SkillsText, props.Language); |
1143 | } | 1417 | } |
@@ -1155,6 +1429,16 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1155 | { | 1429 | { |
1156 | if (remoteClient.AgentId == newProfile.ID) | 1430 | if (remoteClient.AgentId == newProfile.ID) |
1157 | { | 1431 | { |
1432 | // flush cache for now | ||
1433 | UserProfileCacheEntry uce = null; | ||
1434 | lock(m_profilesCache) | ||
1435 | { | ||
1436 | if(m_profilesCache.TryGetValue(remoteClient.AgentId, out uce) && uce != null) | ||
1437 | { | ||
1438 | uce.props = null; | ||
1439 | } | ||
1440 | } | ||
1441 | |||
1158 | UserProfileProperties prop = new UserProfileProperties(); | 1442 | UserProfileProperties prop = new UserProfileProperties(); |
1159 | 1443 | ||
1160 | prop.UserId = remoteClient.AgentId; | 1444 | prop.UserId = remoteClient.AgentId; |
@@ -1189,24 +1473,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1189 | /// <returns> | 1473 | /// <returns> |
1190 | /// The profile data. | 1474 | /// The profile data. |
1191 | /// </returns> | 1475 | /// </returns> |
1192 | bool GetProfileData(ref UserProfileProperties properties, bool foreign, out string message) | 1476 | bool GetProfileData(ref UserProfileProperties properties, bool foreign, string serverURI, out string message) |
1193 | { | 1477 | { |
1194 | // Can't handle NPC yet... | ||
1195 | ScenePresence p = FindPresence(properties.UserId); | ||
1196 | |||
1197 | if (null != p) | ||
1198 | { | ||
1199 | if (p.PresenceType == PresenceType.Npc) | ||
1200 | { | ||
1201 | message = "Id points to NPC"; | ||
1202 | return false; | ||
1203 | } | ||
1204 | } | ||
1205 | |||
1206 | string serverURI = string.Empty; | ||
1207 | GetUserProfileServerURI(properties.UserId, out serverURI); | ||
1208 | // This is checking a friend on the home grid | ||
1209 | // Not HG friend | ||
1210 | if (String.IsNullOrEmpty(serverURI)) | 1478 | if (String.IsNullOrEmpty(serverURI)) |
1211 | { | 1479 | { |
1212 | message = "User profile service unknown at this time"; | 1480 | message = "User profile service unknown at this time"; |
@@ -1247,10 +1515,14 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1247 | 1515 | ||
1248 | return false; | 1516 | return false; |
1249 | } | 1517 | } |
1250 | // else, continue below | ||
1251 | } | 1518 | } |
1252 | 1519 | ||
1253 | properties = (UserProfileProperties)Prop; | 1520 | properties = (UserProfileProperties)Prop; |
1521 | if(foreign) | ||
1522 | { | ||
1523 | cacheForeignImage(properties.UserId, properties.ImageId); | ||
1524 | cacheForeignImage(properties.UserId, properties.FirstLifeImageId); | ||
1525 | } | ||
1254 | 1526 | ||
1255 | message = "Success"; | 1527 | message = "Success"; |
1256 | return true; | 1528 | return true; |
@@ -1258,49 +1530,6 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1258 | #endregion Avatar Properties | 1530 | #endregion Avatar Properties |
1259 | 1531 | ||
1260 | #region Utils | 1532 | #region Utils |
1261 | bool GetImageAssets(UUID avatarId) | ||
1262 | { | ||
1263 | string profileServerURI = string.Empty; | ||
1264 | string assetServerURI = string.Empty; | ||
1265 | |||
1266 | bool foreign = GetUserProfileServerURI(avatarId, out profileServerURI); | ||
1267 | |||
1268 | if(!foreign) | ||
1269 | return true; | ||
1270 | |||
1271 | assetServerURI = UserManagementModule.GetUserServerURL(avatarId, "AssetServerURI"); | ||
1272 | |||
1273 | if(string.IsNullOrEmpty(profileServerURI) || string.IsNullOrEmpty(assetServerURI)) | ||
1274 | return false; | ||
1275 | |||
1276 | OSDMap parameters= new OSDMap(); | ||
1277 | parameters.Add("avatarId", OSD.FromUUID(avatarId)); | ||
1278 | OSD Params = (OSD)parameters; | ||
1279 | if(!rpc.JsonRpcRequest(ref Params, "image_assets_request", profileServerURI, UUID.Random().ToString())) | ||
1280 | { | ||
1281 | return false; | ||
1282 | } | ||
1283 | |||
1284 | parameters = (OSDMap)Params; | ||
1285 | |||
1286 | if (parameters.ContainsKey("result")) | ||
1287 | { | ||
1288 | OSDArray list = (OSDArray)parameters["result"]; | ||
1289 | |||
1290 | foreach (OSD asset in list) | ||
1291 | { | ||
1292 | OSDString assetId = (OSDString)asset; | ||
1293 | |||
1294 | Scene.AssetService.Get(string.Format("{0}/{1}", assetServerURI, assetId.AsString())); | ||
1295 | } | ||
1296 | return true; | ||
1297 | } | ||
1298 | else | ||
1299 | { | ||
1300 | m_log.ErrorFormat("[PROFILES]: Problematic response for image_assets_request from {0}", profileServerURI); | ||
1301 | return false; | ||
1302 | } | ||
1303 | } | ||
1304 | 1533 | ||
1305 | /// <summary> | 1534 | /// <summary> |
1306 | /// Gets the user account data. | 1535 | /// Gets the user account data. |
@@ -1451,6 +1680,27 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1451 | } | 1680 | } |
1452 | } | 1681 | } |
1453 | 1682 | ||
1683 | void cacheForeignImage(UUID agent, UUID imageID) | ||
1684 | { | ||
1685 | if(imageID == null || imageID == UUID.Zero) | ||
1686 | return; | ||
1687 | |||
1688 | string assetServerURI = UserManagementModule.GetUserServerURL(agent, "AssetServerURI"); | ||
1689 | if(string.IsNullOrWhiteSpace(assetServerURI)) | ||
1690 | return; | ||
1691 | |||
1692 | string imageIDstr = imageID.ToString(); | ||
1693 | |||
1694 | |||
1695 | if(m_assetCache != null && m_assetCache.Check(imageIDstr)) | ||
1696 | return; | ||
1697 | |||
1698 | if(Scene.AssetService.Get(imageIDstr) != null) | ||
1699 | return; | ||
1700 | |||
1701 | Scene.AssetService.Get(string.Format("{0}/{1}", assetServerURI, imageIDstr)); | ||
1702 | } | ||
1703 | |||
1454 | /// <summary> | 1704 | /// <summary> |
1455 | /// Finds the presence. | 1705 | /// Finds the presence. |
1456 | /// </summary> | 1706 | /// </summary> |
@@ -1519,9 +1769,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1519 | webRequest.ContentType = "application/json-rpc"; | 1769 | webRequest.ContentType = "application/json-rpc"; |
1520 | webRequest.Method = "POST"; | 1770 | webRequest.Method = "POST"; |
1521 | 1771 | ||
1522 | Stream dataStream = webRequest.GetRequestStream(); | 1772 | using(Stream dataStream = webRequest.GetRequestStream()) |
1523 | dataStream.Write(content, 0, content.Length); | 1773 | dataStream.Write(content,0,content.Length); |
1524 | dataStream.Close(); | ||
1525 | 1774 | ||
1526 | WebResponse webResponse = null; | 1775 | WebResponse webResponse = null; |
1527 | try | 1776 | try |
@@ -1601,9 +1850,8 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles | |||
1601 | webRequest.ContentType = "application/json-rpc"; | 1850 | webRequest.ContentType = "application/json-rpc"; |
1602 | webRequest.Method = "POST"; | 1851 | webRequest.Method = "POST"; |
1603 | 1852 | ||
1604 | Stream dataStream = webRequest.GetRequestStream(); | 1853 | using(Stream dataStream = webRequest.GetRequestStream()) |
1605 | dataStream.Write(content, 0, content.Length); | 1854 | dataStream.Write(content,0,content.Length); |
1606 | dataStream.Close(); | ||
1607 | 1855 | ||
1608 | WebResponse webResponse = null; | 1856 | WebResponse webResponse = null; |
1609 | try | 1857 | try |