HGFriendsServerPostHandler.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSimulator Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using Nini.Config;
  28. using log4net;
  29. using System;
  30. using System.Reflection;
  31. using System.IO;
  32. using System.Net;
  33. using System.Text;
  34. using System.Text.RegularExpressions;
  35. using System.Xml;
  36. using System.Xml.Serialization;
  37. using System.Collections.Generic;
  38. using OpenSim.Server.Base;
  39. using OpenSim.Services.Interfaces;
  40. using FriendInfo = OpenSim.Services.Interfaces.FriendInfo;
  41. using GridRegion = OpenSim.Services.Interfaces.GridRegion;
  42. using OpenSim.Framework;
  43. using OpenSim.Framework.Servers.HttpServer;
  44. using OpenMetaverse;
  45. namespace OpenSim.Server.Handlers.Hypergrid
  46. {
  47. public class HGFriendsServerPostHandler : BaseStreamHandler
  48. {
  49. private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  50. private IUserAgentService m_UserAgentService;
  51. private IFriendsSimConnector m_FriendsLocalSimConnector;
  52. private IHGFriendsService m_TheService;
  53. public HGFriendsServerPostHandler(IHGFriendsService service, IUserAgentService uas, IFriendsSimConnector friendsConn) :
  54. base("POST", "/hgfriends")
  55. {
  56. m_TheService = service;
  57. m_UserAgentService = uas;
  58. m_FriendsLocalSimConnector = friendsConn;
  59. m_log.DebugFormat("[HGFRIENDS HANDLER]: HGFriendsServerPostHandler is On ({0})",
  60. (m_FriendsLocalSimConnector == null ? "robust" : "standalone"));
  61. if (m_TheService == null)
  62. m_log.ErrorFormat("[HGFRIENDS HANDLER]: TheService is null!");
  63. }
  64. protected override byte[] ProcessRequest(string path, Stream requestData,
  65. IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
  66. {
  67. string body;
  68. using(StreamReader sr = new StreamReader(requestData))
  69. body = sr.ReadToEnd();
  70. body = body.Trim();
  71. //m_log.DebugFormat("[XXX]: query String: {0}", body);
  72. try
  73. {
  74. Dictionary<string, object> request =
  75. ServerUtils.ParseQueryString(body);
  76. if (!request.ContainsKey("METHOD"))
  77. return FailureResult();
  78. string method = request["METHOD"].ToString();
  79. switch (method)
  80. {
  81. case "getfriendperms":
  82. return GetFriendPerms(request);
  83. case "newfriendship":
  84. return NewFriendship(request);
  85. case "deletefriendship":
  86. return DeleteFriendship(request);
  87. /* Same as inter-sim */
  88. case "friendship_offered":
  89. return FriendshipOffered(request);
  90. case "validate_friendship_offered":
  91. return ValidateFriendshipOffered(request);
  92. case "statusnotification":
  93. return StatusNotification(request);
  94. /*
  95. case "friendship_approved":
  96. return FriendshipApproved(request);
  97. case "friendship_denied":
  98. return FriendshipDenied(request);
  99. case "friendship_terminated":
  100. return FriendshipTerminated(request);
  101. case "grant_rights":
  102. return GrantRights(request);
  103. */
  104. }
  105. m_log.DebugFormat("[HGFRIENDS HANDLER]: unknown method {0}", method);
  106. }
  107. catch (Exception e)
  108. {
  109. m_log.DebugFormat("[HGFRIENDS HANDLER]: Exception {0}", e);
  110. }
  111. return FailureResult();
  112. }
  113. #region Method-specific handlers
  114. byte[] GetFriendPerms(Dictionary<string, object> request)
  115. {
  116. if (!VerifyServiceKey(request))
  117. return FailureResult();
  118. UUID principalID = UUID.Zero;
  119. if (request.ContainsKey("PRINCIPALID"))
  120. UUID.TryParse(request["PRINCIPALID"].ToString(), out principalID);
  121. else
  122. {
  123. m_log.WarnFormat("[HGFRIENDS HANDLER]: no principalID in request to get friend perms");
  124. return FailureResult();
  125. }
  126. UUID friendID = UUID.Zero;
  127. if (request.ContainsKey("FRIENDID"))
  128. UUID.TryParse(request["FRIENDID"].ToString(), out friendID);
  129. else
  130. {
  131. m_log.WarnFormat("[HGFRIENDS HANDLER]: no friendID in request to get friend perms");
  132. return FailureResult();
  133. }
  134. int perms = m_TheService.GetFriendPerms(principalID, friendID);
  135. if (perms < 0)
  136. return FailureResult("Friend not found");
  137. return SuccessResult(perms.ToString());
  138. }
  139. byte[] NewFriendship(Dictionary<string, object> request)
  140. {
  141. bool verified = VerifyServiceKey(request);
  142. FriendInfo friend = new FriendInfo(request);
  143. bool success = m_TheService.NewFriendship(friend, verified);
  144. if (success)
  145. return SuccessResult();
  146. else
  147. return FailureResult();
  148. }
  149. byte[] DeleteFriendship(Dictionary<string, object> request)
  150. {
  151. FriendInfo friend = new FriendInfo(request);
  152. string secret = string.Empty;
  153. if (request.ContainsKey("SECRET"))
  154. secret = request["SECRET"].ToString();
  155. if (secret.Length == 0)
  156. return BoolResult(false);
  157. bool success = m_TheService.DeleteFriendship(friend, secret);
  158. return BoolResult(success);
  159. }
  160. byte[] FriendshipOffered(Dictionary<string, object> request)
  161. {
  162. UUID fromID = UUID.Zero;
  163. UUID toID = UUID.Zero;
  164. string message = string.Empty;
  165. string name = string.Empty;
  166. if (!request.ContainsKey("FromID") || !request.ContainsKey("ToID"))
  167. return BoolResult(false);
  168. if (!UUID.TryParse(request["ToID"].ToString(), out toID))
  169. return BoolResult(false);
  170. message = request["Message"].ToString();
  171. if (!UUID.TryParse(request["FromID"].ToString(), out fromID))
  172. return BoolResult(false);
  173. if (request.ContainsKey("FromName"))
  174. name = request["FromName"].ToString();
  175. bool success = m_TheService.FriendshipOffered(fromID, name, toID, message);
  176. return BoolResult(success);
  177. }
  178. byte[] ValidateFriendshipOffered(Dictionary<string, object> request)
  179. {
  180. FriendInfo friend = new FriendInfo(request);
  181. UUID friendID = UUID.Zero;
  182. if (!UUID.TryParse(friend.Friend, out friendID))
  183. return BoolResult(false);
  184. bool success = m_TheService.ValidateFriendshipOffered(friend.PrincipalID, friendID);
  185. return BoolResult(success);
  186. }
  187. byte[] StatusNotification(Dictionary<string, object> request)
  188. {
  189. UUID principalID = UUID.Zero;
  190. if (request.ContainsKey("userID"))
  191. UUID.TryParse(request["userID"].ToString(), out principalID);
  192. else
  193. {
  194. m_log.WarnFormat("[HGFRIENDS HANDLER]: no userID in request to notify");
  195. return FailureResult();
  196. }
  197. bool online = true;
  198. if (request.ContainsKey("online"))
  199. Boolean.TryParse(request["online"].ToString(), out online);
  200. else
  201. {
  202. m_log.WarnFormat("[HGFRIENDS HANDLER]: no online in request to notify");
  203. return FailureResult();
  204. }
  205. List<string> friends = new List<string>();
  206. int i = 0;
  207. foreach (KeyValuePair<string, object> kvp in request)
  208. {
  209. if (kvp.Key.Equals("friend_" + i.ToString()))
  210. {
  211. friends.Add(kvp.Value.ToString());
  212. i++;
  213. }
  214. }
  215. List<UUID> onlineFriends = m_TheService.StatusNotification(friends, principalID, online);
  216. Dictionary<string, object> result = new Dictionary<string, object>();
  217. if ((onlineFriends == null) || ((onlineFriends != null) && (onlineFriends.Count == 0)))
  218. result["RESULT"] = "NULL";
  219. else
  220. {
  221. i = 0;
  222. foreach (UUID f in onlineFriends)
  223. {
  224. result["friend_" + i] = f.ToString();
  225. i++;
  226. }
  227. }
  228. string xmlString = ServerUtils.BuildXmlResponse(result);
  229. //m_log.DebugFormat("[GRID HANDLER]: resp string: {0}", xmlString);
  230. return Util.UTF8NoBomEncoding.GetBytes(xmlString);
  231. }
  232. #endregion
  233. #region Misc
  234. private bool VerifyServiceKey(Dictionary<string, object> request)
  235. {
  236. if (!request.ContainsKey("KEY") || !request.ContainsKey("SESSIONID"))
  237. {
  238. m_log.WarnFormat("[HGFRIENDS HANDLER]: ignoring request without Key or SessionID");
  239. return false;
  240. }
  241. if (request["KEY"] == null || request["SESSIONID"] == null)
  242. return false;
  243. string serviceKey = request["KEY"].ToString();
  244. string sessionStr = request["SESSIONID"].ToString();
  245. UUID sessionID;
  246. if (!UUID.TryParse(sessionStr, out sessionID) || serviceKey.Length == 0)
  247. return false;
  248. if (!m_UserAgentService.VerifyAgent(sessionID, serviceKey))
  249. {
  250. m_log.WarnFormat("[HGFRIENDS HANDLER]: Key {0} for session {1} did not match existing key. Ignoring request", serviceKey, sessionID);
  251. return false;
  252. }
  253. m_log.DebugFormat("[HGFRIENDS HANDLER]: Verification ok");
  254. return true;
  255. }
  256. private byte[] SuccessResult()
  257. {
  258. XmlDocument doc = new XmlDocument();
  259. XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
  260. "", "");
  261. doc.AppendChild(xmlnode);
  262. XmlElement rootElement = doc.CreateElement("", "ServerResponse",
  263. "");
  264. doc.AppendChild(rootElement);
  265. XmlElement result = doc.CreateElement("", "Result", "");
  266. result.AppendChild(doc.CreateTextNode("Success"));
  267. rootElement.AppendChild(result);
  268. return Util.DocToBytes(doc);
  269. }
  270. private byte[] SuccessResult(string value)
  271. {
  272. XmlDocument doc = new XmlDocument();
  273. XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
  274. "", "");
  275. doc.AppendChild(xmlnode);
  276. XmlElement rootElement = doc.CreateElement("", "ServerResponse",
  277. "");
  278. doc.AppendChild(rootElement);
  279. XmlElement result = doc.CreateElement("", "RESULT", "");
  280. result.AppendChild(doc.CreateTextNode("Success"));
  281. rootElement.AppendChild(result);
  282. XmlElement message = doc.CreateElement("", "Value", "");
  283. message.AppendChild(doc.CreateTextNode(value));
  284. rootElement.AppendChild(message);
  285. return Util.DocToBytes(doc);
  286. }
  287. private byte[] FailureResult()
  288. {
  289. return FailureResult(String.Empty);
  290. }
  291. private byte[] FailureResult(string msg)
  292. {
  293. XmlDocument doc = new XmlDocument();
  294. XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
  295. "", "");
  296. doc.AppendChild(xmlnode);
  297. XmlElement rootElement = doc.CreateElement("", "ServerResponse",
  298. "");
  299. doc.AppendChild(rootElement);
  300. XmlElement result = doc.CreateElement("", "RESULT", "");
  301. result.AppendChild(doc.CreateTextNode("Failure"));
  302. rootElement.AppendChild(result);
  303. XmlElement message = doc.CreateElement("", "Message", "");
  304. message.AppendChild(doc.CreateTextNode(msg));
  305. rootElement.AppendChild(message);
  306. return Util.DocToBytes(doc);
  307. }
  308. private byte[] BoolResult(bool value)
  309. {
  310. XmlDocument doc = new XmlDocument();
  311. XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration,
  312. "", "");
  313. doc.AppendChild(xmlnode);
  314. XmlElement rootElement = doc.CreateElement("", "ServerResponse",
  315. "");
  316. doc.AppendChild(rootElement);
  317. XmlElement result = doc.CreateElement("", "RESULT", "");
  318. result.AppendChild(doc.CreateTextNode(value.ToString()));
  319. rootElement.AppendChild(result);
  320. return Util.DocToBytes(doc);
  321. }
  322. #endregion
  323. }
  324. }