You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openmeetings.apache.org by so...@apache.org on 2017/05/16 09:30:42 UTC

openmeetings git commit: no jira: Security HTTP headers need to be set

Repository: openmeetings
Updated Branches:
  refs/heads/3.3.x 44800f8a1 -> aadcd3e4e


no jira: Security HTTP headers need to be set


Project: http://git-wip-us.apache.org/repos/asf/openmeetings/repo
Commit: http://git-wip-us.apache.org/repos/asf/openmeetings/commit/aadcd3e4
Tree: http://git-wip-us.apache.org/repos/asf/openmeetings/tree/aadcd3e4
Diff: http://git-wip-us.apache.org/repos/asf/openmeetings/diff/aadcd3e4

Branch: refs/heads/3.3.x
Commit: aadcd3e4eaaba5a6d322eb53f48c3bbb4fd7a5da
Parents: 44800f8
Author: Maxim Solodovnik <so...@gmail.com>
Authored: Tue May 16 16:30:32 2017 +0700
Committer: Maxim Solodovnik <so...@gmail.com>
Committed: Tue May 16 16:30:32 2017 +0700

----------------------------------------------------------------------
 .../remote/red5/ScopeApplicationAdapter.java    | 18 +++++++---
 .../org/apache/openmeetings/IApplication.java   |  2 ++
 .../db/dao/basic/ConfigurationDao.java          | 38 ++++++++++++++++----
 .../installation/ImportInitvalues.java          |  7 +++-
 .../src/site/xdoc/GeneralConfiguration.xml      | 21 +++++++----
 .../util/OpenmeetingsVariables.java             |  4 +++
 .../openmeetings/web/app/Application.java       | 30 ++++++++++++++++
 .../org/apache/openmeetings/web/pages/om-ga.js  | 13 +++----
 8 files changed, 105 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/openmeetings/blob/aadcd3e4/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
----------------------------------------------------------------------
diff --git a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
index ab5f776..7e1c07a 100644
--- a/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
+++ b/openmeetings-core/src/main/java/org/apache/openmeetings/core/remote/red5/ScopeApplicationAdapter.java
@@ -19,7 +19,12 @@
 package org.apache.openmeetings.core.remote.red5;
 
 import static org.apache.openmeetings.util.OmFileHelper.EXTENSION_MP4;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_CSP;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_XFRAME;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.HEADER_CSP_SELF;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.HEADER_XFRAME_SAMEORIGIN;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.wicketApplicationName;
 
 import java.awt.Point;
 import java.io.File;
@@ -111,7 +116,7 @@ public class ScopeApplicationAdapter extends MultiThreadedApplicationAdapter imp
 	@Autowired
 	private RecordingService recordingService;
 	@Autowired
-	private ConfigurationDao configurationDao;
+	private ConfigurationDao cfgDao;
 	@Autowired
 	private AppointmentDao appointmentDao;
 	@Autowired
@@ -156,6 +161,9 @@ public class ScopeApplicationAdapter extends MultiThreadedApplicationAdapter imp
 			}
 
 			InitializationContainer.initComplete = true;
+			IApplication iapp = (IApplication)Application.get(wicketApplicationName);
+			iapp.setXFrameOptions(cfgDao.getConfValue(CONFIG_HEADER_XFRAME, String.class, HEADER_XFRAME_SAMEORIGIN));
+			iapp.setContentSecurityPolicy(cfgDao.getConfValue(CONFIG_HEADER_CSP, String.class, HEADER_CSP_SELF));
 			Version.logOMStarted();
 			recordingDao.resetProcessingStatus(); //we are starting so all processing recordings are now errors
 			sessionManager.clearCache(); // 'sticky' clients should be cleaned up from DB
@@ -198,7 +206,7 @@ public class ScopeApplicationAdapter extends MultiThreadedApplicationAdapter imp
 		StringValue scn = StringValue.valueOf(conn.getScope().getName());
 		long roomId = scn.toLong(Long.MIN_VALUE);
 		Client rcm = new Client();
-		IApplication iapp = (IApplication)Application.get(OpenmeetingsVariables.wicketApplicationName);
+		IApplication iapp = (IApplication)Application.get(wicketApplicationName);
 		if (!Strings.isEmpty(securityCode)) {
 			//this is for external applications like ffmpeg [OPENMEETINGS-1574]
 			if (roomId < 0) {
@@ -655,7 +663,7 @@ public class ScopeApplicationAdapter extends MultiThreadedApplicationAdapter imp
 			}.start();
 
 			if (client.isMobile()) {
-				IApplication app = (IApplication)Application.get(OpenmeetingsVariables.wicketApplicationName);
+				IApplication app = (IApplication)Application.get(wicketApplicationName);
 				app.exit(client.getPublicSID());
 			}
 			sessionManager.removeClient(client.getStreamid(), null);
@@ -1857,11 +1865,11 @@ public class ScopeApplicationAdapter extends MultiThreadedApplicationAdapter imp
 	}
 
 	private boolean getWhiteboardDrawStatus() {
-		return configurationDao.getWhiteboardDrawStatus();
+		return cfgDao.getWhiteboardDrawStatus();
 	}
 
 	public String getCryptKey() {
-		return configurationDao.getCryptKey();
+		return cfgDao.getCryptKey();
 	}
 
 	public IScope getRoomScope(String room) {

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/aadcd3e4/openmeetings-db/src/main/java/org/apache/openmeetings/IApplication.java
----------------------------------------------------------------------
diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/IApplication.java b/openmeetings-db/src/main/java/org/apache/openmeetings/IApplication.java
index b02066f..49e3385 100644
--- a/openmeetings-db/src/main/java/org/apache/openmeetings/IApplication.java
+++ b/openmeetings-db/src/main/java/org/apache/openmeetings/IApplication.java
@@ -47,4 +47,6 @@ public interface IApplication {
 	String urlForActivatePage(PageParameters pp);
 	void invalidateClient(Long userId, String sessionId);
 	void exit(String uid);
+	void setXFrameOptions(String xFrameOptions);
+	void setContentSecurityPolicy(String contentSecurityPolicy);
 }

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/aadcd3e4/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/ConfigurationDao.java
----------------------------------------------------------------------
diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/ConfigurationDao.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/ConfigurationDao.java
index 3e054a0..3697e01 100644
--- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/ConfigurationDao.java
+++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/dao/basic/ConfigurationDao.java
@@ -22,12 +22,15 @@ import static org.apache.openmeetings.util.OpenmeetingsVariables.APPLICATION_NAM
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_APPLICATION_BASE_URL;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_APPLICATION_NAME;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_CRYPT_KEY;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_CSP;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_XFRAME;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_MAX_UPLOAD_SIZE_KEY;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_SIP_ENABLED;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.DEFAULT_BASE_URL;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.configKeyCryptClassName;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.whiteboardDrawStatus;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.wicketApplicationName;
 
 import java.lang.reflect.Constructor;
 import java.util.ArrayList;
@@ -39,10 +42,12 @@ import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.TypedQuery;
 
+import org.apache.openmeetings.IApplication;
 import org.apache.openmeetings.db.dao.IDataProviderDao;
 import org.apache.openmeetings.db.dao.user.UserDao;
 import org.apache.openmeetings.db.entity.basic.Configuration;
 import org.apache.openmeetings.util.DaoHelper;
+import org.apache.wicket.Application;
 import org.red5.logging.Red5LoggerFactory;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -230,14 +235,33 @@ public class ConfigurationDao implements IDataProviderDao<Configuration> {
 			entity.setUpdated(new Date());
 			entity = em.merge(entity);
 		}
-		if (CONFIG_CRYPT_KEY.equals(key)) {
-			configKeyCryptClassName = value;
-		} else if ("show.whiteboard.draw.status".equals(key)) {
-			whiteboardDrawStatus = Boolean.valueOf("1".equals(value));
-		} else if (CONFIG_APPLICATION_NAME.equals(key)) {
-			APPLICATION_NAME = value;
+		switch (key) {
+			case CONFIG_CRYPT_KEY:
+				configKeyCryptClassName = value;
+				break;
+			case "show.whiteboard.draw.status":
+				whiteboardDrawStatus = Boolean.valueOf("1".equals(value));
+				break;
+			case CONFIG_APPLICATION_NAME:
+				APPLICATION_NAME = value;
+				break;
+			case CONFIG_HEADER_XFRAME:
+			{
+				IApplication iapp = (IApplication)Application.get(wicketApplicationName);
+				if (iapp != null) {
+					iapp.setXFrameOptions(value);
+				}
+			}
+				break;
+			case CONFIG_HEADER_CSP:
+			{
+				IApplication iapp = (IApplication)Application.get(wicketApplicationName);
+				if (iapp != null) {
+					iapp.setContentSecurityPolicy(value);
+				}
+			}
+				break;
 		}
-		//TODO ensure entity returned is updated
 		return entity;
 	}
 

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/aadcd3e4/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java
----------------------------------------------------------------------
diff --git a/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java b/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java
index b99a638..9275e07 100644
--- a/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java
+++ b/openmeetings-install/src/main/java/org/apache/openmeetings/installation/ImportInitvalues.java
@@ -34,6 +34,8 @@ import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_DEFAULT_
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_DEFAULT_LDAP_ID;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_FRONTEND_REGISTER_KEY;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_GOOGLE_ANALYTICS_CODE;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_CSP;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_HEADER_XFRAME;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_IGNORE_BAD_SSL;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_IMAGEMAGIC_PATH;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_LOGIN_MIN_LENGTH_KEY;
@@ -50,6 +52,8 @@ import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_SCREENSH
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_SIP_ENABLED;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_SOAP_REGISTER_KEY;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.CONFIG_SYSTEM_EMAIL;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.HEADER_CSP_SELF;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.HEADER_XFRAME_SAMEORIGIN;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.LEVEL_ADMIN;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.LEVEL_GROUP_ADMIN;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.LEVEL_USER;
@@ -352,7 +356,8 @@ public class ImportInitvalues {
 				"Users entered the room via invitationHash or secureHash will be redirected to this URL on connection lost");
 		cfgDao.add(CONFIG_CALENDAR_FIRST_DAY, "0", null, "The day that each week begins. The value must be a number that represents the day of the week. Sunday=0, Monday=1, Tuesday=2, etc.");
 		cfgDao.add(CONFIG_GOOGLE_ANALYTICS_CODE, null, null, "Code for Google Analytics");
-
+		cfgDao.add(CONFIG_HEADER_XFRAME, HEADER_XFRAME_SAMEORIGIN, null, "Value for 'X-Frame-Options' header (default: DENY), more info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options");
+		cfgDao.add(CONFIG_HEADER_CSP, HEADER_CSP_SELF, null, "Value for 'Content-Security-Policy' header (default: default-src 'self';), have to be modified to enable Google analytics site: https://content-security-policy.com/");
 		log.debug("Configurations ADDED");
 	}
 

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/aadcd3e4/openmeetings-server/src/site/xdoc/GeneralConfiguration.xml
----------------------------------------------------------------------
diff --git a/openmeetings-server/src/site/xdoc/GeneralConfiguration.xml b/openmeetings-server/src/site/xdoc/GeneralConfiguration.xml
index 9114bdd..63338f8 100644
--- a/openmeetings-server/src/site/xdoc/GeneralConfiguration.xml
+++ b/openmeetings-server/src/site/xdoc/GeneralConfiguration.xml
@@ -13,16 +13,13 @@
    limitations under the License.
  -->
 <document xmlns="http://maven.apache.org/XDOC/2.0"
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
-
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd">
 	<properties>
 		<title>List of general configuration options</title>
 		<author email="dev@openmeetings.apache.org">Apache OpenMeetings Team</author>
 	</properties>
-
 	<body>
-
 		<section name="List of general configuration options">
 			<p>In Administration &gt; Configuration there are a number of
 				configuration values.
@@ -298,9 +295,19 @@
 					<td> Code for Google Analytics. </td>
 					<td> 3.1.0 </td>
 				</tr>
+				<tr>
+					<td> header.x.frame.options </td>
+					<td> SAMEORIGIN </td>
+					<td> Value for 'X-Frame-Options' header, more info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options </td>
+					<td> 3.3.0 </td>
+				</tr>
+				<tr>
+					<td> header.content.security.policy </td>
+					<td> default-src 'self'; </td>
+					<td> Value for 'Content-Security-Policy' header, have to be modified to enable Google analytics site: https://content-security-policy.com/ </td>
+					<td> 3.3.0 </td>
+				</tr>
 			</table>
 		</section>
-
 	</body>
-
 </document>

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/aadcd3e4/openmeetings-util/src/main/java/org/apache/openmeetings/util/OpenmeetingsVariables.java
----------------------------------------------------------------------
diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/OpenmeetingsVariables.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/OpenmeetingsVariables.java
index 180be2f..32eecae 100644
--- a/openmeetings-util/src/main/java/org/apache/openmeetings/util/OpenmeetingsVariables.java
+++ b/openmeetings-util/src/main/java/org/apache/openmeetings/util/OpenmeetingsVariables.java
@@ -49,6 +49,10 @@ public class OpenmeetingsVariables {
 	public static final String CONFIG_GOOGLE_ANALYTICS_CODE = "google.analytics.code";
 	public static final String CONFIG_SYSTEM_EMAIL = "system_email_addr";
 	public static final String CONFIG_IMAGEMAGIC_PATH = "imagemagick_path";
+	public static final String CONFIG_HEADER_XFRAME = "header.x.frame.options";
+	public static final String HEADER_XFRAME_SAMEORIGIN = "SAMEORIGIN";
+	public static final String HEADER_CSP_SELF = "default-src 'self';";
+	public static final String CONFIG_HEADER_CSP = "header.content.security.policy";
 	public static final String MENU_ROOMS_NAME = "Conference Rooms";
 	public static final int RECENT_ROOMS_COUNT = 5;
 	public static final int LEVEL_USER = 1;

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/aadcd3e4/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
index 691f550..19fb3b0 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/app/Application.java
@@ -19,6 +19,7 @@
 package org.apache.openmeetings.web.app;
 
 import static org.apache.openmeetings.core.util.WebSocketHelper.sendRoom;
+import static org.apache.openmeetings.util.OpenmeetingsVariables.HEADER_XFRAME_SAMEORIGIN;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;
 import static org.apache.openmeetings.util.OpenmeetingsVariables.wicketApplicationName;
 import static org.apache.openmeetings.web.pages.HashPage.INVITATION_HASH;
@@ -59,6 +60,7 @@ import org.apache.openmeetings.db.entity.room.Room.Right;
 import org.apache.openmeetings.db.entity.user.User;
 import org.apache.openmeetings.db.entity.user.User.Type;
 import org.apache.openmeetings.util.InitializationContainer;
+import org.apache.openmeetings.util.OpenmeetingsVariables;
 import org.apache.openmeetings.util.message.RoomMessage;
 import org.apache.openmeetings.web.pages.AccessDeniedPage;
 import org.apache.openmeetings.web.pages.ActivatePage;
@@ -95,10 +97,13 @@ import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.protocol.http.CsrfPreventionRequestCycleListener;
 import org.apache.wicket.protocol.ws.api.WebSocketMessageBroadcastHandler;
 import org.apache.wicket.protocol.ws.api.WebSocketRequestHandler;
+import org.apache.wicket.protocol.ws.api.WebSocketResponse;
 import org.apache.wicket.request.IRequestHandler;
+import org.apache.wicket.request.Response;
 import org.apache.wicket.request.Url;
 import org.apache.wicket.request.component.IRequestablePage;
 import org.apache.wicket.request.cycle.RequestCycle;
+import org.apache.wicket.request.http.WebResponse;
 import org.apache.wicket.request.mapper.info.PageComponentInfo;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.request.mapper.parameter.PageParametersEncoder;
@@ -130,6 +135,8 @@ public class Application extends AuthenticatedWebApplication implements IApplica
 	public static final String HASH_MAPPING = "/hash";
 	public static final String SIGNIN_MAPPING = "/signin";
 	public static final String NOTINIT_MAPPING = "/notinited";
+	private String xFrameOptions = HEADER_XFRAME_SAMEORIGIN;
+	private String contentSecurityPolicy = OpenmeetingsVariables.HEADER_CSP_SELF;
 
 	@Override
 	protected void init() {
@@ -145,6 +152,19 @@ public class Application extends AuthenticatedWebApplication implements IApplica
 		getJavaScriptLibrarySettings().setJQueryReference(new JavaScriptResourceReference(DynamicJQueryResourceReference.class, DynamicJQueryResourceReference.VERSION_2));
 		getRequestCycleListeners().add(new CsrfPreventionRequestCycleListener() {
 			@Override
+			public void onEndRequest(RequestCycle cycle) {
+				Response resp = cycle.getResponse();
+				if (resp instanceof WebResponse && !(resp instanceof WebSocketResponse)) {
+					WebResponse wresp = (WebResponse)resp;
+					wresp.setHeader("X-XSS-Protection", "1; mode=block");
+					wresp.setHeader("Strict-Transport-Security", "max-age=31536000; includeSubDomains; preload");
+					wresp.setHeader("X-Content-Type-Options", "nosniff");
+					wresp.setHeader("X-Frame-Options", xFrameOptions);
+					wresp.setHeader("Content-Security-Policy", contentSecurityPolicy);
+				}
+			}
+
+			@Override
 			protected boolean isChecked(IRequestHandler handler) {
 				if (handler instanceof WebSocketRequestHandler || handler instanceof WebSocketMessageBroadcastHandler) {
 					return false;
@@ -646,4 +666,14 @@ public class Application extends AuthenticatedWebApplication implements IApplica
 	public String getOmString(String key, final Locale loc, String... params) {
 		return getString(key, loc, params);
 	}
+
+	@Override
+	public void setXFrameOptions(String xFrameOptions) {
+		this.xFrameOptions = xFrameOptions;
+	}
+
+	@Override
+	public void setContentSecurityPolicy(String contentSecurityPolicy) {
+		this.contentSecurityPolicy = contentSecurityPolicy;
+	}
 }

http://git-wip-us.apache.org/repos/asf/openmeetings/blob/aadcd3e4/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/om-ga.js
----------------------------------------------------------------------
diff --git a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/om-ga.js b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/om-ga.js
index d5b7f12..a3226af 100644
--- a/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/om-ga.js
+++ b/openmeetings-web/src/main/java/org/apache/openmeetings/web/pages/om-ga.js
@@ -24,19 +24,16 @@
 	a=s.createElement(o),m=s.getElementsByTagName(o)[0];
 	a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
 })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
-
 function initGA(code) {
 	ga('create', code, 'auto');
 }
-
 function init() {
-    ga('send', 'pageview');
+	ga('send', 'pageview');
 }
-
 function initHash() {
-    ga('send', 'pageview', window.location.hash);
+	ga('send', 'pageview', window.location.hash);
 
-    $(window).bind( 'hashchange', function( e ) {
-            ga('send', 'pageview', window.location.hash);
-    });
+	$(window).bind( 'hashchange', function( e ) {
+		ga('send', 'pageview', window.location.hash);
+	});
 }