/* You may not modify, use, reproduce, or distribute this software except in compliance with the terms of the License at: http://developer.sun.com/berkeley_license.html $Id: GenericService.java,v 1.5 2007/06/04 18:29:15 gmurray71 Exp $ */ package jmaki.service; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; // for MD5 import java.security.MessageDigest; /** * @author Greg Murray */ public class GenericService extends HttpServlet { private MessageDigest md; // Server Side Token to Append to client provide tokens and host name private static String SERVER_TOKEN = "JMAKI_SERVICE"; public GenericService() { } private String callback = "callback"; public void init(ServletConfig config) throws ServletException { super.init(config); try { md = MessageDigest.getInstance("MD5"); } catch (java.security.NoSuchAlgorithmException nsa) { throw new ServletException(nsa); } } public void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException { PrintWriter writer = response.getWriter(); String action = req.getParameter("action"); if (action != null) { // generate an api key if ("genkey".equals(action)) { // build up the host name String host = req.getScheme() + "://" + req.getServerName(); int port = req.getServerPort(); if (port != 80) host += ":" + port; host += req.getContextPath(); host += req.getServletPath(); String url = req.getParameter("url"); if (!url.endsWith("/")) url += "/"; if (url != null) { writer.print("{ 'service' : '" + host + "'," + " 'key' : '" + generateHash(url + SERVER_TOKEN) + "'}"); } else writer.println("url required to generate an api key"); return; } } else { if (req.getParameter("apikey") != null) { boolean valid = testAPIKey(req, req.getParameter("apikey")); String lc = req.getParameter("callback"); String format = req.getParameter("format"); if (valid) { if ("jsonp".equals(format)) { response.setContentType("text/javascript"); if (lc == null) lc = callback; writer.write(lc + "(" + jsonContent + ");"); return; } else if ("json".equals(format)) { response.setContentType("text/json"); writer.write(jsonContent); return; } else { response.setContentType("text/xml"); writer.write(xmlContent); } } else { String referer = req.getHeader("Referer"); // check if it's a relative URL and make sure we end with a slash if (!referer.startsWith("http") && !referer.endsWith("/") ) referer = referer + "/"; writer.println("alert('Invalid apikey for " + referer + "');"); return; } } else { writer.println("Please provide an apikey."); return; } } } /** * Check the Referer against the API key provided * * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html */ private boolean testAPIKey(HttpServletRequest req, String apiKey) { String referer = req.getHeader("Referer"); // check if it's a relative URL and make sure we end with a slash if (!referer.startsWith("http") && !referer.endsWith("/") ) referer = referer + "/"; // get the key for the host used by the request String refererKey = generateHash(referer + SERVER_TOKEN); if (apiKey != null) return refererKey.equals(apiKey); else return false; } private String generateHash(String key) { key += SERVER_TOKEN; // start fresh md.reset(); md.update(key.getBytes()); byte[] bytes = md.digest(); // buffer to write the md5 hash to StringBuffer buff = new StringBuffer(); for (int l=0;l< bytes.length;l++) { String hx = Integer.toHexString(0xFF & bytes[l]); // make sure the hex string is correct if 1 character if(hx.length() == 1) buff.append("0"); buff.append(hx); } return buff.toString().trim(); } private String jsonContent = "{\n" + " 'columns' :[\n" + " {'title' : 'Company'},\n" + " {'title' : 'Price'},\n" + " {'title' : 'Change'},\n" + " {'title' : '% Change'},\n" + " {'title' : 'Last Updated'}\n" + " ],\n" + " 'rows' :\n" + " [\n" + " ['A Co',71.72,0.02,0.03,'9/1 12:00am'],\n" + " ['B Inc',29.01,0.42,1.47,'9/1 12:00am'],\n" + " ['C Group Inc',83.81,0.28,0.34,'9/1 12:00am'],\n" + " ['D Company',52.55,0.01,0.02,'9/1 12:00am']\n" + " ]\n" + "}\n"; private String xmlContent = "\n" + " \n" + " Company\n" + " Price\n" + " Company\n" + " Change\n" + " % Change\n" + " Last Updated\n" + " \n" + " \n" + " \n" + " A Co\n" + " 71.72\n" + " 0.02\n" + " 0.03\n" + " 9/1 12:00am\n" + " \n" + " \n" + " B Inc\n" + " 29.01\n" + " 0.42\n" + " 1.47\n" + " 9/1 12:00am\n" + " \n" + " \n" + " B Inc\n" + " 29.01\n" + " 0.42\n" + " 1.47\n" + " 9/1 12:00am\n" + " \n" + " \n" + " C Group Inc\n" + " 83.81\n" + " 0.28\n" + " 0.34\n" + " 9/1 12:00am\n" + " \n" + " \n" + " D Company\n" + " 52.55\n" + " 0.01\n" + " 0.02\n" + " 9/1 12:00am\n" + " \n" + " \n" + "
"; }