PageRenderTime 53ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/jive_messenger/vendor/current/src/java/org/jivesoftware/openfire/http/HttpBindServlet.java

https://gitlab.com/manoj-makkuboy/magnetism
Java | 342 lines | 281 code | 41 blank | 20 comment | 30 complexity | bf8f2f31a00724be59f75e5d85e9e495 MD5 | raw file
  1. /**
  2. * $Revision: $
  3. * $Date: $
  4. *
  5. * Copyright (C) 2007 Jive Software. All rights reserved.
  6. *
  7. * This software is published under the terms of the GNU Public License (GPL),
  8. * a copy of which is included in this distribution.
  9. */
  10. package org.jivesoftware.openfire.http;
  11. import org.xmlpull.v1.XmlPullParserFactory;
  12. import org.xmlpull.v1.XmlPullParserException;
  13. import org.jivesoftware.util.Log;
  14. import org.jivesoftware.util.JiveGlobals;
  15. import org.jivesoftware.openfire.net.MXParser;
  16. import org.jivesoftware.openfire.auth.UnauthorizedException;
  17. import org.dom4j.io.XMPPPacketReader;
  18. import org.dom4j.Document;
  19. import org.dom4j.DocumentException;
  20. import org.dom4j.Element;
  21. import org.dom4j.DocumentHelper;
  22. import org.mortbay.util.ajax.ContinuationSupport;
  23. import org.apache.commons.lang.StringEscapeUtils;
  24. import javax.servlet.http.HttpServlet;
  25. import javax.servlet.http.HttpServletRequest;
  26. import javax.servlet.http.HttpServletResponse;
  27. import javax.servlet.ServletException;
  28. import javax.servlet.ServletConfig;
  29. import java.io.IOException;
  30. import java.io.InputStream;
  31. import java.io.ByteArrayInputStream;
  32. import java.net.InetAddress;
  33. import java.net.URLDecoder;
  34. /**
  35. * Servlet which handles requests to the HTTP binding service. It determines if there is currently
  36. * an {@link HttpSession} related to the connection or if one needs to be created and then passes it
  37. * off to the {@link HttpBindManager} for processing of the client request and formulating of the
  38. * response.
  39. *
  40. * @author Alexander Wenckus
  41. */
  42. public class HttpBindServlet extends HttpServlet {
  43. private HttpSessionManager sessionManager;
  44. private static XmlPullParserFactory factory;
  45. static {
  46. try {
  47. factory = XmlPullParserFactory.newInstance(MXParser.class.getName(), null);
  48. }
  49. catch (XmlPullParserException e) {
  50. Log.error("Error creating a parser factory", e);
  51. }
  52. }
  53. private ThreadLocal<XMPPPacketReader> localReader = new ThreadLocal<XMPPPacketReader>();
  54. public HttpBindServlet() {
  55. }
  56. @Override
  57. public void init(ServletConfig servletConfig) throws ServletException {
  58. super.init(servletConfig);
  59. sessionManager = HttpBindManager.getInstance().getSessionManager();
  60. sessionManager.start();
  61. }
  62. @Override
  63. public void destroy() {
  64. super.destroy();
  65. sessionManager.stop();
  66. }
  67. @Override
  68. protected void doGet(HttpServletRequest request, HttpServletResponse response)
  69. throws ServletException, IOException
  70. {
  71. boolean isScriptSyntaxEnabled =
  72. JiveGlobals.getBooleanProperty("xmpp.httpbind.scriptSyntax.enabled", false);
  73. if(!isScriptSyntaxEnabled) {
  74. sendLegacyError(response, BoshBindingError.itemNotFound);
  75. return;
  76. }
  77. if (isContinuation(request, response)) {
  78. return;
  79. }
  80. String queryString = request.getQueryString();
  81. if (queryString == null || "".equals(queryString)) {
  82. sendLegacyError(response, BoshBindingError.badRequest);
  83. return;
  84. }
  85. queryString = URLDecoder.decode(queryString, "utf-8");
  86. parseDocument(request, response, new ByteArrayInputStream(queryString.getBytes()));
  87. }
  88. private void sendLegacyError(HttpServletResponse response, BoshBindingError error)
  89. throws IOException
  90. {
  91. response.sendError(error.getLegacyErrorCode());
  92. }
  93. @Override
  94. protected void doPost(HttpServletRequest request, HttpServletResponse response)
  95. throws ServletException, IOException {
  96. if (isContinuation(request, response)) {
  97. return;
  98. }
  99. parseDocument(request, response, request.getInputStream());
  100. }
  101. private void parseDocument(HttpServletRequest request, HttpServletResponse response,
  102. InputStream documentContent)
  103. throws IOException {
  104. Document document;
  105. try {
  106. document = createDocument(documentContent);
  107. }
  108. catch (Exception e) {
  109. Log.warn("Error parsing user request. [" + request.getRemoteAddr() + "]");
  110. sendLegacyError(response, BoshBindingError.badRequest);
  111. return;
  112. }
  113. Element node = document.getRootElement();
  114. if (node == null || !"body".equals(node.getName())) {
  115. Log.warn("Body missing from request content. [" + request.getRemoteAddr() + "]");
  116. sendLegacyError(response, BoshBindingError.badRequest);
  117. return;
  118. }
  119. String sid = node.attributeValue("sid");
  120. // We have a new session
  121. if (sid == null) {
  122. createNewSession(request, response, node);
  123. }
  124. else {
  125. handleSessionRequest(sid, request, response, node);
  126. }
  127. }
  128. private boolean isContinuation(HttpServletRequest request, HttpServletResponse response)
  129. throws IOException
  130. {
  131. HttpSession session = (HttpSession) request.getAttribute("request-session");
  132. if (session == null) {
  133. return false;
  134. }
  135. synchronized (session) {
  136. try {
  137. respond(response, session.getResponse((Long) request.getAttribute("request")),
  138. request.getMethod());
  139. }
  140. catch (HttpBindException e) {
  141. sendError(request, response, e.getBindingError(), session);
  142. }
  143. }
  144. return true;
  145. }
  146. private void sendError(HttpServletRequest request, HttpServletResponse response,
  147. BoshBindingError bindingError, HttpSession session)
  148. throws IOException
  149. {
  150. try {
  151. if (session.getVersion() >= 1.6) {
  152. respond(response, createErrorBody(bindingError.getErrorType().getType(),
  153. bindingError.getCondition()), request.getMethod());
  154. }
  155. else {
  156. sendLegacyError(response, bindingError);
  157. }
  158. }
  159. finally {
  160. if (bindingError.getErrorType() == BoshBindingError.Type.terminal) {
  161. session.close();
  162. }
  163. }
  164. }
  165. private String createErrorBody(String type, String condition) {
  166. Element body = DocumentHelper.createElement("body");
  167. body.addNamespace("", "http://jabber.org/protocol/httpbind");
  168. body.addAttribute("type", type);
  169. body.addAttribute("condition", condition);
  170. return body.asXML();
  171. }
  172. private void handleSessionRequest(String sid, HttpServletRequest request,
  173. HttpServletResponse response, Element rootNode)
  174. throws IOException
  175. {
  176. long rid = getLongAttribue(rootNode.attributeValue("rid"), -1);
  177. if (rid <= 0) {
  178. response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Body missing RID (Request ID)");
  179. return;
  180. }
  181. HttpSession session = sessionManager.getSession(sid);
  182. if (session == null) {
  183. Log.warn("Client provided invalid session: " + sid + ". [" +
  184. request.getRemoteAddr() + "]");
  185. response.sendError(HttpServletResponse.SC_NOT_FOUND, "Invalid SID.");
  186. return;
  187. }
  188. synchronized (session) {
  189. HttpConnection connection;
  190. try {
  191. connection = sessionManager.forwardRequest(rid, session,
  192. request.isSecure(), rootNode);
  193. }
  194. catch (HttpBindException e) {
  195. sendError(request, response, e.getBindingError(), session);
  196. return;
  197. }
  198. catch (HttpConnectionClosedException nc) {
  199. Log.error("Error sending packet to client.", nc);
  200. return;
  201. }
  202. String type = rootNode.attributeValue("type");
  203. if ("terminate".equals(type)) {
  204. session.close();
  205. respond(response, createEmptyBody(), request.getMethod());
  206. }
  207. else {
  208. connection
  209. .setContinuation(ContinuationSupport.getContinuation(request, connection));
  210. request.setAttribute("request-session", connection.getSession());
  211. request.setAttribute("request", connection.getRequestId());
  212. try {
  213. respond(response, session.getResponse(connection.getRequestId()),
  214. request.getMethod());
  215. }
  216. catch (HttpBindException e) {
  217. sendError(request, response, e.getBindingError(), session);
  218. }
  219. }
  220. }
  221. }
  222. private void createNewSession(HttpServletRequest request, HttpServletResponse response,
  223. Element rootNode)
  224. throws IOException
  225. {
  226. long rid = getLongAttribue(rootNode.attributeValue("rid"), -1);
  227. if (rid <= 0) {
  228. response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Body missing RID (Request ID)");
  229. return;
  230. }
  231. try {
  232. HttpConnection connection = new HttpConnection(rid, request.isSecure());
  233. InetAddress address = InetAddress.getByName(request.getRemoteAddr());
  234. connection.setSession(sessionManager.createSession(address, rootNode, connection));
  235. respond(response, connection, request.getMethod());
  236. }
  237. catch (UnauthorizedException e) {
  238. // Server wasn't initialized yet.
  239. response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
  240. "Server Not initialized");
  241. }
  242. catch (HttpBindException e) {
  243. response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
  244. }
  245. }
  246. private void respond(HttpServletResponse response, HttpConnection connection, String method)
  247. throws IOException
  248. {
  249. String content;
  250. try {
  251. content = connection.getResponse();
  252. }
  253. catch (HttpBindTimeoutException e) {
  254. content = createEmptyBody();
  255. }
  256. respond(response, content, method);
  257. }
  258. private void respond(HttpServletResponse response, String content, String method)
  259. throws IOException {
  260. response.setStatus(HttpServletResponse.SC_OK);
  261. response.setContentType("GET".equals(method) ? "text/javascript" : "text/xml");
  262. response.setCharacterEncoding("utf-8");
  263. if ("GET".equals(method)) {
  264. content = "_BOSH_(\"" + StringEscapeUtils.escapeJavaScript(content) + "\")";
  265. }
  266. byte[] byteContent = content.getBytes("utf-8");
  267. response.setContentLength(byteContent.length);
  268. response.getOutputStream().write(byteContent);
  269. }
  270. private static String createEmptyBody() {
  271. Element body = DocumentHelper.createElement("body");
  272. body.addNamespace("", "http://jabber.org/protocol/httpbind");
  273. return body.asXML();
  274. }
  275. private long getLongAttribue(String value, long defaultValue) {
  276. if (value == null || "".equals(value)) {
  277. return defaultValue;
  278. }
  279. try {
  280. return Long.valueOf(value);
  281. }
  282. catch (Exception ex) {
  283. return defaultValue;
  284. }
  285. }
  286. private XMPPPacketReader getPacketReader() {
  287. // Reader is associated with a new XMPPPacketReader
  288. XMPPPacketReader reader = localReader.get();
  289. if (reader == null) {
  290. reader = new XMPPPacketReader();
  291. reader.setXPPFactory(factory);
  292. localReader.set(reader);
  293. }
  294. return reader;
  295. }
  296. private Document createDocument(InputStream request) throws
  297. DocumentException, IOException, XmlPullParserException
  298. {
  299. return getPacketReader().read("utf-8", request);
  300. }
  301. }