226 lines
7.9 KiB
Plaintext
Executable File
226 lines
7.9 KiB
Plaintext
Executable File
<%@ page language="java"
|
|
contentType="image/gif"
|
|
import="java.io.ByteArrayOutputStream,
|
|
java.io.IOException,
|
|
java.io.OutputStream,
|
|
java.io.UnsupportedEncodingException,
|
|
java.math.BigInteger,
|
|
java.net.HttpURLConnection,
|
|
java.net.URLConnection,
|
|
java.net.URL,
|
|
java.net.URLEncoder,
|
|
java.net.URLDecoder,
|
|
java.security.MessageDigest,
|
|
java.security.NoSuchAlgorithmException,
|
|
javax.servlet.http.Cookie,
|
|
java.util.regex.Pattern,
|
|
java.util.regex.Matcher,
|
|
java.util.UUID" %><%!
|
|
|
|
/**
|
|
Copyright 2009 Google Inc. All Rights Reserved.
|
|
**/
|
|
|
|
// Tracker version.
|
|
private static final String version = "4.4sj";
|
|
|
|
private static final String COOKIE_NAME = "__utmmobile";
|
|
|
|
// The path the cookie will be available to, edit this to use a different
|
|
// cookie path.
|
|
private static final String COOKIE_PATH = "/";
|
|
|
|
// Two years in seconds.
|
|
private static final int COOKIE_USER_PERSISTENCE = 63072000;
|
|
|
|
// 1x1 transparent GIF
|
|
private static final byte[] GIF_DATA = new byte[] {
|
|
(byte)0x47, (byte)0x49, (byte)0x46, (byte)0x38, (byte)0x39, (byte)0x61,
|
|
(byte)0x01, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x80, (byte)0xff,
|
|
(byte)0x00, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x00, (byte)0x00,
|
|
(byte)0x00, (byte)0x2c, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
|
|
(byte)0x01, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x02,
|
|
(byte)0x02, (byte)0x44, (byte)0x01, (byte)0x00, (byte)0x3b
|
|
};
|
|
|
|
// A string is empty in our terms, if it is null, empty or a dash.
|
|
private static boolean isEmpty(String in) {
|
|
return in == null || "-".equals(in) || "".equals(in);
|
|
}
|
|
|
|
// The last octect of the IP address is removed to anonymize the user.
|
|
private static String getIP(String remoteAddress) {
|
|
if (isEmpty(remoteAddress)) {
|
|
return "";
|
|
}
|
|
// Capture the first three octects of the IP address and replace the forth
|
|
// with 0, e.g. 124.455.3.123 becomes 124.455.3.0
|
|
String regex = "^([^.]+\\.[^.]+\\.[^.]+\\.).*";
|
|
Pattern getFirstBitOfIPAddress = Pattern.compile(regex);
|
|
Matcher m = getFirstBitOfIPAddress.matcher(remoteAddress);
|
|
if (m.matches()) {
|
|
return m.group(1) + "0";
|
|
} else {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
// Generate a visitor id for this hit.
|
|
// If there is a visitor id in the cookie, use that, otherwise
|
|
// use the guid if we have one, otherwise use a random number.
|
|
private static String getVisitorId(
|
|
String guid, String account, String userAgent, Cookie cookie)
|
|
throws NoSuchAlgorithmException, UnsupportedEncodingException {
|
|
|
|
// If there is a value in the cookie, don't change it.
|
|
if (cookie != null && cookie.getValue() != null) {
|
|
return cookie.getValue();
|
|
}
|
|
|
|
String message;
|
|
if (!isEmpty(guid)) {
|
|
// Create the visitor id using the guid.
|
|
message = guid + account;
|
|
} else {
|
|
// otherwise this is a new user, create a new random id.
|
|
message = userAgent + getRandomNumber() + UUID.randomUUID().toString();
|
|
}
|
|
|
|
MessageDigest m = MessageDigest.getInstance("MD5");
|
|
m.update(message.getBytes("UTF-8"), 0, message.length());
|
|
byte[] sum = m.digest();
|
|
BigInteger messageAsNumber = new BigInteger(1, sum);
|
|
String md5String = messageAsNumber.toString(16);
|
|
|
|
// Pad to make sure id is 32 characters long.
|
|
while (md5String.length() < 32) {
|
|
md5String = "0" + md5String;
|
|
}
|
|
|
|
return "0x" + md5String.substring(0, 16);
|
|
}
|
|
|
|
// Get a random number string.
|
|
private static String getRandomNumber() {
|
|
return Integer.toString((int) (Math.random() * 0x7fffffff));
|
|
}
|
|
|
|
// Writes the bytes of a 1x1 transparent gif into the response.
|
|
private void writeGifData(HttpServletResponse response) throws IOException {
|
|
response.addHeader(
|
|
"Cache-Control",
|
|
"private, no-cache, no-cache=Set-Cookie, proxy-revalidate");
|
|
response.addHeader("Pragma", "no-cache");
|
|
response.addHeader("Expires", "Wed, 17 Sep 1975 21:32:10 GMT");
|
|
ServletOutputStream output = response.getOutputStream();
|
|
output.write(GIF_DATA);
|
|
output.flush();
|
|
}
|
|
|
|
// Make a tracking request to Google Analytics from this server.
|
|
// Copies the headers from the original request to the new one.
|
|
// If request containg utmdebug parameter, exceptions encountered
|
|
// communicating with Google Analytics are thown.
|
|
private void sendRequestToGoogleAnalytics(
|
|
String utmUrl, HttpServletRequest request) throws Exception {
|
|
try {
|
|
URL url = new URL(utmUrl);
|
|
URLConnection connection = url.openConnection();
|
|
connection.setUseCaches(false);
|
|
|
|
connection.addRequestProperty("User-Agent",
|
|
request.getHeader("User-Agent"));
|
|
connection.addRequestProperty("Accepts-Language",
|
|
request.getHeader("Accepts-Language"));
|
|
|
|
connection.getContent();
|
|
} catch (Exception e) {
|
|
if (request.getParameter("utmdebug") != null) {
|
|
throw new Exception(e);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Track a page view, updates all the cookies and campaign tracker,
|
|
// makes a server side request to Google Analytics and writes the transparent
|
|
// gif byte data to the response.
|
|
private void trackPageView(
|
|
HttpServletRequest request, HttpServletResponse response)
|
|
throws Exception {
|
|
String timeStamp = Long.toString(System.currentTimeMillis() / 1000);
|
|
String domainName = request.getServerName();
|
|
if (isEmpty(domainName)) {
|
|
domainName = "";
|
|
}
|
|
|
|
// Get the referrer from the utmr parameter, this is the referrer to the
|
|
// page that contains the tracking pixel, not the referrer for tracking
|
|
// pixel.
|
|
String documentReferer = request.getParameter("utmr");
|
|
if (isEmpty(documentReferer)) {
|
|
documentReferer = "-";
|
|
} else {
|
|
documentReferer = URLDecoder.decode(documentReferer, "UTF-8");
|
|
}
|
|
String documentPath = request.getParameter("utmp");
|
|
if (isEmpty(documentPath)) {
|
|
documentPath = "";
|
|
} else {
|
|
documentPath = URLDecoder.decode(documentPath, "UTF-8");
|
|
}
|
|
|
|
String account = request.getParameter("utmac");
|
|
String userAgent = request.getHeader("User-Agent");
|
|
if (isEmpty(userAgent)) {
|
|
userAgent = "";
|
|
}
|
|
|
|
// Try and get visitor cookie from the request.
|
|
Cookie[] cookies = request.getCookies();
|
|
Cookie cookie = null;
|
|
if (cookies != null) {
|
|
for(int i = 0; i < cookies.length; i++) {
|
|
if (cookies[i].getName().equals(COOKIE_NAME)) {
|
|
cookie = cookies[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
String visitorId = getVisitorId(
|
|
request.getHeader("X-DCMGUID"), account, userAgent, cookie);
|
|
|
|
// Always try and add the cookie to the response.
|
|
Cookie newCookie = new Cookie(COOKIE_NAME, visitorId);
|
|
newCookie.setMaxAge(COOKIE_USER_PERSISTENCE);
|
|
newCookie.setPath(COOKIE_PATH);
|
|
response.addCookie(newCookie);
|
|
|
|
String utmGifLocation = "http://www.google-analytics.com/__utm.gif";
|
|
|
|
// Construct the gif hit url.
|
|
String utmUrl = utmGifLocation + "?" +
|
|
"utmwv=" + version +
|
|
"&utmn=" + getRandomNumber() +
|
|
"&utmhn=" + URLEncoder.encode(domainName, "UTF-8") +
|
|
"&utmr=" + URLEncoder.encode(documentReferer, "UTF-8") +
|
|
"&utmp=" + URLEncoder.encode(documentPath, "UTF-8") +
|
|
"&utmac=" + account +
|
|
"&utmcc=__utma%3D999.999.999.999.999.1%3B" +
|
|
"&utmvid=" + visitorId +
|
|
"&utmip=" + getIP(request.getRemoteAddr());
|
|
|
|
sendRequestToGoogleAnalytics(utmUrl, request);
|
|
|
|
// If the debug parameter is on, add a header to the response that contains
|
|
// the url that was used to contact Google Analytics.
|
|
if (request.getParameter("utmdebug") != null) {
|
|
response.setHeader("X-GA-MOBILE-URL", utmUrl);
|
|
}
|
|
// Finally write the gif data to the response.
|
|
writeGifData(response);
|
|
}
|
|
%><%
|
|
// Let exceptions bubble up to container, for better debugging.
|
|
trackPageView(request, response);
|
|
%>
|